Skip to content

launchbynttdata/tf-aws-module_primitive-vpc_endpoint

Repository files navigation

tf-aws-module_primitive-vpc_endpoint

License License: CC BY-NC-ND 4.0

Overview

A Terraform primitive module for creating and managing AWS VPC Endpoints. VPC endpoints allow resources inside a VPC to communicate privately with AWS services and VPC endpoint services without requiring internet gateways, NAT devices, VPN connections, or AWS Direct Connect connections.

This module supports all three endpoint types — Interface, Gateway, and GatewayLoadBalancer — and conditionally applies the correct set of arguments for each type. An optional resource-based access policy can be attached to restrict which principals and actions are permitted through the endpoint.

Features

  • All Endpoint Types: Supports Interface (PrivateLink), Gateway (S3/DynamoDB), and GatewayLoadBalancer endpoints
  • Type-Aware Configuration: Automatically scopes subnet IDs, security groups, route table IDs, and private DNS to the correct endpoint type
  • Custom Access Policies: Attach an IAM resource policy via aws_vpc_endpoint_policy to restrict endpoint access; omit for default full-access
  • DNS Customization: Configurable dns_options block for Interface endpoints including dualstack and IPv6 record types
  • IP Address Types: Supports ipv4, dualstack, and ipv6 address families
  • Flexible Tagging: Pass any tag map; applied directly to the endpoint resource
  • Input Validation: Built-in validation for vpc_endpoint_type and ip_address_type values

Usage

Interface Endpoint (S3 over PrivateLink)

module "vpc_endpoint" {
  source = "github.com/launchbynttdata/tf-aws-module_primitive-vpc_endpoint?ref=1.0.0"

  vpc_id              = "vpc-0abc123"
  service_name        = "com.amazonaws.us-east-1.s3"
  vpc_endpoint_type   = "Interface"
  private_dns_enabled = false
  subnet_ids          = ["subnet-aaa", "subnet-bbb"]
  security_group_ids  = ["sg-123"]

  tags = {
    Environment = "production"
    Application = "my-app"
  }
}

Gateway Endpoint (S3 or DynamoDB)

module "vpc_endpoint" {
  source = "github.com/launchbynttdata/tf-aws-module_primitive-vpc_endpoint?ref=1.0.0"

  vpc_id            = "vpc-0abc123"
  service_name      = "com.amazonaws.us-east-1.s3"
  vpc_endpoint_type = "Gateway"
  route_table_ids   = ["rtb-aaa", "rtb-bbb"]

  tags = {
    Environment = "production"
  }
}

Interface Endpoint with Custom Access Policy

module "vpc_endpoint" {
  source = "github.com/launchbynttdata/tf-aws-module_primitive-vpc_endpoint?ref=1.0.0"

  vpc_id              = "vpc-0abc123"
  service_name        = "com.amazonaws.us-east-1.execute-api"
  vpc_endpoint_type   = "Interface"
  private_dns_enabled = true
  subnet_ids          = ["subnet-aaa"]
  security_group_ids  = ["sg-123"]

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Sid       = "AllowSpecificAPI"
      Effect    = "Allow"
      Principal = "*"
      Action    = ["execute-api:Invoke"]
      Resource  = "arn:aws:execute-api:us-east-1:123456789012:abc123/*"
    }]
  })

  tags = {
    Environment = "production"
    Application = "my-api"
  }
}

GatewayLoadBalancer Endpoint

module "vpc_endpoint" {
  source = "github.com/launchbynttdata/tf-aws-module_primitive-vpc_endpoint?ref=1.0.0"

  vpc_id            = "vpc-0abc123"
  service_name      = "com.amazonaws.vpce.us-east-1.vpce-svc-0abc123"
  vpc_endpoint_type = "GatewayLoadBalancer"
  subnet_ids        = ["subnet-aaa"]

  tags = {
    Environment = "production"
  }
}

Important Notes

Endpoint Type and Argument Scoping

AWS VPC endpoint types each require a different set of arguments. This module automatically scopes attributes to the appropriate type:

Attribute Interface Gateway GatewayLoadBalancer
subnet_ids
security_group_ids
private_dns_enabled
route_table_ids
dns_options

Passing attributes for a different type is silently ignored by the module — they are not forwarded to the resource.

Access Policies

When policy is null (default), AWS applies a default policy that grants full access to the service. To restrict access, provide a JSON policy string. The policy is managed via a separate aws_vpc_endpoint_policy resource, which allows it to be updated independently of the endpoint itself.

Private DNS for Interface Endpoints

Setting private_dns_enabled = true requires that the VPC has both enableDnsSupport and enableDnsHostnames enabled. Without these VPC settings, the endpoint will fail to provision private DNS entries.

Service Name Format

AWS service names follow the pattern com.amazonaws.<region>.<service> (e.g., com.amazonaws.us-east-1.s3). For partner or custom services, the name follows com.amazonaws.vpce.<region>.<service-id>. Use the AWS CLI or console to discover available service names for your region.

Development Setup

Install required development dependencies:

make configure-dependencies
make configure-git-hooks

This installs:

  • Terraform
  • Go
  • Pre-commit hooks
  • Other development tools specified in .tool-versions

Testing

Tests are implemented using Terraform Test Framework for input validation, Terratest + LCAF testing framework for post-deploy integration, and conftest / Regula for policy validation.

Running Tests

# Run the full test suite (Terraform plan/apply tests + Go functional integration tests)
make test

# Run lint + full test suite (authoritative CI entrypoint)
make check

make check is the authoritative top-level entrypoint used by CI and covers linting followed by all make test stages. make test is the module-level test stage used by that framework entrypoint and is useful for local development when you intentionally want to skip linting.

The make test target runs two stages via GNU Make's double-colon rule composition:

  1. Terraform test framework suite (tfmodule/test/terraform) — Runs all tests under tests/terraform/*.tftest.hcl:

    • inputs_validation.tftest.hcl — plan-based input validation checks; no AWS credentials required
    • examples_complete_apply.tftest.hcl — apply-based integration test against examples/complete; requires AWS credentials and creates real resources
  2. Go functional integration tests (tfmodule/test/go) — Runs tests/post_deploy_functional/ via Terratest:

    • Deploys examples/complete using test.tfvars, verifies the endpoint state via the AWS EC2 SDK, performs a lightweight tag write probe to confirm mutating access, then destroys all resources
    • tests/post_deploy_functional_readonly/ is excluded from this stage by design (see below)

Readonly Tests

tests/post_deploy_functional_readonly/ contains a non-destructive test (TestVpcEndpointPrimitiveReadOnly) that runs read-only SDK assertions against pre-existing infrastructure without calling terraform apply or terraform destroy. It is intentionally excluded from make test because it requires infrastructure to already be deployed.

To run it against a live environment:

cd tests/post_deploy_functional_readonly && go test -v -timeout 30m

Requirements

Name Version
terraform ~> 1.10
aws ~> 5.100

Providers

Name Version
aws 5.100.0

Modules

No modules.

Resources

Name Type
aws_vpc_endpoint.endpoint resource
aws_vpc_endpoint_policy.endpoint resource

Inputs

Name Description Type Default Required
vpc_id The ID of the VPC in which to create the endpoint. string n/a yes
service_name The service name for the endpoint (e.g. com.amazonaws.us-east-1.s3). string n/a yes
vpc_endpoint_type The VPC endpoint type. Valid values: Interface, Gateway, GatewayLoadBalancer. string "Interface" no
private_dns_enabled Whether to enable private DNS for the endpoint. Applies to Interface endpoints only. Requires the VPC to have enableDnsSupport and enableDnsHostnames both set to true. bool false no
subnet_ids List of subnet IDs in which to create endpoint network interfaces. Applies to Interface and GatewayLoadBalancer endpoints. list(string) null no
security_group_ids List of security group IDs to associate with the endpoint network interfaces. Applies to Interface endpoints only. list(string) [] no
dns_options DNS options for the endpoint. Applies to Interface endpoints only. Set dns_record_ip_type to control whether A, AAAA, or dualstack records are created. Set private_dns_only_for_inbound_resolver_endpoint to true to restrict private DNS to Route 53 Resolver inbound endpoints.
object({
dns_record_ip_type = optional(string)
private_dns_only_for_inbound_resolver_endpoint = optional(bool)
})
null no
route_table_ids List of route table IDs to associate with the endpoint. Applies to Gateway endpoints only. The AWS provider will add prefix-list routes targeting this endpoint to each specified route table. list(string) [] no
auto_accept Accept the VPC endpoint request automatically. Only relevant for endpoint services in the same AWS account; cross-account requests require explicit acceptance by the service owner. bool false no
ip_address_type The IP address type for the endpoint. Valid values: ipv4, dualstack, ipv6. When null the service default is used. string null no
policy A JSON policy document to attach to the endpoint controlling which principals and actions are permitted. When null, AWS applies a default policy that allows full access to the service. string null no
tags Tags to apply to the VPC endpoint resource. map(string) {} no

Outputs

Name Description
id The ID of the VPC endpoint (e.g. vpce-0abc123).
arn The Amazon Resource Name (ARN) of the VPC endpoint.
state The current state of the VPC endpoint. Common values: pendingAcceptance, pending, available, deleting, deleted.
dns_entry The DNS entries for the VPC endpoint. Each entry is an object containing dns_name (the hostname) and hosted_zone_id (the Route 53 hosted zone). Use these values to configure DNS resolution or alias records.
network_interface_ids List of network interface IDs created for the endpoint ENIs. Populated for Interface type endpoints only. Useful for attaching additional security group rules or for network flow log analysis.
prefix_list_id The managed prefix list ID representing the AWS service CIDR ranges. Populated for Gateway type endpoints only. Can be referenced in security group rules to allow traffic to the service without specifying IP ranges directly.
policy The JSON access policy attached to the endpoint. Returns null when no custom policy was provided (AWS default full-access policy is in effect).

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors