3-2. ユーザー管理とセキュリティ - passwd, sudoers, 最小権限
所要時間: 40-50分(がっつりなら2セッション分) ゴール: Linuxのユーザー/グループ/権限モデルを理解し、本番運用に耐える「最小権限」設計ができる。sudoers を安全に書ける コミット内容: useradd / sudoers の検証ログを
~/learn/linux/day14にまとめる
この章が終わるとできること
/etc/passwdの7フィールドと、/etc/shadow/etc/groupの関係を説明できるuseradd/adduserの差を理解し、適切に新規ユーザーを作れるvisudoで安全に sudoers を編集し、/etc/sudoers.d/でルールを分割できる- 最小権限 の sudoers ルール(コマンド単位の許可)が書ける
- root ログイン無効化、退職者対応の手順を答えられる
/var/log/auth.logで sudo 実行記録を読める
Day 3 / Day 15 とのつながり
- Day 3 でちらっと触れた「ユーザー」「グループ」の正体に、今日本格的に踏み込む
- 昨日(Day 15)の SSH 鍵認証と組み合わせて、専用デプロイユーザー を作る基礎が完成
- Day 11(systemd)の
User=appuserで出てきた「専用ユーザー」を、今日自分の手で作る
これができると何が嬉しいか
- 「root で全員ログイン」みたいな悪夢の運用を絶対に書かなくなる
- 監査ログ(誰が・いつ・何をしたか)を残せる ─ コンプライアンス対応の土台
- 退職者・委託先終了時に 30秒 で安全に締め出せる手順が手に入る
大前提: なぜ「ユーザー管理」が本番運用の根幹なのか
「本番サーバーに root で全員ログインする」運用、まだ世の中に存在します。これは事故が起きた時:
- 誰がやったか分からない: ログに
rootしか残らず、犯人特定不能 - 被害が最大化する: ミス・侵入のどちらでも全権限を持つアカウントが乗っ取られる
- 法令違反になることも: 個人情報保護法・SOX法・PCI-DSS などは「アクセス制御と監査」を要求する
正しい運用は 「1人1アカウント+必要な権限だけ+全操作を記録」。これが最小権限の原則(Principle of Least Privilege, PoLP)。
そして Linux のユーザー管理は、表向きシンプルですが、触ったら戻せないファイルがいくつもあります(/etc/passwd, /etc/shadow, /etc/sudoers)。直接編集して構文ミス → ログインできなくなる、という事故が頻発します。今日は「事故らない手順」を含めて身に着けます。
セッション①: ユーザー/グループの基礎と内部構造(25-30分)
0. 録画スタート
mkdir -p ~/log ~/learn/linux/day14
cd ~/learn/linux/day14
script ~/log/linux_day14.log1. /etc/passwd の構造
Linux のユーザー管理を理解する入り口は、/etc/passwd を読めるようになることです。この1ファイルを音読できれば、ユーザー管理のほぼすべてが繋がります。
- 何のコマンドか:
/etc/passwdは「このシステムに存在するユーザー全員のリスト」が:区切りで並んでいる、誰でも読めるテキストファイル - いつ使うか: 新しいサーバーに入った時に「どんなアカウントが存在するか」を把握する時、サービスアカウント(postgres, www-data)の有無を確認する時、UID 衝突や
nologin設定を調べる時 - 解決する具体的な問題: 「Linux のユーザーとは何か」をファイルの実体として見ることで、抽象概念から「ただのテキスト1行」に降ろせる
# 自分の行を見てみる(macOS では DSCLが本体だが、Linux 互換のpasswdは存在しない)
# Linux VMに繋いで実行する想定:
cat /etc/passwd | head -5
# root:x:0:0:root:/root:/bin/bash
# daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
# bin:x:2:2:bin:/bin:/usr/sbin/nologin
# sys:x:3:3:sys:/dev:/usr/sbin/nologin
# sync:x:4:65534:sync:/bin:/bin/sync/etc/passwd の7フィールド
各行は : 区切りで7フィールド:
root:x:0:0:root:/root:/bin/bash
│ │ │ │ │ │ │
│ │ │ │ │ │ └─ ログインシェル
│ │ │ │ │ └───────── ホームディレクトリ
│ │ │ │ └─────────────── GECOS(フルネームなど)
│ │ │ └────────────────── プライマリGID
│ │ └──────────────────── UID
│ └────────────────────── パスワード(今は "x" でshadowへ)
└────────────────────────── ユーザー名
UID 0 = root(特権)。1-999 はシステム/サービスアカウント、1000以上が一般ユーザー。
/etc/passwd vs /etc/shadow vs /etc/group の役割分担(重要)
ざっくり言うと
Linux のユーザー情報は 3つのファイルに分散している。それぞれ役割と権限が違う。
まず昔の素朴な構成
昔は /etc/passwd 1ファイルにパスワードハッシュも直書きされていた。
/etc/passwd (mode 644: 全員読める)
root:$6$xxxxx$yyyyyy:0:0:root:/root:/bin/bash
↑
ハッシュとはいえ全員に見える
この状態の問題発生フロー
/etc/passwd は 644(全員読める)
↓
攻撃者がログインユーザーで cat /etc/passwd
↓
ハッシュをローカルに持ち帰り
↓
オフラインで辞書攻撃・レインボーテーブル攻撃
↓
パスワード突破
解決策: ハッシュだけ /etc/shadow に隔離
1988年ごろから「パスワードハッシュは別ファイル(root しか読めない)」設計に。
/etc/passwd (644 全員読める): ユーザー名・UID・ホーム・シェル
/etc/shadow (600 root だけ): パスワードハッシュ + 有効期限
/etc/group (644 全員読める): グループ名・GID・所属ユーザー
イメージ:
/etc/passwd= 電話帳の表紙(誰でも見ていい一覧)/etc/shadow= 金庫の中(root だけが開けられる)/etc/group= クラブの名簿(誰がどの部活か)
対比表
| ファイル | 何を持つ | パーミッション | 編集コマンド |
|---|---|---|---|
/etc/passwd | ユーザー名・UID・ホーム・シェル | 644(全員読める) | useradd / adduser |
/etc/shadow | パスワードハッシュ・有効期限 | 600(root だけ) | passwd / chage |
/etc/group | グループ名・GID・所属ユーザー | 644(全員読める) | groupadd / usermod -aG |
sudo cat /etc/shadow | head -3
# root:$6$xxxxx$yyyyyy:19500:0:99999:7:::
# daemon:*:19500:0:99999:7:::* または ! から始まるパスワードフィールド = パスワードログイン無効(鍵認証のみのアカウント)。
一番覚えやすい説明
- passwd: 誰がいるか(公開情報)
- shadow: その人の合言葉(極秘情報)
- group: 誰がどのチームか(公開情報)
2. /etc/group の構造
ユーザーが分かったら次は グループ。「複数ユーザーをまとめて権限を付ける」仕組みで、Linux の権限モデル(rwx の真ん中の桁)の正体です。
- 何のコマンドか:
/etc/groupはグループ名・GID・所属ユーザー一覧を:区切りで持つテキストファイル - いつ使うか: 新メンバーを
developersグループに入れる時、dockerグループの危険性を判断する時、ファイルアクセスを「グループ単位」で開放する時 - 解決する具体的な問題: 1人ずつ権限を付けて回る運用の崩壊を防ぐ。「グループに入れる」だけで全ファイルの権限が自動的に揃う
cat /etc/group | head -10
# root:x:0:
# daemon:x:1:
# sudo:x:27:alice,bob
# docker:x:998:aliceprimary group vs supplementary group の違い
ざっくり言うと
ユーザーはプライマリ1個 + サプリメンタリ複数個のグループに所属できる。新規作成ファイルのデフォルトオーナーになるのが「プライマリ」、追加権限のために入るのが「サプリメンタリ」。
まず普通のパターン
id alice
# uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo),998(docker)
↑ ↑
primary supplementary(複数OK)alice というユーザー
├─ primary group: alice (gid 1000) ← 1個だけ
└─ supplementary groups: sudo, docker, developers ... ← 複数OK
「touch すると何が起きるか」で違いが見える
alice@host:~$ touch newfile.txt
alice@host:~$ ls -l newfile.txt
-rw-r--r-- 1 alice alice 0 May 21 10:00 newfile.txt
↑ ↑
user group ← primary group になる新規ファイルのグループはプライマリで決まる。sudo グループや docker グループにはならない。
イメージ
- primary: 「本籍地」。新しい家(ファイル)を建てるとここの住人になる
- supplementary: 「バイトの掛け持ち」。それぞれの権限(sudo / docker / developers)だけ追加でもらえる
違い
| primary group | supplementary group | |
|---|---|---|
| 数 | 1個だけ | 何個でも |
| 設定箇所 | /etc/passwd の4列目(GID) | /etc/group の最終列 |
| 新規ファイル作成時 | このグループがオーナーに | 関係ない |
| 追加コマンド | usermod -g <group>(置換) | usermod -aG <group>(追加) |
一番覚えやすい説明
- primary: あなたが「何者か」を決める ID
- supplementary: あなたが「何の特権を持つか」を増やす
usermod -gと-aGを間違えるなusermod -g docker alice # NG: alice の primary を docker に「置換」してしまう usermod -aG docker alice # OK: docker を「追加」(既存所属はそのまま)
-aを忘れると 既存の supplementary が全部消える。sudo グループから外れて何もできなくなる事故が定番。
dockerグループは実質 root と同等
dockerグループに入れる =docker run -v /:/host --privileged ...(docker = 軽量な仮想環境を起動するツール。詳しくは「インフラ」章。-vでホスト側ディレクトリをコンテナに繋ぐオプション)でホストのrootファイルシステムをコンテナにマウントできる = root権限と同等。開発機なら割り切ってOKだが、**本番サーバーでは「docker操作したい人にも sudo + audit log を通させる」**運用が安全。「docker groupに入れちゃえばsudo要らなくて楽」は監査の穴になる。
3. useradd vs adduser、/etc/skel
ユーザーを作るコマンドは2系統あります。同じディストリで両方使えることが多いので、違いと使い分けが分からないと混乱します。
- 何のコマンドか:
useraddは低レベルの公式ツール(全フラグ手動指定)、adduserは Debian/Ubuntu の高レベルラッパー(対話的、/etc/skel自動コピー) - いつ使うか: 新メンバー追加(手動なら
adduserが楽)、Ansible / cloud-init で自動化する時(useraddで全フラグ明示)、/etc/skelで全社員共通の.bashrcを配る時 - 解決する具体的な問題: 「ホームディレクトリ作り忘れ」「シェル指定し忘れ」のような典型ミスを
adduser側が吸収してくれる
# Ubuntu/Debian 系: adduser(対話的、便利)
sudo adduser alice
# Adding user `alice' ...
# Adding new group `alice' (1001) ...
# Adding new user `alice' (1001) with group `alice' ...
# Creating home directory `/home/alice' ...
# Copying files from `/etc/skel' ...
# New password: ...
# 低レベル: useradd(手動でフラグ指定)
sudo useradd -m -s /bin/bash -G sudo,docker bob
sudo passwd bob
# 確認
id alice
getent passwd alice
ls -la /home/aliceuseradd vs adduser の違い
ざっくり言うと
両方ともユーザーを作るが、性格が真逆。useradd は素の Linux 公式(不親切)、adduser は Debian/Ubuntu の親切ラッパー。
まず素の useradd で作るとこうなる
sudo useradd alice
# ...終了。何も聞かれないなんとなく成功した気になるが:
ls /home/alice
# ls: cannot access '/home/alice': No such file or directory
↑ ホームがない!
getent passwd alice
# alice:x:1001:1001::/home/alice:/bin/sh
↑ シェルが /bin/sh(bashじゃない)
sudo su - alice
# パスワード設定されていないのでログインできないuseradd の問題発生フロー
useradd alice
↓
ホームディレクトリ作成されない(-m を忘れたから)
↓
シェルがデフォルト(/bin/sh)
↓
パスワード未設定で対話ログイン不可
↓
「alice ログインできない」と問い合わせ
解決策その1: useradd を「全フラグ明示」で使う
sudo useradd -m -s /bin/bash -G sudo,docker alice
↑ ↑ ↑
ホーム シェル 追加グループ
sudo passwd alice # パスワードも別途設定解決策その2: adduser を使う(楽)
sudo adduser alice
# 対話的に:
# ホーム作成 → /etc/skel コピー → パスワード設定 → 氏名・電話番号入力
# 全部やってくれる対比表
| useradd | adduser | |
|---|---|---|
| 種類 | 低レベル公式 | 高レベルラッパー (Perl スクリプト) |
| ホームディレクトリ | -m 必須 | 自動作成 |
| /etc/skel コピー | しない | する |
| パスワード設定 | 別途 passwd | 対話で設定 |
| シェル | ディストリのデフォルト | /bin/bash |
| 対話性 | 非対話 | 対話的 |
| 用途 | Ansible / cloud-init 等の自動化 | 人間が手で作る時 |
| ディストリ | どこでも動く | Debian/Ubuntu のみ |
イメージ
useradd= 「全部自分で指定する DIY」adduser= 「店員さんが対話で全部聞いてくれる」
一番覚えやすい説明
- 人間が手で作る → adduser
- スクリプトで自動化 → useradd(全フラグ明示)
/etc/skelの役割新規ユーザーのホームディレクトリ初期内容をここからコピーする。
ls -la /etc/skel/ # .bashrc # .bash_logout # .profile使い所: 全社員の
.bashrcに共通の alias を入れたい →/etc/skel/.bashrcを整備しておけば、新規ユーザー追加時に自動配布される。Ansible 等を使わない小規模運用で便利。
4. パスワードポリシー(passwd, chage, PAM)
パスワード認証を残す運用なら、パスワードの強度と寿命を制御する仕組みが必要です。Linux では passwd / chage / PAM の3点セットで管理します。
- 何のコマンドか:
passwdは変更、chageは有効期限など寿命管理、PAM は「強さ」のポリシーを/etc/security/pwquality.confで宣言する - いつ使うか: 退職予定者のアカウントに失効日をセットする時、社内規定で「最低12文字+3種類」を強制する時、初回ログイン時にパスワード変更を強制する時
- 解決する具体的な問題: 「password123」のような脆弱パスワードを物理的に設定不能にする。期限切れの放置アカウントを自動的に無効化する
# パスワード変更(本人 or root)
passwd # 自分のパスワードを変える
sudo passwd alice # rootが alice のを変える
# パスワード有効期限設定(chage = change age)
sudo chage -l alice # 状況確認
sudo chage -M 90 alice # 90日で期限切れ
sudo chage -M 90 -m 7 -W 14 -I 30 alice # 細かい設定
# 強制的にパスワード変更を促す
sudo chage -d 0 alice # 次回ログイン時に変更必須
chageの各オプション
-M 90: 最大有効日数(90日でパスワード失効)-m 7: 最小変更可能日数(前回変更から7日経たないと変更不可、頻繁な変更で履歴を回避するのを防ぐ)-W 14: 期限切れ警告日数(14日前から警告)-I 30: 猶予期間(期限切れ後30日でアカウント無効化)-E 2026-12-31: アカウント失効日
PAMで強いパスワードを強制する
Linux のパスワード検証は PAM(Pluggable Authentication Modules)が担う。
pam_pwqualityでポリシーを設定:# /etc/security/pwquality.conf(一例) minlen = 12 # 最低12文字 minclass = 3 # 大文字/小文字/数字/記号のうち3種類 maxrepeat = 3 # 同じ文字を3回まで dictcheck = 1 # 辞書攻撃のような単語を弾くこれを入れると「password123」みたいなのは設定不能になる。
最近のNIST推奨はもっと別物
昔は「90日でパスワード変更必須」が常識だったが、NIST SP 800-63B(2017〜)では頻繁な強制変更は推奨されないようになった。理由:
- 強制変更すると人間は「Password1」→「Password2」→「Password3」のような予測可能な変更をする
- 結局セキュリティが下がる
現代の推奨:
- 長いパスフレーズ(または鍵認証)
- 漏洩が確認された時だけ強制変更
- 多要素認証(MFA)
「90日ローテーション」は今でも企業の規程に残っているが、本質的なセキュリティ向上にはなっていないことを知っておく。
セッション②: sudoers と最小権限、監査(25-30分)
5. sudo vs su の本質的な違い
ざっくり言うと
両方とも「別のユーザーで何かやる」道具だが、設計思想が真逆。
su= 「ユーザーごと切り替わる」(パスワードはターゲットユーザーのもの)sudo= 「自分のままで、1コマンドだけ別ユーザー権限を借りる」(パスワードは自分のもの)
まず素朴な su のパターン
alice@host:~$ su -
Password: ___ ← rootのパスワードを入力
root@host:~# ← rootに「丸ごと」変身
root@host:~# apt update
root@host:~# vim /etc/nginx/nginx.conf
root@host:~# exit
alice@host:~$alice のシェル
↓ su -
root のシェル(環境ごと全部 root)
↓ exit
alice に戻る
この方式の問題発生フロー
チーム5人で1台のサーバーを運用
↓
全員 root のパスワードを知っている必要がある
↓
退職者が出たら root のパスワードを変えないといけない
↓
変えるのを忘れる → 退職者がまだ入れる
↓
さらに /var/log/auth.log には全員「root」としか出ない
↓
誰が rm -rf したか分からない
sudo は「自分のパスワードで、1コマンドだけ昇格」
alice@host:~$ sudo apt update
[sudo] password for alice: ___ ← alice 自身のパスワード
(apt update が root 権限で実行される)
alice@host:~$ ← すぐ alice に戻るalice のシェル
└─ sudo apt update ← この1コマンドだけ root 権限
alice のシェル(継続)
イメージ:
su= 変身(30分間プリキュアになる)sudo= 代行(この書類だけ部長にハンコ押してもらう)
監査ログでの差
/var/log/auth.log:
# su の場合
session opened for user root(uid=0) by alice
(以降のコマンドは「root が何かやった」としか残らない)
# sudo の場合
sudo: alice : TTY=pts/0 ; USER=root ; COMMAND=/usr/bin/apt update
sudo: alice : TTY=pts/0 ; USER=root ; COMMAND=/bin/systemctl restart nginx
(誰が何をやったか1行ずつ残る)
対比表
| su | sudo | |
|---|---|---|
| 何を入力 | ターゲットのパスワード | 自分のパスワード |
| シェル | 切り替わる(root に変身) | 切り替わらない(コマンド単発) |
| 監査ログ | 「root が何かした」 | 「alice が root として X した」 |
| パスワード共有 | 必要 | 不要 |
| きめ細かい制御 | 不可(全権限 or なし) | 可能(コマンド単位で許可) |
| 退職者対応 | root パスワード変更必須 | sudoers から削除するだけ |
一番覚えやすい説明
su= アカウントごと変身(パスワード共有・監査ログ崩壊・退職対応地獄)sudo= 権限だけ借りる(最小権限・監査ログ追跡可能・退職対応簡単)
# 普通の sudo
sudo apt update
# 別ユーザーになって実行(変身ではなく権限借りる)
sudo -u www-data ls /var/www
# どうしても root シェルが欲しい時(極力避ける)
sudo -i # フル環境
sudo su - # 同上の別書き方
# 直前のコマンドに sudo を付け足す
sudo !!sudo = substitute user do
(“super user do” は俗説、開発者本人は前者と説明)。
1980年代に開発開始、Todd C. Miller がメンテし続けて現在に至る Unix 系で最も普及している権限委譲ツール。
6. /etc/sudoers の構造と visudo
sudo の挙動を定義するのが /etc/sudoers ですが、このファイルは触り方を間違えるとサーバーから締め出される最も危険な設定ファイルの1つ。専用エディタの visudo で守られた手順で触ります。
- 何のコマンドか:
visudoは sudoers をロック + 構文チェック付きで編集するための専用コマンド - いつ使うか: チームに新しい sudo 権限を付与する時、CI/CD 用の NOPASSWD ルールを追加する時、本番の運用ルールを更新する時
- 解決する具体的な問題: 「sudo 自体が動かなくなりサーバーを救出できない」事故を、構文チェックで未然に防ぐ
# 絶対に直接編集するな。必ず visudo を使う
sudo visudo
# ファイル分割: /etc/sudoers.d/ 配下に個別ファイルを置くのが現代流
sudo visudo -f /etc/sudoers.d/dev_teamvisudo を必ず使う理由
/etc/sudoersの構文ミスがあると、sudo 自体が動かなくなる。rootパスワードが分からない / rootログイン無効 の状態でこれをやると、サーバーを救うのが超大変(シングルユーザーモード起動が必要)。visudo は:
- 編集中はファイルをロック(同時編集防止)
- 保存時に構文チェックを実行 → エラーがあれば保存しない
- デフォルトエディタは
EDITOR環境変数(vimやnano)絶対に
sudo vi /etc/sudoersしないこと。
sudoers の文法
# 構文: ユーザー ホスト=(実行ユーザー) コマンド # alice はどのホストでも、すべてのユーザーになって、すべてのコマンドが実行可能 alice ALL=(ALL:ALL) ALL # sudo グループ全員に同じ権限 %sudo ALL=(ALL:ALL) ALL # deploy ユーザーは systemctl restart nginx だけパスワード無しで実行可能 deploy ALL=(root) NOPASSWD: /bin/systemctl restart nginx # 複数コマンド deploy ALL=(root) NOPASSWD: /bin/systemctl restart nginx, /usr/bin/rsync
%groupname: グループ指定(先頭の%)NOPASSWD:: パスワード入力スキップ(CI/CDで重要)!: 否定(このコマンドだけ禁止)Defaults: 全体設定
Defaults timestamp_timeout=15 # sudo のパスワードキャッシュ15分 Defaults logfile=/var/log/sudo.log # ログファイル指定 Defaults requiretty # ttyからのみ許可(スクリプト経由禁止)
7. 最小権限の sudoers 設計
sudoers の文法が分かったら、次は設計です。「最小権限の原則(PoLP)」を sudoers ファイルにどう落とすかが、本番運用の品質を分けます。
- 何のコマンドか:
/etc/sudoers.d/配下に「役割ごとのファイル」を作り、%groupname単位で「許可するコマンドだけ」を列挙する - いつ使うか: 開発者に本番への限定アクセスを与える時、デプロイユーザーに
systemctl restart appだけ通す時、監視ユーザーに読み取り系コマンドだけを許可する時 - 解決する具体的な問題: 「sudo 持ち = 何でもできる」状態を解体し、「この人はこの3コマンドだけ」と明文化することで、誤操作と侵入時被害の両方を最小化する
# /etc/sudoers.d/dev_team の例
sudo visudo -f /etc/sudoers.d/dev_team# 開発者グループ: アプリケーションの再起動とログ確認のみ
%developers ALL=(root) NOPASSWD: /bin/systemctl restart app, /bin/systemctl status app
%developers ALL=(root) NOPASSWD: /usr/bin/tail -f /var/log/app/*.log
%developers ALL=(root) NOPASSWD: /usr/bin/journalctl -u app
# 明示的に禁止しておく
%developers ALL=(root) !/bin/su, !/usr/bin/passwd
最小権限の原則(PoLP)
ジョブをこなすのに必要な最小限の権限だけ与える。
良い例:
- デプロイユーザー: アプリの再起動と特定ディレクトリへの書き込みのみ
- 監視ユーザー: 読み取り権限のみ(
tail -f,df -h,topなど)- DBバックアップ用ユーザー:
pg_dump実行と/var/backups書き込みのみなぜ重要か:
- 侵入されてもダメージが小さい: 監視ユーザーが乗っ取られても、アプリは止められない
- ヒューマンエラーが減る: 全権限を持つと、操作ミスで本番が壊れる
- 退職時の引継ぎが簡単: 「このユーザーが何できるか」が明確
アンチパターン: 全員 sudo ALL NOPASSWD
# NG: 楽だからとこう書く %developers ALL=(ALL:ALL) NOPASSWD: ALL「sudo は全員ノーパス、全コマンド許可」。これは「全員 root を持っている」のと同じ。
問題点:
- 誤操作が即本番障害:
rm -rf /var/logが一瞬で通る- 侵入時の被害最大化: 開発者の鍵が漏れたら、即root権限の侵入
- 監査ログがあっても遅い: ログを見るのは事故が起きた後
正解: 最小権限。必要なコマンドだけNOPASSWD、それ以外はsudoでパスワード認証。
アンチパターン: 共有アカウントを作る
# NG: チーム全員が同じユーザー `deploy` でログイン問題:
- 誰がやったか分からない: ログには
deployとしか出ない- 鍵管理がカオス: 誰の公開鍵が
~deploy/.ssh/authorized_keysにあるか分からなくなる- 退職対応が困難: 1人辞めるたびに全員のパスワード/鍵を変える必要
正解: 1人1アカウント。例えば全員に個別アカウントを発行し、それぞれに
sudo -u deploy ...の権限を付ける。これで「誰がdeployとして何を実行したか」がsudo.logに残る。
アンチパターン: 平文パスワードをファイルに置く
# NG: パスワードをスクリプトに直書き mysql -uroot -p'P@ssw0rd123' -e "SELECT * FROM users"問題:
ps auxで他ユーザーから見える: コマンドライン引数は全員に見える- bashの履歴(
~/.bash_history)に残る- GitHub にプッシュした瞬間漏洩
正解:
- 環境変数(
.envを.gitignore)- シークレットマネージャー(AWS Secrets Manager、HashiCorp Vault)
.my.cnfのようなツール標準の設定ファイル(パーミッション600で)
8. root を完全に無効化する運用
sudo 運用が回り始めたら、最後の仕上げとして root アカウント自体を物理的に閉鎖します。これで「root に直接入る」という攻撃ベクトル全体が消えます。
- 何のコマンドか:
passwd -lでパスワードをロック、usermod -s /usr/sbin/nologinでシェルを無効化、両方で root の対話ログインを塞ぐ - いつ使うか: VPS の初期セットアップ最終段階、社内サーバーをセキュリティ強化する時、CIS Benchmark に準拠させる時
- 解決する具体的な問題: 「root のパスワード推測攻撃」を、推測対象を消すことで根絶する。Ubuntu Server などはこの状態がデフォルト
# rootのパスワードを無効化(パスワードログイン不能に)
sudo passwd -l root
# rootのシェルを無効化(rootでログイン試行しても何もできない)
sudo usermod -s /usr/sbin/nologin root
# Ubuntu 系は最初からこれに近い設定(root のパスワードが未設定 → ロック状態)
sudo passwd -S root
# root L 01/01/2024 0 99999 7 -1 ← L = locked「root を直接使わない」運用
多くのモダンなディストリ(Ubuntu Server 等)は初期状態でrootのパスワードが未設定で、最初のユーザーが
sudoグループに入っている。これは意図的な設計。メリット:
- パスワード認証でrootに入る攻撃ベクトルが消える
- 全操作が
sudo経由 = 監査ログが取れる- 「うっかりrootでログイン」が物理的に起きない
rootのシェルにどうしても入る必要がある場合:
sudo -i # フル環境のrootシェル sudo su - # 別の書き方(同等)どちらも
sudo.logに記録される。AWS のEC2や多くのVPSも、デフォルトでこの設計(rootログイン無効、
ubuntuやec2-userなどの初期ユーザーが sudo 持ち)。
9. 監査ログを読む
sudoers を整え、root を閉じても、ログを誰も見ないなら侵入に気づけません。最小権限運用と監査ログ確認はセットです。
- 何のコマンドか:
/var/log/auth.log(Debian系)//var/log/secure(RHEL系)/journalctl -u sshdで、ログイン・sudo 実行・認証失敗をすべて遡って読む - いつ使うか: 朝の業務開始時の流し見、インシデント発生時の犯人特定、退職者の最終ログイン日時の確認、不審な海外IPからのアクセスチェック
- 解決する具体的な問題: 「侵入されたのに気づかない」最悪のシナリオを、ログ確認の習慣で防ぐ。事故が起きた時の「いつ・誰が・何を」も即特定できる
# sudoの実行履歴
sudo tail -100 /var/log/auth.log # Debian/Ubuntu
sudo tail -100 /var/log/secure # RHEL/CentOS
sudo journalctl -u sudo # systemd 系で sudo の journal
# SSHログイン履歴
sudo journalctl -u ssh
sudo journalctl -u sshd
# 直近のログイン成功者
last | head -20
# 失敗ログイン(不正アクセス試行の検知)
sudo lastb | head -20
# 現在ログイン中のユーザー
who
w監査ログを「見る習慣」が大事
監査ログは「事故が起きてから初めて見る」のではなく、定期的に流し見する習慣をつけると、異常に気づきやすい。
本番でチェックすべきパターン:
- 業務時間外のログイン
- 海外IPからのログイン試行
sudoの異常な使い方(大量の cat /etc/shadow など)rootログイン試行(無効化していても試行ログは残る)
/var/log/auth.logの例:May 14 10:00:01 prod sshd[1234]: Accepted publickey for deploy from 203.0.113.5 port 51234 ssh2 May 14 10:00:05 prod sudo: deploy : TTY=pts/0 ; PWD=/home/deploy ; USER=root ; COMMAND=/bin/systemctl restart app May 14 10:05:30 prod sshd[1235]: Failed password for invalid user admin from 198.51.100.10 port 51235 ssh21行目: deployユーザーが公開鍵で正常ログイン 2行目: deployが
systemctl restart appを実行(監査記録) 3行目: 不正なadminログイン試行(攻撃)
10. 実例: 開発者ごとに個別アカウント発行
シナリオ: 新規エンジニア Bob に本番サーバーへのアクセスを与える。
# 1. ローカルでBobの公開鍵を受け取る(GitHubなどから)
curl https://github.com/bob.keys > /tmp/bob.pub
# 2. サーバーで個別アカウント作成
sudo adduser --disabled-password --gecos "Bob Tanaka" bob
sudo mkdir -p /home/bob/.ssh
sudo chmod 700 /home/bob/.ssh
sudo cp /tmp/bob.pub /home/bob/.ssh/authorized_keys
sudo chmod 600 /home/bob/.ssh/authorized_keys
sudo chown -R bob:bob /home/bob/.ssh
# 3. 必要なグループに追加
sudo usermod -aG developers bob
# 4. sudoers で最小権限付与
sudo visudo -f /etc/sudoers.d/bob
# 中身:
# bob ALL=(root) NOPASSWD: /bin/systemctl restart app
# bob ALL=(root) NOPASSWD: /usr/bin/journalctl -u app
# 5. ログインを試す(別端末で)
# ssh bob@example.com
# sudo systemctl restart app
# 6. 監査ログで確認
sudo grep "bob" /var/log/auth.log退職時の対応
# 1. アカウントをロック(即時アクセス遮断) sudo usermod -L bob sudo usermod -s /usr/sbin/nologin bob # 2. SSH 鍵を無効化 sudo mv /home/bob/.ssh/authorized_keys /home/bob/.ssh/authorized_keys.disabled # 3. プロセスを終了 sudo pkill -KILL -u bob # 4. 一定期間後に削除(監査ログ保全のため、即削除しない運用が多い) sudo deluser --remove-home bob
練習課題
# 1. ローカル(Mac)では試しづらいので、UbuntuのDocker内で練習する
# (docker = 軽量な仮想環境を起動するツール。-it で対話シェル、--rm で終了時に自動削除、
# ubuntu:24.04 が使うイメージ。Docker 自体は「インフラ」章で詳しくやる。
# 今は「捨てて良い Ubuntu 環境がワンコマンドで作れる便利な道具」とだけ理解すればOK)
# Docker がインストールされていないなら https://docs.docker.com/desktop/ から入手
docker run -it --rm ubuntu:24.04 bash
# コンテナ内で:
apt update && apt install -y sudo vim adduser
# 2. 新規ユーザー作成
adduser --disabled-password --gecos "" alice
adduser --disabled-password --gecos "" bob
# 3. /etc/passwd と /etc/shadow を観察
grep -E "^(alice|bob)" /etc/passwd
grep -E "^(alice|bob)" /etc/shadow
# 4. グループ作成と所属
addgroup developers
usermod -aG developers alice
id alice
# 5. sudoers 設計
cat > /etc/sudoers.d/developers <<'EOF'
%developers ALL=(root) NOPASSWD: /usr/bin/apt update
%developers ALL=(root) /usr/bin/apt install *
EOF
# 構文チェック
visudo -c
# 6. aliceでsudo実行
su - alice
sudo apt update # NOPASSWD で通る
sudo apt install -y curl # パスワード求められる
sudo rm /etc/passwd # 拒否されることを確認締め: git で証跡を残す
exit # script から抜ける
cd ~/learn/linux/day14
git init
git add .
git commit -m "feat(linux): ユーザー管理・sudoers・最小権限の設計を整理"チェックリスト
-
/etc/passwdの7フィールドを言える -
/etc/shadowがなぜ別ファイルか説明できる -
useraddとadduserの使い分けを判断できる -
idで自分の所属グループを確認できる -
visudoを使わずに/etc/sudoersを直接編集することの危険性を説明できる - 最小権限の sudoers 設計を1つ書ける
- root を完全無効化する手順を3行で書ける
-
/var/log/auth.logの sudo 実行記録を読める - 退職者対応の手順を即答できる
詰まった時のチートシート
| やりたいこと | コマンド |
|---|---|
| 新規ユーザー作成 | sudo adduser <name> |
| 既存ユーザーにグループ追加 | sudo usermod -aG <group> <user> |
| 所属確認 | id <user> |
| パスワード変更 | sudo passwd <user> |
| アカウント無効化 | sudo usermod -L <user> |
| ログインシェル無効化 | sudo usermod -s /usr/sbin/nologin <user> |
| sudoers編集 | sudo visudo または sudo visudo -f /etc/sudoers.d/myrules |
| sudoers構文チェック | sudo visudo -c |
| sudo履歴 | sudo journalctl -u sudo or grep sudo /var/log/auth.log |
| 直近ログイン | last |
| 失敗ログイン | sudo lastb |
| 現在の接続中 | who, w |
| ユーザー削除 | sudo deluser --remove-home <user> |
| パスワード有効期限 | sudo chage -M 90 <user> |
「実務OK」基準
/etc/passwdを見て、サービスアカウントと一般ユーザーを区別できるvisudoを使う癖がついている: 直接編集は絶対しない- 最小権限の sudoers を書ける: コマンド単位での権限委譲ができる
- 共有アカウント禁止の理由を3つ即答できる: 監査・侵入時被害・退職対応
- 退職者対応の手順を間違えない: ロック → 鍵削除 → プロセス停止 → 一定期間後削除
- 監査ログ(auth.log, sudo.log)を流し見できる: 異常パターンを察知
さらに深掘るなら
man sudoers: 全文法と注意点が網羅されている。読み切れば事故率が激減- PAM: Linux認証システム全般を支える土台。
/etc/pam.d/の中を覗いてみる - 書籍: 『UNIXシステム管理 改訂版』(O’Reilly) - 古いが基本概念は今でも有効
- 公式: https://www.sudo.ws/ (sudoの本家、開発者ブログでセキュリティ動向)
- CIS Benchmarks: Linux ディストリのセキュリティハードニングガイド(業界デファクト)
- NIST SP 800-53 / 800-63B: アクセス制御・認証の国際標準
アンチパターン / 初心者やらかし事例
NG 1: vim /etc/sudoers で直接編集 → 構文エラー → sudo 使えなくなる
sudo vim /etc/sudoers # 1行ミス → 全員 sudo 失効→ 対策: 必ず sudo visudo を使う。構文チェックが入って、エラーがあれば保存させてくれない。
NG 2: usermod -G dev user(-a 忘れ)で既存グループから外す
sudo usermod -G dev alice # alice の既存グループが消える!sudo グループも消えて事故→ 対策: 追加は必ず -aG(append + G)。sudo usermod -aG dev alice。
NG 3: chmod 777 で「全員 root 並みの権限」を量産
→ Day 3 でも触れたが、ユーザー管理章でも再強調。本来は 適切なユーザー / グループを作って所有権で解決。
NG 4: 退職者のアカウントを rm -rf /home/user だけで済ませる
→ プロセスがまだ動いている / cron が残っている / ssh セッションが残っているケースあり。
→ 対策: usermod -L でロック → SSH 鍵を authorized_keys から削除 → 関連プロセス kill → 一定期間後に削除(バックアップ取った上で)。
自己評価チェックリスト
-
/etc/passwdの7フィールドを書ける -
visudoを反射で打てる(sudoers 直接編集しない) - 「コマンド単位の sudo 許可」のルールが書ける
-
usermod -aG <group> <user>の-aの意味を答えられる - 退職者対応の4ステップ(ロック→鍵削除→プロセス停止→削除)を即答できる
次のレッスン: Day 17 - Nginx
明日は Nginx ─ Linux 上で動くアプリを「Web に公開する」ための定番ソフトウェア。
リバースプロキシ・ロードバランサ・静的配信・proxy_pass・ヘッダ転送・gzip・ログ・セキュリティ設定まで。今日学んだ「専用ユーザー」「最小権限」がそのまま Nginx の運用設計に活きる。
→ Day 17: Nginx へ