ユーザ・グループ・権限を設計する
自分でユーザとグループを作り、共有ディレクトリを設計します。そして設計者の目ではなく、作ったユーザ自身の目で確かめます。踏み台から別ユーザで SSH し、「書けない」「書けるようになった」を体験します。
| 所要時間 | 約 45 分 |
|---|---|
| 章タイプ | standard |
| 前提知識 | Part 1 Chapter 7(chmod・groups でパーミッションを読む) |
| 使用機材 | 踏み台 workstation01 + 演習用サーバ learner01(Proxmox 操作なし・複数ユーザでのログインあり) |
| 関連章 | 前: Chapter 2「journalctl でログを運用者として読む」/ 後: Chapter 4「sudo と SSH 鍵でアクセスを固める」 |
誰に何を許すか ── 設計が曖昧だと事故になる
Part 1 Chapter 7 では chmod でパーミッションを読み、groups で自分の所属を確認しました。あれはすでにある権限を読む技術でした。
この章で扱うのは設計する技術です。新しいユーザを作り、グループで役割を束ね、共有ディレクトリを設計する。そして ── ここが肝心なところですが ── その設計が本当に意図どおりかを、作ったユーザ自身になって確かめます。
# Part 1 Ch7 でやったこと(読む・自分視点) id # 自分の UID/GID を確認 groups # 自分の所属グループを確認 ls -l /some/file # 既存ファイルの権限を読む # この章でやること(作る・設計する・別のユーザで検証する) sudo useradd -m labuser01 # 他人のユーザを作る(管理者視点) sudo groupadd labgroup # グループを設計する sudo chmod g+s /srv/labshared # setgid で共有ディレクトリを設計する ssh -i ~/.ssh/labuser01_ed25519 labuser01@learner01 # ← ここが核心
この章の核心は 別のユーザとして、別のマシンからログインして確かめることです。workstation01(踏み台)から learner01 へ labuser01 として SSH し、設計した権限が実際に効いているかを「使う人の目」で見ます。
この教材自体が実例です: あなたが普段使っている
studentユーザはadmグループに属さず、sudoも持ちません。一方opsはadmに属しsudoをパスワードなしで使えます。この非対称は「ユーザとグループで役割を分ける」設計そのものです。本章では、それを自分の手で作ります。
labuser01 と labgroup を作り、setgid つきの共有ディレクトリを設計します。わざと権限を奪って「書けない」を体験し、直して「書ける」に戻します。章末のクリーンアップですべて撤去します。この章を終えるとできること
アクセス設計の 4 動詞を手に覚えます。
グループを起こす
引き継がせる
境界を見る
何を分けるか
アクセス設計のしくみを解きほぐす
1. 「役割」で束ねる ── ユーザとグループ
Linux のアクセス管理は 3 つの要素の組み合わせでできています。
├── ユーザ(user) ── 個人を識別する単位。UID で区別する ├── グループ(group)── 複数ユーザの「役割」をまとめる単位。GID で区別する └── パーミッション ── r(読) w(書) x(実行) を owner / group / others に与える
設計の原則は 最小権限の原則です。その仕事に必要な最低限だけを与え、それ以上は与えない。グループを使うと「同じ役割の人たち」にまとめて同じ権限を渡せます。
-aGのaは必ず付ける:usermod -aG labgroup labuser01のaは append(追加)です。-aを忘れて-Gだけで実行すると、それまで所属していた補助グループが全部消えて、指定したグループだけになります。実運用でsudoグループを吹き飛ばす事故の定番です。
2. setgid ── 「このフォルダで作るものは、このグループのもの」
共有ディレクトリを設計するとき、決めるべきなのは「ここに置いたファイルは誰のものになるか」です。
setgid なし(普通のディレクトリ)
labuser01 がファイルを作る
→ ファイルのグループ = labuser01 のプライマリグループ(=labuser01)
→ 同じ labgroup の他の人は読めないかもしれない
setgid あり(g+s を設定)
labuser01 がファイルを作る
→ ファイルのグループ = ディレクトリのグループ(labgroup)を引き継ぐ
→ labgroup の他の人も、そのファイルを「読める」
(書けるかどうかは、作った人の umask が決める)
chmod の値 | 意味 | ls -ld の見え方 |
|---|---|---|
2775 | setgid(2) + owner:rwx(7) + group:rwx(7) + others:r-x(5) | drwxrwsr-x |
775 | setgid なし | drwxrwxr-x |
先頭の 2 が setgid です。ls -ld でグループの実行ビットが x ではなく s になっていれば効いています。
大文字の
Sは設計ミスのサイン:drwxr-Sr-xのように大文字で出たら、「setgid は立っているが実行ビットが無い」状態です。小文字のsは「setgid + 実行ビットあり」、大文字のSは「setgid だけ」を意味します。
3. 検証は「設計者の目」では足りない
権限設計の検証で最大の落とし穴は、作った本人の権限で確認してしまうことです。
root で確認 → chmod 000 のファイルでも読めてしまう
→ 「一般ユーザが読めない」ことを証明できない
ops で確認 → adm グループと sudo を持っている
→ labuser01 が止められるかどうかは分からない
labuser01 で確認 → 実際に使う人の目
→ 止まるべきところで止まることを確認できる
実機価値: この章では
workstation01からlabuser01としてlearner01へ SSH します。ローカルでsuするのではなくネットワーク越しに、踏み台構成の中でログインするため、本番の運用とまったく同じ手順で「設計 → 検証」のサイクルを回すことになります。
試してみよう:作って、壊して、別ユーザの目で確かめる
labuser01 と labgroup を作り、setgid つきの共有ディレクトリを設計します。わざと権限を奪ってから、workstation01 より labuser01 で learner01 にログインし、「書けない」を体験してから直します。
| 項目 | 値 |
|---|---|
| 出発地点 | 踏み台 workstation01 |
| 演習対象 | learner01(ユーザ・グループ作成・権限設計) |
| 権限確認 | workstation01 から labuser01 で learner01 へ SSH |
| 管理者ユーザー | ops(NOPASSWD sudo) |
| この章で作るもの | labuser01 / labgroup / /srv/labshared(すべて章末に削除) |
| 所要時間 | 約 45 分(10 ステップ) |
learner01 に ops で入るもの(管理者役)②workstation01 のもの(鍵を作る)③learner01 に labuser01 で入るもの(利用者役)。この章では役割ごとにターミナルを分けたまま行き来するので、閉じずに残しておいてください。STEP 01 · 現状を確認する
workstation01 から learner01 へ ops で接続します。これが「管理者役」のターミナルです。
ssh ops@learner01 # 前セッションの残骸チェック id labuser01 2>&1 || echo "labuser01 は存在しません(クリーン状態)"
id: `labuser01': そのようなユーザは存在しません
このメッセージが出ればクリーン状態です。labuser01 が見つかる場合は前回の演習が途中で終わった名残なので、先に STEP ⑩「章末クリーンアップ」を実行してから戻ってください。
# UID が 1000 以上のアカウント一覧(人が使うものとは限らない) getent passwd | awk -F: '$3 >= 1000 {print $1, $3, $6}'
nobody 65534 /nonexistent ops 1002 /home/ops student 1003 /home/student (以下、環境によって数行)
いま存在するアカウントが見えました。この章の終わりには、ここに labuser01 が一度現れて、また消えます。
この一覧は「人が使うユーザの一覧」ではありません: 先頭の
nobody(UID 65534)は、権限を持たせたくない処理に割り当てるための特殊なアカウントで、誰もログインしません。getent passwdに UID 1000 以上という条件を掛けただけの一覧なので、こうしたものも混ざります。また、実機にはこの演習環境を運用するためのアカウントも含まれます(表示される行数は環境によって変わります)。一覧に出た名前を「利用者」と決めつけないのが、この章の最初の注意点です。
STEP 02 · グループを作る
設計はグループから始めます。「誰を入れるか」より先に「どんな役割があるか」を決めるのが順序です。
sudo groupadd labgroup getent group labgroup
labgroup:x:1005:
labgroup:x:<GID>: の形なら成功です。GID の数字は環境によって変わります。末尾が空なのは、まだ誰も所属していないからです。
STEP 03 · ユーザを作ってグループに入れる
# ホームディレクトリ付き・ログインシェルは bash sudo useradd -m -s /bin/bash labuser01 # labgroup に「追加」する(-a を忘れない) sudo usermod -aG labgroup labuser01 id labuser01
uid=1005(labuser01) gid=1006(labuser01) groups=1006(labuser01),1005(labgroup)
読み方が 2 つあります。gid=1006(labuser01) がプライマリグループ(useradd が自動で作った同名のグループ)、groups= が所属する全グループです。ここに labgroup が入っていれば成功です。
パスワードは設定しません:
labuser01にはパスワードを与えないので、この時点でアカウントはロック状態です。つまりパスワードでは入れません。STEP ⑦ で鍵を配ることが、このユーザへの唯一のログイン手段になります。
STEP 04 · 共有ディレクトリを setgid つきで作る
sudo mkdir /srv/labshared # ディレクトリのグループを labgroup にする sudo chgrp labgroup /srv/labshared # 2775 = setgid(2) + owner:rwx + group:rwx + others:r-x sudo chmod 2775 /srv/labshared ls -ld /srv/labshared
drwxrwsr-x 2 root labgroup 4096 7月 28 10:03 /srv/labshared
drwxrwsr-x の s が setgid の証拠です。ここが x のままなら、以降のグループ継承は起きません。先に進む前に s を目で確認してください。
STEP 05 · setgid が効いていることを確かめる
ファイルを 1 つ置いて、グループが引き継がれるかを見ます。
echo "root が作ったファイル" | sudo tee /srv/labshared/ops-file.txt ls -l /srv/labshared/
合計 4 -rw-r--r-- 1 root labgroup 30 7月 28 10:03 ops-file.txt
注目すべきは 所有者は root なのに、グループは labgroup という点です。setgid が無ければグループも root になっていました。
setgid が制御するのは group だけ: 所有者(owner)は「作った人」のまま変わりません。setgid が引き継がせるのはグループだけです。owner・group・setgid はそれぞれ独立した仕組みなので、混ぜて覚えると後で混乱します。
STEP 06 · 壊す ── グループの書き込みを奪う
設計を意図的に壊します。labgroup のメンバーが書き込めない状態を作ります。
# グループの書き込み権限を外す sudo chmod g-w /srv/labshared ls -ld /srv/labshared
drwxr-sr-x 2 root labgroup 4096 7月 28 10:03 /srv/labshared
drwxrwsr-x だった w が消えて drwxr-sr-x になりました。変わったのは 1 文字だけです。この 1 文字が何を分けるのかを、次のステップで実際に体験します。
ここで
opsのまま書き込みを試しても意味がありません:opsはsudoを持っているので、権限を外してもsudoを付ければ書けてしまいます。壊れたことを確認できるのは、権限を持たないユーザだけです。
STEP 07 · labuser01 でログインするための鍵を配る
labuser01 にはパスワードがないため、鍵認証だけがログイン手段です。鍵を作り、ops の権限で置きにいきます。
まず workstation01 で新しいターミナルを開いてください(learner01 への ops 接続とは別のものです)。
# 鍵ペアを作る(既にあればスキップ) ls ~/.ssh/labuser01_ed25519 2>/dev/null && echo "鍵は既に存在します" || \ ssh-keygen -t ed25519 -N '' -f ~/.ssh/labuser01_ed25519 # 公開鍵の中身を表示する(この 1 行をコピーする) cat ~/.ssh/labuser01_ed25519.pub
ssh-ed25519 AAAA… ops@workstation01
この ssh-ed25519 … の 1 行をコピーします。次は learner01 の ops ターミナルに戻って、置きにいきます。
# .ssh ディレクトリを用意する sudo -u labuser01 mkdir -p /home/labuser01/.ssh sudo chmod 700 /home/labuser01/.ssh sudo chown labuser01:labuser01 /home/labuser01/.ssh
次に公開鍵を書き込みます。下のコマンドの <ここに公開鍵を貼り付ける> の行を、さきほどコピーした 1 行に置き換えてから実行してください。
sudo -u labuser01 tee /home/labuser01/.ssh/authorized_keys << 'EOF' <ここに公開鍵を貼り付ける> EOF sudo chmod 600 /home/labuser01/.ssh/authorized_keys sudo chown labuser01:labuser01 /home/labuser01/.ssh/authorized_keys # 配置を確認(sudo が要ることに注目) sudo ls -la /home/labuser01/.ssh/
合計 12 drwx------ 2 labuser01 labuser01 4096 7月 28 10:03 . drwxr-x--- 3 labuser01 labuser01 4096 7月 28 10:03 .. -rw------- 1 labuser01 labuser01 99 7月 28 10:03 authorized_keys
sudoを付けずにlsすると失敗します(実測):ls: '/home/labuser01/.ssh/' にアクセスできません: 許可がありませんと出ます。これは失敗ではなく、他人の領域が覗けないという設計が効いている証拠です。ただし、止まっている場所は.sshではありません。
どこで止まっているのかは、経路を 1 階層ずつ表示する namei -l で切り分けられます。
namei -l /home/labuser01/.ssh
f: /home/labuser01/.ssh
drwxr-xr-x root root /
drwxr-xr-x root root home
drwxr-x--- labuser01 labuser01 labuser01
.ssh - 許可がありません
止まっているのは ホームディレクトリ /home/labuser01(drwxr-x--- = 0750)です。useradd -m が作るホームは既定で others に権限がなく、ops は labuser01 グループに属していないため、ここで弾かれます。.ssh の 0700 はその先にあり、この確認では試されていません(.ssh を 0755 に緩めても ops からは見えないことを実測で確認しています)。
SSH 側にも鍵ファイルの置き方に対する検査があります(sshd の StrictModes)。ただし拒否の条件は「権限が緩いこと」ではなく、本人以外が書き換えられる状態になっていることです。
.ssh / authorized_keys | 鍵ログイン(実測) |
|---|---|
700 / 600(この章の設定) | ✅ 成功 |
755 / 644(読み取りだけ緩い) | ✅ 成功 |
777 / 666(他人が書き換えられる) | ❌ Permission denied (publickey,password) |
読み取りが緩いだけでは拒否されません。それでも 0700 / 0600 を使うのは、この条件を確実に満たし、かつ鍵を他人に読ませないためです。「拒否されないから緩くてよい」ではないことに注意してください。
STEP 08 · 別のユーザの目で「壊れた状態」を見る
この章の核心です。ops のターミナルはそのまま残して、workstation01 でもう 1 つターミナルを開きます。
# 作ったユーザとしてログインする(鍵認証) ssh -i ~/.ssh/labuser01_ed25519 labuser01@learner01 # 自分が何者かを確認する id # 共有ディレクトリへの書き込みを試す echo "labuser01 が書いたファイル" > /srv/labshared/labuser01-file.txt
uid=1005(labuser01) gid=1006(labuser01) groups=1006(labuser01),1005(labgroup) bash: 行 1: /srv/labshared/labuser01-file.txt: 許可がありません
「許可がありません」が正解です。ここが重要なところで、id を見ると labuser01 はちゃんと labgroup に所属しています。グループには入っているのに書けない ── STEP ⑥ で外した w の 1 文字が、そのまま効いています。
root のままでは絶対に観測できません(root は権限の検査を素通りするため、常に書けてしまいます)。権限設計を検証したいなら、設計者ではなく制限される側のユーザになる必要があります。
opsで試しても代わりにはなりません(実測):opsはlabgroupに属していないので、壊す前(2775)の時点ですでに書けません。つまりopsの「許可がありません」は、STEP ⑥ で外したwとは無関係です(others として弾かれているだけ)。外した 1 文字がそのまま効いていることを確かめられるのはlabuser01だけです。「一般ユーザなら誰でもいい」ではなく、その権限の対象になっているユーザで検証してください。
この labuser01 のターミナルは閉じないでください。次のステップで、同じ場所にもう一度書き込みます。
STEP 09 · 戻す ── 直した瞬間に書けるようになるか
ops のターミナル(管理者役)に切り替えて、権限を戻します。
sudo chmod g+w /srv/labshared ls -ld /srv/labshared
drwxrwsr-x 2 root labgroup 4096 7月 28 10:03 /srv/labshared
次に labuser01 のターミナルへ戻ります。ログインし直す必要はありません。
# さっきと同じコマンドをもう一度 echo "labuser01 が書いたファイル" > /srv/labshared/labuser01-file.txt ls -l /srv/labshared/
合計 8 -rw-rw-r-- 1 labuser01 labgroup 35 7月 28 10:04 labuser01-file.txt -rw-r--r-- 1 root labgroup 30 7月 28 10:03 ops-file.txt
今度は書けました。しかも labuser01-file.txt のグループが labgroup になっています ── setgid が効いた結果です。作成者のプライマリグループ(labuser01)ではありません。
2 つのファイルでモードが違う理由:
labuser01-file.txtは-rw-rw-r--(664)ですが、STEP ⑤ でrootが作ったops-file.txtは-rw-r--r--(644)です。この差はumaskから来ます(labuser01は0002、rootは0022)。umaskは「新しく作るファイルから外す権限」の設定で、setgidとは別の仕組みです。umaskを確かめたいときは、そのユーザのシェルでumaskと実行してください。ここが設計上の落とし穴です: グループが
labgroupでも、644のファイルには他のメンバーは書けません。実際ops-file.txtはlabgroupのものですが、labuser01からは追記できません(試すならecho x >> /srv/labshared/ops-file.txt)。setgidはグループを揃えるだけで、書けることまでは保証しません。環境のumaskが0022なら、この STEP の出力も-rw-r--r--になります ── それでも setgid は成功しています。見るべきはグループ名です。
再ログインが要らないのはなぜか:
chmodによるパーミッションの変更は即座に反映されます。一方、usermod -aGによるグループ所属の変更は既存セッションには反映されません(ログインし直すかnewgrpが必要)。同じ「権限まわり」でも挙動が違うので、区別して覚えてください。
labuser01 のセッションで /srv/labshared/ への書き込みが成功し、ls -l でそのファイルのグループが labgroup になっていること。確認できたら labuser01 のセッションを exit で終了します。ログインしたままだと次のクリーンアップが失敗します。
STEP 10 · 章末クリーンアップ
ops のターミナルで、作ったものをすべて撤去します。
# 共有ディレクトリごと削除 sudo rm -rf /srv/labshared # ユーザを削除(-r でホームディレクトリも) sudo userdel -r labuser01 # メールスプールの残骸を念のため削除 sudo rm -f /var/mail/labuser01 # グループを削除(ユーザを消した後で) sudo groupdel labgroup # 消えたことを確認 id labuser01 2>&1 || echo "labuser01 は削除されました" getent group labgroup 2>&1 || echo "labgroup は削除されました"
userdel: labuser01 のメールスプール (/var/mail/labuser01) がありません id: `labuser01': そのようなユーザは存在しません labuser01 は削除されました labgroup は削除されました
1 行目はエラーではありません。userdel -r はメールスプールも消そうとしますが、この環境ではメールを扱っていないため最初から存在しないだけです(userdel 自体は成功しています)。続く rm -f /var/mail/labuser01 も、-f があるので対象が無くても黙って終わります。
削除は作成と逆の順序です。ユーザを消してからグループを消します。理由は「グループを先に消すと拒否されるから」ではありません ── labgroup は labuser01 の補助グループなので(主グループは useradd が自動で作った同名の labuser01)、順序を逆にしても groupdel は成功してしまいます。成功してしまうからこそ順序が要るのであって、先にグループを消すと、どのグループに属していたか分からないユーザが残ります。片付けは「参照している側から先に消す」が原則です。
groupdelが拒否されるのはどんなときか: そのグループを主グループにしているユーザが居る場合です(例:labuser01をユーザごと消す前にgroupdel labuser01を実行した場合)。補助グループは対象外なので、labgroupではこの拒否は起きません。
最後に workstation01 のターミナルで、演習用の鍵を削除します。
rm -f ~/.ssh/labuser01_ed25519 ~/.ssh/labuser01_ed25519.pub ls ~/.ssh/labuser01_ed25519* 2>&1 || echo "演習鍵 削除済み(クリーン)"
ls: cannot access '/home/ops/.ssh/labuser01_ed25519*': No such file or directory 演習鍵 削除済み(クリーン)
| 確認項目 | 期待値 |
|---|---|
id labuser01 | そのようなユーザは存在しません(削除済み) |
getent group labgroup | 出力なし(削除済み) |
ls /srv/ | labshared が無い |
workstation01 の演習鍵 | ~/.ssh/labuser01_ed25519* が無い |
| 演習中の別ユーザログイン(STEP ⑧) | labuser01 で SSH し「許可がありません」を確認済み |
| 演習中の壊す→戻す(STEP ⑥⑨) | g-w → g+w で書き込みが回復することを確認済み |
詰まったら
- ハマりポイント: よくある詰まりと対処を以下に列挙しています
- AI に相談: 演習中の疑問を章の内容を踏まえて AI に聞けます
ハマりポイント
STEP ⑧ で Permission denied (publickey) と言われて入れない
SSH は鍵ファイルの置き方が緩いと、鍵が正しくても拒否します。ops のターミナルで次を確認してください。
sudo ls -la /home/labuser01/.ssh/ # 正しい状態に直す sudo chmod 700 /home/labuser01/.ssh sudo chmod 600 /home/labuser01/.ssh/authorized_keys sudo chown -R labuser01:labuser01 /home/labuser01/.ssh
あわせて authorized_keys の中身も確認してください。公開鍵を貼り付けるとき、途中で改行が入ってしまうのがよくある失敗です。鍵は ssh-ed25519 で始まる1 行でなければなりません。
STEP ④ で drwxr-Sr-x と大文字の S が出た
setgid は立っているが、グループの実行ビット(x)が無い状態です。ディレクトリは実行ビットが無いと中に入れないため、このままでは共有ディレクトリとして機能しません。
sudo chmod g+x /srv/labshared で実行ビットを足すと、小文字の s になります。通常は 2775 を指定すれば正しく設定されるので、chmod の値を打ち間違えていないか確認してください。
STEP ⑩ で userdel が「ログイン中」と言って失敗する
labuser01 の SSH セッションが残っています。STEP ⑧ で開いたターミナルに戻り、exit で抜けてから userdel を実行し直してください。
どのターミナルか分からなくなった場合は、ops のターミナルで who を実行するとログイン中のユーザが一覧できます。
上記以外の詰まりと対処を一覧にまとめます。
| 起きたこと | 対処 |
|---|---|
③ useradd: user 'labuser01' already exists | 前回の残骸。sudo userdel -r labuser01 で消してからやり直す |
③ usermod: group 'labgroup' does not exist | STEP ② が抜けている。sudo groupadd labgroup を実行してから再試行 |
⑧ ディレクトリに入れない(cd できない) | /srv/labshared の others 実行ビットが外れている可能性。ls -ld で確認し、sudo chmod o+x /srv/labshared |
⑧ Connection refused | ops のターミナルで systemctl status ssh を確認 |
⑩ groupdel: cannot remove the primary group of user 'labuser01' | 消そうとしているのが labgroup ではなく同名の主グループ labuser01。主グループは sudo userdel -r labuser01 でユーザごと消える |
⑩ userdel: user labuser01 is currently used by process ... | labuser01 のセッションが残っている。STEP ⑧ のターミナルで exit してから再実行 |
id にグループ追加が反映されない | グループ所属の変更は既存セッションに反映されない。ログインし直すか newgrp labgroup を実行 |
AI に相談
修了確認
setgid の役割と、権限設計の検証方法を確認します。
問 1 · setgid は何を引き継がせるのか
/srv/labshared に chgrp labgroup と chmod 2775 を設定したあと、labuser01 がそこにファイルを作ると、ファイルのグループはどうなりますか? chmod 775(setgid なし)だった場合とどう違いますか?
解答を見る
| 設定 | 新規ファイルのグループ | labgroup の他のメンバーにできること |
|---|---|---|
2775(setgid あり) | labgroup(ディレクトリから引き継ぐ) | ディレクトリに新しくファイルを作れる/既存ファイルを読める。既存ファイルに書けるかは umask 次第 |
775(setgid なし) | labuser01(作成者のプライマリグループ) | ファイルを作れるが、他のメンバーからは読めないことがある |
「setgid にすれば全員が読み書きできる」は誤りです(実測): この章の
/srv/labshared/ops-file.txtはrootが作ったため-rw-r--r--(644)になっており、labgroupのメンバーでも追記できません。setgidが保証するのはグループの継承だけで、そのグループに書き込みを許すかどうかはファイル作成時のumaskが決めます。
作った人 umaskできるファイルのモード グループの書き込み root(sudo)0022-rw-r--r--(644)不可 labuser010002-rw-rw-r--(664)可 共有ディレクトリを「全員で書き換える」設計にしたいなら、
setgidに加えてumask(あるいは ACL)まで設計する必要があります。
setgid なしの場合、ファイルのグループは作成者のプライマリグループ(useradd が自動で作った同名グループ)になります。そのグループには本人しか居ないので、共有ディレクトリに置いたのに他の人が触れないという状態になります。
setgid は「このフォルダで作るものは全部このグループのもの」というルールを自動で強制する仕組みです。共有ディレクトリ設計でもっとも基本的な設定です。
なお、setgid が引き継がせるのはグループだけです。所有者は作った人のまま変わりません(STEP ⑤ で、所有者が root のままグループだけ labgroup になったのがその実例です)。
問 2 · なぜ設計者の目では検証にならないのか
権限設計の検証を root や ops で行うと、何が問題ですか? また、この章でやった「別のユーザで、別のマシンから SSH して確かめる」方法はなぜ重要なのでしょうか。
解答を見る
設計者の目では「止まること」を確認できないのが問題です。
root で確認 → chmod 000 のファイルでも読めてしまう
→ 「一般ユーザが読めない」ことの証明にならない
ops で確認 → adm グループと sudo を持っている
→ labuser01 が止まるかどうかは分からない
labuser01 で確認 → 実際に使う人の目
→ 止まるべきところで止まることを確認できる
「別ユーザで別マシンから」が重要な理由:
- 境界を実際に体験できる: そのユーザに何が見えて何ができないかを、想像ではなく画面で確認できる
- ネットワーク越しのアクセスまで含めて確かめられる: ローカルで
suするのと違い、SSH の認証(鍵の権限を含む)まで通した状態で検証できる - 設計ミスが表面化する: setgid の付け忘れやグループの設定漏れは、設計者の視点では気づけない。実際に操作して初めて「書けない」が現れる
本番環境でも、権限を変更したあとはその変更の影響を受けるユーザ自身で対象リソースにアクセスして確かめるのが標準的な手順です。
段階ヒント(問 1・問 2 共通)
段階ヒント 1 段目:作ったら必ず「見て」確認する
ユーザ・グループの操作は「作る(add)→ 確認する(id / getent)→ 直す(usermod)」の順です。操作したら必ず id labuser01 と getent group labgroup で意図どおりかを目で見てください。ディレクトリは ls -ld で確認し、グループの実行ビットが s になっているかを毎回チェックします。
段階ヒント 2 段目:具体的なコマンド手順
sudo groupadd labgroup getent group labgroup # 確認 sudo useradd -m -s /bin/bash labuser01 sudo usermod -aG labgroup labuser01 id labuser01 # groups に labgroup を確認 sudo mkdir /srv/labshared sudo chgrp labgroup /srv/labshared sudo chmod 2775 /srv/labshared ls -ld /srv/labshared # drwxrwsr-x(s があるか)
よくある落とし穴:
usermod -Gで-aを忘れる → 既存の所属グループが全部消えるls -ldで大文字Sが出る → 実行ビットが足りない(chmod g+x)userdelはそのユーザがログイン中だと失敗する → 先にexit
答えを見る(フルコマンド列)
# ── learner01(ops)作成 ── sudo groupadd labgroup sudo useradd -m -s /bin/bash labuser01 sudo usermod -aG labgroup labuser01 id labuser01 sudo mkdir /srv/labshared sudo chgrp labgroup /srv/labshared sudo chmod 2775 /srv/labshared ls -ld /srv/labshared # drwxrwsr-x echo "root が作ったファイル" | sudo tee /srv/labshared/ops-file.txt ls -l /srv/labshared/ # group=labgroup を確認 # ── 壊す ── sudo chmod g-w /srv/labshared ls -ld /srv/labshared # drwxr-sr-x # ── workstation01 鍵作成 ── ssh-keygen -t ed25519 -N '' -f ~/.ssh/labuser01_ed25519 cat ~/.ssh/labuser01_ed25519.pub # 公開鍵をコピー # ── learner01(ops)鍵配布 ── sudo -u labuser01 mkdir -p /home/labuser01/.ssh sudo chmod 700 /home/labuser01/.ssh sudo chown labuser01:labuser01 /home/labuser01/.ssh # authorized_keys に公開鍵を貼り付け(STEP ⑦ 参照) sudo chmod 600 /home/labuser01/.ssh/authorized_keys sudo chown labuser01:labuser01 /home/labuser01/.ssh/authorized_keys # ── workstation01(labuser01 で確認)── ssh -i ~/.ssh/labuser01_ed25519 labuser01@learner01 id echo test > /srv/labshared/labuser01-file.txt # 許可がありません # ── learner01(ops)戻す ── sudo chmod g+w /srv/labshared # ── labuser01 側で再挑戦(再ログイン不要)── echo test > /srv/labshared/labuser01-file.txt # 成功 ls -l /srv/labshared/ # group=labgroup exit # ── クリーンアップ(learner01 の ops)── sudo rm -rf /srv/labshared sudo userdel -r labuser01 sudo rm -f /var/mail/labuser01 sudo groupdel labgroup # ── workstation01 ── rm -f ~/.ssh/labuser01_ed25519 ~/.ssh/labuser01_ed25519.pub
このフローで覚えること:
usermod -aGの-aを必ず付ける(忘れると既存グループが消える)- setgid(
2775)はグループだけを引き継がせる。所有者は変わらない - 検証は制限される側のユーザで行う。設計者の目では「止まること」が見えない
- 作成はグループ → ユーザ、削除はユーザ → グループ(逆順)
次の章へ
ユーザとグループで「誰に何を許すか」を設計しました。次は、そのアクセスをどう守るかです。sudo を引数まで含めて絞り込み、この章で使った鍵認証を対象ユーザだけに閉じた形で強制します。さらに、設定を間違えて内側から直せなくなった状態から復旧する技術まで扱います。
sudoers.dで「このコマンドのこの引数だけ」に絞った権限を設計するMatchを使い、対象ユーザだけを鍵認証限定にする(他の利用者を巻き込まない)- 自分を締め出してしまったところから、スナップショットで復旧する
この章で手で置いた authorized_keys の仕組みが、そのまま次章の土台になります。
もっと知りたい方へ
/etc/passwdの構造:getent passwd labuser01で「ユーザ名:パスワードの置き場:UID:GID:コメント:ホーム:シェル」の 7 項目が見えます。パスワードの実体は/etc/shadowにあります- グループ変更が反映されないのはなぜか:
usermod -aGでグループを足しても、そのユーザの既存セッションには反映されません。ログインし直すかnewgrp labgroupが必要です。一方chmodの変更は即時反映されます(本章 STEP ⑨ がその実例)。この 2 つは混同しやすいので区別してください - プライマリグループと補助グループ:
useradd -gで指定するのがプライマリ(ファイル作成時の既定グループ)、usermod -aGで足すのが補助グループです。idのgid=とgroups=で見分けられます - sticky bit(
1777):chmod 1777 /tmpの先頭1です。これがあると「自分が作ったファイルしか消せない」ルールが働きます。setgid(2000)とは目的が違います newgrp: いまのシェルだけ一時的にプライマリグループを切り替えます。再ログインせずにグループ変更を試したいときに使えますsudoers.dの予習: 次章で扱いますが、/etc/sudoers.d/にファイルを置くと特定ユーザに限定的なsudoを与えられます(例:labuser01 ALL=(ALL) NOPASSWD: /usr/bin/apt)