Skip to content

Commit 0e11c23

Browse files
committed
feat: Add EC2 Instance Connect Endpoint support
1 parent 2bffa61 commit 0e11c23

File tree

10 files changed

+215
-22
lines changed

10 files changed

+215
-22
lines changed

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ No modules.
460460
| <a name="input_igw_tags"></a> [igw\_tags](#input\_igw\_tags) | Additional tags for the internet gateway | `map(string)` | `{}` | no |
461461
| <a name="input_instance_connect_endpoint_create_in_private_subnets"></a> [instance\_connect\_endpoint\_create\_in\_private\_subnets](#input\_instance\_connect\_endpoint\_create\_in\_private\_subnets) | Create EC2 Instance Connect Endpoint(s) in all private subnets if no subnet IDs are provided | `bool` | `true` | no |
462462
| <a name="input_instance_connect_endpoint_subnets"></a> [instance\_connect\_endpoint\_subnets](#input\_instance\_connect\_endpoint\_subnets) | List of subnet IDs where EC2 Instance Connect Endpoint(s) should be created. If null and create\_in\_private\_subnets is true, defaults to private subnets | `list(string)` | `null` | no |
463+
| <a name="input_instance_connect_preserve_client_ip"></a> [instance\_connect\_preserve\_client\_ip](#input\_instance\_connect\_preserve\_client\_ip) | Whether to preserve the client IP address when connecting via EC2 Instance Connect Endpoint | `bool` | `false` | no |
463464
| <a name="input_instance_connect_security_group_ids"></a> [instance\_connect\_security\_group\_ids](#input\_instance\_connect\_security\_group\_ids) | List of security group IDs to associate with EC2 Instance Connect Endpoint(s). If null, defaults to no security groups | `list(string)` | `null` | no |
464465
| <a name="input_instance_connect_tags"></a> [instance\_connect\_tags](#input\_instance\_connect\_tags) | Additional tags for EC2 Instance Connect Endpoint resources | `map(string)` | `{}` | no |
465466
| <a name="input_instance_tenancy"></a> [instance\_tenancy](#input\_instance\_tenancy) | A tenancy option for instances launched into the VPC | `string` | `"default"` | no |
@@ -638,10 +639,7 @@ No modules.
638639
| <a name="output_elasticache_subnets_ipv6_cidr_blocks"></a> [elasticache\_subnets\_ipv6\_cidr\_blocks](#output\_elasticache\_subnets\_ipv6\_cidr\_blocks) | List of IPv6 cidr\_blocks of elasticache subnets in an IPv6 enabled VPC |
639640
| <a name="output_igw_arn"></a> [igw\_arn](#output\_igw\_arn) | The ARN of the Internet Gateway |
640641
| <a name="output_igw_id"></a> [igw\_id](#output\_igw\_id) | The ID of the Internet Gateway |
641-
| <a name="output_instance_connect_endpoint_arns"></a> [instance\_connect\_endpoint\_arns](#output\_instance\_connect\_endpoint\_arns) | ARNs of the EC2 Instance Connect Endpoint(s) |
642-
| <a name="output_instance_connect_endpoint_ids"></a> [instance\_connect\_endpoint\_ids](#output\_instance\_connect\_endpoint\_ids) | IDs of the EC2 Instance Connect Endpoint(s) created |
643-
| <a name="output_instance_connect_endpoint_security_group_ids"></a> [instance\_connect\_endpoint\_security\_group\_ids](#output\_instance\_connect\_endpoint\_security\_group\_ids) | Security group IDs associated with the EC2 Instance Connect Endpoint(s) |
644-
| <a name="output_instance_connect_endpoint_subnet_ids"></a> [instance\_connect\_endpoint\_subnet\_ids](#output\_instance\_connect\_endpoint\_subnet\_ids) | Subnet IDs where EC2 Instance Connect Endpoint(s) were created |
642+
| <a name="output_instance_connect_endpoints"></a> [instance\_connect\_endpoints](#output\_instance\_connect\_endpoints) | Map of EC2 Instance Connect Endpoints created, keyed by subnet index |
645643
| <a name="output_intra_network_acl_arn"></a> [intra\_network\_acl\_arn](#output\_intra\_network\_acl\_arn) | ARN of the intra network ACL |
646644
| <a name="output_intra_network_acl_id"></a> [intra\_network\_acl\_id](#output\_intra\_network\_acl\_id) | ID of the intra network ACL |
647645
| <a name="output_intra_route_table_association_ids"></a> [intra\_route\_table\_association\_ids](#output\_intra\_route\_table\_association\_ids) | List of IDs of the intra route table association |
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# EC2 Instance Connect Endpoint
2+
3+
Configuration in this directory creates a **VPC** with **EC2 Instance Connect Endpoints (EICE)** deployed in private subnets.
4+
This allows secure SSH or RDP access to instances **without using a bastion host** or assigning public IPs.
5+
6+
## Features
7+
8+
This example demonstrates:
9+
10+
- Deployment of a VPC with public and private subnets across multiple Availability Zones
11+
- Creation of a **NAT Gateway** for outbound internet access
12+
- Deployment of **EC2 Instance Connect Endpoints** in private subnets
13+
- Creation of a security group allowing SSH access
14+
- Demonstration of the `preserve_client_ip` and tagging features for EICE resources
15+
16+
---
17+
18+
## Usage
19+
20+
To run this example, execute:
21+
22+
```bash
23+
terraform init
24+
terraform plan
25+
terraform apply
26+
```
27+
28+
⚠️ Note:
29+
This example may create resources that incur costs (such as VPCs, NAT Gateways, and EC2 endpoints).
30+
Run terraform destroy when you no longer need these resources.
31+
32+
<!-- BEGIN_TF_DOCS -->
33+
## Requirements
34+
35+
| Name | Version |
36+
|------|---------|
37+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.7 |
38+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.5 |
39+
40+
## Providers
41+
42+
| Name | Version |
43+
|------|---------|
44+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.5 |
45+
46+
## Modules
47+
48+
| Name | Source | Version |
49+
|------|--------|---------|
50+
| <a name="module_vpc"></a> [vpc](#module\_vpc) | ../.. | n/a |
51+
52+
## Resources
53+
54+
| Name | Type |
55+
|------|------|
56+
| [aws_security_group.allow_ssh](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
57+
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
58+
59+
## Inputs
60+
61+
No inputs.
62+
63+
## Outputs
64+
65+
| Name | Description |
66+
|------|-------------|
67+
| <a name="output_instance_connect_endpoints"></a> [instance\_connect\_endpoints](#output\_instance\_connect\_endpoints) | Map of EC2 Instance Connect Endpoints created |
68+
| <a name="output_vpc_id"></a> [vpc\_id](#output\_vpc\_id) | The ID of the VPC |
69+
<!-- END_TF_DOCS -->
70+
71+
##Example Output
72+
73+
Example output after deployment:
74+
75+
```bash
76+
instance_connect_endpoints = {
77+
"0" = {
78+
"id" = "eice-0c123456789abcd"
79+
"arn" = "arn:aws:ec2:us-east-1:123456789012:ec2-instance-connect-endpoint/eice-0c123456789abcd"
80+
"subnet_id" = "subnet-0123456789abcdef"
81+
"sg_ids" = ["sg-0123456789abcdef"]
82+
}
83+
}
84+
```
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
################################################################################
2+
# Provider Configuration
3+
################################################################################
4+
5+
provider "aws" {
6+
region = local.region
7+
}
8+
9+
data "aws_availability_zones" "available" {}
10+
11+
################################################################################
12+
# Locals
13+
################################################################################
14+
15+
locals {
16+
name = "ex-${basename(path.cwd)}"
17+
region = "us-east-1"
18+
19+
# Get the first 2 availability zones for simplicity
20+
azs = slice(data.aws_availability_zones.available.names, 0, 2)
21+
22+
# Base VPC CIDR
23+
vpc_cidr = "10.0.0.0/16"
24+
25+
# Calculate subnet CIDRs automatically based on AZ count
26+
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)]
27+
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k + 10)]
28+
29+
tags = {
30+
Example = local.name
31+
GithubRepo = "terraform-aws-vpc"
32+
GithubOrg = "terraform-aws-modules"
33+
}
34+
}
35+
36+
################################################################################
37+
# VPC Module
38+
################################################################################
39+
40+
module "vpc" {
41+
source = "../.."
42+
43+
name = local.name
44+
cidr = local.vpc_cidr
45+
46+
azs = local.azs
47+
private_subnets = local.private_subnets
48+
public_subnets = local.public_subnets
49+
50+
enable_nat_gateway = true
51+
single_nat_gateway = true
52+
53+
# EC2 Instance Connect Endpoint Configuration
54+
create_instance_connect_endpoint = true
55+
instance_connect_preserve_client_ip = true
56+
instance_connect_security_group_ids = [aws_security_group.allow_ssh.id]
57+
instance_connect_tags = {
58+
Environment = "example"
59+
}
60+
61+
tags = merge(local.tags, {
62+
Name = local.name
63+
})
64+
}
65+
66+
################################################################################
67+
# Security Group for EC2 Instance Connect
68+
################################################################################
69+
70+
resource "aws_security_group" "allow_ssh" {
71+
name = "${local.name}-allow-ssh"
72+
description = "Allow SSH for EC2 Instance Connect"
73+
vpc_id = module.vpc.vpc_id
74+
75+
ingress {
76+
from_port = 22
77+
to_port = 22
78+
protocol = "tcp"
79+
cidr_blocks = ["0.0.0.0/0"]
80+
}
81+
82+
egress {
83+
from_port = 0
84+
to_port = 0
85+
protocol = "-1"
86+
cidr_blocks = ["0.0.0.0/0"]
87+
}
88+
89+
tags = merge(local.tags, {
90+
Name = "${local.name}-allow-ssh"
91+
})
92+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
output "vpc_id" {
2+
description = "The ID of the VPC"
3+
value = module.vpc.vpc_id
4+
}
5+
6+
output "instance_connect_endpoints" {
7+
description = "Map of EC2 Instance Connect Endpoints created"
8+
value = module.vpc.instance_connect_endpoints
9+
}

examples/ec2-instance-connect-endpoint/variables.tf

Whitespace-only changes.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
terraform {
2+
required_version = ">= 1.5.7"
3+
4+
required_providers {
5+
aws = {
6+
source = "hashicorp/aws"
7+
version = ">= 6.5"
8+
}
9+
}
10+
}

main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,7 @@ resource "aws_ec2_instance_connect_endpoint" "this" {
15711571
: []
15721572
)
15731573

1574+
preserve_client_ip = var.instance_connect_preserve_client_ip
15741575

15751576
tags = merge(
15761577
var.tags,

outputs.tf

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -672,22 +672,14 @@ output "name" {
672672
# EC2 Instance Connect Endpoint
673673
################################################################################
674674

675-
output "instance_connect_endpoint_ids" {
676-
description = "IDs of the EC2 Instance Connect Endpoint(s) created"
677-
value = try([for v in aws_ec2_instance_connect_endpoint.this : v.id], [])
678-
}
679-
680-
output "instance_connect_endpoint_subnet_ids" {
681-
description = "Subnet IDs where EC2 Instance Connect Endpoint(s) were created"
682-
value = try([for v in aws_ec2_instance_connect_endpoint.this : v.subnet_id], [])
683-
}
684-
685-
output "instance_connect_endpoint_security_group_ids" {
686-
description = "Security group IDs associated with the EC2 Instance Connect Endpoint(s)"
687-
value = try(var.instance_connect_security_group_ids, [])
688-
}
689-
690-
output "instance_connect_endpoint_arns" {
691-
description = "ARNs of the EC2 Instance Connect Endpoint(s)"
692-
value = try([for v in aws_ec2_instance_connect_endpoint.this : v.arn], [])
675+
output "instance_connect_endpoints" {
676+
description = "Map of EC2 Instance Connect Endpoints created, keyed by subnet index"
677+
value = try({
678+
for k, v in aws_ec2_instance_connect_endpoint.this : k => {
679+
id = v.id
680+
arn = v.arn
681+
subnet_id = v.subnet_id
682+
sg_ids = v.security_group_ids
683+
}
684+
}, {})
693685
}

variables.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,3 +1712,9 @@ variable "instance_connect_tags" {
17121712
default = {}
17131713
description = "Additional tags for EC2 Instance Connect Endpoint resources"
17141714
}
1715+
1716+
variable "instance_connect_preserve_client_ip" {
1717+
type = bool
1718+
default = false
1719+
description = "Whether to preserve the client IP address when connecting via EC2 Instance Connect Endpoint"
1720+
}

wrappers/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ module "wrapper" {
186186
igw_tags = try(each.value.igw_tags, var.defaults.igw_tags, {})
187187
instance_connect_endpoint_create_in_private_subnets = try(each.value.instance_connect_endpoint_create_in_private_subnets, var.defaults.instance_connect_endpoint_create_in_private_subnets, true)
188188
instance_connect_endpoint_subnets = try(each.value.instance_connect_endpoint_subnets, var.defaults.instance_connect_endpoint_subnets, null)
189+
instance_connect_preserve_client_ip = try(each.value.instance_connect_preserve_client_ip, var.defaults.instance_connect_preserve_client_ip, false)
189190
instance_connect_security_group_ids = try(each.value.instance_connect_security_group_ids, var.defaults.instance_connect_security_group_ids, null)
190191
instance_connect_tags = try(each.value.instance_connect_tags, var.defaults.instance_connect_tags, {})
191192
instance_tenancy = try(each.value.instance_tenancy, var.defaults.instance_tenancy, "default")

0 commit comments

Comments
 (0)