演習進捗 0 / 4 未完了
⏱ 約 45 分 · setgid・別ユーザ検証
Part 3Chapter 03/サーバ運用

ユーザ・グループ・権限を設計する

自分でユーザとグループを作り、共有ディレクトリを設計します。そして設計者の目ではなく、作ったユーザ自身の目で確かめます。踏み台から別ユーザで SSH し、「書けない」「書けるようになった」を体験します。

教材は登録なしで読めます。実機でコマンドを試す場合のみ、Google ログインで2時間枠の予約が必要です。
所要時間約 45 分
章タイプstandard
前提知識Part 1 Chapter 7(chmod・groups でパーミッションを読む)
使用機材踏み台 workstation01 + 演習用サーバ learner01Proxmox 操作なし・複数ユーザでのログインあり)
関連章前: 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(踏み台)から learner01labuser01 として SSH し、設計した権限が実際に効いているかを「使う人の目」で見ます。

この教材自体が実例です: あなたが普段使っている student ユーザは adm グループに属さず、sudo も持ちません。一方 opsadm に属し sudo をパスワードなしで使えます。この非対称は「ユーザとグループで役割を分ける」設計そのものです。本章では、それを自分の手で作ります。

この章のゴール: labuser01labgroup を作り、setgid つきの共有ディレクトリを設計します。わざと権限を奪って「書けない」を体験し、直して「書ける」に戻します。章末のクリーンアップですべて撤去します。

この章を終えるとできること

アクセス設計の 4 動詞を手に覚えます。

groupadd labgroup
useradd -m labuser01
usermod -aG
groups=…labgroup
① 作る
ユーザと
グループを起こす
useradd · usermod
chgrp labgroup
chmod 2775
$ ls -ld
drwxrwsr-x
② 設計する
グループを
引き継がせる
setgid · chgrp
ssh -i …_ed25519
labuser01@
learner01
許可がありません
③ 確かめる
使う人の目で
境界を見る
ssh · id
chmod g-w
書けない
chmod g+w
書けた
④ 壊して戻す
1 文字の差が
何を分けるか
chmod g-w · g+w

アクセス設計のしくみを解きほぐす

1. 「役割」で束ねる ── ユーザとグループ

Linux のアクセス管理は 3 つの要素の組み合わせでできています。

アクセス設計の 3 要素
├── ユーザ(user)   ── 個人を識別する単位。UID で区別する
├── グループ(group)── 複数ユーザの「役割」をまとめる単位。GID で区別する
└── パーミッション   ── r(読) w(書) x(実行) を owner / group / others に与える

設計の原則は 最小権限の原則です。その仕事に必要な最低限だけを与え、それ以上は与えない。グループを使うと「同じ役割の人たち」にまとめて同じ権限を渡せます。

-aGa は必ず付ける: usermod -aG labgroup labuser01a は append(追加)です。-a を忘れて -G だけで実行すると、それまで所属していた補助グループが全部消えて、指定したグループだけになります。実運用で sudo グループを吹き飛ばす事故の定番です。

2. setgid ── 「このフォルダで作るものは、このグループのもの」

共有ディレクトリを設計するとき、決めるべきなのは「ここに置いたファイルは誰のものになるか」です。

setgid のあるなしで何が変わるか
setgid なし(普通のディレクトリ)
  labuser01 がファイルを作る
  → ファイルのグループ = labuser01 のプライマリグループ(=labuser01)
  → 同じ labgroup の他の人は読めないかもしれない

setgid あり(g+s を設定)
  labuser01 がファイルを作る
  → ファイルのグループ = ディレクトリのグループ(labgroup)を引き継ぐ
  → labgroup の他の人も、そのファイルを「読める」
     (書けるかどうかは、作った人の umask が決める)
chmod の値意味ls -ld の見え方
2775setgid(2) + owner:rwx(7) + group:rwx(7) + others:r-x(5)drwxrwsr-x
775setgid なし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 するのではなくネットワーク越しに、踏み台構成の中でログインするため、本番の運用とまったく同じ手順で「設計 → 検証」のサイクルを回すことになります。

試してみよう:作って、壊して、別ユーザの目で確かめる

labuser01labgroup を作り、setgid つきの共有ディレクトリを設計します。わざと権限を奪ってから、workstation01 より labuser01learner01 にログインし、「書けない」を体験してから直します。

項目
出発地点踏み台 workstation01
演習対象learner01(ユーザ・グループ作成・権限設計)
権限確認workstation01 から labuser01learner01 へ SSH
管理者ユーザーops(NOPASSWD sudo)
この章で作るものlabuser01 / labgroup / /srv/labshared(すべて章末に削除)
所要時間約 45 分(10 ステップ)
ターミナルを 3 つ使います: ①learner01ops で入るもの(管理者役)②workstation01 のもの(鍵を作る)③learner01labuser01 で入るもの(利用者役)。この章では役割ごとにターミナルを分けたまま行き来するので、閉じずに残しておいてください。

STEP 01 · 現状を確認する

workstation01 から learner01ops で接続します。これが「管理者役」のターミナルです。

bash · workstation01 → learner01(ops)
ssh ops@learner01

# 前セッションの残骸チェック
id labuser01 2>&1 || echo "labuser01 は存在しません(クリーン状態)"
期待される出力(クリーン状態)
id: `labuser01': そのようなユーザは存在しません

このメッセージが出ればクリーン状態です。labuser01 が見つかる場合は前回の演習が途中で終わった名残なので、先に STEP ⑩「章末クリーンアップ」を実行してから戻ってください。

bash · learner01(ops)
# 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 passwdUID 1000 以上という条件を掛けただけの一覧なので、こうしたものも混ざります。また、実機にはこの演習環境を運用するためのアカウントも含まれます(表示される行数は環境によって変わります)。一覧に出た名前を「利用者」と決めつけないのが、この章の最初の注意点です。

STEP 02 · グループを作る

設計はグループから始めます。「誰を入れるか」より先に「どんな役割があるか」を決めるのが順序です。

bash · learner01(ops)
sudo groupadd labgroup
getent group labgroup
期待される出力
labgroup:x:1005:

labgroup:x:<GID>: の形なら成功です。GID の数字は環境によって変わります。末尾が空なのは、まだ誰も所属していないからです。

STEP 03 · ユーザを作ってグループに入れる

bash · learner01(ops)
# ホームディレクトリ付き・ログインシェルは 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 つきで作る

bash · learner01(ops)
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-xs が setgid の証拠です。ここが x のままなら、以降のグループ継承は起きません。先に進む前に s を目で確認してください。

STEP 05 · setgid が効いていることを確かめる

ファイルを 1 つ置いて、グループが引き継がれるかを見ます。

bash · learner01(ops)
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 のメンバーが書き込めない状態を作ります。

bash · learner01(ops)
# グループの書き込み権限を外す
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 のまま書き込みを試しても意味がありません: opssudo を持っているので、権限を外しても sudo を付ければ書けてしまいます。壊れたことを確認できるのは、権限を持たないユーザだけです。

STEP 07 · labuser01 でログインするための鍵を配る

labuser01 にはパスワードがないため、鍵認証だけがログイン手段です。鍵を作り、ops の権限で置きにいきます。

まず workstation01 で新しいターミナルを開いてくださいlearner01 への ops 接続とは別のものです)。

bash · workstation01
# 鍵ペアを作る(既にあればスキップ)
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 行をコピーします。次は learner01ops ターミナルに戻って、置きにいきます。

bash · 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 行に置き換えてから実行してください。

bash · learner01(ops)
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 で切り分けられます。

bash · learner01(ops)
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/labuser01drwxr-x--- = 0750)です。useradd -m が作るホームは既定で others に権限がなく、opslabuser01 グループに属していないため、ここで弾かれます。.ssh0700その先にあり、この確認では試されていません.ssh0755 に緩めても ops からは見えないことを実測で確認しています)。

SSH 側にも鍵ファイルの置き方に対する検査があります(sshdStrictModes)。ただし拒否の条件は「権限が緩いこと」ではなく、本人以外が書き換えられる状態になっていることです。

.ssh / authorized_keys鍵ログイン(実測)
700 / 600(この章の設定)✅ 成功
755 / 644(読み取りだけ緩い)✅ 成功
777 / 666(他人が書き換えられる)Permission denied (publickey,password)

読み取りが緩いだけでは拒否されません。それでも 0700 / 0600 を使うのは、この条件を確実に満たし、かつ鍵を他人に読ませないためです。「拒否されないから緩くてよい」ではないことに注意してください。

STEP 08 · 別のユーザの目で「壊れた状態」を見る

この章の核心です。ops のターミナルはそのまま残してworkstation01 でもう 1 つターミナルを開きます。

bash · workstation01 → learner01(labuser01)
# 作ったユーザとしてログインする(鍵認証)
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 で試しても代わりにはなりません(実測): opslabgroup に属していないので、壊す前(2775)の時点ですでに書けません。つまり ops の「許可がありません」は、STEP ⑥ で外した w とは無関係です(others として弾かれているだけ)。外した 1 文字がそのまま効いていることを確かめられるのは labuser01 だけです。「一般ユーザなら誰でもいい」ではなく、その権限の対象になっているユーザで検証してください。

この labuser01 のターミナルは閉じないでください。次のステップで、同じ場所にもう一度書き込みます。

STEP 09 · 戻す ── 直した瞬間に書けるようになるか

ops のターミナル(管理者役)に切り替えて、権限を戻します。

bash · learner01(ops)
sudo chmod g+w /srv/labshared
ls -ld /srv/labshared
期待される出力
drwxrwsr-x 2 root labgroup 4096 7月 28 10:03 /srv/labshared

次に labuser01 のターミナルへ戻ります。ログインし直す必要はありません。

bash · learner01(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 から来ます(labuser010002root0022)。umask は「新しく作るファイルから外す権限」の設定で、setgid とは別の仕組みです。umask を確かめたいときは、そのユーザのシェルで umask と実行してください。

ここが設計上の落とし穴です: グループが labgroup でも、644 のファイルには他のメンバーは書けません。実際 ops-file.txtlabgroup のものですが、labuser01 からは追記できません(試すなら echo x >> /srv/labshared/ops-file.txt)。setgid はグループを揃えるだけで、書けることまでは保証しません。環境の umask0022 なら、この STEP の出力も -rw-r--r-- になります ── それでも setgid は成功しています。見るべきはグループ名です。

再ログインが要らないのはなぜか: chmod によるパーミッションの変更は即座に反映されます。一方、usermod -aG によるグループ所属の変更は既存セッションには反映されません(ログインし直すか newgrp が必要)。同じ「権限まわり」でも挙動が違うので、区別して覚えてください。

復旧したと判定する条件: labuser01 のセッションで /srv/labshared/ への書き込みが成功し、ls -l でそのファイルのグループが labgroup になっていること。

確認できたら labuser01 のセッションを exit で終了します。ログインしたままだと次のクリーンアップが失敗します。

STEP 10 · 章末クリーンアップ

ops のターミナルで、作ったものをすべて撤去します。

bash · learner01(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 があるので対象が無くても黙って終わります。

削除は作成と逆の順序です。ユーザを消してからグループを消します。理由は「グループを先に消すと拒否されるから」ではありません ── labgrouplabuser01補助グループなので(主グループは useradd が自動で作った同名の labuser01)、順序を逆にしても groupdel は成功してしまいます。成功してしまうからこそ順序が要るのであって、先にグループを消すと、どのグループに属していたか分からないユーザが残ります。片付けは「参照している側から先に消す」が原則です。

groupdel が拒否されるのはどんなときか: そのグループを主グループにしているユーザが居る場合です(例: labuser01 をユーザごと消す前に groupdel labuser01 を実行した場合)。補助グループは対象外なので、labgroup ではこの拒否は起きません。

最後に workstation01 のターミナルで、演習用の鍵を削除します。

bash · 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-wg+w で書き込みが回復することを確認済み

詰まったら

ハマりポイント

STEP ⑧ で Permission denied (publickey) と言われて入れない

SSH は鍵ファイルの置き方が緩いと、鍵が正しくても拒否します。ops のターミナルで次を確認してください。

bash · learner01(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 existSTEP ② が抜けている。sudo groupadd labgroup を実行してから再試行
⑧ ディレクトリに入れない(cd できない)/srv/labshared の others 実行ビットが外れている可能性。ls -ld で確認し、sudo chmod o+x /srv/labshared
Connection refusedops のターミナルで 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 に相談

AI 権限設計の詰まりを自由に質問できます
この章の useradd・setgid・共有ディレクトリ設計を前提に、インフラの基礎をやさしく答えます

修了確認

setgid の役割と、権限設計の検証方法を確認します。

問 1 · setgid は何を引き継がせるのか

/srv/labsharedchgrp labgroupchmod 2775 を設定したあと、labuser01 がそこにファイルを作ると、ファイルのグループはどうなりますか? chmod 775(setgid なし)だった場合とどう違いますか?

解答を見る
設定新規ファイルのグループlabgroup の他のメンバーにできること
2775(setgid あり)labgroup(ディレクトリから引き継ぐ)ディレクトリに新しくファイルを作れる/既存ファイルを読める。既存ファイルに書けるかは umask 次第
775(setgid なし)labuser01(作成者のプライマリグループ)ファイルを作れるが、他のメンバーからは読めないことがある

「setgid にすれば全員が読み書きできる」は誤りです(実測): この章の /srv/labshared/ops-file.txtroot が作ったため -rw-r--r--(644)になっており、labgroup のメンバーでも追記できませんsetgid が保証するのはグループの継承だけで、そのグループに書き込みを許すかどうかはファイル作成時の umaskが決めます。

作った人umaskできるファイルのモードグループの書き込み
rootsudo0022-rw-r--r--(644)不可
labuser010002-rw-rw-r--(664)

共有ディレクトリを「全員で書き換える」設計にしたいなら、setgid に加えて umask(あるいは ACL)まで設計する必要があります。

setgid なしの場合、ファイルのグループは作成者のプライマリグループ(useradd が自動で作った同名グループ)になります。そのグループには本人しか居ないので、共有ディレクトリに置いたのに他の人が触れないという状態になります。

setgid は「このフォルダで作るものは全部このグループのもの」というルールを自動で強制する仕組みです。共有ディレクトリ設計でもっとも基本的な設定です。

なお、setgid が引き継がせるのはグループだけです。所有者は作った人のまま変わりません(STEP ⑤ で、所有者が root のままグループだけ labgroup になったのがその実例です)。

問 2 · なぜ設計者の目では検証にならないのか

権限設計の検証を rootops で行うと、何が問題ですか? また、この章でやった「別のユーザで、別のマシンから SSH して確かめる」方法はなぜ重要なのでしょうか。

解答を見る

設計者の目では「止まること」を確認できないのが問題です。

誰で確認したかで、分かることが変わる
root で確認     → chmod 000 のファイルでも読めてしまう
                  → 「一般ユーザが読めない」ことの証明にならない

ops で確認      → adm グループと sudo を持っている
                  → labuser01 が止まるかどうかは分からない

labuser01 で確認 → 実際に使う人の目
                  → 止まるべきところで止まることを確認できる

「別ユーザで別マシンから」が重要な理由:

  • 境界を実際に体験できる: そのユーザに何が見えて何ができないかを、想像ではなく画面で確認できる
  • ネットワーク越しのアクセスまで含めて確かめられる: ローカルで su するのと違い、SSH の認証(鍵の権限を含む)まで通した状態で検証できる
  • 設計ミスが表面化する: setgid の付け忘れやグループの設定漏れは、設計者の視点では気づけない。実際に操作して初めて「書けない」が現れる

本番環境でも、権限を変更したあとはその変更の影響を受けるユーザ自身で対象リソースにアクセスして確かめるのが標準的な手順です。

段階ヒント(問 1・問 2 共通)

段階ヒント 1 段目:作ったら必ず「見て」確認する

ユーザ・グループの操作は「作る(add)→ 確認する(id / getent)→ 直す(usermod)」の順です。操作したら必ず id labuser01getent group labgroup で意図どおりかを目で見てください。ディレクトリは ls -ld で確認し、グループの実行ビットが s になっているかを毎回チェックします。

段階ヒント 2 段目:具体的なコマンド手順
作成フェーズ(learner01・ops)
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 + workstation01)
# ── 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 を引数まで含めて絞り込み、この章で使った鍵認証を対象ユーザだけに閉じた形で強制します。さらに、設定を間違えて内側から直せなくなった状態から復旧する技術まで扱います。

Chapter 4: sudo と SSH 鍵でアクセスを固める:
  • sudoers.d で「このコマンドのこの引数だけ」に絞った権限を設計する
  • Match を使い、対象ユーザだけを鍵認証限定にする(他の利用者を巻き込まない)
  • 自分を締め出してしまったところから、スナップショットで復旧する

この章で手で置いた authorized_keys の仕組みが、そのまま次章の土台になります。

もっと知りたい方へ