LFCS — Linux Foundation認定システム管理者
権限はファイルではなくプロセスに付く
一言でいうと
Linuxのアクセス制御は、「このファイルを誰が読めるか」ではなく、今このプロセスが持っている資格情報が、このinodeの権限ビットとどう一致するかで判定されます。この見方を押さえると、setgidディレクトリもACLマスクも、自然に理解できます。
なぜ必要なのか
ユーザーをグループに追加したのに権限が付かないという問い合わせが、後を絶ちません。原因はたいてい1つです。補助グループは、ログイン時点でプロセスの資格情報にコピーされます。すでに起動しているシェルは、古いグループ一覧をそのまま持っていて、ファイルアクセスの判定は、その一覧で行われます。グループを変更したら、再ログインするか、新しいセッションを開く必要があります。
/etc/passwdは名前・UID・GID・ホーム・シェルを持ち、パスワードに関する情報はすべて/etc/shadowに分離されています。分離された理由は単純です。/etc/passwdは全員が読める必要があり、そうでないとls -lがUIDを名前に変換して表示できませんが、ハッシュはそうであってはいけないからです。
/etc/shadowのフィールドはコロンで区切られます。
| 番号 | 内容 |
|---|---|
| 2 | パスワードハッシュ。先頭の感嘆符はロック、アスタリスクはパスワードでのログイン不可 |
| 3 | 最後のパスワード変更日(1970-01-01からの日数) |
| 4 | 最小使用日数 |
| 5 | 最大使用日数 |
| 6 | 期限切れ前の警告日数 |
| 8 | アカウントの有効期限(こちらも日数) |
日付ではなく日数であるという点が、試験でよく出ます。人が読める形に変換してくれるのがchage -lです。
どう動くのか
setgidディレクトリが、協業ディレクトリの正解である理由。新しく作成したファイルのグループは、通常、作成した人のプライマリグループになります。チームメンバー3人のプライマリグループがそれぞれ違うと、共有ディレクトリにファイルがバラバラのグループで溜まります。ディレクトリにsetgidを設定しておくと、その中で作成されたファイルがディレクトリのグループを引き継ぎます。新しいサブディレクトリはsetgidビットまで引き継ぐので、ツリー全体が維持されます。
stickyビットは、削除の権限を取り戻します。ファイルを削除するのに必要なのは、そのファイルではなくそのディレクトリに対する書き込み権限です。共有ディレクトリを全員に書き込み可能にして開くと、他人のファイルも削除できてしまいます。stickyを設定すると、所有者とディレクトリの所有者、rootだけが削除できます。/tmpが、まさにこの構成です。
ACLが必要になる瞬間は、「1人だけ例外」のときです。所有者・グループ・その他の3つの欄では、「このグループは読み取り、ただし監査担当者1人は書き込み」を表現できません。グループを新しく作る代わりに、名前付きのエントリを追加するのが、ACLです。
ここでマスクが登場します。マスクは、所有者とその他を除くすべてのエントリ(名前付きユーザー、名前付きグループ、グループ所有者)の権限の上限です。getfaclが#effective:を付けて表示する行が、まさにマスクで削られたエントリです。そして落とし穴が1つあります。ファイルにchmodをかけると、そのグループビットがマスクとして解釈され、先ほど付与したACLが静かに無力になります。
ディレクトリにはdefault ACLを設定できます。これは、そのディレクトリ自体のアクセス判定には使われず、今後その中に作成される項目の初期ACLとして継承されます。
現場での姿
筆者のファイルディスクリプター・inodeの記事には、この問題が一文でまとめられています。ファイルに対する書き込み権限と削除権限は別物であり、共有ディレクトリで他人のファイルが消される事故が、まさにここから生まれます。その記事が示す標準的な解決策が、chmod 1777、つまりstickyビットです。逆に、setgidなしで共有ディレクトリを運用すると、ファイルごとにグループが違ってしまい、あとで一括でchgrp -Rを実行する整理作業が、定期的に発生します。
アカウント側で最も高くつく間違いは、補助グループを追加するときに、追加のオプションを書き漏らすことです。usermod -Gだけを使うと、既存の補助グループが、すべて指定した一覧に置き換えられます。sudoグループから自分自身を外してしまい、rootシェルもない状態になると、そこからはコンソールアクセスの問題に変わります。
試験会場でよく引っかかる権限の問題
LFCSは実技なので、「説明できる」ではなく「手が覚えている」が問われます。権限の領域で繰り返し出る形が、いくつかあります。
特殊ビットは、数字の先頭の桁として付きます。
| ビット | 数字 | ファイルでは | ディレクトリでは |
|---|---|---|---|
| setuid | 4000 | 所有者の権限で実行 | (意味なし) |
| setgid | 2000 | グループの権限で実行 | 新しいファイルが、そのディレクトリのグループを引き継ぐ |
| sticky | 1000 | (意味なし) | 所有者だけが自分のファイルを削除できる(/tmp) |
協業ディレクトリの問題は、ほぼいつもsetgidです。「チームメンバーなら誰でも読み書きできるように」という要求は、chgrp team dir; chmod 2775 dirで解決します。setgidがないと、新しいファイルが作成した人のプライマリグループを持つことになり、ほかのチームメンバーが読めません。
ACLは、デフォルト(default)ACLも一緒に設定する必要があります。今あるファイルにだけ設定すると、あとで作成されるファイルには適用されません。
setfacl -m u:alice:rwx /srv/data # 지금 있는 것
setfacl -d -m u:alice:rwx /srv/data # 앞으로 만들어질 것
getfacl /srv/data
ls -lで権限の末尾に+が見えれば、ACLが設定されているという意味です。これを見落とすと、「権限は合っているのに、なぜ動かないのか」で、長く迷います。
umaskは、これから作成するものにだけ適用されます。すでにあるファイルは、chmodで直す必要があります。逆に、「これから作成するファイルもそうなるように」という要求にchmodで答えると、間違いです。
ユーザーを削除するときは、ホームとメールキューをどうするかが問われます。userdel -rは、ホームディレクトリまで削除します。削除しないと、そのUIDが再利用されたときに、新しいユーザーが古いファイルを所有することになります。そのため、削除しないのであれば、先に所有権を移します。
変更したあとは、必ず確認します。id 사용자、groups 사용자、sudo -l -U 사용자の3行で、ほとんどの設定の問題が表面化します(プレースホルダーはユーザー名です)。
次のラボですること
まず、実際にユーザーとグループを作成します。UID・プライマリグループ・ホーム・シェルを指定してアカウントを立て、補助グループを追加し、chageでパスワードポリシーを設定し、/etc/passwd・/etc/group・/etc/shadowからその値を直接読み取って確認します。最後に、アカウントだけを削除してホームを残し、孤立したUIDができる様子を見ます。続くラボでは、8進数とシンボリックモード、umask、特殊ビット、ACLとマスクを順に扱います。