CloudFormationで定義したAPI GatewayでAuthorizerにCognitoを設定する

# CloudFormationでAPI Gatewayを定義する

swaggerで定義したり、SAMを使ってスタイリッシュに書いたりする方法があるのでApiGatewayリソースをがっつり書くケースは少ないかもしれない。
しかし、少し凝ったことをしようとすると（それが本当に必要かどうかの議論は置いておくとして）AWS::ApiGateway::XXXというリソース群を大量に定義する必要がある。
~~ぶっちゃけコンソールでやった方が早~~


こんなかんじのやつを書く。

```yaml

Resources:
  RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: !Ref restApiName
  Method:
    Type: AWS::ApiGateway::Method
    Properties:
      HttpMethod: POST
      ResourceId: !GetAtt RestApi.RootResourceId
      RestApiId: !Ref RestApi
      AuthorizationType: NONE
      Integration:
        Type: MOCK
        ContentHandling: !Ref contentHandling
        IntegrationResponses:
          - ContentHandling: !Ref contentHandling
            StatusCode: 400
      RequestValidatorId: !Ref RequestValidator
      OperationName: !Ref operationName
  RequestValidator:
    Type: AWS::ApiGateway::RequestValidator
    Properties:
      Name: !Ref validatorName
      RestApiId: !Ref RestApi
      ValidateRequestBody: !Ref validateRequestBody
      ValidateRequestParameters: !Ref validateRequestParameters

```

# Authorizerを定義したい

CognitoのAuthorizerを下記のように定義する。

```yaml

Resources:
  RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: !Ref restApiName
  Authorizer: 
    Type: AWS::ApiGateway::Authorizer
    Properties: 
      ProviderARNs: 
        - !GetAtt userPool.Arn
      AuthorizerResultTtlInSeconds: "300"
      Type: "COGNITO_USER_POOLS"
      IdentitySource: "method.request.header.Auth"
      Name: "DefaultAuthorizer"
      RestApiId: 
        Ref: "RestApi"

```

# API GatewayのMethodを定義する

Authorizerを使用するメソッドに**AuthorizerId**と**AuthorizationType**を定義していく。

> **AuthorizerId**
If you specify this property, specify CUSTOM for the AuthorizationType property.
(このプロパティを指定した場合、CUSTOM プロパティには AuthorizationType を指定します。)

> **AuthorizationType**
If you specify the AuthorizerId property, specify CUSTOM for this property.
(AuthorizerId プロパティを指定した場合、このプロパティには CUSTOM を指定します。)

ドキュメントに記載されている通り、AuthorizerIdに先程設定したAuthorizerをRefで指定、AuthorizationTypeに"CUSTOM"を指定する。

```yaml

Resources:
  Method:
    Type: AWS::ApiGateway::Method
    Properties:
      HttpMethod: POST
      ResourceId: !GetAtt RestApi.RootResourceId
      RestApiId: !Ref RestApi
      AuthorizerId: !Ref Authorizer
      AuthorizationType: CUSTOM
      Integration:
        Type: MOCK
        ContentHandling: !Ref contentHandling
        IntegrationResponses:
          - ContentHandling: !Ref contentHandling
            StatusCode: 400
      RequestValidatorId: !Ref RequestValidator
      OperationName: !Ref operationName

```


しかしこれはエラーになるのでビルドされない・・・。

# 解決： AuthorizationTypeをCOGNITO_USER_POOLSにする

AuthorizerはCognitoなので、AuthorizationTypeも素直にCOGNITO_USER_POOLSにしよう。


```yaml

Resources:
  Method:
    Type: AWS::ApiGateway::Method
    Properties:
      HttpMethod: POST
      ResourceId: !GetAtt RestApi.RootResourceId
      RestApiId: !Ref RestApi
      AuthorizerId: !Ref Authorizer
      AuthorizationType: COGNITO_USER_POOLS # CUSTOM→ COGNITO_USER_POOLSに変更
      Integration:
        Type: MOCK
        ContentHandling: !Ref contentHandling
        IntegrationResponses:
          - ContentHandling: !Ref contentHandling
            StatusCode: 400
      RequestValidatorId: !Ref RequestValidator
      OperationName: !Ref operationName

```

これで無事にビルドが通るようになりました！


### ドキュメントに一言でいいから書いておいてほしかったな〜〜〜


まぁ、言葉の綾と言えばそうなんですけどね！！！


---

参考：[AWS::ApiGateway::Method](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-method.html#cfn-apigateway-method-authorizationtype) ほかAWSドキュメント