動機
以前書いた記事で、NextAuthの検証のためにCognitoのユーザープールを作成していた。が、その時は手動で作成しており、色々と面倒だと感じていた。
そこで、cdkを使ってIaC的に、また、試行錯誤しやすい形で作ろうという動機で調査を行った。
前提条件
- 検証環境:
- Ubuntu 22.04LTS(AMD64)
- cdk: version 2.34.2(新しいv2系を使用)
- TypeScriptで記述
- nodejs: v16.16.0
- AWS環境: リージョンはap-northeast-1を使用
検証
プロジェクト作成
詳細はAWSのDeveloper Guideを参照のこと。
Getting Startの部分にTypeScriptでのプロジェクトの立ち上げ方の例がある。
今回だと、確か
mkdir test-app && cd test-app
cdk init app --language typescript
のような感じで立ち上げている。
処理の記述
bin/test-app.ts
(※test-app
部分は、以降も同様だが作成環境次第で変化する)については、例えば以下のような感じ:
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { TestAppStack } from '../lib/test-app-stack';
const app = new cdk.App();
new TestAppStack(app, 'TestCognitoAppStack', {
});
- Stack作成クラスコンストラクタの第2引数はスタック名を指しており、
今回だと、CloudFormationの画面からTestCognitoAppStack
というスタックが作成されることが確認できる。
(↑実際には後の手順でcdk deploy
した後に作成される)
一番肝心なcognitoのリソースを作成する部分はlib/test-app-stack.ts
で記述している。
作り方にはバリエーションがあるが、以前書いた記事に適用できるようにする(NextAuthと連携できるようにする)例としては、
- OpenID Connectに対応する
- アプリクライアントを作成する
- アプリクライアントのシークレットを設定する
- ドメインを設定し、ホストされたUIを使えるようにする
あたりの設定を行う必要がある。(この辺はユースケースに応じて、API referenceを参考に適宜設定・調整すれば良い)
とりあえず今回のケースでは以下のような感じでstack用のコードを作成した。
import {
Duration,
Stack,
StackProps,
aws_cognito as cognito,
} from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class TestAppStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const pool = new cognito.UserPool(this, 'Pool');
pool.addClient('app-client', {
oAuth: {
flows: {
authorizationCodeGrant: true,
},
scopes: [cognito.OAuthScope.OPENID],
callbackUrls: ['http://localhost:3000/api/auth/callback/cognito'], // TMP ローカル開発時においてNextAuthと連携するためのTemporaryな設定
},
generateSecret: true,
refreshTokenValidity: Duration.hours(12), // トークンの有効期限を12hにしている(デフォルト: 30日)
});
pool.addDomain('CognitoDomain', {
cognitoDomain: {
domainPrefix: 'custom-domain-prefix-xxxxxx', // TMP 実際はパラメータストアから値を読み出すなど動的に設定できるようにする
},
});
}
}
なお、ちゃんとした形で作成する際は少なくとも以下2点は直す必要がある:
-
callbackUrls
:localhost:3000
を含んでおり、ローカルで開発・検証をしているときしか現状では動かないようになっているので、実行環境に合わせて要修正・追加 - ドメインの
domainPrefix
に関して、上記のコードだとハードコードしている感じになっているが、実際はパラメータストアから値を読むなどして動的に設定出来る工夫が必要だと考えられる:- ハードコードしていると、ドメイン名が既に作成済みのものと衝突し、作成に失敗して困るケースが考えられる。
- 特に、Pipelinesの複数ステージや、あるいは複数アカウントなどで共通して使おうとすると確実に衝突が起きると思われる。
デプロイ
npm ci # npmをパッケージマネージャーに使う場合
cdk synth
cdk deploy --profile <使用するプロファイル名>
のようにしてスタックの作成とデプロイが出来る
作成例について、主要なものを抜粋
以前書いた記事で作ったユーザープールと全く設定という訳ではないが、このくらいまで設定しておくと同じような形で使うことが出来る。
あとはユースケースに応じて適宜調整して再度cdk deploy
すれば、設定の変更や他のケースへの対応が出来る。
NextAuthなどでの実行例は以前書いた記事と同じなので省略。
クリーンアップ
例えば
cdk destroy --all --profile <プロファイル名>
で消せる。
が、Stackが削除されてもユーザープールは残る様子?なのでこれは手動で消さないと行けないかもしれない。
(なお、アプリクライアントやドメインは消える)
感想
(細かい設定をしなければ)思ったよりも少ない行数で記述出来たので便利
また、cdkは全般的に公式リファレンスの例が充実している印象で、典型的なケースではexampleのコピペ+αでもそこそこ作れそうな感じで良い。