5
votes

Question

From the API Gateway in the public facing AWS network to the Lambda function in a VPC subnet, where the traffice goes through?

Introducing Amazon API Gateway Private Endpoints

With this launch, you could build API-based services that did not require a publicly available endpoint. They could still interact with private services, such as databases, inside your VPC. enter image description here

Background

When the lambda is not in VPC (in the AWS public facing network), the traffic goes through the Internet. But not sure when the lambda is in VPC.

From the AWS console, I created a lambda function in a VPC and confirmed the API Gateway (NOT in VPC) can tak to the lambda in VPC.

Since the lambda is in a subnet in VPC, it does not have public IP, then it should not go through the Internet. However, there is no VPC private link which is used to connect from API Gateway to NLB in a VPC as explained in API Gateway Private Integration.

Hence I have no idea where the traffic is going through.

enter image description here

Terraform

Terraform aws_api_gateway_integration resource, connection_type says:

(Optional) The integration input's connectionType. Valid values are INTERNET (default for connections through the public routable internet), and VPC_LINK (for private connections between API Gateway and a network load balancer in a VPC).

Hence, it looks it may go through the Internet as the connection_type default is INTERNET, and VPC_LINK is currently for 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}"
}
1
Not sure what are you asking. Api gateway communicates with lambda using aws internal network. AWS_PROXY is special integration type for lambda only. There is no internet traffic involved, even if lambda is not in vpc.Marcin
Thanks @Marcin, could you point me to AWS documentations or any articles about how API Gateway communicate with other AWS services? It is what I am trying to have clear picture, because AWS services, in my understanding, are public facing. e.g. EC2 to DynamoDB or ECS Agent to ECS Services all go through the Internet, if they are not in VPC or not having private VPC endpoint (+private DNS).mon
I don't have links now. But for the other services you would need to use HTTP or AWS integrations, not AWS_PROXY. If you use AWS_PROXY to invoke lambda from api gateway, you can execute it whether it is in public subnet of VPC, a private subnet of VPC or outside of a VPC. Don't need to do anything special for that.Marcin
Thanks @Marcin. Understood it is an AWS proprietary wired connection that does not go through the public Internet like other HTTPS API of the AWS services.mon
No problem. If you use aws_proxy for lambda (recommended way) than working with api_gateway and lambda is not that difficult.Marcin

1 Answers

7
votes

As answerd by @Marcin, it goes through the AWS internal network.

Current my understanding of API Gateway integrations (please correct me if wrong).

Hope others will not have to go through the same efforts to figure them out.

enter image description here

Update

As per How API Gateway talk to Firehose VPC endpoint, current understanding is API gateway talk to AWS services, that are not in VPC, internally in the AWS network, not via the Internet.

enter image description here enter image description here