【実践シェルスクリプト講座 第3回】「えっ、手動で50人分登録するの!?」面倒なユーザー作成を全自動化しよう
こんにちは!「リナックス先生」です。
前回は、サーバーを守るための「バックアップ」と「通知」の仕組みを構築しました。
これで守りは完璧…と言いたいところですが、コウ君、なんだかお疲れ気味じゃない?
先生…実は、来週から新しいプロジェクトが始まるらしくて、開発メンバー20人分のユーザーアカウントを作成することになったんです。
しかも、「セキュリティのため全員SSH鍵認証にして、秘密鍵を個別に配布してくれ」って言われて…。
ユーザー作って、パスワード設定して、鍵を作って、権限変えて…これを20回繰り返すなんて、指が取れちゃいますよ!(泣)
それは大変ね。でも、エンジニアにとって「単純な繰り返し作業」は最大の敵であり、同時に自動化のチャンスでもあるの。
エクセル(CSV)で作った名簿さえあれば、その作業、スクリプト一つで1秒で終わらせられるわよ。
今回は、シェルスクリプトの真骨頂である「ループ処理」と「テキスト読み込み」をマスターしましょう!
「実践シェルスクリプト講座」第3回のテーマは、インフラエンジニアの業務効率を劇的に改善する「ユーザー管理の自動化」です。while ループを使ってCSVファイルを一行ずつ読み込み、ユーザー作成からSSH鍵の生成・配置までを一気に処理するプロ仕様のスクリプトを作成します。
本講座のカリキュラム(全5回)
本シリーズでは、現場で即使えるレベルの実践的なスクリプトを作成します。
- サーバー停止の恐怖から解放!「ディスク容量監視」と「ログ自動整理」の完全自動化【完了】
- データ消失をゼロにする!「堅牢バックアップ」と「Slack通知」の構築【完了】
- 【今回】手作業を撲滅せよ!「ユーザー一括作成」と「SSH鍵配布」の自動化スクリプト
- 攻撃者を秒でブロック!ログ解析による「SSH総当たり攻撃」自動防御システム
- プロの品質へ!スクリプトの「安全性向上(デバッグ)」と「トラブルシューティング」
1. 手作業の恐怖と自動化の設計図
まず、コウ君がやろうとしている手作業の手順を書き出してみましょう。
ユーザー1人あたり、これだけのコマンドが必要です。
# 1. ユーザー作成 useradd -m -s /bin/bash tanaka # 2. パスワード設定(対話式で入力が必要) passwd tanaka # 3. .sshディレクトリ作成 mkdir /home/tanaka/.ssh chmod 700 /home/tanaka/.ssh # 4. SSH鍵ペアの生成 ssh-keygen -t rsa -f /home/tanaka/.ssh/id_rsa -N "" # 5. 公開鍵をauthorized_keysに登録 cat /home/tanaka/.ssh/id_rsa.pub > /home/tanaka/.ssh/authorized_keys chmod 600 /home/tanaka/.ssh/authorized_keys # 6. 所有者の変更 chown -R tanaka:tanaka /home/tanaka/.ssh
これを20人分、一度もタイプミスせずに打つ自信はありますか?
途中で誰かの権限設定を間違えてログインできなくなったり、SSH鍵を他人のものと取り違えたりするリスクが非常に高いです。
今回は、「ユーザー名と初期パスワードを書いたCSVファイル」を用意し、それをスクリプトに読み込ませることで、これら全てを自動実行させます。
2. ループ処理の主役「while read」構文
シェルスクリプトでファイルを一行ずつ読み込むには、while read という構文を使います。
これはLinuxの定型文として覚えてしまいましょう。
基本構文
while IFS=, read -r 変数1 変数2 ...; do
# ここに処理を書く
echo "読み込んだ値: $変数1, $変数2"
done < 読み込むファイル名
💡 呪文の解説
IFS=,(Internal Field Separator):
「区切り文字はカンマ(,)ですよ」という宣言です。CSVを読む時は必須です。read -r:
ファイルから一行読み込みます。-rはバックスラッシュを文字として扱うオプションで、安全のために付けます。< ファイル名:
ループの最後に書くことで、指定したファイルの中身をループに流し込みます。
3. 準備:CSVファイルの作成
まずは、ユーザーリストとなる user_list.csv を作成します。
フォーマットは「ユーザー名,初期パスワード」としましょう。
[root@localhost ~]# vi user_list.csv
user_list.csv の中身
tanaka,Pass1234 suzuki,P@ssword5678 sato,Linux2024!
※実務では、パスワードを平文(そのままの文字)でファイルに保存するのはリスクがあります。
作業が終わったらこのCSVファイルは即座に削除するか、後述するパスワード自動生成テクニックを使うのが一般的ですが、今回はわかりやすく「指定したパスワードを設定する」方式で進めます。
4. 実装:一括ユーザー作成スクリプト
それでは、スクリプト create_users.sh を作成していきましょう。
今回は「SELinux」環境でもエラーが出ないよう、プロ仕様の調整も含めます。
Step 1: 秘密鍵の生成と配置
ユーザーを作成した直後に、そのユーザー専用のSSH鍵ペア(秘密鍵と公開鍵)をサーバー上で生成し、ログインできるように設定してあげます。
完成したスクリプト create_users.sh は以下のようになります。
#!/bin/bash
# --- 安全設定 ---
# set -u : 未定義変数エラーチェック
set -u
# ==========================================
# 設定エリア
# ==========================================
CSV_FILE="user_list.csv"
KEY_DIR="generated_keys" # 生成した秘密鍵を集める場所
# root権限チェック
if [[ $EUID -ne 0 ]]; then
echo "エラー: このスクリプトはrootユーザーで実行してください。"
exit 1
fi
# ==========================================
# メイン処理
# ==========================================
# ファイル存在チェック
if [ ! -f "$CSV_FILE" ]; then
echo "エラー: $CSV_FILE が見つかりません。"
exit 1
fi
# 配布用鍵ディレクトリの作成
mkdir -p "$KEY_DIR"
chmod 700 "$KEY_DIR"
echo "=== ユーザー一括作成処理を開始します ==="
while IFS=, read -r USERNAME PASSWORD; do
# 1. データチェック(空行・コメント行スキップ)
[[ -z "$USERNAME" || "$USERNAME" =~ ^# ]] && continue
# 2. ユーザー存在チェック
if id "$USERNAME" &>/dev/null; then
echo "[SKIP] ユーザー $USERNAME は既に存在します。"
continue
fi
# 3. ユーザー作成
# -m: ホームディレクトリ作成
# -s: ログインシェル指定
useradd -m -s /bin/bash "$USERNAME"
# 直前のコマンドの成功可否チェック
if [ $? -ne 0 ]; then
echo "[ERROR] $USERNAME の作成に失敗しました。"
continue
fi
# 4. パスワード設定(chpasswdコマンドで非対話設定)
echo "${USERNAME}:${PASSWORD}" | chpasswd
# 5. SSHディレクトリの準備
USER_HOME="/home/$USERNAME"
SSH_DIR="$USER_HOME/.ssh"
mkdir -p "$SSH_DIR"
chmod 700 "$SSH_DIR"
# 6. SSH鍵ペアの生成
# -t rsa: 暗号化方式
# -N "": パスフレーズなし(自動化のため)
# -f: 出力先ファイル名
# -C: コメント(誰の鍵かわかるように)
# > /dev/null 2>&1 : 余計な出力を捨てる
ssh-keygen -t rsa -b 2048 -N "" -f "$SSH_DIR/id_rsa" -C "Key for $USERNAME" > /dev/null 2>&1
# 7. 公開鍵をauthorized_keysに登録
cat "$SSH_DIR/id_rsa.pub" >> "$SSH_DIR/authorized_keys"
chmod 600 "$SSH_DIR/authorized_keys"
# 8. 権限と所有者の修正(超重要!)
# rootで作ってしまったファイルを、ユーザーの所有に変更する
chown -R "$USERNAME:$USERNAME" "$SSH_DIR"
# 9. SELinuxコンテキストの修正(RHEL/AlmaLinux/CentOS用)
# これをやらないと、権限が合っていてもSSHログインが拒否される場合がある
if command -v restorecon &> /dev/null; then
restorecon -R "$SSH_DIR"
fi
# 10. 秘密鍵を管理者が回収(配布用)
# ユーザー本人に渡すために、手元のディレクトリにコピーしておく
cp "$SSH_DIR/id_rsa" "$KEY_DIR/${USERNAME}_id_rsa"
echo "[OK] $USERNAME を作成し、SSH鍵(${USERNAME}_id_rsa)を生成しました。"
done < "$CSV_FILE"
echo "=== 全処理完了 ==="
echo "生成された秘密鍵は $KEY_DIR に保存されています。"
echo "各ユーザーに安全な方法で配布してください。"
おおお!実行したら一瞬で全員分の秘密鍵ができあがりました!generated_keys フォルダの中身を本人に配るだけでいいんですね!
ところで、restorecon って何ですか?
いいところに気がついたわね!
AlmaLinuxなどのRHEL系OSには「SELinux」という強力なセキュリティ機能があるの。
これが有効だと、単にファイル権限(chmod)が合っていても、「ラベル」が合っていないとアクセスを拒否するのよ。restorecon はそのラベルを正常に戻すコマンド。これを入れ忘れると「設定は完璧なのにログインできない!」って3日悩むことになるわ。
5. パーミッション(権限)の落とし穴
このスクリプトで一番ハマりやすいポイントは、ステップ8の chown(所有者の変更) です。
これを忘れるとどうなると思いますか?
スクリプトは root 権限で実行しているため、作られた .ssh ディレクトリや authorized_keys ファイルの所有者は、デフォルトで root になってしまいます。
すると、ユーザー(例:tanakaさん)がログインしようとした時、「自分の家(ホームディレクトリ)にある鍵ファイルなのに、root様の持ち物だから読み取れない!」という状態になり、SSHログインが拒否されてしまうのです。
SSHのトラブル原因のNo.1は、この「パーミッションと所有権の間違い」です。
自動化スクリプトを書くときは、「誰の権限でファイルが作られるか」を常に意識しましょう。
まとめ:ループ処理を制する者はサーバーを制す
今回は、シェルスクリプトによる「繰り返し処理(ループ)」の実践編として、ユーザー一括作成ツールを作りました。
| 技術要素 | 解説 |
|---|---|
while read |
ファイルを行単位で読み込む基本構文 |
chpasswd |
スクリプトから非対話でパスワードを設定するコマンド |
ssh-keygen -N "" |
パスフレーズなしのSSH鍵を自動生成するオプション |
restorecon |
SELinux環境下でのアクセス権トラブルを防ぐおまじない |
20人のユーザー作成も、1000人のユーザー作成も、このスクリプトがあれば労力は変わりません。
これが「自動化(Automation)」の威力です。
次回予告:見えない攻撃者との戦い
さて、ユーザーを作成してSSHを開放したということは、外部からのアクセスの入り口が増えたことも意味します。
あなたのサーバーは今この瞬間も、世界中から「総当たり攻撃(ブルートフォースアタック)」を受けているかもしれません。
次回は、ログをリアルタイムで解析し、何度もログインに失敗してくる怪しいIPアドレスを自動的に検知して、ファイアウォールでブロックする「自動防衛システム」を作成します。
まさに「サーバーの守護神」となるスクリプトを作りましょう!
今回のスクリプトで使ったCSVファイルは、パスワードが平文で書かれているから、作業が終わったら必ず削除(rm user_list.csv)するのを忘れないでね!
ゴミ箱に残すのも厳禁よ!
▼スクリプトの実験場に最適!推奨VPS


コメント