Lambdaを利用してIAMユーザ作成を自動化してみた

AWSのサーバレスアーキテクチャを実際に触ってみたくて手始めにLambdaを用いてみることにしました。

【やりたいこと】
---
![実現イメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840619/3d24e664-fae4-50d0-74da-c1ca12dad527.jpeg)



ExcelベースのIAMユーザの登録申請書の内容を基に申請書をS3へアップロードしたらLambdaが実行されて申請書に記載されているIAMユーザを自動作成する。


【使用環境】
boto3
Python3.9
pandasライブラリ

【実現方法】
---
Excelベースでの読み込みは私には難易度が高かったのでcsv形式に変換するVBAを作成(この部分の詳細は割愛)

csv形式で以下のフォーマットで記載することに決定
1カラム目,2カラム目,3カラム目
IAMユーザ名,IAMグループ,メールアドレス

IAMユーザを作成する際のパスワードはセキュリティの観点からランダムに自動生成したいです。


さて、方針が固まったのでLambdaにて実装したいのですがその前に権限回りの設定をします。

Lambdaの実行ロールに以下の権限を付与します。

:::note info
【IAMポリシー】
iam:AttachUserPolicy
iam:DetachUserPolicy
iam:AddUserToGroup
iam:RemoveUserFromGroup
s3:Get*
s3:List*
iam:Get*
iam:List*
:::

また、Lambdaのデフォルトタイムアウトは3秒なので適当に伸ばしておきます。

次にS3へのアップロードをトリガーにLambdaをキックしたいのでトリガーに以下を指定します

:::note info
【トリガー】
サービス：s3.amazonaws.com
バケット名：S3のバケット名を指定する
Prefix：前方一致のフォルダ名などを指定する
Suffix：後方一致の拡張子やファイル名等を指定する
:::

これで準備が整いましたのでコードに以下をコピペします。

:::note warn
【注意】
以下は適宜ご利用の環境に応じて置き換えてください
SRC_BUCKET_NAME="sample_bucket"
SRC_OBJECT_KEY_NAME="sample_appform.csv"
messages内のメール本文
アカウントID
:::

【コード】
---
```Python
import boto3
import io
import pandas as pd
import csv
import random
import string

SRC_BUCKET_NAME="sample_bucket"
SRC_OBJECT_KEY_NAME="sample_appform.csv"
SRC_FILE_ENCODING="utf-8"


# パスワード自動生成
def get_random_password():
    random_source = string.ascii_letters + string.digits + string.punctuation
    password = random.choice(string.ascii_lowercase)
    password += random.choice(string.ascii_uppercase)
    password += random.choice(string.digits)
    password += random.choice(string.punctuation)

    for i in range(6):
        password += random.choice(random_source)

    password_list = list(password)
    random.SystemRandom().shuffle(password_list)
    password = ''.join(password_list)
    return password

### メール機能 ###
SRC_MAIL = "hogehoge@gmail.com"
DST_MAIL = "hogehoge@gmail.com"
REGION = "ap-northeast-1"

def send_email(source, to, subject, body):
    client = boto3.client('ses', region_name=REGION)

    mailresponse = client.send_email(
        Source=source,
        Destination={
            'ToAddresses': [
                to,
            ]
        },
        Message={
            'Subject': {
                'Data': subject,
            },
            'Body': {
                'Text': {
                    'Data': body,
                },
            }
        }
    )
    
    return mailresponse
    
email = "アカウント作成完了メール"

### メール機能ここまで ###


s3 = boto3.resource('s3')
iam = boto3.resource('iam')
client = boto3.client('iam')

def lambda_handler(event, context):
  
# csvを変数に格納
  src_obj = s3.Object(
    SRC_BUCKET_NAME,
    SRC_OBJECT_KEY_NAME
  )
  body_in = src_obj.get()['Body'].read().decode(SRC_FILE_ENCODING)
#body_in = src_obj.get()['Body'].read()


# 配列に入れて吐き出す
# 文字列をファイルオブジェクトのように扱うことができる
  st = io.StringIO()
# writeで書き込み
  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]
    )

    Password_temp = get_random_password()
    print('初期パスワード:{}'.format(Password_temp))

    response = client.create_login_profile(
      UserName=row[0],
      Password=Password_temp,
      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]
    )
    mailaddr=row[2]
    message = "申請者様\n"\
              "\n"\
              "お疲れ様です。AWS担当○○です。\n"\
              "\n"\
              "ご依頼いただいたAWSのアカウント作成が完了しましたので\n"\
              "以下の通りご連絡いたします。\n"\
              "\n"\
              "ログインURL：https://console.aws.amazon.com/console/home\n"\
              "アカウントID：123456789012\n"\
              "パスワード：{}\n"\
              "\n"\
              "\n"\
              "送付先メールアドレス：{}\n"\
              "\n"\
              "以上です。"
    message = message.format(Password_temp,mailaddr)
    r = send_email(SRC_MAIL, DST_MAIL, email, message)
```
:::note 
pandasライブラリはデフォルトで提供されていないようなのでGit等からご利用のPythonバージョン用のpandasライブラリを「Layers」に追加してください。
:::


コメントやいいねをいただけると励みになりますのでお願いいたします。