-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathmain.tf
More file actions
253 lines (228 loc) · 8.57 KB
/
main.tf
File metadata and controls
253 lines (228 loc) · 8.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# AWS provider configuration
provider "aws" {
profile = var.profile # AWS profile
region = var.region # AWS region
ignore_tags {
key_prefixes = ["kubernetes.io", "openshift"]
}
}
## RESOURCES
# Create a VPC
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr_block
enable_dns_support = true
enable_dns_hostnames = true
tags = { Name = "${var.name_prefix}-vpc" }
}
# Create an Internet Gateway and attach it to the VPC
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main.id
tags = { Name = "${var.name_prefix}-igw" }
}
# Create a public subnet within the VPC (where the proxy machine will live)
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = var.public_subnet_cidr_block # CIDR block for public subnet
availability_zone = var.availability_zone
map_public_ip_on_launch = true
tags = { Name = "${var.name_prefix}-public" }
}
# Create a route table for the public subnet
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
tags = { Name = "${var.name_prefix}-public-rtb" }
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
}
# Associate the public subnet with its route table (skipping this because default RTB is fine for public sub)
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public.id
}
# Create a security group for the proxy machine (rules below)
resource "aws_security_group" "proxy_machine_sg" {
name_prefix = var.name_prefix
description = "Allow all outbound traffic and inbound traffic from proxied subnet or developer SSH client"
vpc_id = aws_vpc.main.id
}
# proxy_machine_sg: Allow all ingress traffic from the proxied subnet
resource "aws_vpc_security_group_ingress_rule" "allow_proxied_traffic" {
security_group_id = aws_security_group.proxy_machine_sg.id
cidr_ipv4 = aws_subnet.proxied.cidr_block
ip_protocol = "-1" # semantically equivalent to all ports
}
# proxy_machine_sg: Allow SSH traffic from the developer's IP
resource "aws_vpc_security_group_ingress_rule" "allow_developer_ssh" {
security_group_id = aws_security_group.proxy_machine_sg.id
cidr_ipv4 = var.developer_cidr_block
from_port = 22
to_port = 22
ip_protocol = "tcp"
}
# proxy_machine_sg: Allow webUI traffic from the developer's IP
resource "aws_vpc_security_group_ingress_rule" "allow_developer_webui" {
security_group_id = aws_security_group.proxy_machine_sg.id
cidr_ipv4 = var.developer_cidr_block
from_port = 8443
to_port = 8443
ip_protocol = "tcp"
}
# proxy_machine_sg: Allow all IPv4 egress traffic from the proxy
resource "aws_vpc_security_group_egress_rule" "allow_all_traffic_ipv4" {
security_group_id = aws_security_group.proxy_machine_sg.id
cidr_ipv4 = "0.0.0.0/0"
ip_protocol = "-1" # semantically equivalent to all ports
}
# proxy_machine_sg: Allow all IPv6 egress traffic from the proxy
resource "aws_vpc_security_group_egress_rule" "allow_all_traffic_ipv6" {
security_group_id = aws_security_group.proxy_machine_sg.id
cidr_ipv6 = "::/0"
ip_protocol = "-1" # semantically equivalent to all ports
}
# End proxy_machine_sg rules
# Create an SSH keypair that the user can use for debugging the proxy_machine
resource "aws_key_pair" "proxy_machine_key" {
key_name_prefix = var.name_prefix
public_key = var.proxy_machine_ssh_pubkey
}
# Generate a random password for the proxy web UI
resource "random_password" "proxy_webui_password" {
length = 16
special = false
}
# Create the proxy EC2 instance inside the public subnet
resource "aws_instance" "proxy_machine" {
ami = data.aws_ami.rhel10.id
instance_type = "t3.micro"
key_name = aws_key_pair.proxy_machine_key.key_name # SSH key for debugging
availability_zone = var.availability_zone
tags = { Name = "${var.name_prefix}-proxy-machine" }
user_data = templatefile(
"assets/userdata.yaml.tpl",
{
mitmproxy_sysctl_b64 = filebase64("assets/mitmproxy-sysctl.conf")
mitmproxy_service_b64 = base64encode(templatefile(
"assets/mitmproxy.service.tpl",
{
proxy_webui_password = random_password.proxy_webui_password.result
}
))
caddyfile_b64 = base64encode(templatefile(
"assets/Caddyfile.tpl",
{
proxy_webui_password = random_password.proxy_webui_password.result
proxy_webui_password_hash = random_password.proxy_webui_password.bcrypt_hash
proxy_webui_username = var.proxy_webui_username
}
))
}
)
user_data_replace_on_change = true # Destroy and re-create this instance if user-data.yaml changes
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.proxy_machine_sg.id]
associate_public_ip_address = true # Necessary b/c we're not using a NAT gateway
source_dest_check = false # Critical for correct routing
}
# Create a proxied subnet (where the test/"captive" machines will live)
resource "aws_subnet" "proxied" {
vpc_id = aws_vpc.main.id
availability_zone = var.availability_zone
cidr_block = var.proxied_subnet_cidr_block
tags = { Name = "${var.name_prefix}-proxied" }
}
# If any escape routes specified, create an unproxied NAT gateway
resource "aws_eip" "escape_nat_eip" {
count = min(1, length(var.proxied_subnet_escape_routes))
domain = "vpc"
tags = { Name = "${var.name_prefix}-escape-nat-eip" }
depends_on = [aws_internet_gateway.igw]
}
resource "aws_nat_gateway" "escape_nat_gw" {
count = min(1, length(var.proxied_subnet_escape_routes))
allocation_id = aws_eip.escape_nat_eip[0].id
subnet_id = aws_subnet.public.id
tags = { Name = "${var.name_prefix}-escape-nat-gw" }
depends_on = [aws_internet_gateway.igw]
}
# Create a route table for the proxied subnet that routes all traffic into the proxy_machine
resource "aws_route_table" "proxied" {
vpc_id = aws_vpc.main.id
tags = { Name = "${var.name_prefix}-proxied-rtb" }
route {
cidr_block = "0.0.0.0/0"
network_interface_id = aws_instance.proxy_machine.primary_network_interface_id
}
dynamic "route" {
for_each = toset(var.proxied_subnet_escape_routes)
content {
cidr_block = route.value
gateway_id = aws_nat_gateway.escape_nat_gw[0].id
}
}
}
# Associate the proxied subnet with its route table
resource "aws_route_table_association" "proxied" {
subnet_id = aws_subnet.proxied.id # ID of proxied subnet
route_table_id = aws_route_table.proxied.id # ID of proxied route table
}
## OUTPUTS
output "region" {
description = "VPC region"
value = data.aws_region.current.name
}
output "proxy_machine_instance_id" {
description = "Proxy machine instance ID"
value = aws_instance.proxy_machine.id
}
output "proxy_machine_ssh_url" {
description = "SSH URL for logging into the proxy machine"
value = "ssh://ec2-user@${aws_instance.proxy_machine.public_ip}"
}
output "proxy_webui_url" {
description = "URL for accessing the proxy webUI (available in 2-5 minutes)"
value = "https://${aws_instance.proxy_machine.public_ip}:8443/"
}
output "proxy_webui_username" {
description = "Proxy webUI username"
value = var.proxy_webui_username
}
output "proxy_webui_password" {
description = "Proxy webUI password"
value = random_password.proxy_webui_password.result
sensitive = true
}
output "proxy_machine_cert_url" {
description = "Credentialed URL for downloading the proxy CA cert (available in 2-5 minutes)"
value = "https://${var.proxy_webui_username}:${random_password.proxy_webui_password.result}@${aws_instance.proxy_machine.public_ip}:8443/mitmproxy-ca-cert.pem"
sensitive = true
}
output "proxied_subnet_id" {
description = "Proxied subnet ID (launch your test/'captive' instances here)"
value = aws_subnet.proxied.id
}
## DATA
# Get the current AWS region
data "aws_region" "current" {}
# Automatic lookup of the latest official RHEL 10 AMI
data "aws_ami" "rhel10" {
most_recent = true
filter {
name = "platform-details"
values = ["Red Hat Enterprise Linux"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
filter {
name = "manifest-location"
values = ["amazon/RHEL-10.*_HVM-*-x86_64-*-Hourly2-GP3"]
}
owners = ["309956199498"] # Amazon's "Official Red Hat" account
}