AWS - 从公共 API 网关到 VPC 内 lambda 的路由

Posted

技术标签:

【中文标题】AWS - 从公共 API 网关到 VPC 内 lambda 的路由【英文标题】:AWS - Route from public API Gateway to in-VPC lambda 【发布时间】:2020-06-25 23:07:00 【问题描述】:

问题

从面向公众的 AWS 网络中的 API 网关到流量经过的 VPC 子网中的 Lambda 函数?

Introducing Amazon API Gateway Private Endpoints

通过此次发布,您可以构建不需要公开可用端点的基于 API 的服务。他们仍然可以与您的 VPC 内的私有服务(例如数据库)进行交互。

背景

当 lambda 不在 VPC 中(在 AWS 面向公众的网络中)时,流量会通过 Internet。但不确定 lambda 何时在 VPC 中。

通过 AWS 控制台,我在 VPC 中创建了一个 lambda 函数,并确认 API 网关(VPC 中没有)可以连接到 VPC 中的 lambda。

由于 lambda 在 VPC 中的子网中,它没有公共 IP,所以它不应该通过 Internet。但是,如API Gateway Private Integration 中所述,没有用于从 API 网关连接到 VPC 中的 NLB 的 VPC 专用链接。

因此我不知道交通流向何处。

地形

Terraform aws_api_gateway_integration 资源,connection_type 说:

(可选)集成输入的连接类型。有效值为 INTERNET(默认用于通过公共可路由互联网的连接)和 VPC_LINK(用于 API 网关和 VPC 中的网络负载均衡器之间的私有连接)。

因此,它看起来可能会通过 Internet,因为 connection_type 默认为 INTERNET,而 VPC_LINK 目前用于 API Gateway Private Integration with NLB。

# Variables
variable "myregion" 
  default = "us-east-2"


variable "accountId" 

  default = var.account_id


# API Gateway
resource "aws_api_gateway_rest_api" "api" 
  name = "api-lambda-vpc-test"


resource "aws_api_gateway_resource" "resource" 
  path_part   = "resource"
  parent_id   = "$aws_api_gateway_rest_api.api.root_resource_id"
  rest_api_id = "$aws_api_gateway_rest_api.api.id"


resource "aws_api_gateway_method" "method" 
  rest_api_id   = "$aws_api_gateway_rest_api.api.id"
  resource_id   = "$aws_api_gateway_resource.resource.id"
  http_method   = "GET"
  authorization = "NONE"


resource "aws_api_gateway_integration" "integration" 
  rest_api_id             = "$aws_api_gateway_rest_api.api.id"
  resource_id             = "$aws_api_gateway_resource.resource.id"
  http_method             = "$aws_api_gateway_method.method.http_method"
  integration_http_method = "POST"
  type                    = "AWS_PROXY"
  uri                     = "$aws_lambda_function.lambda.invoke_arn"


# Lambda
resource "aws_lambda_permission" "apigw_lambda" 
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = "$aws_lambda_function.lambda.function_name"
  principal     = "apigateway.amazonaws.com"

  # More: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-control-access-using-iam-policies-to-invoke-api.html
  source_arn = "arn:aws:execute-api:$var.myregion:$var.accountId:$aws_api_gateway_rest_api.api.id/*/$aws_api_gateway_method.method.http_method$aws_api_gateway_resource.resource.path"


resource "aws_lambda_function" "lambda" 
  filename      = "lambda.zip"
  function_name = "mylambda"
  role          = "$aws_iam_role.role.arn"
  handler       = "lambda.lambda_handler"
  runtime       = "python3.6"

  vpc_config 
    security_group_ids = var.sg_ids
    subnet_ids         = var.subnet_ids
  
  # The filebase64sha256() function is available in Terraform 0.11.12 and later
  # For Terraform 0.11.11 and earlier, use the base64sha256() function and the file() function:
  # source_code_hash = "$base64sha256(file("lambda.zip"))"
  source_code_hash = "$filebase64sha256("lambda.zip")"


# IAM
resource "aws_iam_role" "role" 
  name = "myrole"

  assume_role_policy = <<POLICY

  "Version": "2012-10-17",
  "Statement": [
    
      "Action": "sts:AssumeRole",
      "Principal": 
        "Service": "lambda.amazonaws.com"
      ,
      "Effect": "Allow",
      "Sid": ""
    
  ]

POLICY

data "aws_iam_policy" "admin" 
  arn = "arn:aws:iam::aws:policy/AdministratorAccess"

resource "aws_iam_role_policy_attachment" "admin" 
  role       = "$aws_iam_role.role.id"
  policy_arn = "$data.aws_iam_policy.admin.arn"

【问题讨论】:

不知道你在问什么。 Api 网关使用 aws 内部网络与 lambda 通信。 AWS_PROXY 是仅适用于 lambda 的特殊集成类型。不涉及互联网流量,即使 lambda 不在 vpc 中。 谢谢@Marcin,您能否指出 AWS 文档或任何有关 API Gateway 如何与其他 AWS 服务通信的文章?这是我想要清楚了解的,因为据我了解,AWS 服务是面向公众的。例如EC2 到 DynamoDB 或 ECS 代理到 ECS 服务都通过 Internet,如果它们不在 VPC 中或没有私有 VPC 端点(+私有 DNS)。 我现在没有链接。但对于其他服务,您需要使用 HTTP 或 AWS 集成,而不是 AWS_PROXY。如果您使用 AWS_PROXY 从 api 网关调用 lambda,则无论它是在 VPC 的公共子网、VPC 的私有子网还是在 VPC 之外,您都可以执行它。不需要为此做任何特别的事情。 谢谢@Marcin。理解为 AWS 专有的有线连接,不像 AWS 服务的其他 HTTPS API 那样通过公共 Internet。 没问题。如果您将 aws_proxy 用于 lambda(推荐方式),那么使用 api_gateway 和 lambda 并没有那么困难。 【参考方案1】:

正如@Marcin 所说,它通过 AWS 内部网络。

目前我对 API Gateway 集成的理解(如有错误请纠正我)。

希望其他人不必通过同样的努力来弄清楚它们。

更新

根据How API Gateway talk to Firehose VPC endpoint,目前的理解是 API 网关与 AWS 服务对话,这些服务不在 VPC 中,在 AWS 网络内部,而不是通过 Internet。

【讨论】:

API Gateway 将对 AWS Lambda 端点进行 API 调用(不是特定函数)。然后 Lambda 服务将触发 Lambda 函数。只有 Lambda 函数中的代码会与 VPC 通信,而不是 调用 函数的操作。 嗨@JohnRotenstein,感谢您的评论。我想知道如何将 HTTP 请求标头和正文从 API GW 传递到 VPC 中的 Lambda 函数? API GW 是否将它们作为 API 调用的参数传递给通过 Internet 的 Lambda 端点? API Gateway 和 Lambda 之间的通信可能是通过连接服务的“背板”进行的,但我还没有看到任何关于此的发布信息。 没有公开证据表明需要使用特殊背板,而且实际上没有必要甚至有益。单独的魔法路径会引入潜在的漏洞和不必要/无用的复杂性。 API Gateway 的后端使用 Invoke 请求调用 Lambda 服务 API,从 Lambda 服务的角度来看,该请求与从控制台进行的测试调用完全相同。服务到服务的交互通过 HTTPS 进行,请求/响应标头/正文序列化为 JSON(这就是原始二进制有效负载需要 base64 序列化的原因)。

以上是关于AWS - 从公共 API 网关到 VPC 内 lambda 的路由的主要内容,如果未能解决你的问题,请参考以下文章

如何从 AWS 胶水访问 VPC 中的 aws 资源?

无法设置到私有 AWS API 网关 API 的 SSH 隧道

Cors - 如何处理需要自定义标头的预检选项请求? (AWS:使用 vpc 端点的私有 API 网关)

如何从私有 AWS ALB 公开 API 端点

AWS Lambda + NAT 网关的替代方案

如何从亚马逊 vpc 连接到外部世界?