【実践シェルスクリプト講座 第3回】手作業を撲滅せよ!「ユーザー一括作成」と「SSH鍵配布」の自動化スクリプト

【実践シェルスクリプト講座 第3回】「えっ、手動で50人分登録するの!?」面倒なユーザー作成を全自動化しよう

こんにちは!「リナックス先生」です。
前回は、サーバーを守るための「バックアップ」と「通知」の仕組みを構築しました。
これで守りは完璧…と言いたいところですが、コウ君、なんだかお疲れ気味じゃない?

コウ君

先生…実は、来週から新しいプロジェクトが始まるらしくて、開発メンバー20人分のユーザーアカウントを作成することになったんです。
しかも、「セキュリティのため全員SSH鍵認証にして、秘密鍵を個別に配布してくれ」って言われて…。
ユーザー作って、パスワード設定して、鍵を作って、権限変えて…これを20回繰り返すなんて、指が取れちゃいますよ!(泣)

リナックス先生

それは大変ね。でも、エンジニアにとって「単純な繰り返し作業」は最大の敵であり、同時に自動化のチャンスでもあるの。
エクセル(CSV)で作った名簿さえあれば、その作業、スクリプト一つで1秒で終わらせられるわよ。
今回は、シェルスクリプトの真骨頂である「ループ処理」「テキスト読み込み」をマスターしましょう!

「実践シェルスクリプト講座」第3回のテーマは、インフラエンジニアの業務効率を劇的に改善する「ユーザー管理の自動化」です。
while ループを使ってCSVファイルを一行ずつ読み込み、ユーザー作成からSSH鍵の生成・配置までを一気に処理するプロ仕様のスクリプトを作成します。

本講座のカリキュラム(全5回)

本シリーズでは、現場で即使えるレベルの実践的なスクリプトを作成します。

  1. サーバー停止の恐怖から解放!「ディスク容量監視」と「ログ自動整理」の完全自動化【完了】
  2. データ消失をゼロにする!「堅牢バックアップ」と「Slack通知」の構築【完了】
  3. 【今回】手作業を撲滅せよ!「ユーザー一括作成」と「SSH鍵配布」の自動化スクリプト
  4. 攻撃者を秒でブロック!ログ解析による「SSH総当たり攻撃」自動防御システム
  5. プロの品質へ!スクリプトの「安全性向上(デバッグ)」と「トラブルシューティング」

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

【2026年最新】Linuxサーバー構築におすすめのVPS比較3選!現役エンジニアが速度とコスパで厳選
Linuxの勉強、まだ「自分のPC」でやって消耗していませんか?「Linuxを覚えたいけど、環境構築でエラーが出て先に進めない…」「VirtualBoxを入れたらパソコンが重くなった…」これは、Linux学習を始める9割の人がぶつかる壁です...

コメント