20334: Batch permission updates during link dedup migration.
[arvados.git] / tools / salt-install / terraform / aws / vpc / main.tf
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: CC-BY-SA-3.0
4
5 terraform {
6   required_providers {
7     aws = {
8       source = "hashicorp/aws"
9     }
10   }
11 }
12
13 provider "aws" {
14   region = var.region_name
15   default_tags {
16     tags = {
17       Arvados = var.cluster_name
18     }
19   }
20 }
21
22 resource "aws_vpc" "arvados_vpc" {
23   cidr_block = "10.1.0.0/16"
24   enable_dns_hostnames = true
25   enable_dns_support = true
26 }
27 resource "aws_subnet" "public_subnet" {
28   vpc_id = aws_vpc.arvados_vpc.id
29   availability_zone = local.availability_zone
30   cidr_block = "10.1.1.0/24"
31 }
32 resource "aws_subnet" "private_subnet" {
33   vpc_id = aws_vpc.arvados_vpc.id
34   availability_zone = local.availability_zone
35   cidr_block = "10.1.2.0/24"
36 }
37
38 #
39 # VPC S3 access
40 #
41 resource "aws_vpc_endpoint" "s3" {
42   vpc_id = aws_vpc.arvados_vpc.id
43   service_name = "com.amazonaws.${var.region_name}.s3"
44 }
45 resource "aws_vpc_endpoint_route_table_association" "compute_s3_route" {
46   vpc_endpoint_id = aws_vpc_endpoint.s3.id
47   route_table_id = aws_route_table.private_subnet_rt.id
48 }
49
50 #
51 # Internet access for Public IP instances
52 #
53 resource "aws_internet_gateway" "internet_gw" {
54   vpc_id = aws_vpc.arvados_vpc.id
55 }
56 resource "aws_eip" "arvados_eip" {
57   for_each = toset(local.public_hosts)
58   depends_on = [
59     aws_internet_gateway.internet_gw
60   ]
61 }
62 resource "aws_route_table" "public_subnet_rt" {
63   vpc_id = aws_vpc.arvados_vpc.id
64   route {
65     cidr_block = "0.0.0.0/0"
66     gateway_id = aws_internet_gateway.internet_gw.id
67   }
68 }
69 resource "aws_route_table_association" "public_subnet_assoc" {
70   subnet_id = aws_subnet.public_subnet.id
71   route_table_id = aws_route_table.public_subnet_rt.id
72 }
73
74 #
75 # Internet access for Private IP instances
76 #
77 resource "aws_eip" "nat_gw_eip" {
78   depends_on = [
79     aws_internet_gateway.internet_gw
80   ]
81 }
82 resource "aws_nat_gateway" "nat_gw" {
83   # A NAT gateway should be placed on a subnet with an internet gateway
84   subnet_id = aws_subnet.public_subnet.id
85   allocation_id = aws_eip.nat_gw_eip.id
86 }
87 resource "aws_route_table" "private_subnet_rt" {
88   vpc_id = aws_vpc.arvados_vpc.id
89   route {
90     cidr_block = "0.0.0.0/0"
91     nat_gateway_id = aws_nat_gateway.nat_gw.id
92   }
93 }
94 resource "aws_route_table_association" "private_subnet_assoc" {
95   subnet_id = aws_subnet.private_subnet.id
96   route_table_id = aws_route_table.private_subnet_rt.id
97 }
98
99 resource "aws_security_group" "arvados_sg" {
100   name = "arvados_sg"
101   vpc_id = aws_vpc.arvados_vpc.id
102
103   dynamic "ingress" {
104     for_each = local.allowed_ports
105     content {
106       description = "Ingress rule for ${ingress.key}"
107       from_port = "${ingress.value}"
108       to_port = "${ingress.value}"
109       protocol = "tcp"
110       cidr_blocks = ["0.0.0.0/0"]
111       ipv6_cidr_blocks = ["::/0"]
112     }
113   }
114   # Allows communication between nodes in the VPC
115   ingress {
116     from_port = 0
117     to_port = 0
118     protocol = "-1"
119     cidr_blocks = [ aws_vpc.arvados_vpc.cidr_block ]
120   }
121   # Even though AWS auto-creates an "allow all" egress rule,
122   # Terraform deletes it, so we add it explicitly.
123   egress {
124     from_port = 0
125     to_port = 0
126     protocol = "-1"
127     cidr_blocks = ["0.0.0.0/0"]
128     ipv6_cidr_blocks = ["::/0"]
129   }
130 }
131
132 #
133 # Route53 split-horizon DNS zones
134 #
135
136 # PUBLIC DNS
137 resource "aws_route53_zone" "public_zone" {
138   name = local.arvados_dns_zone
139 }
140 resource "aws_route53_record" "public_a_record" {
141   zone_id = aws_route53_zone.public_zone.id
142   for_each = local.public_ip
143   name = each.key
144   type = "A"
145   ttl = 300
146   records = [ each.value ]
147 }
148 resource "aws_route53_record" "main_a_record" {
149   zone_id = aws_route53_zone.public_zone.id
150   name = ""
151   type = "A"
152   ttl = 300
153   records = [ local.public_ip["controller"] ]
154 }
155 resource "aws_route53_record" "public_cname_record" {
156   zone_id = aws_route53_zone.public_zone.id
157   for_each = {for i in local.cname_by_host: i.record => "${i.cname}.${local.arvados_dns_zone}" }
158   name = each.key
159   type = "CNAME"
160   ttl = 300
161   records = [ each.value ]
162 }
163
164 # PRIVATE DNS
165 resource "aws_route53_zone" "private_zone" {
166   name = local.arvados_dns_zone
167   vpc {
168     vpc_id = aws_vpc.arvados_vpc.id
169   }
170 }
171 resource "aws_route53_record" "private_a_record" {
172   zone_id = aws_route53_zone.private_zone.id
173   for_each = local.private_ip
174   name = each.key
175   type = "A"
176   ttl = 300
177   records = [ each.value ]
178 }
179 resource "aws_route53_record" "private_main_a_record" {
180   zone_id = aws_route53_zone.private_zone.id
181   name = ""
182   type = "A"
183   ttl = 300
184   records = [ local.private_ip["controller"] ]
185 }
186 resource "aws_route53_record" "private_cname_record" {
187   zone_id = aws_route53_zone.private_zone.id
188   for_each = {for i in local.cname_by_host: i.record => "${i.cname}.${local.arvados_dns_zone}" }
189   name = each.key
190   type = "CNAME"
191   ttl = 300
192   records = [ each.value ]
193 }
194
195 #
196 # Route53's credentials for Let's Encrypt
197 #
198 resource "aws_iam_user" "letsencrypt" {
199   name = "${var.cluster_name}-letsencrypt"
200   path = "/"
201 }
202
203 resource "aws_iam_access_key" "letsencrypt" {
204   user = aws_iam_user.letsencrypt.name
205 }
206 resource "aws_iam_user_policy" "letsencrypt_iam_policy" {
207   name = "${var.cluster_name}-letsencrypt_iam_policy"
208   user = aws_iam_user.letsencrypt.name
209   policy = jsonencode({
210     "Version": "2012-10-17",
211     "Statement": [{
212       "Effect": "Allow",
213       "Action": [
214         "route53:ListHostedZones",
215         "route53:GetChange"
216       ],
217       "Resource": [
218           "*"
219       ]
220     },{
221       "Effect" : "Allow",
222       "Action" : [
223         "route53:ChangeResourceRecordSets"
224       ],
225       "Resource" : [
226         "arn:aws:route53:::hostedzone/${aws_route53_zone.public_zone.id}"
227       ]
228     }]
229   })
230 }
231