AWS CDKでCognitoのIdentity Poolを作る

:::note warn
Cognito Identity PoolのL2コンストラクトが利用可能になったため、今はそちらを使う方が便利でしょう。
[Amazon Cognito Identity Pool Construct Library
](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cognito-identitypool-alpha-readme.html)
この記事は参考情報として残しておきます。
:::



## 概要
AWS CDKでCognitoのIdentity Poolを作成する方法をまとめる。

CDK v1.72.0現在では、IdentityPoolにはL1 Constructしかないため使いづらい。
今回は、独自のL2 Constructを定義し、AWSマネジメントコンソール相当の設定を自動でしてくれる状態を目指す。


## Constructの定義
まず、作成したL2 Constructのコードを示す。

```identity_pool.ts
import * as cdk from '@aws-cdk/core';
import * as iam from '@aws-cdk/aws-iam';
import * as cognito from '@aws-cdk/aws-cognito';

export interface IdentityPoolProps extends cognito.CfnIdentityPoolProps {
    authenticatedPolicyDocument?: iam.PolicyDocument,
    unauthenticatedPolicyDocument?: iam.PolicyDocument,
}

export class IdentityPool extends cdk.Construct {
    readonly pool: cognito.CfnIdentityPool;

    constructor(scope: cdk.Construct, id: string, props: IdentityPoolProps) {
        super(scope, id);

        const authenticatedPolicyDocument = props.authenticatedPolicyDocument ?? new iam.PolicyDocument({
            statements: [
                new iam.PolicyStatement({
                    effect: iam.Effect.ALLOW,
                    actions: [
                        "cognito-sync:*",
                        "cognito-identity:*"
                    ],
                    resources: ["*"],
                })
            ]
        });

        const unauthenticatedPolicyDocument = props.unauthenticatedPolicyDocument ?? new iam.PolicyDocument({
            statements: [
                new iam.PolicyStatement({
                    effect: iam.Effect.ALLOW,
                    actions: [
                        "cognito-sync:*",
                    ],
                    resources: ["*"],
                })
            ]
        });

        const identityPool = new cognito.CfnIdentityPool(this, 'identityPool', {
            ...props,
            allowUnauthenticatedIdentities: props.allowUnauthenticatedIdentities,
        })

        const authenticatedRole = new iam.Role(this, 'authRole', {
            assumedBy:
                new iam.FederatedPrincipal("cognito-identity.amazonaws.com", {
                    "StringEquals": { "cognito-identity.amazonaws.com:aud": identityPool.ref },
                    "ForAnyValue:StringLike": { "cognito-identity.amazonaws.com:amr": "authenticated" },
                }),
            inlinePolicies: { 'policy': authenticatedPolicyDocument },
        });

        const unauthenticatedRole = new iam.Role(this, 'unauthRole', {
            assumedBy:
                new iam.FederatedPrincipal("cognito-identity.amazonaws.com", {
                    "StringEquals": { "cognito-identity.amazonaws.com:aud": identityPool.ref },
                    "ForAnyValue:StringLike": { "cognito-identity.amazonaws.com:amr": "unauthenticated" },
                }),
            inlinePolicies: { 'policy': unauthenticatedPolicyDocument },
            });

        new cognito.CfnIdentityPoolRoleAttachment(this, 'roleAttachment', {
            identityPoolId: identityPool.ref,
            roles: {
                "authenticated": authenticatedRole.roleArn,
                "unauthenticated": unauthenticatedRole.roleArn,
            }
        })
    }
}
```

`IdentityPool` というConstructには、IdentityPool自体とそれに必要なRoleの設定が含まれる。

RoleのPolicyは、マネジメントコンソールで作成したものと同様のポリシーがデフォルトで付与される。
また、Contructの引数で指定することもできる。


## 使い方
Stackからは下記のように呼び出す。
L1 Constructと同じで `allowUnauthenticatedIdentities` の指定は必要なことに注意。

```cognito-stack.ts
import * as cdk from '@aws-cdk/core';
import { IdentityPool } from './identity-pool';

export class CognitoStack extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        const identityPool = new IdentityPool(this, 'identityPool', {
            allowUnauthenticatedIdentities: true,
        })
    }
}
```