简体   繁体   English

CloudFormation:Lambda函数的无效权限

[英]CloudFormation: Invalid permissions on Lambda function

I am trying to create an Api-Gateway as a Lambda proxy using just CloudFormation. 我正在尝试仅使用CloudFormation将Api网关创建为Lambda代理。 There seems to be an issue with getting the correct permissions on the Lambda function even though I have looked all over and seemingly tried everything possible, I am getting nowhere. 即使我四处张望并且似乎已尝试了所有可能的方法,但对Lambda函数获得正确的权限似乎仍然存在问题,但是我却一无所获。 The documentation around some important small details seem to be missing, (or I am just misinterpreting them?). 一些重要的小细节的文档似乎丢失了(或者我只是在误解它们?)。

Here is what I have: 这是我所拥有的:

    {
        "Description": "",
        "Parameters": {
            "IngressLambdaName": {
                "Type": "String",
                "Description": "Name of the lambda behind Api Gateway",
                "Default": "LambdaIngress"
            }
        },

        "Mappings": {

        },

        "Resources": {
            "ApiGatewayToLambdaRole": {
                "Type": "AWS::IAM::Role",
                "Properties": {
                    "AssumeRolePolicyDocument": {
                        "Version": "2012-10-17",
                        "Statement": [ {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [ "apigateway.amazonaws.com" ]
                            },
                            "Action": "sts:AssumeRole"
                        }]
                    },
                    "Policies": [{
                        "PolicyName": "ApiGatewayToLambdaPolicy",
                        "PolicyDocument": {
                            "Version": "2012-10-17",
                            "Statement": [{
                                "Effect": "Allow",
                                "Action": [
                                    "lambda:InvokeFunction"
                                ],
                                "Resource": "*"
                            }]
                        }
                    }]
                }
            },

            "IngressLambda":{
                "Type": "AWS::Lambda::Function",
                "Properties": {
                    "Handler": "index.handler",
                    "FunctionName": {"Ref": "IngressLambdaName"},
                    "Runtime": "nodejs4.3",
                    "Role": { "Fn::GetAtt": ["**Role that isn't shown here**", "Arn"]},
                    "Code": {
                        "ZipFile": { "Fn::Join": ["", [
                            "exports.handler = function(event, context) {",
                    "  console.log('invoked the lambda!');",
                    "  context.succeed({statusCode: 200, headers: {}, body: JSON.stringify({message: 'invoked the lambda!'})});",
                    "};"
                        ]]}
                    }
                }

            },

            "IngressLambdaPermission":{
                "Type" : "AWS::Lambda::Permission",
                "Properties" : {
                    "Action" : "lambda:InvokeFunction",
                    "FunctionName" : { "Ref" : "IngressLambdaName"},
                    "Principal" : "apigateway.amazonaws.com",
                    "SourceArn" : {"Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/*"}
                },
                "DependsOn": ["IngressLambda"]
            },

            "RestApi": {
                "Type": "AWS::ApiGateway::RestApi",
                "Properties": {
                    "Name": "API Gateway"
                }
            },

            "TagModel": {
                "Type": "AWS::ApiGateway::Model",
                "Properties": {
                    "ContentType": "application/json",
                    "Name": "Tag",
                    "RestApiId": { "Ref": "RestApi" },
                    "Schema": {
                        "$schema": "http://json-schema.org/draft-04/schema#",
                        "title": "TagModel",
                        "type": "object",
                        "properties": {
                            "payload": {"type": "object"},
                            "domain": {"type": "string"}
                        }
                    }
                }
            },

            "TagsResource": {
                "Type": "AWS::ApiGateway::Resource",
                "Properties": {
                    "RestApiId": { "Ref": "RestApi" },
                    "ParentId": { "Fn::GetAtt": ["RestApi", "RootResourceId"] },
                    "PathPart": "tag"
                }
            },

            "TagsPost": {
                "Type": "AWS::ApiGateway::Method",
                "Properties": {
                    "ApiKeyRequired": "False",
                    "AuthorizationType": "NONE",
                    "HttpMethod": "POST",
                    "RestApiId": {"Ref": "RestApi"},
                    "ResourceId": { "Fn::GetAtt": ["RestApi", "RootResourceId"] },
                    "Integration": {
                        "Type": "AWS_PROXY",
                        "IntegrationHttpMethod": "POST",
                        "PassthroughBehavior": "NEVER", 
                        "Uri": {"Fn::Join" : ["", ["arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/", {"Fn::GetAtt": ["IngressLambda", "Arn"]}, "/invocations"]]}
                    }
                }
            },

            "RestApiDeployment": {
                "Type": "AWS::ApiGateway::Deployment",
                "Properties": {
                    "RestApiId": { "Ref": "RestApi" },
                    "StageName": "v1"
                },
                "DependsOn": ["RestApi", "TagModel", "TagsResource", "TagsPost"]
            },

        },

        "Outputs": {

        }

    }

When running the test in API Gateway in the aws web portal console, i get the error: Execution failed due to configuration error: Invalid permissions on Lambda function 在AWS Web Portal控制台的API Gateway中运行测试时,出现错误: Execution failed due to configuration error: Invalid permissions on Lambda function

This is driving me mad. 这让我发疯。 Any direction here would be great. 这里的任何方向都很好。 I would guess that my Permission is wrong somehow, but I am not sure how (this is where I struggle with the documentation). 我想我的Permission某种程度上是错误的,但是我不确定如何(这是我在文档中苦苦挣扎的地方)。

According to the API Gateway documentation section Resource Format of Permissions for Executing API in API Gateway , the SourceArn property should have the following structure: 根据API网关文档的“ API网关中执行API的权限的资源格式”部分, SourceArn属性应具有以下结构:

arn:aws:execute-api: region : account-id : api-id / stage-name / HTTP-VERB / resource-path-specifier arn:aws:execute-api: regionaccount-idapi-id / stage-name / HTTP-VERB / resource-path-specifier

where: 哪里:

  • region is the AWS region (such as us-east-1 or * for all AWS regions) that corresponds to the deployed API for the method. region是与该方法的已部署API对应的AWS区域(例如us-east-1或*对于所有AWS区域)。
  • account-id is the 12-digit AWS account Id of the REST API owner. account-id是REST API所有者的12位数字的AWS账户ID。
  • api-id is the identifier API Gateway has assigned to the API for the method. api-id是API网关已分配给该方法的API的标识符。 ( * can be used for all APIs, regardless of the API's identifier.) *可以用于所有API,与API的标识符无关。)
  • stage-name is the name of the stage associated with the method ( * can be used for all stages, regardless of the stage's name.) stage-name是与方法关联的阶段的名称( *可以用于所有阶段,而不管阶段的名称如何。)
  • HTTP-VERB is the HTTP verb for the method. HTTP-VERB是该方法的HTTP动词。 It can be one of the following: GET , POST , PUT , DELETE , PATCH , HEAD , OPTIONS . 它可以是以下之一: GETPOSTPUTDELETEPATCHHEADOPTIONS
  • resource-path-specifier is the path to the desired method. resource-path-specifier是所需方法的路径。 ( * can be used for all paths). *可以用于所有路径)。

Your current template provided: 您当前的模板提供了:

arn:aws:execute-api:us-west-2::${RestApi.RootResourceId}/null/POST

Try something like this (using Fn::Sub and ${} syntax to simplify references): 尝试这样的事情(使用Fn::Sub${}语法简化引用):

arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/*

In addition, a proxy-integration Lambda function must return output according to the Output Format of a Lambda Function for Proxy Integration , otherwise it will return a 502 Bad Gateway error: 此外,代理集成Lambda函数必须根据用于代理集成的Lambda函数输出格式返回输出,否则它将返回502 Bad Gateway错误:

{
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "body": "..."
}

Change your Lambda function to the following: 将您的Lambda函数更改为以下内容:

exports.handler = function(event, context) {
  context.succeed({statusCode: 200, headers: {}, body: "invoked the lambda!"});
};

Here's a complete, self-contained, working example template that demonstrates a properly-executing Lambda proxy function from an API Gateway (I've converted the original example to YAML for readability): 这是一个完整的,独立的工作示例模板,演示了从API网关正确执行的Lambda代理功能(出于可读性,我已将原始示例转换为YAML):

启动堆栈

Resources:
  ApiGatewayToLambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Principal: {Service: [apigateway.amazonaws.com]}
          Action: "sts:AssumeRole"
      Policies:
      - PolicyName: ApiGatewayToLambdaPolicy
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Action: ["lambda:InvokeFunction"]
            Resource: "*"
  IngressLambda:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs4.3
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: !Sub |
          exports.handler = (event, context) =>
            context.succeed({statusCode: 200, headers: {}, body: "Invoked the Lambda!"});
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal: {Service: [lambda.amazonaws.com]}
          Action: ['sts:AssumeRole']
      Path: /
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
  IngressLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !Ref IngressLambda
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/POST/*"
  RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: API Gateway
  TagModel:
    Type: AWS::ApiGateway::Model
    Properties:
      ContentType: application/json
      Name: Tag
      RestApiId: !Ref RestApi
      Schema:
        $schema: "http://json-schema.org/draft-04/schema#"
        title: TagModel
        type: object
        properties:
          payload: {type: object}
          domain: {type: string}
  TagsResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      RestApiId: !Ref RestApi
      ParentId: !GetAtt RestApi.RootResourceId
      PathPart: tag
  TagsPost:
    Type: AWS::ApiGateway::Method
    Properties:
      ApiKeyRequired: False
      AuthorizationType: NONE
      HttpMethod: POST
      RestApiId: !Ref RestApi
      ResourceId: !GetAtt RestApi.RootResourceId
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        PassthroughBehavior: NEVER
        Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${IngressLambda.Arn}/invocations"
  RestApiDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn: [RestApi, TagModel, TagsResource, TagsPost]
    Properties:
      RestApiId: !Ref RestApi
      StageName: v1
  HttpRequestFunction:
    Type: AWS::Lambda::Function
    Properties:
      Description: Returns an HTTP request as a Custom Resource
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: !Sub |
          var response = require('cfn-response');
          exports.handler = (event, context) => {
              console.log("Request received:\n", JSON.stringify(event));
              var success = data => response.send(event, context, response.SUCCESS, data);
              var failed = e => response.send(event, context, response.FAILED, e);
              process.on('uncaughtException', e=>failed(e));
            try {
              if (event.RequestType == 'Delete') { return success({}); }
              var https = require("https");
              var url = require("url");
              var parsedUrl = url.parse(event.ResourceProperties.Url);
              var options = {
                hostname: parsedUrl.hostname,
                path: parsedUrl.path,
                method: event.ResourceProperties.Method || 'GET',
              };
              var request = https.request(options, response => {
                console.log("Status code: " + response.statusCode);
                console.log("Status message: " + response.statusMessage);
                var body = '';
                response.setEncoding('utf8');
                response.on('data', chunk => body += chunk);
                response.on('end', ()=>success({Data: body}));
              });
              request.on("error", e=>failed(e));
              request.end();
            } catch (e) { failed(e); }
          };
      Timeout: 30
      Runtime: nodejs4.3
  HttpRequest:
    Type: Custom::HttpRequest
    DependsOn: RestApiDeployment
    Properties:
      ServiceToken: !GetAtt HttpRequestFunction.Arn
      Url: !Sub "https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/v1"
      Method: POST
Outputs:
  Result:
    Value: !GetAtt HttpRequest.Data

This stack returns Invoked the lambda! 该堆栈返回Invoked the lambda! in its Stack Outputs, indicating a successful HTTP request to the newly-created API Gateway backed by the simple Lambda function. 在其堆栈输出中,表示通过简单的Lambda函数支持的对新创建的API网关的成功HTTP请求。 If it fails, it's possible your CloudFormation stack is lacking IAM permissions or there are unsupported services in your AWS region. 如果失败,则可能是您的CloudFormation堆栈缺少IAM权限,或者您的AWS区域中有不受支持的服务。

Similar to wjordan's recent comment, I think the source arn is the problem. 与wjordan最近的评论类似,我认为问题源于arn。 It should be of a format like this: 它应该是这样的格式:

arn:aws:execute-api:REGION:ACCOUNT_ID:API_ID/*/*/API_NAME

because this is how I execute the command with CLI: 因为这是我使用CLI执行命令的方式:

aws lambda add-permission --function-name ${FUNCTION_ARN} --action "lambda:InvokeFunction" --statement-id 1 --principal apigateway.amazonaws.com --source-arn "arn:aws:execute-api:"${REGION}":"${ACCOUNT_ID}":"${API_ID}"/*/*/"${API_NAME}

I did some digging and it may be due to because you missed the Account ID. 我做了一些挖掘,可能是由于您错过了帐户ID。 I'm editing my answer based on Michael Wittig's example on GitHub: https://github.com/AWSinAction/apigateway/blob/master/template.json 我正在基于Michael Wittig在GitHub上的示例来编辑答案: https : //github.com/AWSinAction/apigateway/blob/master/template.json

Yours: 你:

"SourceArn" : { "Fn::Join" : ["", ["arn:aws:execute-api:us-west-2::", {"Fn::GetAtt": ["RestApi", "RootResourceId"]}, "/null/POST" ]]}

His: 他:

"SourceArn": {"Fn::Join": ["", ["arn:aws:execute-api:", {"Ref": "AWS::Region"}, ":", {"Ref": "AWS::AccountId"}, ":", {"Ref": "RestApi"}, "/*"]]}

Notice how he used the reference: 注意他如何使用该引用:

{"Ref": "AWS::AccountId"}

Amazon says that "ARNs for some resources don't require an account number, so this component might be omitted." 亚马逊表示: “某些资源的ARN不需要帐号,因此可以省略此组件。” but it's unclear which ones require and which don't. 但目前尚不清楚哪些要求,哪些不需要。

Reference: http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html 参考: http : //docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html

your ApiGateway may not have right to call your lambda function. 您的ApiGateway可能无权调用您的lambda函数。 try below steps; 请尝试以下步骤;

select your API Gateway Rest end point select resources select one of your methods select 'Integration Request' click edit button next to your 'Lambda Function' click confirm button, this step will ask you to approve you are giving right your ApiGateway to call your lambda function confirm the access right 选择您的API Gateway Rest端点选择资源选择一种方法选择“集成请求”单击“ Lambda函数”旁边的编辑按钮单击确认按钮,此步骤将要求您批准您授予您的ApiGateway调用您的lambda的权限功能确认访问权限

--- now you can retest your method ---现在您可以重新测试您的方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 AWS Cloudformation:“Lambda 函数的权限无效”怎么了? - AWS Cloudformation: “Invalid permissions on Lambda function” What's wrong? API-Gateway 和 Lambda 部署:Lambda 函数的权限无效 - API-Gateway and Lambda deploy: Invalid permissions on Lambda function 带有代理 Lambda 的 AWS API Gatewat:Lambda 函数的权限无效 - AWS API Gatewat with proxy Lambda: Invalid permissions on Lambda function AWS CloudFormation中的Lambda函数 - Lambda Function in AWS CloudFormation AWS Cloudformation:授予Cloudwatch *调用Lambda的权限 - AWS Cloudformation: Give Cloudwatch * Permissions to invoke Lambda CLI - 由于配置错误,执行失败:Lambda function 上的权限无效 - CLI - Execution failed due to configuration error: Invalid permissions on Lambda function CloudFormation:将列表传递给Lambda函数 - CloudFormation: Pass List to Lambda Function CloudFormation - 无法创建 Lambda 函数 - CloudFormation - not able to create Lambda Function CloudFormation模板中的Lambda资源将CodeUri报告为无效 - Lambda Resource in CloudFormation Template Reports CodeUri as Invalid AWS APIGateway Lambda代理集成 - 由于配置错误导致执行失败:Lambda函数的权限无效 - AWS APIGateway Lambda proxy integration- Execution failed due to configuration error: Invalid permissions on Lambda function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM