AWS API Gateway Method Response in CloudFormation - Output passthrough: No - aws-cloudformation

I am trying to configure the Integration Response - Output Passthrough as No. I have configure the parameter PassthroughBehavior as NEVER, however it doesn´t change the output as desired.
Here is my method resource (in YAML):
apiresourcemsactualizartrxtransaccionesv1actualizarTransaccionesoptions:
Type: 'AWS::ApiGateway::Method'
Properties:
RestApiId: !Ref apigateway
ResourceId: !Ref apiresourcemsactualizartrxtransaccionesv1actualizarTransacciones
HttpMethod: OPTIONS
AuthorizationType: NONE
RequestParameters:
method.request.path.proxy: true
Integration:
PassthroughBehavior: NEVER
Type: MOCK
IntegrationHttpMethod: OPTIONS
IntegrationResponses:
-
StatusCode: 200
ResponseParameters:
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-Methods: "'OPTIONS,PATCH'"
method.response.header.Access-Control-Allow-Origin: "'*'"
MethodResponses:
-
StatusCode: 200
ResponseModels:
application/json: Empty
ResponseParameters:
method.response.header.Access-Control-Allow-Headers: true
method.response.header.Access-Control-Allow-Methods: true
method.response.header.Access-Control-Allow-Origin: true
DependsOn: apiresourcemsactualizartrxtransaccionesv1actualizarTransacciones
Thank you very much for the help in advance.

My understanding is PassthroughBehavior refers to the request, not the output.
I think your output passthrough is setting to "Yes" because your response model is empty. If you set up a model/transform, that should change output passthrough to No.

Related

I can't add proxy with ApiGateway using Serverless Framework v3

i’m trying to add proxy to my lambda function, but i’m getting error:
“CREATE_FAILED: ApiGatewayResourceJokes (AWS::ApiGateway::Resource)
Resource handler returned message: “Another resource with the same
parent already has this name: example (Service: ApiGateway, Status
Code: 409, Request ID: 3fb2a85c-6fd2-4414-ad3f-72ee095da48b)”
(RequestToken: f33a6da3-be94-9696-3fd6-35a7bc52ef0a, HandlerErrorCode:
AlreadyExists)”
example:
handler: lambdas/endpoints/proxy.handler
events:
- http: GET /example
ProxyResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId:
Fn::GetAtt:
- ApiGatewayRestApi # our default Rest API logical ID
- RootResourceId
PathPart: jokes # the endpoint in your API that is set as proxy
RestApiId:
Ref: ApiGatewayRestApi
ProxyMethod:
Type: AWS::ApiGateway::Method
Properties:
ResourceId:
Ref: ProxyResource
RestApiId:
Ref: ApiGatewayRestApi
HttpMethod: GET # the method of your proxy. Is it GET or POST or ... ?
MethodResponses:
- StatusCode: 200
Integration:
IntegrationHttpMethod: POST
Type: HTTP
Uri: http://api.icndb.com/jokes/random # the URL you want to set a proxy to
IntegrationResponses:
- StatusCode: 200

Cloudformation - Type: "AWS::ApiGateway::Method" returns {"message": "Internal server error"}

I get {"message": "Internal server error"} return from AWS API gateway when I write a Cloudformation template. Everything works well if I configure them on AWS console.
curl https://abcdefgh.execute-api.ap-southeast-1.amazonaws.com/demo/getitems
{"message": "Internal server error"}
I check all parts in the CF template and I think the problem is in "AWS::ApiGateway::Method". All configuration/parameters are the same between CF template and AWS console ( I checked them on console). When I delete the method created by CF, re-create and re-deploy it manually, it works.
I believe that "AWS::Lambda::Permission" works because I see it in Resource-based policy.
Does anyone have a solution to this problem? Thank you in advance.
The CF template:
apigwGETMethod:
DependsOn:
- apiResourceGET
- lambdaFunction3
Type: "AWS::ApiGateway::Method"
Properties:
AuthorizationType: "NONE"
HttpMethod: "GET"
ResourceId: !Ref apiResourceGET
RestApiId: !Ref apiGateway
Integration:
IntegrationHttpMethod: "GET"
Type: "AWS"
Credentials: !GetAtt ServerlessIAMRole.Arn
Uri: !Sub
- "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations"
- lambdaArn: !GetAtt lambdaFunction3.Arn
IntegrationResponses:
- ResponseTemplates:
"application/json": ""
StatusCode: 200
MethodResponses:
- ResponseModels:
"application/json": "Empty"
StatusCode: 200
apiGatewayDeployment:
Type: "AWS::ApiGateway::Deployment"
DependsOn:
- apiGatewayGETMethod
Properties:
RestApiId: !Ref apiGateway
StageName: !Ref apiGatewayStageName
lambdaFunction3:
DependsOn:
- ServerlessIAMRole
Type: "AWS::Serverless::Function"
Properties:
FunctionName: !Ref lambdaFunction3Name
Handler: lambda_function3.lambda_handler
Description: "get all items from DynamoDB table"
Runtime: python3.6
CodeUri: .
Role: !GetAtt ServerlessIAMRole.Arn
lambda3ApiGatewayInvoke:
DependsOn:
- lambdaFunction3
- apiGatewayGETMethod
Type: "AWS::Lambda::Permission"
Properties:
Action: "lambda:InvokeFunction"
FunctionName: !GetAtt lambdaFunction3.Arn
Principal: "apigateway.amazonaws.com"
SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/*"

serverless-offline: Custom authorizer will not work if http_proxy is specified

I want to use serverless-offline to authenticate with a custom authorizer.
The file serverless.yml is shown below.
functions:
auth:
handler: src/authorizer.handler
...
custom:
serverless-offline:
httpPort: 4000
resourceRoutes: true
...
resources:
Resources:
ProxyResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId:
Fn::GetAtt:
- ApiGatewayRestApi
- RootResourceId
PathPart: protected
RestApiId:
Ref: ApiGatewayRestApi
ProxyPathResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId:
Ref: ProxyResource
PathPart: "{proxy+}"
RestApiId:
Ref: ApiGatewayRestApi
ProxyPathMethod:
Type: AWS::ApiGateway::Method
Properties:
AuthorizationType: "CUSTOM"
AuthorizerId:
Ref: AuthApiGatewayAuthorizer
ResourceId:
Ref: ProxyPathResource
RestApiId:
Ref: ApiGatewayRestApi
HttpMethod: ANY
RequestParameters:
method.request.path.proxy: false
MethodResponses:
- StatusCode: 200
- StatusCode: 401
Integration:
IntegrationHttpMethod: ANY
Type: HTTP_PROXY
Uri: https://my-json-server.typicode.com/{proxy}
RequestParameters:
integration.request.path.proxy: method.request.path.proxy
IntegrationResponses:
- StatusCode: 200
- StatusCode: 401
Run it.
$ sls offline
...
offline: ANY /development/auth-test/{proxy*} -> https://my-json-server.typicode.com/{proxy}
offline: [HTTP] server ready: http://localhost:4000 🚀
After that, accessing the following uri will return a normal response.
The custom authorizer does not seem to be working.
$ curl 'http://localhost:4000/development/protected/typicode/demo/profile'
{"name": "typicode"}
Running curl through the api-gateway will result in 401
$ sls deploy
$ curl 'https://xxxx.execute-api.{region}.amazonaws.com/development/protected/typicode/demo/profile' // This is a 401
$ curl 'https://xxxx.execute-api.{region}.amazonaws.com/development/protected/typicode/demo/profile' --header 'Authorization: Bearer {valid_token}' // This is 200
Does serverless-offline go through authentication with http_proxy?
Pardon my broken English!

Create methods under / using CF for API Gateway

How do I create methods under API Gateway's root / folder using CF? So for example I have a Gateway that looks like the following:
/
OPTIONS
POST
However when trying to do that with CF I get:
Resource's path part only allow a-zA-Z0-9._- and curly braces at the beginning and the end. So my PathPart is the offending line.
ApiGate:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !GetAtt
- ApiGateApi
- RootResourceId
PathPart: '{/}'
RestApiId: !Ref ApiGateApi
I can change the PathPart to something else but then it creates it as a child object under / which is what I don't want.
Turns out after adding the following to my AWS::ApiGateway::Method it works now.
MyMethodOPTIONS:
Type: 'AWS::ApiGateway::Method'
Properties:
ResourceId: !GetAtt MyRestApi.RootResourceId
Here is more context into my Template:
ApiGatewayMethodOPTIONS:
Type: 'AWS::ApiGateway::Method'
Properties:
ResourceId: !GetAtt ApiGatewayRestApi.RootResourceId
RestApiId: !Ref ApiGatewayRestApi
AuthorizationType: NONE
HttpMethod: OPTIONS
Integration:
Type: MOCK
IntegrationResponses:
- ResponseParameters:
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-Methods: "'POST,OPTIONS'"
method.response.header.Access-Control-Allow-Origin: "'*'"
ResponseTemplates:
application/json: ''
StatusCode: '200'
PassthroughBehavior: NEVER
RequestTemplates:
application/json: '{"statusCode": 200}'
MethodResponses:
- ResponseModels:
application/json: Empty
ResponseParameters:
method.response.header.Access-Control-Allow-Headers: true
method.response.header.Access-Control-Allow-Methods: true
method.response.header.Access-Control-Allow-Origin: true
StatusCode: '200'
ApiGatewayRestApi:
Type: AWS::ApiGateway::RestApi
Properties:
ApiKeySourceType: HEADER
EndpointConfiguration:
Types:
- REGIONAL
Name: SearchAPI
This fixes my problem, in my case I needed to have 2 methods:
1. will respond to requests to root e.g. https://<api-url>/prod or https://<api-url>/prod/. This will use the RootResourceId of the API Gateway:
ResourceId: !GetAtt myApiGateway.RootResourceId
this will respond to requests to whatever has been set under https://<api-url>/prod/. Could be petstore or if using {proxy+} then the backend workload will try to resolve the request. It will refer to the Resource type defined in the template:
ResourceId: !Ref myResource

How to enable ApiKeyRequired for an Api Method?

I want to use the standard API Keys feature of API Gateway. If I use standard cloudformation this is possible by setting the property ApiKeyRequired to true for a method. How can I do this with SAM?
I tried using swagger but that does not seem to work:
swagger: "2.0"
info:
title: !Ref AWS::StackName
paths:
"/machines/{resourceid}":
get:
parameters:
- name: resourceid
in: path
type: string
required: true
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyLambda.Arn}/invocations
responses: {}
security:
- authorizer: []
securityDefinitions:
authorizer:
type: apiKey
name: Authorization
in: header
Any suggestions?
The following swagger definition works:
DefinitionBody:
swagger: "2.0"
info:
title: !Ref AWS::StackName
x-amazon-apigateway-api-key-source : "HEADER"
paths:
"/machines/{resourceId}":
get:
parameters:
- name: resourceId
in: path
type: string
required: true
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MessagingServiceTestHandler.Arn}/invocations
responses: {}
security:
- api_key: []
securityDefinitions:
api_key:
type: "apiKey"
name: "x-api-key"
in: "header"
The name of the api key header must be x-api-key rather than the standard Authorization header.