はじめに
釣りが好きなCS部CS2課オールドルーキー有川です。 アオリイカを釣りに伊豆に行きたい。イカチョップしたい。
参考:イカチョップとは https://www.youtube.com/watch?v=z-FoT6QFU9g&t=20s
※釣ったイカの神経を断つことで鮮度を保ち、美味しくいただくための方法。 〆用の刃物などもあるが、家の鍵でもいい。動画の通りチョップでも〆ることが出来ます
この記事では何を得ることが出来る?
さて、本記事ではLambdaとS3を用いて、IAMuserの作成を自動化してみました。 CSVリストにあるユーザーを一気に作成するためのLambdaで用いるPythonスクリプトと関連する権限設定について記載しています。
- AWS Lambda+S3を用いたIAMユーザーの作成の自動化の方式
- 自動化出来た暁には大量のIAMユーザー作成業務からの解放
構成図
再帰読込による無限ループ発生を防ぐため、入力用のS3と、作業終了したS3は別のバケットで管理します。 同一バケットでの入出力も可能ですが、上記の危険がありアンチパターンです。 以下の記事で紹介するように無限ループの自動検出機能もありますが、設計段階で排除できる危険は排除したいところです。
前提
- 検証時は、Lambda内のPython3.12を用いました
- 参加するIAMグループは事前に作成が必要です
- 作成したユーザーへの通知は手動です(イケてない・・・)
- 作成したユーザーは初回ログイン時にご自身でのパスワード変更が必要です
※3の通知はSES連携やSNSでSlackと連携するなどを実装することで自動化できます
実際にどういう運用手順になるか
- 作成対象者をリスト化したCSVを作成する
- 作成したCSVをS3にアップロードする
- マネコンやCLIにて、IAM上にユーザーが作成されている事を確認
- 対象者にログイン確認&パスワード変更を実施頂く通知を実施
構築手順
手順1:S3バケットの用意
1-1. S3バケットの用意(ソース用と処理済み格納用の2種)
- バケット名に指定はありません。その他の設定もデフォルトで良いです。
※既存のバケット使用でも構いませんが、src側のバケットに.csvがアップロードされるたびにLambdaが走るので新規作成をお勧めします。
※1つのバケットで設定する事も可能ですが、再帰呼び出しの可能性を含むためアンチパターンです。最悪超高額なLambda料金の請求が来ますのでお勧めしません。
手順2:Lambdaの準備
2-1. Lambdaを作成します
以下のコードを用いてLambdaを作成します
import boto3 import io import csv import datetime # ご自身の環境に合わせて変更してください SRC_BUCKET_NAME="YOURBACKETPREFIX-iam-useradd-src" DST_BUCKET_NAME="YOURBACKETPREFIX-iam-useradd-dst" SRC_OBJECT_KEY_NAME="iam_useradd.csv" SRC_FILE_ENCODING="utf-8" s3 = boto3.resource('s3') s3c = boto3.client("s3") iam = boto3.resource('iam') client = boto3.client('iam') dt_now = datetime.datetime.now() t = str(dt_now.strftime("%Y%m%d-%H:%M:%S")) dst_f = t + "_" + SRC_OBJECT_KEY_NAME +".done" dst = "added/" + dst_f #S3上のファイルリネームを関数化 def s3_move_object(s3c, *, BucketFrom: str, BucketTo: str | None = None, KeyFrom: str, KeyTo: str): if BucketTo is None: BucketTo = BucketFrom s3c.copy_object(Bucket=BucketTo, Key=KeyTo, CopySource={"Bucket": BucketFrom, "Key": KeyFrom}) s3c.delete_object(Bucket=BucketFrom, Key=KeyFrom) #処理部 def lambda_handler(event, context): src_obj = s3.Object( SRC_BUCKET_NAME, SRC_OBJECT_KEY_NAME ) body_in = src_obj.get()['Body'].read().decode(SRC_FILE_ENCODING) st = io.StringIO() st.write(body_in) st.seek(0) csv_f =csv.reader(st) for row in csv_f: #print('ユーザ名:{}'.format(row[0])) response = client.create_user( UserName=row[0] ) response = client.create_login_profile( UserName=row[0], Password=row[2], PasswordResetRequired=True ) waiter = client.get_waiter('user_exists') waiter.wait( UserName=row[0], WaiterConfig={ 'Delay': 5, 'MaxAttempts': 5 } ) user = iam.User(row[0]) response = user.add_group( GroupName=row[1] ) response = user.attach_policy( PolicyArn='arn:aws:iam::aws:policy/IAMUserChangePassword' ) else: s3_move_object(s3c, BucketFrom=SRC_BUCKET_NAME, BucketTo=DST_BUCKET_NAME, KeyFrom=SRC_OBJECT_KEY_NAME, KeyTo=dst)
※ソース作成に当たり、以下のサイト記述を参考にしています
2-2. Lambda実行ロールに以下の許可を与えます
以下のユーザーポリシーを作成し、ロールにアタッチを行ってください。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iam:AttachUserPolicy", "iam:DetachUserPolicy", "iam:AddUserToGroup", "iam:RemoveUserFromGroup", "iam:Get*", "iam:List*", "iam:CreateUser", "iam:CreateLoginProfile", "s3:Get*", "s3:List*", "s3:PutObject", "s3:DeleteObject" ], "Resource": "*" } ] }
2-3. Lambdaの実行時間タイムアウトを30秒程度に伸ばします
ここは実際の作業ボリュームに合わせて適宜変更してください。私の環境では、3名作成するのに7秒程度必要でした。
2-4. Lambdaのトリガーに1-1で作成したバケット「すべてのオブジェクト作製イベント」を設定します
手順3:CSVファイルを用意
3-1. カラム構成は以下のようにする
ユーザー名 | 参加グループ名 | 仮パスワード |
---|---|---|
TEST_USER_001 | TEST_GROUP_001 | TEST_PaSsWoRd01! |
TEST_USER_002 | TEST_GROUP_002 | TEST_PaSsWoRd02! |
※実際のCSVにタイトル行は不要です
動作確認
- 作成したCSVを、1-1で作成したソース用S3バケットにアップロードしてください。
- IAM画面で、想定通りのユーザーが作成されているか確認をしてください。
- アップロードしたファイルがリネームされ、DST_BUCKET_NAME/added/に移動している事を確認してください。

- 作成したユーザーと仮パスワードでログインを試行し、本パスワードへの変更が実施可能かを確認してください。
注意事項
・エラー制御の考慮がありません。例えば既に同一ユーザー名がいた場合、Lambdaはエラーで終了します。
・削除は手動で実施する想定です。(自動で消すのはなんか怖い・・・)
・アクセスキーなど関連設定の付与は考慮していません。
・グループに付与した権限が付与されるのみで、個別のアクセス権限はパスワード変更以外の考慮はありません。
まとめ
4月に入ると、IAMユーザーを一斉に作成する作業で半日終わる、なんて嘆く方も多いのではないでしょうか。 本手順が皆様の運用負荷を下げる一助となれば幸いです。
ありかわ りゅうた(執筆記事の一覧)
カスタマーサクセス部 CS2課
2024年11月中途入社
自動車、釣り、キャンプ、ギターが趣味です。
経験こそ至高と思っているので、趣味的な事柄は何でも手を出します。
妻(パート)と娘(小学低学年)と息子(小学高学年)と犬(ゴールデンレトリバー)と猫(ミックス)で暮らす日々が煩わしくてうるさくて面倒くさいのに、かけがえの無いものなのが不思議です。