LoginSignup
19
6

More than 5 years have passed since last update.

AWS SAMでAPIキーと使用量プランのリソース作成に失敗する場合の対処方法

Last updated at Posted at 2018-03-16

エラーの内容

AWS SAM で AWS::Serverless::Api リソースと AWS::ApiGateway::ApiKey および AWS::ApiGateway::UsagePlan
リソースを同じテンプレート内で指定し、デプロイすると以下のエラーで作成に失敗しました。
以下はCloudFormationのコンソールに出力されるエラーメッセージです。

Invalid stage identifier specified              # API キーの CREATE_FAILED
API Stage not found: <APIの物理ID>:<ステージ名>   # 使用量プランの CREATE_FAILED

原因としては、AWS::Serverless::Api リソースで APIステージのデプロイが行われる前に
AWS::ApiGateway::ApiKey および AWS::ApiGateway::UsagePlan リソースによる使用量プランの
作成がはじまってしまい、ステージの指定に問題があるというエラーになっているようです。

どう対処したか

ワークアラウンドとして、DependsOn プロパティに デプロイメントステージの論理IPを追記したところ
CloudFormation のデプロイが正常終了しました。
この論理IDは テンプレート内で明示的に作成していませんが、AWS::Serverless::Api リソースによって
作成されるため、

  • <APIの論理ID>Stage

という形式で指定します。

エラーがでるテンプレート例

CFn_sample_NG.yaml
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: Sample API

Parameters:
  EnvType:
    Description: Type of API Gateway stage.
    Default: dev
    Type: String
    AllowedValues:
      - dev
      - stg
      - prd
    ConstraintDescription: must specify dev or stg or prd.

  ProjectName:
    Description: Project name.
    Default: samplepj
    Type: String
    MinLength: "3"
    MaxLength: "10"
    AllowedPattern: "[a-zA-Z0-9]*"
    ConstraintDescription: must specify Project name.

Resources:
# Create API Gateway from swagger
  Api:
    Type: AWS::Serverless::Api
    Properties:
      DefinitionUri: ./templates/swagger-apigateway.yaml
      StageName: !Ref EnvType

# Create API Key
  ApiKey:
    Type: AWS::ApiGateway::ApiKey
    DependsOn: 
      - Api
    Properties:
      Enabled: "true"
      StageKeys:
        - RestApiId: !Ref Api
          StageName: !Ref EnvType
      Name: !Join
        - '-'
        - - !Ref EnvType
          - !Ref ProjectName
          - 'apikey'

# Create API Usage Plan
  ApiUsagePlan:
    Type: AWS::ApiGateway::UsagePlan
    DependsOn: 
      - Api
    Properties:
      ApiStages:
        - ApiId: !Ref Api
          Stage: !Ref EnvType
      UsagePlanName: !Join
        - '-'
        - - !Ref EnvType
          - !Ref ProjectName
          - 'usageplan'

# Link API Key and Usage Plan
  ApiUsagePlanKey:
    Type: AWS::ApiGateway::UsagePlanKey
    DependsOn:
      - ApiKey
      - ApiUsagePlan
    Properties : 
      KeyId: !Ref ApiKey
      KeyType: API_KEY
      UsagePlanId: !Ref ApiUsagePlan

上記のテンプレートを package 後、deploy すると ApiUsagePlan と ApiKey の作成に失敗します。

image.png

正常終了するテンプレート例

CFn_sample_OK.yaml
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: Sample API

Parameters:
  EnvType:
    Description: Type of API Gateway stage.
    Default: dev
    Type: String
    AllowedValues:
      - dev
      - stg
      - prd
    ConstraintDescription: must specify dev or stg or prd.

  ProjectName:
    Description: Project name.
    Default: samplepj
    Type: String
    MinLength: "3"
    MaxLength: "10"
    AllowedPattern: "[a-zA-Z0-9]*"
    ConstraintDescription: must specify Project name.

Resources:
# Create API Gateway from swagger
  Api:
    Type: AWS::Serverless::Api
    Properties:
      DefinitionUri: ./templates/swagger-apigateway.yaml
      StageName: !Ref EnvType

# Create API Key
  ApiKey:
    Type: AWS::ApiGateway::ApiKey
    DependsOn: 
      - Api
      - ApiStage # ★追記
    Properties:
      Enabled: "true"
      StageKeys:
        - RestApiId: !Ref Api
          StageName: !Ref EnvType
      Name: !Join
        - '-'
        - - !Ref EnvType
          - !Ref ProjectName
          - 'apikey'

# Create API Usage Plan
  ApiUsagePlan:
    Type: AWS::ApiGateway::UsagePlan
    DependsOn: 
      - Api
      - ApiStage # ★追記
    Properties:
      ApiStages:
        - ApiId: !Ref Api
          Stage: !Ref EnvType
      UsagePlanName: !Join
        - '-'
        - - !Ref EnvType
          - !Ref ProjectName
          - 'usageplan'

# Link API Key and Usage Plan
  ApiUsagePlanKey:
    Type: AWS::ApiGateway::UsagePlanKey
    DependsOn:
      - ApiKey
      - ApiUsagePlan
    Properties : 
      KeyId: !Ref ApiKey
      KeyType: API_KEY
      UsagePlanId: !Ref ApiUsagePlan

ApiUsagePlan と ApiKey の DependsOn プロパティに <APIの論理ID>Stage を追記します。
今回 API の論理ID をそのまま Api としているので、ステージの論理IDは ApiStage です。
ステージのデプロイメントが先に行われ、使用量プランとAPIキーの作成にも成功しました。

image.png

補足

AWS SAM 1.4.0 の リリースノート によれば 以下のように Refなどの組み込み関数でAPI Gateway Stage
とAPI Gateway Deployment の論理IDを取得できます。

!Ref MyApi.Stage #SAMによって生成されたステージを参照
!Ref MyApi.Deployment #SAMによって生成されたデプロイメントリソースを参照

しかし DepedsOn プロパティは文字列のみ指定可能であるため、今回の対応では直接記述しました。
特にデプロイメントリソースについては、API のデプロイ毎に論理IDが変化するので組み込み関数による
参照は重要ですね。

以上です。
参考になれば幸いです。

19
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
6