この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので十分ご注意ください。
背景
自社で検証環境でCognitoを作成し、動作確認を行う場合があります。
今までAWSコンソール上でユーザプールを作成し、ユーザを作成する流れになっていました。検証した後、手動で削除する必要があります。
前回、1個のテンプレートでユーザプールとユーザをまとめて作成してみましたが、
今回、CognitoユーザプールとCognitoユーザを2個のテンプレートで作成してみましたので、テンプレートを共有します。これで複数のユーザを作成する場合、お役に立てればと思います。
前回の記事
CloudFormationでCognitoユーザを作成し、SecretsManagerで生成したパスワードを利用してCONFIRMEDにしてみました。
テンプレート
Cognitoユーザプールのテンプレート
CognitoUserPool.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "Cognito User Pool."
Resources:
UserPool:
Type: "AWS::Cognito::UserPool"
Properties:
Policies:
PasswordPolicy:
MinimumLength: 8
RequireUppercase: true
RequireLowercase: true
RequireNumbers: true
RequireSymbols: true
UserPoolName: CpiDev3-Cognito-UserPool-Test1
MfaConfiguration: 'OFF'
AdminCreateUserConfig:
AllowAdminCreateUserOnly: true
UnusedAccountValidityDays: 7
UserPoolClient:
Type: "AWS::Cognito::UserPoolClient"
Properties:
ExplicitAuthFlows:
- ALLOW_ADMIN_USER_PASSWORD_AUTH
- ALLOW_CUSTOM_AUTH
- ALLOW_USER_PASSWORD_AUTH
- ALLOW_USER_SRP_AUTH
- ALLOW_REFRESH_TOKEN_AUTH
UserPoolId:
Ref: UserPool
ClientName: CpiDev3-Cognito-UserPool-Test1-AppClient
RefreshTokenValidity: 30
Outputs:
UserPoolClientId:
Description: The UserPoolClient Id
Value: !Ref UserPoolClient
Export:
Name: "CpiDev3-Cognito-UserPool-Test1-AppClient"
UserPoolId:
Description: The UserPool Id
Value: !Ref UserPool
Export:
Name: "CpiDev3-Cognito-UserPool-Test1-UserPool"
Cognitoユーザのテンプレート
CognitoUser.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "Cognito User."
Parameters:
SystemId:
Type: String
Description: >-
Your System Id. For example:CpiDev3
ConstraintDescription: System Id is required
Default: ''
CognitoUserName:
Type: String
Description: >-
Your Cognito User Name. For example:CpiDev3CognitoTestUser
ConstraintDescription: System Id is required
Default: ''
Resources:
CreateSecret:
Type: AWS::SecretsManager::Secret
Properties:
Name:
!Join
- ''
- - 'secret-'
- !Ref SystemId
- '-'
- !Ref CognitoUserName
GenerateSecretString:
PasswordLength: 8
ExcludeCharacters: '#$%&()*+,-./:;<=>?@[\]^`{|}~"'
AdminCreateCognitoUser:
Type: Custom::CustomResource
Properties:
ServiceToken: !GetAtt CognitoAdminCreateUserFunction.Arn
CognitoAdminCreateUserFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName:
!Join
- ''
- - 'lmd-'
- !Ref SystemId
- '-'
- !Ref CognitoUserName
- '-CreateCognitoUser-1'
Handler: index.handler
Environment:
Variables:
UserPoolId :
!ImportValue CpiDev3-Cognito-UserPool-Test1-UserPool
UserPoolClientId :
!ImportValue CpiDev3-Cognito-UserPool-Test1-AppClient
SecretName: !Ref CreateSecret
UserName: !Ref CognitoUserName
Role: !GetAtt CognitoAdminCreateUserFunctionRole.Arn
Code:
ZipFile: !Sub |
import cfnresponse
import boto3
import os
def handler(event, context):
print(event['RequestType'])
client_id = os.getenv('UserPoolClientId')
print(f'client_id: {client_id}')
user_pool_id = os.getenv('UserPoolId')
print(f'user_pool_id: {user_pool_id}')
secret_name = os.getenv('SecretName')
print(f'secret_name: {secret_name}')
cognito_idp = boto3.client('cognito-idp')
# ユーザー名を取得する
username = os.getenv('UserName')
print(f'username: {username}')
# パスワードを取得する
password = get_secret(secret_name)
# print(f'password: {password}')
# スタック削除時にユーザーを削除します。
response_data = {}
if event['RequestType'] == 'Delete':
response_data = cognito_idp.admin_delete_user(
UserPoolId=user_pool_id,
Username=username
)
cfnresponse.send(event, context, cfnresponse.SUCCESS,
{'Response': 'Success','CognitoUserName': username})
return
print(response_data)
# ユーザーを作成する
response_data = {}
try:
response_data = cognito_idp.admin_create_user(
UserPoolId=user_pool_id,
Username=username,
TemporaryPassword=password,
MessageAction='SUPPRESS'
)
print('admin_create_user')
print(response_data)
# ログインを試みる。(パスワードの変更を要求される。)
response_data = cognito_idp.admin_initiate_auth(
UserPoolId=user_pool_id,
ClientId=client_id,
AuthFlow='ADMIN_NO_SRP_AUTH',
AuthParameters={'USERNAME': username, 'PASSWORD': password},
)
print('admin_initiate_auth')
print(response_data)
session = response_data['Session']
# パスワードを変更する。
response_data = cognito_idp.admin_respond_to_auth_challenge(
UserPoolId=user_pool_id,
ClientId=client_id,
ChallengeName='NEW_PASSWORD_REQUIRED',
ChallengeResponses={'USERNAME': username, 'NEW_PASSWORD': password},
Session=session
)
print('admin_respond_to_auth_challenge')
print(response_data)
except Exception as e:
print("error: " + str(e))
response_data = {'error': str(e)}
cfnresponse.send(event, context, cfnresponse.FAILED,
{'Response': 'FAILED'})
return
print(response_data)
cfnresponse.send(event, context, cfnresponse.SUCCESS,
{'Response': 'Success','CognitoUserName': username})
def get_secret(secret_name):
"""SecretsManagerから情報を取得する"""
try:
rt = None
region_name = "ap-northeast-1"
# Create a Secrets Manager client
client = boto3.client(
service_name='secretsmanager',
region_name=region_name
)
get_secret_value_response = client.get_secret_value(
SecretId=secret_name
)
if 'SecretString' in get_secret_value_response:
rt = get_secret_value_response['SecretString']
except Exception:
print ('[ConfiRule_Notification] get secret exception error.')
rt=None
return rt
Runtime: python3.9
CognitoAdminCreateUserFunctionRole:
Type: AWS::IAM::Role
Properties:
RoleName:
!Join
- ''
- - 'irl-'
- !Ref SystemId
- '-'
- !Ref CognitoUserName
- '-CreateCognitoUser-1'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
Policies:
- PolicyName: root
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: "arn:aws:logs:*:*:*"
- Effect: Allow
Action:
- cognito-idp:*
Resource: "arn:aws:cognito-idp:*:*:userpool/*"
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
Resource: "arn:aws:secretsmanager:*:*:*"
スタック間のデータ連携
ExportとImportValueを使ってスタック間のパラメータ出力と参照を実装
Export
Cognitoユーザプールのテンプレートから抜粋
構築時のCloudFormation画面が下記のように表示されます。
ImportValue
Cognitoユーザのテンプレートから抜粋
まとめ
今回、CognitoユーザプールとCognitoユーザを2個のテンプレートで作成してみました。ユーザの作成と削除に問題がないですが、ユーザ名の変更に対応していないので、変更したい場合、スタックを削除してから、新規作成でお願いいたします。
以上です。
お役に立てれば幸いです。
参考
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/walkthrough-crossstackref.html