この記事を読むのに必要な時間は 約10分 です。
この記事では、以下の内容をまとめています👇️
詳しく知りたい・質問等がありましたら、ぜひコメント欄へお願いします。
Amazon Cognito のユーザプールに 認証済みユーザをまとめて作成する方法
+ Admin 権限を有した CodeEditor からboto3 を利用して一撃作成
(背景)GenU ユーザ認証での課題
皆さまは GenU 使っていますでしょうか?
<Generative AI Use Cases: AWSさまのありがたいページ>
AWS上で、生成AIのユースケースをさくっと構築して、利用可能な超便利な OSS リポジトリです!!
私の職場でも、社内向けの RAGチャット(いわゆる文書検索アシスタント) として活用しており、ありがたいことに「うちの部署でも使いたい!」というお声をいただいております。
ところが…
めっちゃ便利ですね!
100人くらい新規ユーザを登録したいんだけど
良いですね!
セルフサインアップ有効化してあるので、ユーザ登録してね♫
なんだかエラーで登録できないんだが…!?
という自体に遭遇しました。
よく調べてみると、 ユーザ登録するときに「Cognito からEメールを送信」するのですが、「1日に送信可能なメールは50通まで」という制限がありました…!?
GenU では、ユーザ認証に Amazon Cognito を利用しています。
Amazon SES を利用すれば、50通/日という制限を気にしなくて良いのですが、定常的に発生するイベントではなく、スパイク的な事象なので、そのためだけに SES を利用するのもナンセンスです。
ということで、
たまにしかないことなら、 管理者権限で一撃作成できるようにしておこう!
って感じで、boto3 使って認証済みユーザを作成できるようにしてみました。
💡Cognito の制限については、こちらのページでも詳しく解説されています。
これから Cognito でユーザ認証をいじる方は、ぜひ参考にしてください〜
👉️ 知らなかったCognitoの制限 – NCDCエンジニアブログ[Zenn]
boto3 で認証済みユーザを作成する
Cognito のセルフサインアップを利用してユーザ作成する場合は、以下の流れで作成されます。
- ユーザ名(アドレス)とパスワードを設定
- Cognito からアドレス確認用のメールが届く
- メールのリンクにアクセスすることでアドレスを有効化
👉️ユーザ登録完了
一方で、boto3で Cognito のユーザ登録をする場合は、以下のように実装できます。
作成した ノートブック形式ファイルはこちら です。
新規作成するユーザ情報を確認しながら操作できるので、ノートブック形式ファイルの方がおすすめです。
import boto3
import pandas as pd
from tqdm import tqdm
def get_all_users(user_pool_id):
""" Cognitoユーザプールからユーザリストを取得
Args:
user_pool_id (string): CognitoユーザプールID
Returns:
users (list): ユーザプール内の全てのユーザリスト
"""
cognito_client = boto3.client('cognito-idp')
users = []
pagination_token = None
while True:
if pagination_token:
response = cognito_client.list_users(
UserPoolId=user_pool_id,
PaginationToken=pagination_token
)
else:
response = cognito_client.list_users(
UserPoolId=user_pool_id
)
users.extend(response['Users'])
if 'PaginationToken' in response:
pagination_token = response['PaginationToken']
else:
break
return users
def users_to_dataframe(users):
""" Cognitoユーザプールから取得したユーザリストをデータフレームに変換
Args:
users (list): ユーザプール内の全てのユーザリスト
Returns:
(pd.DataFrame): Cognitoのユーザリスト
"""
user_data = []
for user in users:
user_dict = {
'Username': user['Username'],
'UserStatus': user['UserStatus'],
'UserCreateDate': user['UserCreateDate'].strftime('%Y-%m-%d %H:%M:%S'),
'UserLastModifiedDate': user['UserLastModifiedDate'].strftime('%Y-%m-%d %H:%M:%S'),
}
# Add user attributes
for attr in user['Attributes']:
user_dict[attr['Name']] = attr['Value']
user_data.append(user_dict)
return pd.DataFrame(user_data)
def check_string_in_column(df, column_name, string_to_check):
"""
Args:
df(Dataframe): チェック対象のデータフレーム
column_name(str): チェック対象の列名
string_to_check(str): 検索する文字列
Return:
(list): データフレームの各行について、True|False のリスト
"""
return df[column_name].str.contains(string_to_check, na=False)
def create_cognito_users(USER_POOL_ID, df):
""" Cognito ユーザプールに新規ユーザをまとめて作成する
Args:
USER_POOL_ID (str): CognitoユーザプールID
df (pd.DataFrame): 登録したいユーザと初期パスワードをまとめたデータフレーム
"""
cognito_client = boto3.client('cognito-idp')
# Cognito ユーザプールから最新のユーザリストを取得
user_list = get_all_users(USER_POOL_ID)
# print(f"Cognito ユーザプールに登録されている人数: {len(user_list)}")
# ユーザリストをデータフレームに変換
df_users = users_to_dataframe(user_list)
# 一時的な仮パスワード
PASS_TEMP = "Karipass#9020"
# Admin権限でユーザを新規作成する
for index, row in tqdm(df.iterrows(), total=len(df)):
EMAIL = row["メールアドレス"]
PASS = row["初期パスワード"]
# Cognitoユーザプール内に重複が無いかをチェック
if check_string_in_column(df_users, 'email', EMAIL).sum():
print(f'Creatig user >>> {EMAIL} >>> pass')
continue
print(f'Creatig user >>> {EMAIL}')
# 共通の仮パスワードを使って、とりあえずユーザ作成
# ここで一時パスワードを設定すると時限付となってしまう
# メール認証は `済` にしてしまう
cognito_client.admin_create_user(
UserPoolId=USER_POOL_ID,
Username=EMAIL,
TemporaryPassword=PASS_TEMP,
UserAttributes=[
{
'Name': 'email_verified',
'Value': 'true'
},
{
'Name': 'email',
'Value': EMAIL
}
],
MessageAction='SUPPRESS'
)
# 初期パスワードを確認済みとして設定
cognito_client.admin_set_user_password(
UserPoolId=USER_POOL_ID,
Username=EMAIL,
Password=PASS,
Permanent=True
)
print("New user created in the Cognito user pool.")
def main():
df = pd.read_excel('GenU_一括登録リスト(テスト).xlsx')
df = df.dropna(subset='メールアドレス')
df = df.filter(['メールアドレス', '初期パスワード']) # 余計な情報があった場合は、フィルタリングする
# Cognito ユーザプールID
USER_POOL_ID = "XXXXXXXXXXXXXXXXXXXXXXX"
# ユーザ名と初期パスワードをまとめたデータフレーム
df = pd.read_csv("users.csv")
create_cognito_users(USER_POOL_ID, df)
print("Done.")
if __name__ == "__main__":
main()
ポイントとしては、こんな感じです👇️
- boto3 の
admin_create_user
を利用してAdmin権限でユーザを新規作成するときに、- email_verified を trueにする
💡 ここで メール認証は済
になります!
(メール配信されずに済む) - emailには、(テキトーな)仮パスワードを設定
(次のステップでちゃんとパスワードを設定します)
- email_verified を trueにする
- boto3 の
admin_set_user_password
を利用して、Admin権限でパスワードを設定しちゃう
admin_create_user
で仮パスワードを設定できるのですが、時限付きなので、一定時間を経過すると、Admin 権限(Cognito のコンソール画面等)で、再度設定が必要になってしまいます。
ユーザ側としては、かなりメンドクサイ事になるので、(セキュリティ的な課題はありそうですが、)すぐに GenU にアクセスできるようにしています。
あとは、作成したユーザ名&パスワードをお知らせすれば、すぐにGenUを使ってもらうことができます!!
生成AIは、さわってナンボ、ですから、ハードルは少ないほうが良いですね。
(今回は社内向けですが、社外向けだと、もっとちゃんと考える必要があります…!)
まとめ
新規ユーザリストから 100名分のユーザを一撃作成できました!
ありがとうございます〜
GenU で遊んでみますね〜
という感じで、100名規模でも、Cognito の制限を突破してユーザ作成することができました!
自分でイチからAIチャットボットを作ると、大変ですが、 GenU 等の OSS を活用するとサクッと社内向けチャットボットを作成できていいですよね。
次回も、生成AI関係でなにか書いてみようと思います〜
コメント