i use the serverless framework and would like to deploy an API Gateway HTTP Proxy but i don't have a Lambda function connected with API Gateway.
I found this in the internet, but this example require one lambda function connected to API Gateway
# ProxyResource:
# Type: AWS::ApiGateway::Resource
# Properties:
# ParentId:
# Fn::GetAtt:
# - ApiGatewayRestApi # our default Rest API logical ID
# - RootResourceId
# PathPart: serverless # 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://serverless.com # the URL you want to set a proxy to
# IntegrationResponses:
# - StatusCode: 200
If i deploy this i got the error:
The CloudFormation template is invalid: Template format error: Unresolved resource dependencies [ApiGatewayRestApi] in the Resources block of the template
It is possible to deploy just an API Gateway HTTP Proxy ?
Thanks
I figure out how to create an API Gateway if i don't have any lambda function in serverless. I just need to add this to resources and change Ref: ApiGatewayRestApi to Ref: ProxyApi
resources:
Resources:
ProxyApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: ApiGateway
To fulfill my requirement to use AppSync without any ApiKey - it's possible with these lines:
ProxyApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: AppSync Graph Proxy
ProxyResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId:
Fn::GetAtt:
- ProxyApi # our default Rest API logical ID
- RootResourceId
PathPart: graphql # the endpoint in your API that is set as proxy
RestApiId:
Ref: ProxyApi
ProxyMethod:
Type: AWS::ApiGateway::Method
Properties:
ResourceId:
Ref: ProxyResource
RestApiId:
Ref: ProxyApi
AuthorizationType: NONE
HttpMethod: ANY # the method of your proxy. Is it GET or POST or ... ?
MethodResponses:
- StatusCode: 200
Integration:
IntegrationHttpMethod: POST
Type: HTTP
Uri: { Fn::GetAtt: [GraphQlApi, GraphQLUrl] } # the URL you want to set a proxy to
IntegrationResponses:
- StatusCode: 200
RequestParameters:
"integration.request.header.x-api-key": "stageVariables.API_KEY"
ProxyDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn: "ProxyMethod"
Properties:
RestApiId:
Ref: ProxyApi
ProxyStage:
Type: AWS::ApiGateway::Stage
Properties:
StageName: ${opt:stage, self:provider.stage}
RestApiId:
Ref: ProxyApi
DeploymentId:
Ref: ProxyDeployment
Variables:
API_KEY: { Fn::GetAtt: [GraphQlApiKeyDefault, ApiKey] }
For this, you need an working and configured serverless-appsync-plugin in your serverless config
Related
I need to create an API endpoint, which will trigger a Lambda function and return an image from an S3 bucket.
Example URL: https://abc.execute-api.eu-west-1.amazonaws.com/dev/xyz/00/01/23911414.jpeg
I created an APIGateway instance manually using the web console and it’s working fine.
And I created the same (I guess) using CloudFormation and it’s not working.
The Lambda gets triggered, but it doesn't get the path parameter in the event.
But I want the Lambda function to get /xyz/00/01/23911414.jpeg as the event['path'].
Here is a part of my CloudFormation Template:
RestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Description: Example API Gateway
EndpointConfiguration:
Types:
- REGIONAL
Name: imaginary-api
ProxyResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref RestApi
ParentId: !GetAtt
- RestApi
- RootResourceId
PathPart: '{proxy+}'
ProxyResourceANY:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RestApi
ResourceId: !Ref ProxyResource
HttpMethod: ANY
AuthorizationType: NONE
MethodResponses:
- StatusCode: 200
Integration:
Type: AWS
IntegrationHttpMethod: POST
Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImaginaryLambda.Arn}/invocations
Credentials: !GetAtt ApiGatewayIamRole.Arn
PassthroughBehavior: WHEN_NO_TEMPLATES
RequestTemplates:
"image/jpeg": ""
"image/jpg": ""
IntegrationResponses:
- StatusCode: 200
RestAPIDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn:
- ProxyResource
Properties:
RestApiId: !Ref RestApi
StageName: dev
ImaginaryInvoke:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt ImaginaryLambda.Arn
Principal: apigateway.amazonaws.com
SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:abc/dev
This is the first time I'm using APIGateway and I might have done something wrong here. Any help would be highly appreciated.
UPDATE:
Adding RequestParameters to the Method won't work either.
RequestParameters:
method.request.path.proxy: true
You have different possible integrations:
aws (requires data mapping)
aws_proxy
mock
http
http_proxy
The AWS integration type requires data mapping to get the required attributes (check https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html).
You can use AWS_PROXY to get the complete event (check: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format) including the path attribute.
You can return binary file (be careful with content length) or return a s3 presigned url (thru a redirection for example).
Let me answer my own question.
I was able to fix this with the following values.
RestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Description: Example API Gateway
BinaryMediaTypes:
- "*/*" # <-- Important
EndpointConfiguration:
Types:
- REGIONAL
Name: imaginary-api
ProxyResourceANY:
Type: AWS::ApiGateway::Method
DependsOn:
ProxyResource
Properties:
RestApiId: !Ref RestApi
ResourceId: !Ref ProxyResource
HttpMethod: ANY
AuthorizationType: NONE
RequestParameters:
method.request.path.proxy: true # <-- Important
MethodResponses:
- StatusCode: 200
Integration:
Type: AWS_PROXY # <-- Important
IntegrationHttpMethod: POST
ContentHandling: CONVERT_TO_TEXT # <-- Important, depends on your code
PassthroughBehavior: WHEN_NO_MATCH
Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImaginaryLambda.Arn}/invocations
Credentials: !GetAtt ApiGatewayIamRole.Arn
Something strange I noticed is, even though the manually created one showed as AWS in the web console, it showed as AWS_PROXY when I exported the stage as a Swagger definition.
Comparing the two Swagger definitions helped me a lot comparing the YAMLs taken out from Export as Swagger + API Gateway Extensions option.
I am trying to create an AWS API gateway using cloud formation yaml template which integrate with HTTP function but could not succeed.
Anyone having experience on this please help.
Snippets i am using:
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS API Gateway with a HTTP Integration
Resources:
ApiGatewayRestApi:
Type: AWS::ApiGateway::RestApi
Properties:
ApiKeySourceType: HEADER
Description: An API Gateway with a HTTP Integration
EndpointConfiguration:
Types:
- EDGE
Name: HTTP-api
ApiGatewayResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !GetAtt ApiGatewayRestApi.RootResourceId
PathPart: 'HTTP'
RestApiId: !Ref ApiGatewayRestApi
ApiGatewayMethod:
Type: AWS::ApiGateway::Method
Properties:
ApiKeyRequired: false
AuthorizationType: NONE
HttpMethod: POST
Integration:
ConnectionType: INTERNET
IntegrationResponses:
Uri: !Sub 'http://www.msn.com/'
Type: HTTP
TimeoutInMillis: 29000
MethodResponses:
- ResponseModels:
application/json: !Ref ApiGatewayModel
StatusCode: 200
- ResponseModels:
application/json: !Ref ApiGatewayModel
StatusCode: 500
OperationName: 'HTTP'
ResourceId: !Ref ApiGatewayResource
RestApiId: !Ref ApiGatewayRestApi
ApiGatewayModel:
Type: AWS::ApiGateway::Model
Properties:
ContentType: 'application/json'
RestApiId: !Ref ApiGatewayRestApi
Schema: {}
ApiGatewayStage:
Type: AWS::ApiGateway::Stage
Properties:
DeploymentId: !Ref ApiGatewayDeployment
Description: HTTP API Stage v0
RestApiId: !Ref ApiGatewayRestApi
StageName: 'v0'
ApiGatewayDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn: ApiGatewayMethod
Properties:
Description: HTTP API Deployment
RestApiId: !Ref ApiGatewayRestApi
Thanks,
Sanjeev
I have a serverless app with a http event. I need to create a child resource to the endpoint created by serverless.
How can I accomplish this with serverless?
The template looks like this so far:
provider:
name: aws
runtime: nodejs8.10
region: <REGION>
functions:
myFunc:
timeout: 30
handler: "index.handler"
name: "myFunc"
events:
- http:
path: /myFunc
method: post
cors: true
resources:
Resources:
saysResource:
Type: "AWS::ApiGateway::Resource"
Properties:
RestApiId:
Ref: ApiGatewayRestApi
ParentId:
Ref: <NEED_/myFunc_RESOURCE_ID_HERE>
PathPart: "{says}"
GetMethod:
Type: "AWS::ApiGateway::Method"
Properties:
HttpMethod: GET
RequestParameters:
'method.request.path.says': true
RestApiId:
Ref: ApiGatewayRestApi
ResourceId:
Ref: saysResource
Integration:
Type: aws
Credentials:
Ref: S3ReadAccessRole
IntegrationHttpMethod: GET
PassthroughBehavior: WHEN_NO_MATCH
RequestParameters:
'integration.request.path.key': 'method.request.path.says'
Uri: 'arn:aws:s3:::my-bucket/users/{key}'
As an attempt to get it working, I re-declaration of the resource for /myFunc was performed(hoping that CFN would not create already created resources):
myFuncResource:
Type: "AWS::ApiGateway::Resource"
Properties:
RestApiId:
Ref: ApiGatewayRestApi
ParentId:
Fn::GetAtt:
- ApiGatewayRestApi
- RootResourceId
PathPart: "/myFunc"
This failed with the error:
An error occurred: myFuncResource - Another resource with the same parent
already has this name: my-func (Service: AmazonApiGateway; Status Code:
409; Error Code: ConflictException; Request ID: <Request_Id>).
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
I'm trying to create an API Gateway, which uses an AWS_IAM Authorizer, and using Amplify to sign in to my app using Federated Identities.
This all works fine, however I'm not getting an identity in my backend service.
What I want is to be able to access the identity of the user in my backend service. Eg a header with a user-id or something like that.
I've been looking at this example: https://github.com/matsev/cloudformation-api-gateway/blob/master/cloudformation.template to try to map the $context, however it seems it doesn't work with HTTP_PROXY?
RefreshProxy:
Type: AWS::ApiGateway::Resource
Properties:
ParentId:
Ref: SomeOtherHandler
PathPart: '{proxy+}'
RestApiId:
Ref: ApiGatewayRestApi
RefreshProxyMethod:
Type: AWS::ApiGateway::Method
Properties:
ResourceId:
Ref: RefreshProxy
RestApiId:
Ref: ApiGatewayRestApi
AuthorizationType: AWS_IAM
HttpMethod: POST
RequestParameters:
method.request.path.proxy: true
Integration:
IntegrationHttpMethod: POST
Type: HTTP_PROXY
Uri: url/{proxy}
IntegrationResponses:
- StatusCode: 200
RequestParameters:
integration.request.path.proxy: method.request.path.proxy
integration.request.header.Accept-Encoding: "'identity'"
PassthroughBehavior: WHEN_NO_MATCH
You need to add a header with the cognitoIdentityId from the context. So in the integration section you need:
integration.request.header.Identity: context.identity.cognitoIdentityId