Reputation: 1750
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
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.
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
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