title: AWS - Route from public API Gateway to in-VPC lambda
body: <h1>Question</h1>
  
  <p>From the API Gateway in the public facing AWS network to the Lambda function in a VPC subnet, where the traffice goes through?</p>
  
  <p><a href="https://aws.amazon.com/blogs/compute/introducing-amazon-api-gateway-private-endpoints/" rel="noreferrer">Introducing Amazon API Gateway Private Endpoints</a></p>
  
  <blockquote>
    <p>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.
    <a href="https://i.stack.imgur.com/N7mGc.png" rel="noreferrer"><img src="https://i.stack.imgur.com/N7mGc.png" alt="enter image description here"></a></p>
  </blockquote>
  
  <h1>Background</h1>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>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 <a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-private-integration.html" rel="noreferrer">API Gateway Private Integration</a>.</p>
  
  <p>Hence I have no idea where the traffic is going through.</p>
  
  <p><a href="https://i.stack.imgur.com/s3IsY.png" rel="noreferrer"><img src="https://i.stack.imgur.com/s3IsY.png" alt="enter image description here"></a></p>
  
  <h2>Terraform</h2>
  
  <p>Terraform <a href="https://www.terraform.io/docs/providers/aws/r/api_gateway_integration.html" rel="noreferrer">aws_api_gateway_integration</a> resource, <strong>connection_type</strong> says:</p>
  
  <blockquote>
    <p>(Optional) The integration input's connectionType. Valid values are <strong>INTERNET (default for connections through the public routable internet)</strong>, and VPC_LINK (for private connections between API Gateway and a network load balancer in a VPC).</p>
  </blockquote>
  
  <p>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.</p>
  
  <pre><code># 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 = &lt;&lt;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}"
  }
  </code></pre>