niqui
niqui

Reputation: 1750

AWS::Serverless::Api Resource Policy with Cloudformation SAM

Recently AWS announced that Amazon API Gateway Supports Resource Policies for APIs

Is it possible to attach a resource policy to a AWS::Serverless::Api created via Cloudformation with SAM?

Upvotes: 3

Views: 4266

Answers (2)

Colm Bhandal
Colm Bhandal

Reputation: 3831

Yes, I have reproduced a minimal example of this based on this old Python example from AWS. I modified it because the bucket it references is region-specific and doesn't seem to grant public access anyway. My example below is fully inline, not depending on any external resources. I also changed the language to JS.

Note that the policy goes under the Auth element which must be nested under Properties*. Here is a snippet:

      Auth:
        ResourcePolicy:
          CustomStatements: {
              Effect: 'Allow',
              Action: 'execute-api:Invoke', 
              Resource: ['execute-api:/*/*/*'],
              Principal: '*'
            }

And here is full example code that you can deploy with SAM:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Runtime: nodejs12.x
    Timeout: 30
    AutoPublishAlias: live

Resources:
  ExplicitApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Auth:
        ResourcePolicy:
          CustomStatements: {
              Effect: 'Allow',
              Action: 'execute-api:Invoke', 
              Resource: ['execute-api:/*/*/*'],
              Principal: '*'
            }
  MinimalFunction:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: index.handler
      InlineCode: |
        exports.handler = (event, context, callback) => {
            callback(
                null,
                {
                    statusCode: 200,
                    body: JSON.stringify({
                        message: 'Hello World'
                    })
                });
        };
      Events:
        AddItem:
          Type: Api
          Properties:
            RestApiId: 
              Ref: ExplicitApi
            Path: /add
            Method: post

After deploying this, I can go to the API Gateway in the AWS console, and under "Resource Policies" I can see:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "XXX"
        }
    ]
}

Note: I've redacted the Resource ARN in the above.

*I originally had a bug in my code, with Auth nested directly under the AWS::Serverless::Api. SAM did not throw an error, nor did my VS linter, but the policy upload silently failed.

Alternative Syntax

The above uses a JSON object within YAML. If you want to stick with pure YAML, use this:

  Auth:
    ResourcePolicy:
      CustomStatements:
        Effect: Allow
        Action: execute-api:Invoke
        Resource:
        - execute-api:/*/*/*
        Principal: '*'  

Upvotes: 2

Adam
Adam

Reputation: 388

I haven't had the chance to try this yet but I assume you can use it like you would use an S3 Bucket Policy. The trickiest part for you would be to grab the api-id to be able to use in the Resource ARN(s).

So, in your template you would have a piece that contains similar YAML (or JSON). This would allow <some user> to use the API

Statement:
- Effect: Allow
  Principal:
    AWS:
    - arn:aws:iam::<account-id>:user/<some user>
    - account-id
  Action: execute-api:Invoke
  Resource:
  - execute-api:/*/*/*

Note that the execute-api:/*/*/* gets converted automatically during deployment to something that looks like arn:aws:execute-api:<region>:<account-id>:<api-id>/*/*/*

This approach should work just like bucket policies and this is how you apply a policy to a Bucket.

Good luck!

Upvotes: 3

Related Questions