手のかかるCognitoくん
Cognitoを使っていて属性を変更したいと思ったのですが、実は必須の属性は変更できません。
既にある程度ユーザを作ってしまっていたのでなんとかユーザのデータ移行できないかと調べたところ、AWS公式ドキュメントでは2つの方法が紹介されていました。
しかしそう上手くいかないのがAWS。
1番の方法では認証フローに USER_PASSWORD_AUTH
を使用する必要があり既存の実装にマッチせず、2番の方法ではパスワードが移行できません。さすがです。
悩み抜いた末にしぶしぶ2番の方法でデータ移行することにしました。
じゃあもうCSVでデータ移行するよ
CSVをインポートすれば簡単にできそうですが、実はインポートデータを作るところは自前でやる必要があるので意外と大変。
既存データのエクスポート
権限のある状態で次のコマンドでユーザデータを抽出
aws cognito-idp list-users --user-pool-id <元のユーザープールID> > users.json
インポートデータへの変換
データ変換が億劫だったので生成AIにコードを出してもらって魔改造したコードがこちら。
import json
import csv
# ヘッダー
headers = [
'profile', 'address', 'birthdate', 'gender', 'preferred_username',
'updated_at', 'website', 'picture', 'phone_number', 'phone_number_verified',
'zoneinfo', 'custom:tmp_password', 'locale', 'email', 'email_verified',
'given_name', 'family_name', 'middle_name', 'name', 'nickname',
'cognito:mfa_enabled', 'cognito:username'
]
# JSONファイルを読み込む
with open('users.json', 'r') as f:
data = json.load(f)
# CSVファイルを作成し、ヘッダーを書き込む
with open('cognito_users.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=headers)
writer.writeheader()
# ユーザーデータを処理してCSVに書き込む
for user in data['Users']:
row = {'cognito:username': user['Username']}
for attr in user['Attributes']:
if attr['Name'] in headers:
row[attr['Name']] = attr['Value']
# MFA状態を設定(ユーザーデータに含まれていない場合はFalseとする)
row['cognito:mfa_enabled'] = row.get('cognito:mfa_enabled', 'false')
# すべてのヘッダーが含まれるように未定義のフィールドを空欄に設定
for header in headers:
if header not in row:
row[header] = ''
writer.writerow(row)
print("CSVファイルが作成されました: cognito_users.csv")
なおヘッダーについてはコマンドでも取得できるようだが、アップロード時にエラーのサジェストでtemplate.cvs
をコンソールからダウンロードできたのそちらを利用している。
ヘッダー不足や順序で何回か失敗してストレスゲージが貯まるので注意。
インポート
インポートについては「ユーザーインポートジョブの作成と実行」の通りに実施すればOK。コンソールからアップロード時実施した。
まとめ
Cognitoくんってもしかしてイケてないの?