CloudFormationを用いてCognitoのユーザープール・グループ・ユーザーを作成する

#1. はじめに
　以前に、[Amplyfyを用いてReactにログイン画面を作成してみた](https://qiita.com/N_H_tennis/items/9f52ed033e4bef379366)という記事を出しました。当時は言われるがままにAmplifyを用いてcognitoのユーザープールを作成していたのですが、結局これってAmplifyを通してCloudFormationを動かしていただけに過ぎない、ということに気づいてしまいました。
　最近、cloudformationにも慣れてきたところですし、改めてcloudformationを用いてcognitoのユーザープールを作成してみました。ついでに、そのユーザープール内にグループとユーザーの登録も行ってみましたのでその忘備録とします。
（当初の目的はパスワードを指定した状態でのユーザー一括登録だったのですが、それはcloudformationでは不可でした。結局lambdaでやっちゃいました。）

#2. 各種仕様
###ユーザープール
・ユーザープール名：UserPoolTest
・サインインオプションのユーザー名入力で大文字と小文字を区別するかどうか：区別する
・以下のアカウント属性を必須とする：name
・下記のカスタム属性を追加：customAttribute
・パスワードの強度：最小８文字、数字・特殊文字・大文字・小文字を含む
・ユーザーの自己サインアップの許可：許可しない
・管理者が設定した一時パスワードの有効期限：９０日
・ユーザーはどのようにアカウントを回復させるか：管理者のみが回復できる

###ユーザープールのアプリクライアント
・アプリクライアントの名前：ClientTest
・各種トークンの有効期限：リフレッシュトークン→30日、アクセストークン→30分、IDトークン→30分
・クライアントシークセットの生成：生成する
・認証フローの設定：ALLOW_USER_PASSWORD_AUTH, ALLOW_REFRESH_TOKEN_AUTH

###グループ
・グループ名：TestGroup
・優先順位：０

###ユーザー
・ユーザー名：UserName
・name属性：UserName
・customAttribute属性：userAttribute
・所属グループ：TestGroup

　以上が設定する項目になります。特に記述がない箇所はデフォルトの設定で作成していきます。それではテンプレートファイルに各種リソースを記述していきます。
#3. テンプレートファイル
　以下にテンプレートファイルとその細かい設定を記述しました。説明が若干雑になりましたが、見逃してください。他の設定をいじりたい方、詳しく知りたい方は[こちらの公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpool.html)をご覧ください。

```yaml
AWSTemplateFormatVersion: 2010-09-09
Resources:
###ユーザープール
  CognitoUserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: UserPoolTest #ユーザープール名の設定
      UsernameConfiguration: #サインインオプションのユーザー名入力で大文字、小文字を区別するかどうか
        CaseSensitive: true
      Schema: #アカウント属性の追加
        - Name: name #name属性を必須とする設定
          AttributeDataType: String
          Required: true
        - Name: customAttribute #カスタム属性：customAttributeの追加（必須は不可）
          AttributeDataType: String
      Policies: #パスワードポリシーの設定
        PasswordPolicy:
          MinimumLength: 8
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: true
          RequireUppercase: true
          TemporaryPasswordValidityDays: 90
      AdminCreateUserConfig: #ユーザー自己サインアップの設定
        AllowAdminCreateUserOnly: true
      AccountRecoverySetting: #アカウントの回復の設定
        RecoveryMechanisms:
          - Name: admin_only
            Priority: 1

###ユーザープールのアプリクライアント
  UserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      ClientName: ClientTest #アプリクライアントの名前
      GenerateSecret: true #クライアントシークレットを生成するかどうか
      TokenValidityUnits: #トークンの有効期限の単位
        AccessToken: minutes
        IdToken: minutes
        RefreshToken: days
      AccessTokenValidity: 720 #各種トークンの有効期限
      IdTokenValidity: 720
      RefreshTokenValidity: 30
      ExplicitAuthFlows: #認証フローの設定
        - ALLOW_USER_PASSWORD_AUTH
        - ALLOW_REFRESH_TOKEN_AUTH
      UserPoolId: #ユーザープールとの紐づけ
        Ref: CognitoUserPool

###グループの作成
  TestGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties:
      GroupName: TestGroup #グループ名
      UserPoolId: #ユーザープールとの紐づけ
        Ref: CognitoUserPool
      Precedence: 0 #グループの優先順位

###ユーザーの作成
  UserPoolUser:
    Type: AWS::Cognito::UserPoolUser
    Properties:
      Username: UserName #ユーザー名
      UserAttributes: #ユーザーの属性の設定
        - Name: name
          Value: userName
        - Name: custom:customAttribute
          Value: userAttribute
      UserPoolId: #ユーザープールとの紐づけ
        Ref: CognitoUserPool

###ユーザーとグループとの紐づけ
  UserGroupAttach:
    Type: AWS::Cognito::UserPoolUserToGroupAttachment
    Properties:
      GroupName: #紐づけるグループ
        Ref: TestGroup
      Username: #紐づけるユーザー
        Ref: UserPoolUser
      UserPoolId: #ユーザープールとの紐づけ
        Ref: CognitoUserPool
    DependsOn: #TestGroup, UserPoolUser作成後にUserGroupAttachを作成するように記述
      - TestGroup
      - UserPoolUser
```

#4. おわりに
　いかがだったでしょうか。上記のテンプレートファイルを実行すれば、ユーザープールとそれに付随する機能を作成することができます。ただ、ユーザーの登録は初期パスワードの送付がありますので、属性にメールアドレスか電話番号を追加したいところです。
　ここまでご精読ありがとうございました。