How to add non authenticated routes in AWS SAM template - amazon-web-services

So this is my SAM template:
webApi:
Type: AWS::Serverless::Api
Properties:
Auth:
DefaultAuthorizer: CognitoAuthorizer
Authorizers:
CognitoAuthorizer:
UserPoolArn: !GetAtt myUserPool.Arn
AddDefaultAuthorizerToCorsPreflight: false
Cors:
AllowMethods: "'*'"
AllowHeaders: "'*'"
AllowOrigin: "'*'"
StageName: !Ref Environment
DefinitionBody:
swagger: "2.0"
info:
title:
Ref: AWS::StackName
paths:
/path/one:
post:
responses: {}
x-amazon-apigateway-integration:
uri: myFunction.Arn
httpMethod: "POST"
type: "aws_proxy"
/path/two:
post:
responses: {}
x-amazon-apigateway-integration:
uri: myFunction.Arn
httpMethod: "POST"
type: "aws_proxy"
How can I make the path/two an non authenticated route?
I tried to google but there was nothing.
If possible I don't want to create another API Gateway. I would like to do it within the same resource.

As OpenAPI, you can use security: [] to disable auth in some path.
Refer:
https://github.com/zalando/connexion/issues/944
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body

In AWS SAM template, to disable security for specific endpoints in the DefinitionBody, what worked for me is the following:
swagger: "2.0"
info:
title:
Ref: AWS::StackName
paths:
/path/one:
post:
security:
- NONE: []

Related

Override default auth in SAM templates and Open API

I have made a SAM template that deploys a mix of public and authenticated endpoints. The default auth is oauth. For public endpoints, I use overrides to make it auth NONE. This worked fine.
After I have added the OpenAPI for documentation. The auth override for public endpoints does not work anymore. What else should I do?
#sam-template.yaml
Resources:
RestApi:
Type: AWS::Serverless::Api
Properties:
Name: !Ref ApiStackName
StageName: Prod
Auth:
AddDefaultAuthorizerToCorsPreflight: false
DefaultAuthorizer: TokenAuthorizer
Authorizers:
TokenAuthorizer:
FunctionArn: !GetAtt Authorizer.Arn
Identity:
Header: Authorization
ValidationExpression: Bearer.*
ReauthorizeEvery: 0
DefinitionBody: // this is what I added.
Fn::Transform:
Name: AWS::Include
Parameters:
Location:
Fn::Join:
- ''
- - 's3://'
- Ref: S3BucketName
- '/swagger.yaml'
GetFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./functions
FunctionName: !Sub ${Environment}-api-get
Description: get
Handler: ./src/get.handler
Role: !Sub arn:aws:iam::${AWS::AccountId}:role/pam-${Environment}-${AWS::Region}-get-lambda-role
Events:
Api:
Type: Api
Properties:
RestApiId: !Ref RestApi
Path: /p
Method: GET
Auth:
Authorizer: NONE // this overrides the default auth
#swagger.yaml
/p:
get:
summary: Get
description: Get
responses:
200:
description: "200 response"
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/P"
500:
description: "500 response"
content: {}
x-amazon-apigateway-auth:
type: "NONE"
x-amazon-apigateway-integration:
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetFunction.Arn}/invocations
responses:
default:
statusCode: "200"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
contentHandling: "CONVERT_TO_TEXT"
type: "aws_proxy"
security: {}
OR
security:
- {}
Didn't work for me.
The below mentioned code snippet worked.
security:
- NONE: []
you are looking for security in OpenAPI. This sets Authorization on ApiGateway endpoint to NONE.
/p:
get:
summary: Get
description: Get
responses:
...
security:
- {}
x-amazon-apigateway-integration:
...

Getting access denied due to origin blocked by CORS in AWS Api-Gateway

I have an AWS SAM template, which creates lambda function and post method in API Gateway. By default, it uses Lambda Proxy integration and it is working fine when I am testing through the PostMan tool but when I am using the API gateway URL with my sandbox app, it is displaying the following error.
Access to XMLHttpRequest at 'https://abcdef.execute-api.eu-west-2.amazonaws.com/dev/my-api' from origin 'https://abcd.csb.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
but when I am creating API gateway post method manually and trying then it is working fine.
Lambda function also returning following header in the response.
response = {
'statusCode': status_code,
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS,POST'
},
'body': json.dumps(response_data)
}
Following is AWS SAM template.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
AWS SAM Template
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 10
Parameters:
DeploymentEnv:
Type: String
Resources:
ApiGatewayApi:
DependsOn: LambdaFunction
Type: AWS::Serverless::Api
Properties:
StageName: !Ref DeploymentEnv
EndpointConfiguration:
Type: REGIONAL
Cors:
AllowMethods: "'POST,OPTIONS'"
AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
AllowOrigin: "'*'"
MaxAge: "'600'"
AllowCredentials: false
Auth:
DefaultAuthorizer: NONE
ApiKeyRequired: true # sets for all methods
LambdaFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
FunctionName: !Join [ "", [ !Ref DeploymentEnv, "-my-lambda"]]
CodeUri: my_api/
Handler: app.lambda_handler
Runtime: python3.9
Architectures:
- x86_64
Events:
EventTriggerlambda:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
RestApiId: !Ref ApiGatewayApi
Path: /my-api
Method: POST
Auth:
ApiKeyRequired: true
Role: Role_URN
Environment:
Variables:
URI: Test
USER_NAME: Test
PASSWORD: Test
ApiKey:
Type: AWS::ApiGateway::ApiKey
DependsOn: ApiGatewayApiStage
Properties:
Name: !Join ["", [{"Ref": "AWS::StackName"}, "-apikey"]]
Enabled: true
StageKeys:
- RestApiId: !Ref ApiGatewayApi
StageName: !Ref DeploymentEnv
UsagePlan:
DependsOn:
- ApiGatewayApiStage
Type: AWS::ApiGateway::UsagePlan
Properties:
ApiStages:
- ApiId: !Ref ApiGatewayApi
Stage: !Ref DeploymentEnv
Throttle:
BurstLimit: 500
RateLimit: 100
UsagePlanName: MY-UsagePlan
UsagePlanKey:
Type: AWS::ApiGateway::UsagePlanKey
Properties:
KeyId: !Ref ApiKey
KeyType: API_KEY
UsagePlanId: !Ref UsagePlan
Outputs:
LambdaFunction:
Description: "Lambda Function ARN"
Value: !GetAtt LambdaFunction.Arn
Please help, Thanks :)
Configuration is not proper for API creation in API-Gateway in the AWS SAM template. because SAM deployment uses lambda proxy integration by default that's why in method response, there are few values required which can not be set automatically using the above configuration. So I use open API specification where I defined Rest API configuration and it is working fine without any manual intervention after deployment.
Following configuration is fine.
ApiGatewayApi:
DependsOn: LambdaFunction
Type: AWS::Serverless::Api
Properties:
StageName: !Ref DeploymentEnv
DefinitionBody:
'Fn::Transform':
Name: 'AWS::Include'
Parameters:
Location: !Join [ '', [ 's3://mybucket', '/openapi-spec.yaml' ] ]
EndpointConfiguration:
Type: REGIONAL
OpenAPi Configuration
openapi: "3.0.1"
info:
title: "test-api"
description: "Created by AWS Lambda"
version: "2022-01-07T18:00:40Z"
paths:
/test-api:
post:
responses:
"200":
description: "200 response"
headers:
Access-Control-Allow-Origin:
schema:
type: "string"
content:
application/json:
schema:
$ref: "#/components/schemas/Empty"
x-amazon-apigateway-integration:
httpMethod: "POST"
uri:
Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations"
responses:
default:
statusCode: "200"
responseParameters:
method.response.header.Access-Control-Allow-Origin: "'*'"
passthroughBehavior: "when_no_match"
contentHandling: "CONVERT_TO_TEXT"
type: "aws_proxy"
options:
responses:
"200":
description: "200 response"
headers:
Access-Control-Allow-Origin:
schema:
type: "string"
Access-Control-Allow-Methods:
schema:
type: "string"
Access-Control-Allow-Headers:
schema:
type: "string"
content:
application/json:
schema:
$ref: "#/components/schemas/Empty"
x-amazon-apigateway-integration:
responses:
default:
statusCode: "200"
responseParameters:
method.response.header.Access-Control-Allow-Methods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
method.response.header.Access-Control-Allow-Origin: "'*'"
requestTemplates:
application/json: "{\"statusCode\": 200}"
passthroughBehavior: "when_no_match"
type: "mock"
x-amazon-apigateway-any-method:
responses:
"200":
description: "200 response"
content: {}
security:
- api_key: []
x-amazon-apigateway-integration:
httpMethod: "POST"
uri: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaFunction.Arn}/invocations"
responses:
".*":
statusCode: "200"
passthroughBehavior: "when_no_match"
type: "aws_proxy"
components:
schemas:
Empty:
title: "Empty Schema"
type: "object"
securitySchemes:
api_key:
type: "apiKey"
name: "x-api-key"
in: "header"
here openapi-spec.yaml file was kept in the same folder as the AWS SAM template and it was uploaded to the S3 bucket before deployment start using the following command in the GitHub workflow pipeline file.
- run: aws s3 cp openapi-spec.yaml s3://mnai-code-deployments
- run: sam build
- run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --stack-name my-stack --s3-bucket mybucket --capabilities CAPABILITY_IAM --region eu-west-2 --parameter-overrides ParameterKey=DeploymentEnv,ParameterValue=dev ParameterKey=S3Bucket,ParameterValue=mybucket
Thanks

How to import variable into Swagger file for AWS ApiGateway

I Want to use APIGateway for my RESTful application by OpenApi file but How could I inject my variables from outside of swagger file into it
Swagger.yml
openapi: "3.0.1"
info:
title: !Join ['-', ['XXXX', !Ref ServiceName]]
paths:
/:
get:
responses:
default:
description: "Default response for GET /"
x-amazon-apigateway-integration:
payloadFormatVersion: "1.0"
connectionId: !Ref VPCLink
type: "http_proxy"
httpMethod: "ANY"
uri: !GetAtt ServiceDiscovery.Arn
connectionType: "VPC_LINK"
/health:
get:
responses:
default:
description: "Default response for GET /health"
x-amazon-apigateway-integration:
payloadFormatVersion: "1.0"
connectionId: !Ref VPCLink
type: "http_proxy"
httpMethod: "ANY"
uri: !GetAtt ServiceDiscovery.Arn
connectionType: "VPC_LINK"
x-amazon-apigateway-cors:
allowOrigins:
- '*'
allowHeaders:
- '*'
allowMethods:
- 'GET'
x-amazon-apigateway-importexport-version: "1.0"
Cloudformation template :
HttpApi:
Type: AWS::ApiGatewayV2::Api
Properties:
Body:
Fn::Transform:
Name: AWS::Include
Parameters:
Location: "s3://XXXX/Swagger.yml"
But It has following error in cloudformation :
"Transform AWS::Include failed with: The specified S3 object's content should be valid Yaml/JSON"
And when I remove built-in functions like Join and GetAtt from my swagger.yml it works.

How to make sure the API Gateway token authorizer is invoked only for specific paths

We have an API Gateway utilising a custom Token authoriser. We have 2 lambdas - Greetings and GenerateToken.
We only want the Greetings lambda to be behind a authoriser - requires to be called in the following way utilising SAM:
curl -X GET \
https://<apigatewayid>.execute-api.eu-west-1.amazonaws.com/Prod/generateToken \
-H 'X-API-KEY: allow'
How can we achieve that the GenerateToken path does not require a HTTP token for authenticating?
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: API Gateway with Lambda Token Authorizer
Resources:
GreetingsApiGateway:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
DefinitionBody:
swagger: 2.0
x-amazon-apigateway-policy:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal: "*"
Action: execute-api:Invoke
Resource:
- execute-api:/*/*/*
paths:
"/hello":
get:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GreetingsLambda.Arn}/invocations
responses: {}
"/generateToken":
get:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GenerateTokenLambda.Arn}/invocations
responses: {}
Auth:
DefaultAuthorizer: CustomAuthorizer
Authorizers:
MyAuthorizer:
FunctionArn: !GetAtt AuthLambda.Arn
Identity:
Header: X-API-KEY
GenerateTokenLambda:
Type: AWS::Serverless::Function
Properties:
Role: !GetAtt LambdaRole.Arn
CodeUri: "s3://<bucket-name>/code.zip"
Handler: src/generateToken.handler
Events:
GetRoot:
Type: Api
Properties:
RestApiId: !Ref GreetingsApiGateway
Path: /generateToken
Method: get
GreetingsLambda:
Type: AWS::Serverless::Function
Properties:
Role: !GetAtt LambdaRole.Arn
CodeUri: "s3://<bucket-name>/code.zip"
Handler: src/greetings.handler
Events:
GetRoot:
Type: Api
Properties:
RestApiId: !Ref GreetingsApiGateway
Path: /hello
Method: get
AuthLambda:
Type: AWS::Serverless::Function
Properties:
Role: !GetAtt LambdaRole.Arn
CodeUri: "s3://<bucket-name>/code.zip"
Handler: src/auth.handler
Globals:
Function:
Runtime: nodejs8.10
Outputs:
ApiURL:
Description: "OUR API URL"
Value: !Sub "https://${GreetingsApiGateway}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
I am not very sure if I completely understood what you want, but here's a Cloudformation template to create api-gateway resources with & without authorization enabled. I am using Cognito User Pool authorization method but it can be just as easily be a custom authorizer.
RestAPI:
Type: AWS::ApiGateway::RestApi
DeletionPolicy: Delete
Properties:
Name: {"Ref": "AWS::StackName"}
ApiKeySourceType: HEADER
EndpointConfiguration:
Types:
- EDGE
ApiAuthorizer:
Type: AWS::ApiGateway::Authorizer
DeletionPolicy: Retain
DependsOn: UserPoolList
Properties:
Name: !Join ["-", [{"Ref": "AWS::StackName"}, "authorizer"]]
RestApiId: !Ref RestAPI
Type: COGNITO_USER_POOLS
AuthType: cognito_user_pools
IdentitySource: "method.request.header.Authorization"
ProviderARNs: <User Pool ARN>
ResourceSignin:
Type: AWS::ApiGateway::Resource
DeletionPolicy: Delete
Properties:
RestApiId: !Ref RestAPI
ParentId: !GetAtt RestAPI.RootResourceId
PathPart: "signin"
SigninPostMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RestAPI
ResourceId: !Ref ResourceSignin
HttpMethod: POST
AuthorizationType: NONE
ApiKeyRequired: <true/false>
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${UserHandlerFunction.Arn}/invocations
Credentials: !GetAtt GenApiGatewayRole.Arn
ResourceUserCreate:
Type: AWS::ApiGateway::Resource
DeletionPolicy: Delete
Properties:
RestApiId: !Ref RestAPI
ParentId: !GetAtt RestAPI.RootResourceId
PathPart: "create"
CreatePostMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RestAPI
ResourceId: !Ref ResourceUserCreate
HttpMethod: POST
AuthorizationType: COGNITO_USER_POOLS
AuthorizerId: !Ref ApiAuthorizer
ApiKeyRequired: <true/false>
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${UserHandlerFunction.Arn}/invocations
Credentials: !GetAtt UserApiGatewayRole.Arn
Here resource signin has a POST method with no authorization while create resource has a POST method with authorization enabled.
If you are planning to use API keys this might be the only way possible. I could not get API keys to work with SAM (I believe API keys with SAM is not yet supported - this was about a month back, but you can double check).
We can achieve this via swagger within API Gateway:
The World lambda is a public API and the Hello lambda resides behind the AuthLambda authorizer
OurApiGateway:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Auth:
Authorizers:
MyAuthorizer:
FunctionPayloadType: REQUEST
FunctionArn: !GetAtt AuthLambda.Arn
DefinitionBody:
swagger: 2.0
basePath: /prod
info:
title: AwsSamExample
x-amazon-apigateway-policy:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal: "*"
Action: execute-api:Invoke
Resource:
- execute-api:/*/*/*
schemes:
- https
paths:
"/hello":
get:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloLambda.Arn}/invocations
responses: {}
security:
- MyAuthorizer: []
"/world":
get:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${WorldLambda.Arn}/invocations
responses: {}
security: []
Use the Serverless framework and easily manage this with just an attribute.
https://www.npmjs.com/package/serverless

SAM Template : Cognito User Pool integrate in APIgateway - Authorizer doesn't work

I want to integrate Cognito token in my application.
How can i do it in AWS Sam Template ?
To update my template, I look on https://docs.aws.amazon.com/fr_fr/apigateway/latest/developerguide/apigateway-enable-cognito-user-pool.html?shortFooter=true
Info:
My UserPool is created in the AWS console (on web)
I test with Postman without header: if it worked I should be refused ==> reallity: I have results (my Authorizer doesn't work)
=========================
My question is : why Authorizer doesn't work ?
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Globals:
Function:
Runtime: nodejs6.10
Handler: index.handler
Timeout: 30
Resources:
GRApi:
Type: 'AWS::Serverless::Api'
Properties:
Name: 'Myname'
StageName: !Ref Stage
Cors: "'*'"
EndpointConfiguration: REGIONAL
DefinitionBody:
swagger: "2.0"
info:
version: "1.0"
title: "myTitle"
host: !Ref Host
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..."
schemes:
- "https"
consumes:
- application/json
produces:
- application/json
paths:
/project:
get:
responses: {}
security:
- cognitoUserPool: []
x-amazon-apigateway-integration:
uri:
- 'arn:aws:apigateway:....Arn'
passthroughBehavior: "when_no_match"
httpMethod: "POST"
type: "aws_proxy"
GetAllProjectsFunction:
Type: 'AWS::Serverless::Function'
Properties:
CodeUri: URI/
Handler: index.handler
Runtime: nodejs8.10
MemorySize: 128
Timeout: 30
Role: 'arn:....role'
Events:
GetAllProjects:
Type: Api
Properties:
Path: /project
Method: get
RestApiId: !Ref GRApi
Outputs:
...