【问题标题】:rest api calling lambda function , terraform deploymentrest api 调用 lambda 函数,terraform 部署
【发布时间】:2023-02-21 03:18:34
【问题描述】:

我在 terraform 中设置 rest api 以调用 lambda 函数时遇到问题。我遗漏了一些东西,因为当我从 terraform 部署 lambda 函数并从具有相同配置的 aws 控制台手动创建 rest api 时(已经检查控制台配置 5 次,它与使用 terraform 部署的相同)。因此,当我使用 terraform 进行部署时,我会得到 {"message": "Internal server error"} 响应。在我的 lambda、rest api 和 ham 的 terraform 代码下方。知道我在 terraform conf 中遗漏了什么。很确定我在其余的 api 部分遗漏了一些东西......

resource "aws_api_gateway_rest_api" "search_api" {
  name = "search_api"
  endpoint_configuration {
    types = ["REGIONAL"]
  }
}

resource "aws_api_gateway_resource" "search_api" {
  rest_api_id = aws_api_gateway_rest_api.search_api.id
  parent_id   = aws_api_gateway_rest_api.search_api.root_resource_id
  path_part   = "search"
}

resource "aws_api_gateway_method" "search_api" {
  rest_api_id   = aws_api_gateway_rest_api.search_api.id
  resource_id   = aws_api_gateway_resource.search_api.id
  http_method   = "GET"
  authorization = "NONE"
}

resource "aws_api_gateway_method_response" "response_200" {
  rest_api_id = aws_api_gateway_rest_api.search_api.id
  resource_id = aws_api_gateway_resource.search_api.id
  http_method = aws_api_gateway_method.search_api.http_method
  status_code = "200"

  response_models = {
    "application/json" = null
  }
}

resource "aws_api_gateway_integration" "search_api" {
  rest_api_id             = aws_api_gateway_rest_api.search_api.id
  resource_id             = aws_api_gateway_resource.search_api.id
  http_method             = aws_api_gateway_method.search_api.http_method
  integration_http_method = "GET"
  type                    = "AWS"
  uri                     = aws_lambda_function.lambda_search_py.invoke_arn
  credentials = aws_iam_role.search_py_lambda_execution.arn

  request_templates = {
    "application/json" = jsonencode(
      {
        name = "$input.params('name')"
    })
  }

  depends_on = [aws_lambda_permission.lambda_search_py]
}

resource "aws_api_gateway_integration_response" "search_api" {
  http_method = aws_api_gateway_method.search_api.http_method
  resource_id = aws_api_gateway_resource.search_api.id
  rest_api_id = aws_api_gateway_rest_api.search_api.id
  status_code = aws_api_gateway_method_response.response_200.status_code

  depends_on = [
    aws_api_gateway_integration.search_api
  ]
}

resource "aws_api_gateway_deployment" "search_api" {
  rest_api_id = aws_api_gateway_rest_api.search_api.id
  stage_name  = "test"

  depends_on = [aws_api_gateway_integration.search_api]
}

output "search_api_url" {
  value = aws_api_gateway_deployment.search_api.invoke_url
}

resource "aws_lambda_function" "lambda_search_py" {
  function_name    = "SearchField"
  s3_bucket        = aws_s3_bucket.lambda.id
  s3_key           = aws_s3_object.s3_search_py.key
  runtime          = "python3.9"
  handler          = "lambda_function.lambda_handler"
  source_code_hash = data.archive_file.data_lambda_search_py.output_base64sha256
  role             = aws_iam_role.lambda_role.arn

  vpc_config {
    subnet_ids         = [data.terraform_remote_state.infra.outputs.subnet_main_prv1a_id, data.terraform_remote_state.infra.outputs.subnet_main_prv2b_id]
    security_group_ids = [data.terraform_remote_state.infra.outputs.secgrp_ec2_id]
  }
}

resource "aws_lambda_permission" "lambda_search_py" {
  statement_id  = "AllowAPIGatewayInvoke"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.lambda_search_py.function_name
  principal     = "apigateway.amazonaws.com"
  source_arn    = "${aws_api_gateway_rest_api.search_api.execution_arn}/*/GET/search"
}

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

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Sid    = ""
      Principal = {
        Service = "lambda.amazonaws.com"
      }
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "AWSLambda_FullAccess" {
  role       = aws_iam_role.lambda_role.name
  policy_arn = "arn:aws:iam::aws:policy/AWSLambda_FullAccess"
}

resource "aws_iam_role_policy_attachment" "AWSLambdaVPCAccessExecutionRole" {
  role       = aws_iam_role.lambda_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
}


resource "aws_iam_role" "search_py_lambda_execution" {
  name = "lambda_execution"
  
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "apigateway.amazonaws.com"
        }
      }
    ]
  })
}
  
resource "aws_iam_policy" "search_py_lambda_execution" {
  name = "search_py_lambda_execution"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "lambda:InvokeFunction"
        Effect = "Allow"
        Resource = "*"
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "search_py_lambda_execution1" {
  role = aws_iam_role.search_py_lambda_execution.name
  policy_arn = aws_iam_policy.search_py_lambda_execution.arn
}

resource "aws_iam_role_policy_attachment" "AmazonAPIGatewayInvokeFullAccess" {
  role = aws_iam_role.search_py_lambda_execution.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonAPIGatewayInvokeFullAccess"
}

我收到内部服务器错误,当我调用 rest api 时,我应该从 lambda 函数得到响应。如果我只从 Amazon 控制台创建 rest api 那么它就可以工作

【问题讨论】:

  • 对于 Lambda,我认为您可能需要使用 integration_http_method = "POST"type = "AWS_PROXY"
  • 这是权限问题吗?您是否拥有在 TF 中具有正确权限的 AWS 凭证?
  • @LHWizard aws 凭据没问题我可以部署到 terraform 我的 api gw 和所有 necesarry
  • 我启用了日志记录并想到了以下内容,但不知道在从 aws 控制台部署相同内容时我缺少什么访问问题 (e1770769-c366-4097-b301-446d82d15437) 转换前的端点响应正文: <AccessDeniedException> <Message>无法确定要授权的服务/操作名称</Message></AccessDeniedException> (e1770769-c366-4097-b301-446d82d15437) Lambda 调用失败,状态:403。Lambda 请求 ID:adf1a992-6ca6 -4974-b0e8-d7163cd68910 (e1770769-c366-4097-b301-446d82d15437) 由于配置错误导致执行失败:
  • @MarkoE 谢谢你的建议,我把 post 作为集成,它起作用了,对于我不想使用代理集成的类型,所以我把它留给了 AWS。它现在正在工作,所以解决方案是使用 integration_http_method = "POST"

标签: aws-lambda terraform aws-api-gateway terraform-provider-aws


【解决方案1】:

使用 integration_http_method = "POST" 并且有效,感谢 Marko E 的建议

【讨论】:

    猜你喜欢
    • 2019-04-12
    • 2018-08-12
    • 1970-01-01
    • 2018-07-28
    • 1970-01-01
    • 2021-04-08
    • 2021-07-29
    • 2022-07-22
    • 1970-01-01
    相关资源
    最近更新 更多