🐥

Cognitoユーザープールのバックアップ・リストア(前編)

2023/11/29に公開

背景

最近関わっているプロジェクトでCognitoユーザープールのデータが消失した場合を想定して、ユーザーの属性情報をバックアップし、障害時にリストアすることができるか検討していました。

AWSが公式に出しているツール(Cfnテンプレート)があり、実際に試してみた結果を備忘として記載しました。

長くなりそうなので、アカウントのバックアップ(エクスポート)を前編、リストア(インポート)を後編という構成にしています。

Cognito User Profiles Export リファレンスアーキテクチャ

概要

https://aws.amazon.com/jp/solutions/implementations/cognito-user-profiles-export-reference-architecture/

AWSが公式に発表しているCognitoユーザー情報のエクスポート・インポートを行うアーキテクチャ。

主な使用サービス

  • Amazon Cognito
    • バックアップ元またはリストア先となるユーザープール。これらのユーザープールは CloudFormation テンプレートでは作成されないため自分で作成する必要がある。
  • Amazon DynamoDB
    • ユーザープールのユーザー情報・グループ情報を global table に保存することで、非同期的にセカンダリリージョンへデータを転送する。
  • AWS Step Functions
    • 複数の Amazon Lambda 関数を順序関係を維持し実行し、ユーザー情報のバックアップとリストアの工程を管理する。
  • AWS Lambda
    • バックアップとリストアの各工程(ユーザープールや DynamoDB への読み書きなど)を実行する。
  • Amazon SQS
    • 後で処理するユーザー情報などを一時的に溜めておくために使用する。
  • Amazon SNS
    • Workflow の完了やエラーなどを通知するために使用する。
  • Amazon EventBridge
    • Export Workflow を定期実行するために使用する。
  • Amazon S3
    • Import Workflow のログが保存される。トラブルシューティングに用いるものであり、リストアが正常に完了した場合には参照する必要はなし。

制限・注意事項

セキュリティの観点から、Amazon Cognito はユーザーのパスワードをエクスポートする機能を提供しないため、パスワードはバックアップされません。リストアされたユーザープールを使用する際には、ユーザーにパスワードをリセットしていただくようご依頼ください。

  • パスワードのエクスポートはセキュリティを考慮し対応していないため、ユーザー復元後にパスワードリセットと再設定が必要となる。

バックアップ元とリストア先のユーザープールでは、各ユーザーの sub 属性が変わります。アプリケーションのロジックにおいて、一意の ID として sub 属性を使用している場合は、バックアップ元とリストア先のユーザープールで sub 属性を対応させる必要があります。この際、バックアップ元のユーザープールで sub 属性をカスタム属性としてコピーしておくと、DynamoDB テーブルにバックアップできるようになり、リストア後のユーザープールで sub 属性の対応関係を確認するために利用できます。

  • ユーザー復元前後でユーザーIDの"sub"の値も変わってしまうため、業務に影響がないか考慮が必要。

Amazon Cognito 経由で登録されたユーザー情報のみバックアップできます。サードパーティの認証(ソーシャルログイン)を使用して登録されたユーザーの情報はバックアップされません。ソーシャルログイン経由で登録されたユーザーは、リストア先のユーザープールに切り替わった段階で再度ログインしていただくようご依頼ください。また、ID プロバイダーの設定も引き継がれないため、リストア先のユーザープールでバックアップ元と同様に設定してください。

  • ユーザー情報のエクスポート・インポートの対象はローカルユーザー(Eメール・パスワード)のみ。
  • ソーシャルユーザー(Google、LINEなど)は対象外なので注意。
  • ソーシャルユーザーも対象にしたい場合はエクスポート・インポートの仕組みを独自に実装する必要がある。

その他以下注意点がある。

  • ユーザープールのアドバンスドセキュリティ機能を使用している場合、ログイン履歴はバックアップされない。
  • グループに紐づけられた IAM ロールの情報はバックアップされない。
  • 記憶済みデバイスの情報はバックアップされない。

コスト

AWS のインポートツールを使用して、既存のユーザーを Amazon Cognito ユーザープールに移行できます。ユーザー属性値は .csv ファイルからインポートされます。このファイルはコンソール、API、または CLI によってアップロードできます。インポートされたユーザーは、初回サインイン時に、E メールアドレスや携帯電話に送信されたコードを使って自分のアカウントを確認し、新しいパスワードを作成します。インポートツールを使用しても追加コストは発生しません。

  • インポート実行によるコストの発生は無し。

やってみた

テンプレートのデプロイ

リファレンスアーキテークチャを実際にデプロイしてみる。
https://docs.aws.amazon.com/pdfs/solutions/latest/cognito-user-profiles-export-reference-architecture/cognito-user-profiles-export-reference-architecture.pdf

Cfnテンプレートのデプロイ

  • 手順書のリンクからAWSマネコンを開きCfnテンプレート(スタック)をデプロイする。
  • デフォルトではUS Eastリージョンにデプロイされる。必要に応じてリージョンを変更する。
  • 前提として、対象となるCognitoユーザープールが作成済みであること。

手順書のリンクをクリック。

デフォルトではUS Eastのマネコンが開くのでAP North Eastに変更。
設定はそのままで次へ。

スタックの設定を行う。基本デフォルトのまま。

スタックオプションの設定。迷わず次へ。

設定の確認。承認チェックボックスにチェックを入れて送信。

対象となるCognitoユーザープール名ではなくユーザープールIDだったので修正し送信。

スタックのデプロイが開始。
10分ほど待つそうなので、冷やしておいたパイの実を食べる。

SNS TopicのSubscriptionの承認メールが届いていたので、Confirm subscriptionをクリックして承認。

13分でデプロイ完了。

大量のリソースが作成されている。
リソースを確認してみる。

DynamoDB

Exportしたユーザーデータ(バックアップ)を格納するDynamoDBテーブル。

今回大阪リージョンにレプリケーションしているので、グローバルテーブルが作成されている。

ポイントインタイムリカバリ (PITR)はプライマリ(東京)では有効でセカンダリ(大阪)では無効になっていた。

Step Functions

全部で4つのStep FunctionsのState Machineが作成されていた。

  • ImportWorkflow-XXX
  • ExportWorkflow-XXX
  • StackSetCheckStatusWorkflow-XXX
  • SecondaryUserPoolTableStepFunctions-XXX

デプロイ後すぐに一度だけ実行されているよう。

Graph View

ExportのState Machine。気が遠くなるようなステップ数、、。

Importも同様。ただ実行はされていない。

Event Bridge

この3つのルールが作成されたもの?
上から1つ目のルールがExport job起動のトリガー。デフォルトで1日1回実行する設定になっている。
時間指定したい場合は設定変更が必要。

SNS

Job実行結果の通知用SNSトピックが作成されていた。
Subscriptionの承認をしてメールが届くようになっている。

S3

バックアップのImport Job実行時にCSVを一時的に出力するS3バケットが、東京と大阪両方のリージョンに作成されていた。
Job実行時のログ用?のバケットもあった。

Export実行

まず、Export対象のアカウントを作成する。
今回はCSV Import機能を使って1万件のアカウント情報をCognitoに作成する。
10分くらいでImport Job完了。

Export実行前のDynamoDB。アカウント情報は1件のみ。

Export Job(Step Functions)を手動実行。

3分で実行完了した。ドキュメント上の記載では5分弱だったのでそこまで齟齬は無さそう。

メールで通知も届いた。

AWS CLIで対象のDynamoDBテーブルの件数を検索。
10000件追加されている。残り1件は実行ログ?

$ aws dynamodb scan --table-name cognito-export-import-BackupTable --select "COUNT"
{
    "Count": 10001,
    "ScannedCount": 10001,
    "ConsumedCapacity": null
}

まとめ

前編は以上です。
ボタンを数回押しただけでCognitoユーザープールのバックアップ・リストアのアーキテクチャができるのは便利だなと思いました。

一方で制限事項が多かったリ、内部でやっている処理が多く理解しきれないことがあるので使いどころはよく検討する必要がありそうです。

次回後編はリストアを試してみます。

参考

https://aws.amazon.com/jp/solutions/implementations/cognito-user-profiles-export-reference-architecture/
https://aws.amazon.com/jp/builders-flash/202302/cognito-user-prof-export-ref-architecture/?awsf.filter-name=*all
https://github.com/aws-solutions/cognito-user-profiles-export-reference-architecture

Discussion