Amazon Cognito User Pools にカスタムドメインを設定する場合,内部的に追加される Amazon CloudFront で「バージニア北部リージョン (us-east-1)」の AWS Certificate Manager (ACM) 証明書が必要になる📝
しかし AWS CDK(もしくは AWS CloudFormation)ではクロスリージョンスタックリファレンス(リージョン間のクロススタックリファレンス)ができず,実装するときに AWS Systems Manager Parameter Store を使ったり,Props に静的に ARN (Amazon Resource Names) を設定したり,何かしら考慮が必要になるという課題がある.
ちなみに Amazon Cognito User Pools のカスタムドメインに限った話ではなく,例えば Amazon CloudFront と Amazon S3 を組み合わせる場合にも出てくる仕様になる.
実際に試すと以下のエラーが出る🔥
Cross stack references are only supported for stacks deployed to the same environment or between nested stacks and their parent stack.
crossRegionReferences
プロパティ
現在まだ実験的機能 (experimental) ではあるけど,AWS CDK の crossRegionReferences
プロパティを使うとイイ感じにクロスリージョンスタックリファレンス(リージョン間のクロススタックリファレンス)を実現できる👌
仕組みをザックリと説明すると,AWS CloudFormation のカスタムリソース (AWS Lambda 関数) で us-east-1 リージョンの AWS Certificate Manager 証明書 ARN を ap-northeast-1 リージョンの AWS Systems Manager Parameter Store に登録して,ap-northeast-1 リージョンの AWS CloudFormation スタックでは AWS Systems Manager Parameter Store の動的参照を使って AWS Certificate Manager 証明書 ARN を取得する.ザックリではあるけどアーキテクチャ図も描いておいた❗️
詳細な仕組みは AWS CDK ドキュメントを参照してもらえればと📝
サンプルコード
動作確認に使ったサンプルコードを載せておく👌
👾 bin/cdk.ts
ここで crossRegionReferences
プロパティを設定している❗️そして AWS Certificate Manager 証明書 ARN を CognitoCustomDomainStack に渡している.
const envVirginia = { account: '000000000000', region: 'us-east-1', } const envTokyo = { account: '000000000000', region: 'ap-northeast-1', } const cognitoCustomDomainAcmStack = new CognitoCustomDomainAcmStack(app, 'CognitoCustomDomainAcmStack', { env: envVirginia, crossRegionReferences: true, }) new CognitoCustomDomainStack(app, 'CognitoCustomDomainStack', { env: envTokyo, crossRegionReferences: true, certificate: cognitoCustomDomainAcmStack.certificate, })
👾 cognito-custom-domain-acm.ts
AWS Certificate Manager 証明書を作ってクロススタックで取得できるようにしておく.今回は userpool.xxxxx.net
というカスタムドメインにした📝
import { Stack, StackProps, aws_certificatemanager, aws_route53, } from 'aws-cdk-lib' import { Construct } from 'constructs' export class CognitoCustomDomainAcmStack extends Stack { public readonly certificate: aws_certificatemanager.Certificate constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props) const hostedZone = aws_route53.HostedZone.fromHostedZoneAttributes(this, 'HostedZone', { hostedZoneId: 'XXXXX', zoneName: 'xxxxx.net', }) this.certificate = new aws_certificatemanager.Certificate(this, 'Certificate', { domainName: 'userpool.xxxxx.net', validation: aws_certificatemanager.CertificateValidation.fromDns(hostedZone), }) } }
👾 cognito-custom-domain.ts
AWS Certificate Manager 証明書を ARN を StackProps から取得して,Amazon Cognito User Pools のカスタムドメインに設定する👌
import { Stack, StackProps, aws_certificatemanager, aws_cognito, aws_route53, aws_route53_targets, } from 'aws-cdk-lib' import { Construct } from 'constructs' interface CustomStackProps extends StackProps { certificate: aws_certificatemanager.Certificate } export class CognitoCustomDomainStack extends Stack { constructor(scope: Construct, id: string, props: CustomStackProps) { super(scope, id, props) const userPool = new aws_cognito.UserPool(this, 'UserPool', { userPoolName: 'sandbox', }) const userPoolDomain = userPool.addDomain('UserPoolDomain', { customDomain: { domainName: 'userpool.xxxxx.net', certificate: props.certificate, }, }) const hostedZone = aws_route53.HostedZone.fromHostedZoneAttributes(this, 'HostedZone', { hostedZoneId: 'XXXXX', zoneName: 'xxxxx.net', }) new aws_route53.ARecord(this, 'ApexARecod', { zone: hostedZone, target: aws_route53.RecordTarget.fromIpAddresses('8.8.8.8'), }) new aws_route53.ARecord(this, 'UserPoolARecord', { zone: hostedZone, recordName: 'userpool', target: aws_route53.RecordTarget.fromAlias(new aws_route53_targets.UserPoolDomainTarget(userPoolDomain)), }) } }
デプロイ確認
実際にデプロイした結果(既にリソースは削除済)を抜粋して載せておく👌
👇️ us-east-1 リージョンに AWS Certificate Manager 証明書を登録できた
👇️ ap-northeast-1 リージョンの AWS Systems Manager Parameter Store に AWS Certificate Manager 証明書 ARN が登録されていた
👇️ ap-northeast-1 リージョンの Amazon Cognito User Pools に us-east-1 リージョンの AWS Certificate Manager 証明書が登録されていた
まとめ
AWS CDK の crossRegionReferences
プロパティを使って,Amazon Cognito User Pools にカスタムドメインを設定してみた.イイ感じにクロスリージョンスタックリファレンス(リージョン間のクロススタックリファレンス)を実現できて便利だった❗️
しかし現状ではまだ「実験的機能 (experimental)」でプロダクション環境では採用しにくく,最近似たような構成を仕事で実装したときは crossRegionReferences
プロパティは使わずに独自に実装をした.正式リリースを待つぞー \( 'ω')/
参考リンク
AWS CloudFormation のカスタムリソース実装は以下にある🔗