0
votes

I have built out an API Gateway that integrates with Dynamodb using the AWS Console and have it up and running as a proof of concept. Now I want to take that API Gateway and re-produce it via CloudFormation for actual usage.

I've been able to get most of it deployed using my CFT but I'm stuck on the AWS::ApiGateway::Method resource. Specifically, the Integration property.

  ResourceHttpGet:
    Type: AWS::ApiGateway::Method
    Properties:
      AuthorizationScopes:
        - openid
      AuthorizationType: COGNITO_USER_POOLS
      AuthorizerId: {'Fn::ImportValue': !Sub '${ProductName}-${TargetEnvironment}-authorizer-customerpool' }
      HttpMethod: GET
      OperationName: GetFoo
      RequestModels:
        "application/json": {'Fn::ImportValue': !Sub '${ProductName}-${TargetEnvironment}-apigw-foomodel' }
      Integration: 
        Credentials: !Ref ApiGatewayDynamoDbRole
        IntegrationHttpMethod: POST
        RequestTemplates:
         application/json: !Sub '{ "TableName": "${ProductName}-${TargetEnvironment}-dynamo-primaryapi", "KeyConditionExpression": "UserId = :val", "Limit": 50, "ExpressionAttributeValues": { ":val": { "S": "$context.authorizer.claims.sub" } } }'
        Type: AWS
        Uri: !Sub "arn:aws:apigateway:${AWS::Region}:dynamodb:action/Query"
      ResourceId: !Ref FooResource
      RestApiId: {'Fn::ImportValue': !Sub '${ProductName}-${TargetEnvironment}-apigw-primaryapi' }

When I upload this into the CloudFormation Console and run it the CF Stack fails with the following error on the ResourceHttpGet resource:

Invalid ARN specified in the request (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: e6767c61-96dc-461a-ab7c-fd625344b59f; Proxy: null)

I can comment out the Integration property and the Stack successfully deploys. I've used a couple of different resources to help validate the ARN I'm using is accurate. One being a blog post I found on API Gateway/Dynamodb integration and a second being here on Stackoverflow

Can someone point out what I'm doing wrong here? Why doesn't it like the Uri I provide when it confirms to the specification/API requirements below:

arn:aws:apigateway:region:subdomain.service|service:path|action/service_api. For example, a Lambda function URI follows this form: arn:aws:apigateway:region:lambda:path/path.

I've also removed the !sub function usage and just hard-coded the Region into the Uri in order to test if the usage of intrinsic functions caused the issue but that didn't make a difference.

Totally confused and would appreciate any guidance someone can give to me on this.

1
Can you make it work in AWS Console? If it works there, you could then inspect what is the actual form of the URI that the console setups.Marcin
I tried to use the template designer tool to create this specific resource in the Console but could not figure it out. When I dragged the resource onto the designer there weren't any properties for me to enter. When I check the API Gateway Console for the working Gateway the Request Integration doesn't provide me with the Uri/Arn. It just lists the service I've integrated with as DynamoDb.Johnathon Sullinger
Your uri looks fine. What exactly is ApiGatewayDynamoDbRole, because the error does not specify that uri is only suspect. Maybe your credentails have wrong ARN?Marcin
I actually tested that - created a DynamoDB Table in the template itself and referenced it via !GetAtt MyTable.Arn but it still failed with the same error. Doesn't appear to be the IAM Role.Johnathon Sullinger

1 Answers

0
votes

If you're trying to create a CloudFormation file based on an API Gateway setup that you've created manually, I would take a look at AWS SAM. Which is much less verbose and easier to set up. Specifically, I would have a look at the DefinitionBody property of the AWS::Serverless::Api type. This property allows you to pass in an openapi body definition of your API.

As a starting point, you can also export your current api using the console or one of the other methods indicated in the documentation.

Combining those two things would make it a lot easier to construct your API Gateway in CloudFormation.