VPC endpoints - #120
Merged
Merged
Conversation
Add free S3 and DynamoDB gateway endpoints attached to all route tables, plus selectable interface endpoints (PrivateLink) placed in private subnets with private DNS and a shared HTTPS security group. Expose all three as inputs on the rvn-aws-network definition (1.1.0).
Ravion Module Publish PlanDry run only. No Ravion API mutations were made.
Diffsrvn-aws-network 1.0.1 -> 1.1.0--- remote
+++ compiled
label: NAT gateway Elastic IP allocation IDs
required: false
type: string_array
+ - id: section_vpc_endpoints
+ label: VPC endpoints
+ type: section
+ - collapsible: true
+ default: true
+ description: Route S3 traffic through a free gateway VPC endpoint instead of the NAT gateway. Avoids NAT data processing charges (including ECR image layer pulls) and keeps S3 traffic inside AWS.
+ id: vpc_endpoint_s3_gateway_enabled
+ label: S3 gateway endpoint
+ type: boolean
+ - collapsible: true
+ default: false
+ description: Route DynamoDB traffic through a free gateway VPC endpoint instead of the NAT gateway.
+ id: vpc_endpoint_dynamodb_gateway_enabled
+ label: DynamoDB gateway endpoint
+ type: boolean
+ - collapsible: true
+ description: |-
+ Create interface VPC endpoints (AWS PrivateLink) in the private subnets for private access to AWS services without a NAT gateway.
+
+ Each endpoint costs about $8/month per AZ plus data processing charges, so a multi-service set can cost more than a NAT gateway. Pulling ECR images privately requires ECR API, ECR Docker registry, and the S3 gateway endpoint together.
+ id: vpc_endpoint_interface_services
+ label: Interface endpoints
+ required: false
+ type: string_array
+ values:
+ - label: ECR API
+ value: ecr.api
+ - label: ECR Docker registry
+ value: ecr.dkr
+ - label: CloudWatch Logs
+ value: logs
+ - label: CloudWatch metrics
+ value: monitoring
+ - label: Secrets Manager
+ value: secretsmanager
+ - label: Systems Manager
+ value: ssm
+ - label: Systems Manager Session Manager
+ value: ssmmessages
+ - label: EC2 messages
+ value: ec2messages
+ - label: KMS
+ value: kms
+ - label: STS
+ value: sts
+ - label: SQS
+ value: sqs
+ - label: SNS
+ value: sns
+ - label: EventBridge
+ value: events
- id: section_soc2
label: SOC 2
type: section
@@
- **Public and private subnets** across multiple availability zones for high availability
- **NAT Gateway** options for outbound internet access from private subnets
+ - **VPC endpoints** for private access to S3, DynamoDB, and other AWS services
- **VPC Flow Logs** for network traffic monitoring and SOC 2 compliance
- **VPC Peering** to connect with existing VPCs across accounts or regions
- Terraform source: [ravionhq/modules/networking/vpc](https://github.com/ravionhq/modules/tree/rvn-aws-network@1.0.1/networking/vpc)
+ Terraform source: [ravionhq/modules/networking/vpc](https://github.com/ravionhq/modules/tree/rvn-aws-network@1.1.0/networking/vpc)
## Use cases
@@
| SOC 2 compliance | Enabling flow logs for network traffic auditing |
| Multi-region architecture | Peering VPCs across regions for low-latency communication |
| Partner IP allowlisting | Using stable NAT Gateway IPs with pre-allocated EIPs |
+ | Reducing NAT data charges | Routing S3/DynamoDB traffic through free gateway endpoints |
## Subnet types
@@
To keep the same IP permanently, create your Elastic IPs separately and pass in the allocation IDs. This way, even if you destroy and recreate the entire VPC, your NAT Gateway will use the same public IP — no need to update partner allowlists or firewall rules.
+ ## VPC endpoints
+
+ VPC endpoints let resources in the VPC reach AWS services without traversing the internet or the NAT gateway.
+
+ ### Gateway endpoints (free)
+
+ Gateway endpoints for **S3** and **DynamoDB** are free and simply add routes to the VPC's route tables. The S3 gateway endpoint is enabled by default for new VPCs: it keeps S3 traffic — including ECR image layer downloads — off the NAT gateway, cutting NAT data processing charges.
+
+ One caveat: S3 traffic no longer exits through the NAT gateway's public IP, so S3 bucket policies that allowlist your NAT IP need to be updated (for example to match the endpoint via `aws:SourceVpce`).
+
+ ### Interface endpoints (PrivateLink)
+
+ Interface endpoints provide private connectivity to most other AWS services (ECR, CloudWatch Logs, Secrets Manager, Systems Manager, and more). The module places each endpoint in every private subnet with private DNS enabled and a shared security group allowing HTTPS from within the VPC, so AWS SDKs work without configuration changes.
+
+ | Consideration | Detail |
+ | --------------- | --------------------------------------------------------------------- |
+ | Cost | ~$8/month per endpoint per AZ, plus $0.01/GB processed |
+ | ECR without NAT | Requires ECR API + ECR Docker registry + the S3 gateway endpoint |
+ | Region scope | Endpoints connect to services in the VPC's own region only |
+
+ A typical ECS bundle (ECR API, ECR Docker registry, CloudWatch Logs, Secrets Manager) across 3 AZs runs ~$96/month — more than a single NAT gateway (~$32/month). Choose interface endpoints for private networking and compliance requirements rather than cost savings.
+
## Configuration
| Field | Required | Default | Description |
@@
| NAT Gateway | No | `true` | Enable outbound internet from private subnets |
| NAT Gateway High Availability | No | `false` | Deploy one NAT per AZ instead of a single shared NAT |
| NAT Gateway EIP Allocation IDs | No | — | Pre-allocated EIPs for stable NAT public IPs |
+ | S3 gateway endpoint | No | `true` | Free gateway endpoint keeping S3 traffic off the NAT gateway |
+ | DynamoDB gateway endpoint | No | `false` | Free gateway endpoint keeping DynamoDB traffic off the NAT gateway |
+ | Interface endpoints | No | — | Interface VPC endpoints (PrivateLink) for private AWS service access |
| Flow Logs | No | `false` | Enable VPC Flow Logs (required for SOC 2) |
| Tags | No | Environment, Project | Custom tags applied to all resources |
@@
base_path: networking/vpc
branch: main
execution_environment_id: << module.input.execution_environment_id >>
- ref: rvn-aws-network@1.0.1
+ ref: rvn-aws-network@1.1.0
repo: https://github.com/ravionhq/modules
stack_id: <<stack.id>>
terraform_variables:
@@
Owner: Ravion
ProjectGivenId: <<project.given_id>>
vpc_cidr: << module.input.vpc_cidr >>
+ vpc_endpoint_dynamodb_gateway_enabled: << module.input.vpc_endpoint_dynamodb_gateway_enabled >>
+ vpc_endpoint_interface_services: << module.input.vpc_endpoint_interface_services >>
+ vpc_endpoint_s3_gateway_enabled: << module.input.vpc_endpoint_s3_gateway_enabled >>
vpc_peering_connections: << module.input.vpc_peering_connections >>
tool: opentofu
tool_version: << module.input.opentofu_version || defaults.opentofu_version >> |
| vpc_endpoint_type = "Interface" | ||
| subnet_ids = aws_subnet.private[*].id | ||
| security_group_ids = [aws_security_group.vpc_endpoints[0].id] | ||
| private_dns_enabled = true |
There was a problem hiding this comment.
Private DNS prerequisites unenforced
When a caller enables interface endpoints while setting dns_support_enabled or dns_hostnames_enabled to false, every endpoint still enables private DNS, causing AWS to reject endpoint creation during apply.
Prompt To Fix With AI
This is a comment left during a code review.
Path: networking/vpc/vpc_endpoints.tf
Line: 67
Comment:
**Private DNS prerequisites unenforced**
When a caller enables interface endpoints while setting `dns_support_enabled` or `dns_hostnames_enabled` to false, every endpoint still enables private DNS, causing AWS to reject endpoint creation during apply.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| The list length must equal `1` when `nat_gateway_high_availability_enabled = false`, or the resolved subnet count when `nat_gateway_high_availability_enabled = true`. EIP allocations are consumed in order, so `allocation_ids[i]` is attached to the NAT Gateway in `availability_zones[i]`. | ||
|
|
||
| ### With VPC Endpoints | ||
|
|
There was a problem hiding this comment.
Endpoint example pins old release
The new VPC-endpoint example pins v1.0.0, which predates the endpoint arguments shown below it, so copying the example produces unsupported-argument errors instead of creating endpoints.
Prompt To Fix With AI
This is a comment left during a code review.
Path: networking/vpc/README.md
Line: 90
Comment:
**Endpoint example pins old release**
The new VPC-endpoint example pins `v1.0.0`, which predates the endpoint arguments shown below it, so copying the example produces unsupported-argument errors instead of creating endpoints.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Greptile Summary
Adds optional S3 and DynamoDB gateway endpoints plus selectable AWS PrivateLink interface endpoints to the VPC module.
Confidence Score: 4/5
The PR should not merge until interface endpoints reject or support DNS-disabled VPC configurations; the documentation example should also reference the endpoint-capable release.
Interface endpoints always request private DNS while the module still permits either required VPC DNS attribute to be disabled, producing an AWS apply failure for a supported input combination; separately, the new example pins a release that lacks its endpoint arguments.
Files Needing Attention: networking/vpc/vpc_endpoints.tf, networking/vpc/variables.tf, networking/vpc/README.md
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart LR Input[Endpoint inputs] --> Gateway{Gateway endpoints enabled?} Gateway -->|S3| S3[S3 gateway endpoint] Gateway -->|DynamoDB| DDB[DynamoDB gateway endpoint] S3 --> Routes[Public and private route tables] DDB --> Routes Input --> Interface{Interface services nonempty?} Interface --> SG[Shared HTTPS security group] Interface --> VPCE[Interface endpoints] SG --> VPCE PrivateSubnets[Private subnets] --> VPCE VPCE --> PrivateDNS[Private DNS enabled] VPCDNS[VPC DNS support and hostnames] -. required .-> PrivateDNSPrompt To Fix All With AI
Reviews (1): Last reviewed commit: "feat(vpc): enable S3 gateway endpoint by..." | Re-trigger Greptile