API-Gateway 和 Lambda 部署:Lambda 函数的权限无效

问题描述 投票:0回答:2

我正在尝试使用 Terraform 部署 AWS API 网关和 Lambda。网关只是我的功能的代理。在运行

terraform apply
之后,对端点的每个 Web 请求都失败了。

API 网关将此错误消息记录到 Cloudwatch:

由于配置错误导致执行失败:Lambda 函数的权限无效

但现在它变得很奇怪:如果我点击 AWS Web 控制台中的部署按钮并再次部署(没有其他改变)API 网关,一切正常。下一个“terraform apply”再次部署

aws_api_gateway_stage.staging
,这再次破坏了一切。

这是我的 Terraform 设置:

lambda.tf:

resource "aws_lambda_function" "contactform-api" {
  filename      = "deploy.zip"
  function_name = "contactform-api"
  handler       = "main"
  runtime       = "go1.x"
  role          = "${aws_iam_role.lambda_role.arn}"
  publish       = "false"
  timeout       = "60"
}

resource "aws_iam_role" "lambda_role" {
  name = "iam_for_lambda"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": "IAMRoleForLambda"
    }
  ]
}
EOF
}

resource "aws_lambda_permission" "apigw" {
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = "${aws_lambda_function.contactform-api.arn}"
  principal     = "apigateway.amazonaws.com"
  source_arn    = "${aws_api_gateway_rest_api.contactform.execution_arn}/*/*/*"
}

api_gateway.tf:

resource "aws_api_gateway_rest_api" "contactform" {
  name        = "ContactformAPI"
  description = "Contactform REST API"
}

resource "aws_api_gateway_resource" "api" {
  rest_api_id = "${aws_api_gateway_rest_api.contactform.id}"
  parent_id   = "${aws_api_gateway_rest_api.contactform.root_resource_id}"
  path_part   = "{proxy+}"
}

resource "aws_api_gateway_method" "api" {
  rest_api_id   = "${aws_api_gateway_rest_api.contactform.id}"
  resource_id   = "${aws_api_gateway_resource.api.id}"
  http_method   = "ANY"
  authorization = "NONE"
}

resource "aws_api_gateway_integration" "lambda" {
  rest_api_id             = "${aws_api_gateway_rest_api.contactform.id}"
  resource_id             = "${aws_api_gateway_resource.api.id}"
  http_method             = "${aws_api_gateway_method.api.http_method}"
  integration_http_method = "POST"
  type                    = "AWS_PROXY"
  uri                     = "${aws_lambda_function.contactform-api.invoke_arn}"
}

resource "aws_api_gateway_deployment" "staging" {
  depends_on  = ["module.cors", "aws_api_gateway_method.api", "aws_api_gateway_resource.api", "aws_api_gateway_integration.lambda"]
  stage_name  = "staging"
  rest_api_id = "${aws_api_gateway_rest_api.contactform.id}"
}

resource "aws_api_gateway_stage" "staging" {
  stage_name    = "staging"
  rest_api_id   = "${aws_api_gateway_rest_api.contactform.id}"
  deployment_id = "${aws_api_gateway_deployment.staging.id}"
}
amazon-web-services aws-lambda aws-api-gateway terraform
2个回答
1
投票

您正在使用 Lambda 函数的 ARN 作为您的

function_name
资源中的
aws_lambda_permission

将其更改为名称而不是 ARN 应该可以为您解决该问题:

resource "aws_lambda_permission" "apigw" {
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = "${aws_lambda_function.contactform-api.function_name}"
  principal     = "apigateway.amazonaws.com"
  source_arn    = "${aws_api_gateway_rest_api.contactform.execution_arn}/*/*/*"
}

至于为什么当你通过 AWS 控制台部署时它会起作用; AWS 控制台神奇地为您设置了权限,因此您无需通过 Web UI 进行操作。当 Terraform 重新部署更改时,它会再次破坏它,因为 Terraform 需要明确声明 Lambda 函数的权限。


0
投票

对我来说,问题与在我的函数中使用 :live 的 AutoPublishAlias 有关。我必须使用别名创建集成和权限。当您在控制台中查看基于资源的策略语句时,您也可以直观地看到这一点。您可能会在顶层函数上看到一个与它自己的别名。无论哪种方式,这是我的完整示例,其中 :live 是我的别名。专注于

IntegrationUri
FunctionName
.

WSIntegration:
  Type: AWS::ApiGatewayV2::Integration
  Properties:
    ApiId: !Ref WSApi
    IntegrationType: AWS_PROXY
    IntegrationUri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${RailsLambda.Arn}:live/invocations

WSPermission:
  Type: AWS::Lambda::Permission
  Properties:
    Action: lambda:InvokeFunction
    FunctionName: !Sub "${RailsLambda}:live"
    Principal: apigateway.amazonaws.com
    SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${WSApi}/*

请注意,

SourceArn
展示了比您在大多数
AWS::Lambda::Permission
示例中找到的更好的安全模型。如果您在控制台中执行 ClickOps™,AWS 也是这样做的。只限于特定的 API 网关资源而不是所有资源。干杯你们。

© www.soinside.com 2019 - 2024. All rights reserved.