I have an API that is defined as IaC with AWS SAM usign AWS::Serverless::Api for the API Gateway and API Event Source for the Methods.
I developed a method that requires a non lambda proxy integration and some mapping templates in the integration response, so to implement these functionalities in IaC I had to use AWS::ApiGateway::Method from Cloud Formation Templates.
The problem is with the ResourceId property, because is a third level resource in the API, Cloud Formation expects a reference to a AWS::ApiGateway::Resource but the upper levels were implicitly created by AWS SAM with the following code:
PrismShiftDayMacroserviceLambda:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Ref ServiceName
CodeUri: !Ref ServicePath
Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/lambda_execution_role'
Events:
GetShiftDay:
Type: Api
Properties:
Method: GET
Path: /api/shiftDays/{id}
RequestParameters:
- method.request.path.id
RestApiId: !Ref PrismShiftDayMacroserviceApi
PostShiftDay:
Type: Api
Properties:
RestApiId: !Ref PrismShiftDayMacroserviceApi
Path: /api/shiftDays
Method: POST
SearchShiftDay:
Type: Api
Properties:
RestApiId: !Ref PrismShiftDayMacroserviceApi
Path: /api/shiftDays
Method: GET
PatchShiftDay:
Type: Api
Properties:
RestApiId: !Ref PrismShiftDayMacroserviceApi
Path: /api/shiftDays/{id}
Method: PATCH
Is it possible to get a reference to the resource that was implicitly created by AWS SAM?
provider:
name: aws
runtime: nodejs14.x
functions:
hello:
handler: handler.hello
events:
- httpApi:
path: /
method: get
RestApiId:
Ref: TestApi // How to get reference of AWS::Serverless::Api i.e. TestApi here
resources:
Resources:
authFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: .
Handler: handler.hello
TestApi:
DependsOn: AuthFunction
Type: AWS::Serverless::Api
Properties:
StageName: dev
Auth:
DefaultAuthorizer: LambdaRequestAuthorizer
Authorizers:
LambdaRequestAuthorizer:
FunctionPayloadType: REQUEST
FunctionArn: !GetAtt AuthFunction.Arn
Getting error:
Configuration error at 'functions.hello': unrecognized property 'RestApiId'
Let's first clarify a few things.
The httpApi event is using HTTP API, not REST API from AWS Api Gateway.
You can set externally created HTTP API by specifying it in the following way:
provider:
httpApi:
id: <your http api reference>
If you'd like to use REST API, then you would need to use http event type and set it like this:
provider:
apiGateway:
restApiId: <your rest api reference>
I am learning working with AWS lambda and api gateway. I started with sam cli, initialized a hello world template ( code below). when deploy.yaml file is generated via - sam package ... command and stack is generated via cloud formation , it looks like this already generates an api end point. I wanted to create an api gateway with resource, methods, usage plan , api key and so forth. so I started adding following resources to the original template. How can i wire up my api gateway with the lambda function.
ApiGatewayRestApi:
Type: AWS::ApiGateway::RestApi
Properties:
ApiKeySourceType: HEADER
Description: An API Gateway with a Lambda Integration
EndpointConfiguration:
Types:
- EDGE
Name: lambda-api
ApiGatewayResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !GetAtt ApiGatewayRestApi.RootResourceId
PathPart: 'lambda'
RestApiId: !Ref ApiGatewayRestApi
ApiGatewayMethod:
Type: AWS::ApiGateway::Method
Properties:
ApiKeyRequired: false
AuthorizationType: NONE
HttpMethod: GET
ResourceId: !Ref ApiGatewayResource
RestApiId: !Ref ApiGatewayRestApi
original template
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
simple-node-api
Sample SAM Template for simple-node-api
Globals:
Function:
Timeout: 3
Resources:
HelloWorldfunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: python3.7
Events:
HelloWorld:
Type: Api
Properties:
Path: /{proxy+}
Method: get
Outputs:
HelloWorldApi:
Description: API Gateway endpoint URL for Prod stage for Hello World function
Value:
Fn::Sub: https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldfunction:
Description: Express Backend Lambda Function ARN
Value: !Sub HelloWorldfunction.Arn
HelloWorldFunctionIamRole:
Description: Implicit IAM Role created for Hello World function
Value: !Sub HelloWorldFunctionRole.Arn
I'm trying to create Api gateway and lambda function with cloudformation. Current I'm able to create api gateway with swagger, and lambda function. The issue I have is the lambda function dont have the trigger with support to be api gateway. How to add trigger to this lambda function ?
the RestApi Definitation
MyRestApi:
Properties:
ApiKeySourceType: HEADER
BodyS3Location:
Bucket: bucketName
Key: swagger.yaml
Name: OmmaClaimsApi
Type: AWS::ApiGateway::RestApi
The Function Definitation
MyLambda:
Properties:
Code:
S3Bucket: bucketName
S3Key: lambda.zip
FunctionName: MyLambda
Handler: index.handler
MemorySize: 512
Role: !GetAtt 'LambdaExecutionRole.Arn'
Runtime: nodejs8.10
Timeout: 300
Type: AWS::Lambda::Function
Your lambda should go through the API gateway through proxy integration:
/{proxy+}
In your serverless yaml, try to add something like:
functions:
post-transaction:
handler: your.lambda.LambdaHandler
events:
- http:
path: /{proxy+}
method: any
How can I create an API with AWS SAM that does authorization using Cognito User Pools authorizer?
Theres AWS::ApiGateway::Authorizer. But ...
{
"Type" : "AWS::ApiGateway::Authorizer",
"Properties" : {
"AuthorizerCredentials" : String,
"AuthorizerResultTtlInSeconds" : Integer,
"AuthorizerUri" : String,
"IdentitySource" : String,
"IdentityValidationExpression" : String,
"Name" : String,
"ProviderARNs" : [ String, ... ],
"RestApiId" : String,
"Type" : String
}
}
it looks like RestApiId refers to the API which uses this authorizer? But with AWS SAM, my APIs are defined like
Resources:
Ec2Index:
Type: AWS::Serverless::Function
Properties:
Handler: ec2/index.handler
Runtime: nodejs6.10
CodeUri: ./src
FunctionName: 'ApiEc2IndexHandler'
Description: 'List EC2 resources'
Timeout: 30
Role: 'arn:aws:iam::598545985414:role/awsmanagement-lambda-management'
Events:
Ec2Index:
Type: Api
Properties:
Path: /ec2
Method: get
I dont get how do I associate them together?
You can now reference the implicitly created api gateway with 'ServerlessRestApi'.
So in your SAM template add this piece of regular Cloudformation and everything will work fine
ApiCognitoAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
IdentitySource: 'method.request.header.Authorization'
Name: ApiCognitoAuthorizer
ProviderARNs:
- 'arn:aws:cognito-idp:{region}:{userpoolIdentifier}'
RestApiId: !Ref ServerlessRestApi
Type: COGNITO_USER_POOLS
I'm not certain you can specify an authorizer in SAM but you can embed Swagger in SAM files which can do this. It's a new feature as of Feb. 17 [ref].
I'm definitely not an expert on Swagger or SAM but it seems like you would want something like:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Simple API Endpoint configured using Swagger specified inline and backed by a Lambda function
Resources:
Ec2Index:
Type: AWS::Serverless::Api
Properties:
StageName: <stage>
DefinitionBody:
swagger: 2.0
info:
title:
Ref: AWS::StackName
securityDefinitions:
cognitoUserPool:
type: apiKey,
name: "Authorization"
in: header
x-amazon-apigateway-authtype: cognito_user_pools
x-amazon-apigateway-authorizer:
type: cognito_user_pools
providerARNs:
- arn:aws:cognito-idp:${AWS::Region}:{AWS::AccountId}:userpool/<user_pool_id>
paths:
"/ec2":
get:
security:
- cognitoUserPool: []
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Ec2IndexLamb.Arn}/invocations
responses: {}
swagger: '2.0'
Ec2IndexLamb:
Type: AWS::Serverless::Function
Properties:
Handler: ec2/index.handler
Runtime: nodejs6.10
CodeUri: ./src
FunctionName: 'ApiEc2IndexHandler'
Description: 'List EC2 resources'
Timeout: 30
Role: 'arn:aws:iam::598545985414:role/awsmanagement-lambda-management'
Events:
Ec2Index:
Type: Api
Properties:
Path: /ec2
Method: get
References:
https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html#apigateway-enable-cognito-user-pool
https://github.com/awslabs/serverless-application-model/blob/master/examples/2016-10-31/inline_swagger/template.yaml
Edit: Fixed Swagger 2.0 syntax for the 'security' section, it should be a list.
Since AWS SAM v1.8.0, you can do it using the following syntax. You can refer to this article for more information.
In short, define a Cognito Authorizer for your API using API Authorizer Object. Then, set the Auth of your lambda function to refers to this API.
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Auth:
DefaultAuthorizer: MyCognitoAuth # OPTIONAL
Authorizers:
MyCognitoAuth:
# Can also accept an array
UserPoolArn: !GetAtt MyCognitoUserPool.Arn
Identity: # OPTIONAL
# OPTIONAL; Default: 'Authorization'
Header: MyAuthorizationHeader
# OPTIONAL
ValidationExpression: myAuthValidationExp
MyFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: MyFunction
...
Events:
Post:
Type: Api
Properties:
Path: /compute
Method: POST
RestApiId: !Ref MyApi
Auth:
Authorizer: MyCognitoAuth
As #simones mentioned, the following will create the Cognito User Pool authorizer (CF template).
ApiCognitoAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
IdentitySource: 'method.request.header.Authorization'
Name: ApiCognitoAuthorizer
ProviderARNs:
- 'arn:aws:cognito-idp:{region}:{userpoolIdentifier}'
RestApiId: !Ref ServerlessRestApi
Type: COGNITO_USER_POOLS
To attach it to a resource method, the following works (in Swagger file):
securityDefinitions:
ApiCognitoAuthorizer:
type: apiKey
name: Authorization
in: header
x-amazon-apigateway-authtype: cognito_user_pools
x-amazon-apigateway-authorizer:
type: cognito_user_pools
providerARNs:
- arn:aws:cognito-idp:{region}:{userpoolIdentifier}
Then, add to specific methods (in Swagger file):
security:
- ApiCognitoAuthorizer: []
You can add your Cognito User Authorizer directly to your SAM AWS::Serverless::Api.
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Cors: "'*'"
Auth:
DefaultAuthorizer: MyCognitoAuthorizer
Authorizers:
MyCognitoAuthorizer:
UserPoolArn: 'arn:aws:cognito-.....' # YOUR COGNITO USER POOL ARN
and on your AWS::Serverless::Function you can add a function authorizer if you have not set the default one. Or you can deactivate it using Authorizer: 'NONE'.
Auth:
Authorizer: MyCognitoAuthorizer
see also documentation.