Udemyセール開催中(9/19まで)人気教材が1,500円~

Cognitoへユーザを移行する【実装例】(設定手順、Pythonサンプルコードあり)

Cognitoユーザ移行アイキャッチ画像

この記事は以下の記事の実装編となっております。

目次

実装したいこと ログインしたタイミングでユーザを移行する

Cognitoへユーザ移行するlambdaの作成手順とコードの実装例を説明します。
なお、AWS公式ではjwtからメールアドレスなどの情報が取れるとのことでしたが今回は移行元Cognitoからadmin_get_userで取得しています。
jwtからメールアドレスなどの情報を取得したい場合は下記をご参照ください。注意点とともにサンプルコードを紹介しております。

図1 今回実現したいこと

STEP1 移行元のCognitoの設定をしよう(クライアントの発行)

アプリクライアントの発行を行います。既に発行済みの場合はそれを使うことができます。
その際、今回のサンプルコードはクライアントシークレットを生成はしない認証用の管理 API のユーザー名パスワード認証を有効にするユーザー名パスワードベースの認証を有効にするはチェックを入れていないとエラーになるのでご注意ください。

Cognitoアプリクライアント発行

アプリクライアント発行は
AWSマネジメントコンソールのCognito→ユーザプール→移行元のユーザプール→アプリクライアント
の順でアクセスします。

図2 アプリクライアント発行

アプリクライアントの設定内容

設定はクライアントシークレットを生成はしない認証用の管理 API のユーザー名パスワード認証を有効にするユーザー名パスワードベースの認証を有効にするでお願いします。クライアントのシークレットは今回のサンプルコードを書き換えれば動作すると思いますが、そのまま使う場合はチェックを外してください。

図3 アプリクライアントの設定

こちらで発行いただくとアプリクライアントIDが生成されます。

発行されるアプリクライアントIDはサンプルソースに記入する必要があるのでメモしておいてください。

STEP2 移行元のAWS環境でIAMRoleを作成して信頼関係を結ぼう

移行先のlambdaから移行元のCognitoにアクセスする必要があるので移行元のAWSアカウントでIAMロールを作成して移行先のAWSアカウントに信頼関係の設定をします。

IAMRoleの作成

IAMRoleの作成はIAM→ロールから実施します。

図4 IAMRoleの作成

信頼関係の設定

信頼関係を結ぶために信頼されたエンティティタイプAWSアカウントを選択します。AWSのアカウントの項目では別のAWSアカウントを選択して移行先のAWSアカウントIDを記入してください。入力が完了したら次へを押下します。

図5 IAMロールの信頼関係設定

信頼関係を設定することで別のAWSアカウントからこのロールを利用できるようになります

次に許可ポリシーの設定をします。今回はAWSマネージドポリシーのAmazonCognitoPowerUserを選択します。あとは任意の名前を付けて作成してください。

AmazonCognitoPowerUserはCognitoユーザプールに対する読書き権限が含まれています。セキュリティ要件などで権限を絞りたい場合は自分でポリシーを定義することもできます。

ここで発行されるロールのARNは後程サンプルコードに記載する必要があるのでメモしておいてください。

STEP3 ユーザ移行lambdaを作成しよう

PythonランタイムでLambda関数の作成

マネジメントコンソールでLambda→関数関数の作成を押下してLambda関数を作成します。

図7 関数の作成

関数名は好きなものを付けてください。ランタイムはPython3.9を選択します。設定出来たら関数を作成します。

Python3系であれば動くと思います。筆者は3.9で動作確認済みです。

図8 関数の作成

サンプルソースコードにCognitoユーザプールID、アプリクライアント、ロールを記入

ここまで出来たらサンプルソースにCognitoのユーザプール、アプリクライアント、ロールを貼り付けます。これらはSTEP1STEP2で作成したものです。
role_arnに作成したIAMロールのARN、FROM_USER_POOL_IDにCognitoユーザープール、FROM_APP_CLIENT_IDにアプリクライアントを設定してください。7~12行目です。

import boto3
from boto3.session import Session
import json

def lambda_handler(event, context):
    region = "ap-northeast-1"
    # TODO 作成したリソースの情報で更新してください。
    # 移行元 スイッチロールするIAMロールの情報
    role_arn = "arn:aws:iam::123456789012:role/XXXXXXXXX"
    # 移行元Cognito情報
    FROM_USER_POOL_ID = "ap-northeast-1_XXXXXXX"
    FROM_APP_CLIENT_ID = "xxxxxxxxxxxxxxxxxxxxxxx"

    # ユーザが入力したID/PW取得
    username = event['userName']
    password = event['request']['password']

    # 移行元環境にSWITCHする
    sts_cli = boto3.client('sts')
    response = sts_cli.assume_role(
            RoleArn=role_arn,
            RoleSessionName="session"
    )
    session = Session(
        aws_access_key_id=response['Credentials']['AccessKeyId'],
        aws_secret_access_key=response['Credentials']['SecretAccessKey'],
        aws_session_token=response['Credentials']['SessionToken'],
        region_name=region
    )

    # 移行元のCognitoにアクセスし、ログインする
    # 移行元のCognitoにログインできなければここでエラーとなる。(ID/PW間違いなど)
    from_client = session.client('cognito-idp')
    response = from_client.admin_initiate_auth(
        UserPoolId=FROM_USER_POOL_ID,
        ClientId=FROM_APP_CLIENT_ID,
        AuthFlow="ADMIN_NO_SRP_AUTH",
        AuthParameters={
            'USERNAME': username,
            'PASSWORD': password
        }
    )

    # 旧Cognitoからadmin_get_userで必要なユーザ情報を取り出す
    # ここではメールアドレスと電話番号を取り出しています。
    response = from_client.admin_get_user(UserPoolId=FROM_USER_POOL_ID, Username=username)
    for userattribute in response['UserAttributes']:
        if userattribute['Name'] == 'phone_number':
            phone_number = userattribute['Value']
        if userattribute['Name'] == 'email':
            email = userattribute['Value']

    # 移行先Cognitoにユーザを作成する。eventに入れてreturnでeventを返却すればユーザが作成される。
    # なお、作成したユーザーは即時有効化し、メールアドレスと電話番号も検証済みとする
    event['response']['userAttributes'] = {
        'username': username,
        'email': email,
        'email_verified': True,
        'phone_number': phone_number,
        'phone_number_verified': True
    }
    event['response']['finalUserStatus'] = 'CONFIRMED'
    # ユーザー登録時のメール送信は抑制
    event['response']['messageAction'] = 'SUPPRESS'

    # 移行元のユーザを削除する場合はコメントアウトを外す
    # from_client.admin_delete_user(
    #     UserPoolId=FROM_USER_POOL_ID,
    #     Username=username
    # )

    return event

Cognitoの登録APIを呼び出していないのを不思議に思った方もいるでしょう。
event[‘response’]に設定内容を入れておくだけで移行ができます。Cognitoの登録APIを呼び出さなくても登録は呼び出し元のCognitoがやってくれているようです。

ソースコードを貼り付けてLambda関数をデプロイ

サンプルソースコードの修正が完了したらソースをlambdaに貼り付けます。
元のソースをすべて消してサンプルソースを貼り付けて「Deploy」を押下してlambdaをデプロイしてください。数秒でデプロイされます。

図9 ソースの貼り付け、lambdaのデプロイ

ソースを修正した際はDeployボタンを押すのを忘れないようにしてください。

STEP4 ユーザ移行lambdaの実行ロールにスイッチロールを許可しよう

サンプルソースの中の18行目に移行元環境にSWITCHするという箇所があります。これを実現するにはlambdaの実行ロールにスイッチロールする権限を与える必要があります。

Lambda設定から実行ロールを選択

Lambdaの実行ロールにスイッチロールする権限を割り振っていきます。前の手順でデプロイしたlambdaの画面→設定→アクセス権限の順に開いていきます。
開いたらロール名をクリックしてIAMRoleの設定画面にジャンプします。

図10 lambda権限設定からロール名を押下


ロール名を押下するとIAMのコンソールに移動します。

ポリシー作成


画面が遷移したら許可を追加→ポリシーをアタッチの順に選択していきます。

図11 IAMロール設定画面へ飛ぶ


次にポリシーを作成を押下します。

図12 ポリシーの作成

ポリシーの作成でJSONを押下し、以下のJSONを貼り付けてください。スイッチロールを許可するポリシーになっています。
貼り付けたらあとはデフォルトで適当な名前を付けてポリシーを作成します。

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "*"
    }
}

ポリシーの貼り付け画面

図13 ポリシーの作成(JSON)

作成したポリシーのアタッチ

ポリシーの作成後、ポリシーを xxxxxxx にアタッチの画面に戻り、作成したポリシーをlambda実行ロールに割り当ててください。作成したポリシーを選択してポリシーをアタッチを押下します。

図14 ポリシーのアタッチ

STEP5 移行先Cognitoでトリガを設定しよう

トリガを設定することでCognitoでログインがあったときLambda関数を実行するようにできます。

トリガーの選択

Cognito→ユーザプール→トリガーの順でアクセスします。

図15 トリガの設定画面

ユーザー移行トリガーの選択

多数あるトリガの中から今回はユーザーの移行を選択します。Lambda関数からSTEP3で作成したユーザ移行lambdaを選択してください。

図16 Cognitoトリガの設定(ユーザーの移行)

設定は以上です。

動作確認

では実際に動きを見てみましょう。

事前準備:移行元Cognitoにユーザ登録

事前準備として移行元Cognitoにユーザを登録しておきます。コンソールからできますが、アカウントのステータスをCONFIRMEDにしておいてください。作成直後はFORCE_CHANGE_PASSWORDになるかと思うので下記コマンドでCONFIRMEDにしておきます。

aws cognito-idp admin-set-user-password --user-pool-id ap-northeast-1_XXXXXX --username ユーザ名 --password パスワード --permanent

FORCE_CHANGE_PASSWORDままでも正常に動作する可能性がありますが、CONFIRMDになっているケースで利用することが多いと思うのでCONFIRMDで動作確認します。
マネジメントコンソールからはCONFIRMDにできないのでAWSCLIで操作します。

図17 Cognitoに動作確認用ユーザ追加

CLIコマンドを実行するとCONFIRMDになります。

図18 コマンド実行後CONFIRMEDに変わる

Cognitoにサインアップしてみる

移行先Cognitoには移行対象のユーザが存在しないことを確認しておきます。

図19 移行先のCognito(誰もいない)

では事前準備で作成したユーザでサインアップしてみます。

スクリーンショットの例ではmigration_test_userを使っています。

サインアップもコンソールからはできないのでCLIで実行します。

aws cognito-idp admin-initiate-auth --user-pool-id ap-northeast-1_XXXXXXX --client-id クライアントID --auth-flow ADMIN_USER_PASSWORD_AUTH --auth-parameters USERNAME=ユーザ名,PASSWORD=パスワード

対象ユーザが移行される

成功するとCLIでトークンが返却されてきます。そして移行先のCognitoに対象ユーザが登録されます。

サンプルコードでは移行元にユーザが残ります。
移行元のユーザを削除したい場合はサンプルコードのコメントアウトを外していただければ削除されます。

図20 対象ユーザが移行される

PR
当ブログはWordPressテーマSWELLを使用しています。非常に使いやすく、簡単にプロのようなデザインを使えるのでお勧めです!!

SWELL – シンプル美と機能性両立を両立させた、圧巻のWordPressテーマ

ランキング

ランキングに参加しています。クリックして応援いただけると嬉しいです。
にほんブログ村 IT技術ブログ クラウドコンピューティングへ
にほんブログ村
AWSランキング
AWSランキング

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次