ここのことはなかったことにするかもしれない

仕事がらみの記事を主として扱いますが、あくまで個人ブログです。2013年以前の記事は https://yellow-73.hatenablog.com/ にあります。

ZFSのACLをNFSv4形式でいじって全ファイルに自動で実行パーミッション付けたった

はじめに

私の環境では、ファイルパーミッションは、umask付けてて、一般ファイルなら644、ディレクトリなら755になっています。これを一般ファイルも755にしてやるのが今回の目標。

ローカルでDAVを使っていますが、こいつが実行パーミッションを付けよらん。これまではSambaをかませて、smbfsをマウントしているところにDAVで書き込んで実行パーミッションを与える、というなんとも香ばしい手段でどうにかしていましたが、フルZFSにしちゃったら、なんでかsmbfsをマウントできない、という目に遭ってしまったため、この手段を捨てる時が来たのです。

手動でchmodを使ったりして755にするのは可能ですが、断言できます、絶対忘れる。

ご注意

NFSv4 です。POSIX.1e ではありません。

ACLとは

Access Control List の略です。あとは zfs acl でググってください。

パーミッションを見てみる

とりあえず、touchでファイルを作ってみます。なお私の環境では 644 になるように umask 022 を設定してます。

% touch 1.txt
% ls -l 1.txt
 -rw-r--r--  1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx a.txt

このファイルのACLエントリを見てみます。getfaclを使います。

% getfacl 1.txt
# file: 1.txt
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rw-p--aARWcCos:------:allow
            group@:r-----a-R-c--s:------:allow
         everyone@:r-----a-R-c--s:------:allow

最後の3行がACLエントリです。

エントリは":"区切りで、各フィールドは次のような意味を持ちます。

<タグ>:<パーミッション>:<継承フラグ>:<ACLタイプ>
  • タグ: "user:<ユーザ名>"などのユーザ指定(同じようにグループ指定も可能)や、特殊なタグとして"owner@", "group@", "everyone@" があります。
  • パーミッション: マニュアル見て下さい。rは読み取り、wは書き込み、xは実行、です。追加(p)、属性読み書き(a/A, R/W)、ACL読み書き(c/C)などがあります。
  • 継承フラグ: 一般ファイルが継承(f)、ディレクトリが継承(d)、
  • ACLタイプ: "allow"か"deny"を取ります。

なお、"everyone@"については注意が必要です。"others"はownerやgroupを除いたものになりますが、"everyone@"は"owner@"と"group@"を含みます。このため、"owner@", "group@"に実行パーミッションが付いていなくても"everyone@"に実行パーミッションが付いていたら、"owner@"も"group@"も実行パーミッションが付いているのと同じになります(denyしてないという前提)。

ためしに手動で755にしてやる

644から755にするには、everyoneに実行パーミッションを付けます。setfaclを使います。

% setfacl -m everyone@:rxaRcs:allow 1.txt
% getfacl 1.txt
# file: 1.txt
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rw-p--aARWcCos:------:allow
            group@:r-----a-R-c--s:------:allow
         everyone@:r-x---a-R-c--s:------:allow
% ls -l 1.txt
 -rwxr-xr-x+ 1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx 1.txt

everyoneのパーミッションが変更になったことが分かると思います。

ACLを継承する設定

次にACLの設定を継承する設定を行ってみます。
その前に、d1というディレクトリと、ついでにd1/1.txtという一般ファイルを作っておきます。

% mkdir d1
% ls -ld d1
 drwxr-xr-x  2 [ユーザ名]  [グループ名]  2  xx月 xx xx:xx d1
% touch d1/11.txt
% ls -ld d1/11.txt
 -rw-r--r--  1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx d1/1.txt

d1のACLの状態は次の通りです。

% getfacl d1
# file: d1
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:------:allow
            group@:r-x---a-R-c--s:------:allow
         everyone@:r-x---a-R-c--s:------:allow

さて、d1に実行パーミッションを付けて、かつ子ディレクトリ、子ファイルに継承する設定にしてみましょう。

% setfacl -m everyone@:rxaRcs:fd:allow d1
% getfacl d1
# file: d1
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:------:allow
            group@:r-x---a-R-c--s:------:allow
         everyone@:r-x---a-R-c--s:fd----:allow

setfaclのエントリの3番目のフィールドを作って"fd"が付いていますが、これが継承する設定です。

これで継承できているかどうか、ファイルを作ってみます。

% touch d1/2.txt
% ll d1/2.txt 
 -rw-r--r--  1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx d1/2.txt

はい、実行パーミッションが付いてませんね。

ZFSのプロパティを変更しなければならない

ACLで継承設定を用意しても、ZFSが許していなければ、継承されません。

# zfs get aclinherit
NAME        PROPERTY    VALUE          SOURCE
rpool       aclinherit  restricted     default
rpool/home  aclinherit  restricted     default
rpool/root  aclinherit  restricted     default

restrictedをpassthrougにしてやります。

# zfs set aclinherit=passthrough rpool/home
# zfs get aclinherit
NAME        PROPERTY    VALUE          SOURCE
rpool       aclinherit  restricted     default
rpool/home  aclinherit  passthrough    local
rpool/root  aclinherit  restricted     default

あらためて、ファイルを作ってみます。

% touch d1/3.txt
% ls -l d1/3.txt
 -r-xr-xr-x+ 1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx 3.txt

はい、実行パーミッションが付きましたね、ownerの書き込みパーミッションが落ちているのですがね。

755じゃなくて555になっとるがな

ここで改めて3.txtのACL状態を見てみます。

% getfacl d1/3.txt
# file: d1/3.txt
# owner: [ユーザ名]
# group: [グループ名]
         everyone@:r-x---a-R-c--s:------:allow

ownerもgroupもありません。

上のd1のACLの状態を確認して下さい、"f"と"d"が付いているのは、everyoneだけです。ownerもgroupも継承しろとは言ってないのだから、everyoneだけを継承するのは当然です。

また、上述していますが、everyoneはownerもgroupも含むので、everyoneの設定である5がownerとgroupにも影響を与え、555になってしまうわけです。

あらためて、ownerとgorupに設定します。

% setfacl -m owner@:rwxpaARWcCos:fd:allow d1
% setfacl -m group@:rxaRcs:fd:allow d1
% getfacl d1
# file: d1
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:fd----:allow
            group@:r-x---a-R-c--s:fd----:allow
         everyone@:r-x---a-R-c--s:fd----:allow

ファイルを作ってみます。

% touch d1/4.txt
% ls -l d1/4.txt
 -rwxr-xr-x  1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx d1/4.txt
% getfacl d1/4.txt
# file: d1/4.txt
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:------:allow
            group@:r-x---a-R-c--s:------:allow
         everyone@:r-x---a-R-c--s:------:allow

755になりました。

ここまでのまとめを ls -l で見る

% ls -l d1
 total 2
 -rw-r--r--  1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx 1.txt
 -rw-r--r--  1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx 2.txt
 -r-xr-xr-x+ 1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx 3.txt
 -rwxr-xr-x  1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx 4.txt

1.txt - ディレクトリに継承を設定する前
2.txt - ディレクトリにothers@のみ継承を設定した後
3.txt - ZFSに継承許可設定した後
4.txt - ディレクトリに全ての継承を設定した後

再帰的になっているかを見る

% mkdir d1/d1
% getfacl d1/d1
# file: d1/d1
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:fd----:allow
            group@:r-x---a-R-c--s:fd----:allow
         everyone@:r-x---a-R-c--s:fd----:allow
% touch d1/d1/1.txt
% getfacl d1/d1/1.txt
# file: d1/d1/1.txt
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:------:allow
            group@:r-x---a-R-c--s:------:allow
         everyone@:r-x---a-R-c--s:------:allow

chmodとACL継承

ここで、ふと、不用意にchmodすると継承が途切れるのではないか、という疑念が出てきましたので、試してみます。

% mkdir d1/d2
% getfacl d1/d2
# file: d1/d2
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:fd----:allow
            group@:r-x---a-R-c--s:fd----:allow
         everyone@:r-x---a-R-c--s:fd----:allow

mkdirした時点では、"f"と"d"は付いていますので、d1/d2の配下にファイルやディレクトリを作っても継承されます。

% chmod 700 d1/d2
% getfacl d1/d2
# file: d1/d2
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:------:allow
            group@:------a-R-c--s:------:allow
         everyone@:------a-R-c--s:------:allow

はいとれた、"f"も"d"もとれちゃったよ。

ということで、chmodをするときは要注意です。

sftpで取ってくるとき

まず、リモートで、ディレクトリ "00" を掘って、いくつかのパーミッションを持たせたファイルとディレクトリを入れておきます。こんなかんじ。

remote% ls -lR 00
  total 4
  -rw-r--r--  1 [ユーザ名]  [グループ名]    0 xx月 xx xx:xx 644.txt
  drwx------  2 [ユーザ名]  [グループ名]  512 xx月 xx xx:xx 700
  -rwxr-xr-x  1 [ユーザ名]  [グループ名]    0 xx月 xx xx:xx 755.txt

  ./700:
  total 0
  -rw-r--r--  1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx 700_644.txt
  -rwxr-xr-x  1 [ユーザ名]  [グループ名]  0 xx月 xx xx:xx 700_755.txt
remote% 

まずは、"d"と"f"が付いているディレクトリに移動。

% cd d1

sftpで取ってきました。

% sftp -p remote
...
sftp> get -r 00
sftp> ^D

さてこれがどうなっているか。

% getfacl 00
# file: 00
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:fd----:allow
            group@:r-x---a-R-c--s:fd----:allow
         everyone@:r-x---a-R-c--s:fd----:allow

継承されてますね。

% getfacl 00/644.txt 
# file: 00/644.txt
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rw-p--aARWcCos:------:allow
            group@:r-----a-R-c--s:------:allow
         everyone@:r-----a-R-c--s:------:allow
% getfacl 00/755.txt
# file: 00/755.txt
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:------:allow
            group@:r-x---a-R-c--s:------:allow
         everyone@:r-x---a-R-c--s:------:allow

一般ファイルの 00/644.txt と 00/755.txt はchmodされてるようです。

% getfacl 00/700
# file: 00/700
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:fd----:allow
            group@:r-x---a-R-c--s:fd----:allow
         everyone@:r-x---a-R-c--s:fd----:allow

00/700 ディレクトリが755になってます。chmodしてません。

% getfacl 00/700/700_644.txt 
# file: 00/700/700_644.txt
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rw-p--aARWcCos:------:allow
            group@:r-----a-R-c--s:------:allow
         everyone@:r-----a-R-c--s:------:allow
% getfacl 00/700/700_755.txt 
# file: 00/700/700_755.txt
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:------:allow
            group@:r-x---a-R-c--s:------:allow
         everyone@:r-x---a-R-c--s:------:allow

00/700/644.txt, 00/700/755.txt は、ともにchmodされてますね。

ここから言えるのは、ディレクトリはchmodしない、です。

sftpでは常にディレクトリはchmodしないのか

いやそんなことないです。

ACL継承をしていないディレクトリを作り、適当にsftpで取ってきてみます。

% cd (適当なところ)
% mkdir dd
% getfacl dd
# file: dd
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:------:allow
            group@:r-x---a-R-c--s:------:allow
         everyone@:r-x---a-R-c--s:------:allow
% sftp -p ...
...
% getfacl dd/00/700
# file: dd/00/700
# owner: [ユーザ名]
# group: [グループ名]
            owner@:rwxp--aARWcCos:------:allow
            group@:------a-R-c--s:------:allow
         everyone@:------a-R-c--s:------:allow

ddは継承していなくて、さきほどの 00 のツリーを引っ張ってきたところです。00/700ディレクトリは、ちゃんと700になっているので、chmodをやってる。

ということは、ACL継承が付いているディレクトリのみchmodしない、と見ていいようです。

おわりに

ZFS上でファイルに自動で実行パーミッションを付けるのは、ACL設定をいじってどうにかできそうなことが分かりました。これ以上のことは、今回は範囲外なので調べていません。

また、POSIXにするとまるきり記述が変わってしまいますが、今回はパスしました、POSIXにする方法を調べてませんし。

  • ACLの状態を見るのは getfacl
  • ACLの状態を設定するのは setfacl
  • エントリは <タグ(=ロール)>:<パーミッション>:<継承の有無>:{allow|deny}
  • chmodすると継承が消える
  • sftpではACL継承が付いているディレクトリはchmodしない