[英]AWS Cloudformation unable to add permission to Lambda function
I am facing an issue on the Cloudformation template where POST methods are getting created and invoke permissions are being set properly, 我在Cloudformation模板上遇到一个问题,该模板中正在创建POST方法并已正确设置调用权限,
But the GET or any non POST methods are getting created but, 但是正在创建GET或任何非POST方法,但是,
do not seem to have invocation permission being set properly. 似乎没有正确设置调用权限。
Following is the working template with the POST method - 以下是带有POST方法的工作模板-
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS API Gateway with a Lambda Integration
#Creating resusable parameters
Parameters:
CorsOrigin:
Type: String
Default: "'*'"
CorsHeaders:
Type: String
Default: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
CorsMethods:
Type: String
Default: "'OPTIONS,GET,PUT,POST,DELETE'"
Resources:
#Creating Lambda to act as a backend, returning Hello world
BusinessLambda:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: |
exports.handler = async (event) => {
let response = {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json'
},
'body': 'Hello, World!'
};
return response;
};
Description: AWS Lambda function
FunctionName: 'BusinessLambda'
Handler: index.handler
MemorySize: 128
Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/service-role/ScriptRole'
Runtime: nodejs8.10
Timeout: 15
#Creating a Lambda function to act as an Authorizer, returns an allow IAM policy
AuthorizerLambda:
Type: 'AWS::Lambda::Function'
Properties:
FunctionName: 'AuthorizerLambda'
Handler: handler.handler
Runtime: nodejs8.10
Code:
S3Bucket: 'some-bucket-name'
S3Key: 'stage/deployable/authPrivate.zip'
Description: 'Auth test'
MemorySize: 128
Timeout: 15
Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/service-role/ScriptRole'
#Creating an API gateway called => test-api-gw
RestApiGateway:
Type: AWS::ApiGateway::RestApi
Properties:
Name: test-api-gw
ApiKeySourceType: HEADER
Description: An API Gateway with a Lambda Integration
EndpointConfiguration:
Types:
- EDGE
#Creating a url path called => /test
RestApiResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !GetAtt RestApiGateway.RootResourceId
PathPart: 'test'
RestApiId: !Ref RestApiGateway
#Creating an API Gateway Custom Authorizer
RestApiAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
AuthorizerUri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${AuthorizerLambda.Arn}/invocations"
RestApiId: !Ref RestApiGateway
Type: "REQUEST"
IdentitySource: method.request.header.Authorization
Name: custom_authorizer
#Providing permission to Lambda to be used as an Authorizer for the API Gateway
RestApiAuthorizerPermission:
Type: "AWS::Lambda::Permission"
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt AuthorizerLambda.Arn
Principal: "apigateway.amazonaws.com"
SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApiGateway}/authorizers/${RestApiAuthorizer}"
#Creating a POST method with Custom Authorizer
ApiGatewayMethod:
Type: AWS::ApiGateway::Method
Properties:
ApiKeyRequired: false
AuthorizationType: "CUSTOM"
AuthorizerId: !Ref RestApiAuthorizer
HttpMethod: POST
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: "POST"
Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${!stageVariables.lambdaAlias}/invocations'
IntegrationResponses:
- StatusCode: 200
ResponseTemplates:
application/json: $input.json('$')
ResponseParameters:
method.response.header.Access-Control-Allow-Headers: !Ref CorsHeaders
method.response.header.Access-Control-Allow-Methods: !Ref CorsMethods
method.response.header.Access-Control-Allow-Origin: !Ref CorsOrigin
RequestTemplates:
application/json: $input.json('$')
MethodResponses:
- 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'
RequestParameters:
method.request.querystring.name: false
OperationName: 'lambda'
ResourceId: !Ref RestApiResource
RestApiId: !Ref RestApiGateway
#Enabling CORS by creating an OPTIONS method on /test resource path
APIGatewayOptionsMethod:
Type: "AWS::ApiGateway::Method"
Properties:
ResourceId: !Ref RestApiResource
RestApiId: !Ref RestApiGateway
AuthorizationType: NONE
HttpMethod: OPTIONS
Integration:
Type: MOCK
IntegrationResponses:
- ResponseParameters:
method.response.header.Access-Control-Allow-Headers: !Ref CorsHeaders
method.response.header.Access-Control-Allow-Methods: !Ref CorsMethods
method.response.header.Access-Control-Allow-Origin: !Ref CorsOrigin
ResponseTemplates:
application/json: ''
StatusCode: '200'
PassthroughBehavior: WHEN_NO_MATCH
RequestTemplates:
application/json: '{"statusCode": 200}'
MethodResponses:
- ResponseModels:
application/json: 'Empty'
ResponseParameters:
method.response.header.Access-Control-Allow-Headers: false
method.response.header.Access-Control-Allow-Methods: false
method.response.header.Access-Control-Allow-Origin: false
StatusCode: '200'
#Provide permission for API Gateway to Invoke Lambda
LambdaPermission:
Type: "AWS::Lambda::Permission"
Properties:
Action: "lambda:InvokeFunction"
FunctionName: !GetAtt BusinessLambda.Arn
Principal: "apigateway.amazonaws.com"
SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApiGateway}/*/POST/test"
#Deploying the API gateway
ApiGatewayDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn: ApiGatewayMethod
Properties:
Description: Lambda API Deployment
RestApiId: !Ref RestApiGateway
#Create a stage on API Gateway called => dev
ApiGatewayStage:
Type: AWS::ApiGateway::Stage
Properties:
DeploymentId: !Ref ApiGatewayDeployment
Description: API GW Stage dev
RestApiId: !Ref RestApiGateway
StageName: 'dev'
Variables:
'lambdaAlias' : 'BusinessLambda'
But if I change the method to GET, it doesn't work - 但是,如果我将方法更改为GET,它将无法正常工作-
#Creating a GET method with Custom Authorizer
ApiGatewayMethod:
Type: AWS::ApiGateway::Method
Properties:
ApiKeyRequired: false
AuthorizationType: "CUSTOM"
AuthorizerId: !Ref RestApiAuthorizer
HttpMethod: GET
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: "GET"
Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${!stageVariables.lambdaAlias}/invocations'
IntegrationResponses:
- StatusCode: 200
ResponseTemplates:
application/json: $input.json('$')
ResponseParameters:
method.response.header.Access-Control-Allow-Headers: !Ref CorsHeaders
method.response.header.Access-Control-Allow-Methods: !Ref CorsMethods
method.response.header.Access-Control-Allow-Origin: !Ref CorsOrigin
RequestTemplates:
application/json: $input.json('$')
MethodResponses:
- 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'
RequestParameters:
method.request.querystring.name: false
OperationName: 'lambda'
ResourceId: !Ref RestApiResource
RestApiId: !Ref RestApiGateway
#Provide permission for API Gateway to Invoke Lambda
LambdaPermission:
Type: "AWS::Lambda::Permission"
Properties:
Action: "lambda:InvokeFunction"
FunctionName: !GetAtt BusinessLambda.Arn
Principal: "apigateway.amazonaws.com"
SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApiGateway}/*/GET/test"
The code for AuthorizerLambda
is basically this - AuthorizerLambda
的代码基本上是这样的-
https://github.com/awslabs/aws-apigateway-lambda-authorizer-blueprints/blob/master/blueprints/nodejs/index.js https://github.com/awslabs/aws-apigateway-lambda-authorizer-blueprints/blob/master/blueprints/nodejs/index.js
The /test
API work with POST HTTP method
, /test
API与POST HTTP method
,
After changing to GET HTTP method
I get the following error - 更改为GET HTTP method
后,出现以下错误-
{
"message": "Internal server error"
}
I found that in the GET case, the Authorizer is getting called, 我发现在GET情况下,授权者被调用了,
But control doesn't get passed to the Business Lambda function. 但是控制不会传递给Business Lambda函数。
To resolve this - 为了解决这个问题-
1. I have to remove the Authorizer from the method 1.我必须从方法中删除授权者
2. Run the add-permission command using CLI 2.使用CLI运行add-permission命令
3. Deploy the API 3.部署API
4. Add the Authorizer to the method 4.将授权者添加到方法中
5. Deploy again 5.再次部署
Related issue - 相关问题-
https://forums.aws.amazon.com/thread.jspa?threadID=240699 https://forums.aws.amazon.com/thread.jspa?threadID=240699
Do I need to do something like this - 我需要做这样的事情-
ApiGatewayMethod:
Type: AWS::ApiGateway::Method
Properties:
ApiKeyRequired: false
AuthorizationType: "CUSTOM"
AuthorizerId: !Ref RestApiAuthorizer
HttpMethod: GET
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: "POST"
Got this resolved by making IntegrationHttpMethod: "POST"
, 通过使IntegrationHttpMethod: "POST"
解决了此问题,
So irrespective of the Method's HTTP type, 因此,无论方法的HTTP类型如何,
The IntegrationHttpMethod must always be POST it seems. 看起来,IntegrationHttpMethod必须始终为POST。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.