X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/ad17f016de2feecc24a163af77c9c9c5add7dc3b..6b08327fb62cc3cfba12c628ab5a947912ebf749:/tools/salt-install/terraform/aws/vpc/main.tf diff --git a/tools/salt-install/terraform/aws/vpc/main.tf b/tools/salt-install/terraform/aws/vpc/main.tf index eba48b9f9e..dbd17e062c 100644 --- a/tools/salt-install/terraform/aws/vpc/main.tf +++ b/tools/salt-install/terraform/aws/vpc/main.tf @@ -3,9 +3,11 @@ # SPDX-License-Identifier: CC-BY-SA-3.0 terraform { + required_version = "~> 1.3.0" required_providers { aws = { source = "hashicorp/aws" + version = "~> 4.38.0" } } } @@ -13,45 +15,90 @@ terraform { provider "aws" { region = var.region_name default_tags { - tags = { + tags = merge(var.custom_tags, { Arvados = var.cluster_name - } + Terraform = true + }) } } resource "aws_vpc" "arvados_vpc" { + count = var.vpc_id == "" ? 1 : 0 cidr_block = "10.1.0.0/16" enable_dns_hostnames = true enable_dns_support = true + + lifecycle { + precondition { + condition = (var.sg_id == "") + error_message = "vpc_id should be set if sg_id is also set" + } + } } resource "aws_subnet" "public_subnet" { - vpc_id = aws_vpc.arvados_vpc.id + count = var.public_subnet_id == "" ? 1 : 0 + vpc_id = local.arvados_vpc_id availability_zone = local.availability_zone cidr_block = "10.1.1.0/24" + + lifecycle { + precondition { + condition = (var.vpc_id == "") + error_message = "public_subnet_id should be set if vpc_id is also set" + } + } } resource "aws_subnet" "private_subnet" { - vpc_id = aws_vpc.arvados_vpc.id + count = var.private_subnet_id == "" ? 1 : 0 + vpc_id = local.arvados_vpc_id availability_zone = local.availability_zone cidr_block = "10.1.2.0/24" + + lifecycle { + precondition { + condition = (var.vpc_id == "") + error_message = "private_subnet_id should be set if vpc_id is also set" + } + } +} + +# +# Additional subnet on a different AZ is required if RDS is enabled +# +resource "aws_subnet" "additional_rds_subnet" { + count = (var.additional_rds_subnet_id == "" && local.use_rds) ? 1 : 0 + vpc_id = local.arvados_vpc_id + availability_zone = data.aws_availability_zones.available.names[1] + cidr_block = "10.1.3.0/24" + + lifecycle { + precondition { + condition = (var.vpc_id == "") + error_message = "additional_rds_subnet_id should be set if vpc_id is also set" + } + } } # # VPC S3 access # resource "aws_vpc_endpoint" "s3" { - vpc_id = aws_vpc.arvados_vpc.id + count = var.vpc_id == "" ? 1 : 0 + vpc_id = local.arvados_vpc_id service_name = "com.amazonaws.${var.region_name}.s3" } resource "aws_vpc_endpoint_route_table_association" "compute_s3_route" { - vpc_endpoint_id = aws_vpc_endpoint.s3.id - route_table_id = aws_route_table.private_subnet_rt.id + count = var.private_subnet_id == "" ? 1 : 0 + vpc_endpoint_id = aws_vpc_endpoint.s3[0].id + route_table_id = aws_route_table.private_subnet_rt[0].id } # # Internet access for Public IP instances # resource "aws_internet_gateway" "internet_gw" { - vpc_id = aws_vpc.arvados_vpc.id + count = var.vpc_id == "" ? 1 : 0 + vpc_id = local.arvados_vpc_id } resource "aws_eip" "arvados_eip" { for_each = toset(local.public_hosts) @@ -60,45 +107,59 @@ resource "aws_eip" "arvados_eip" { ] } resource "aws_route_table" "public_subnet_rt" { - vpc_id = aws_vpc.arvados_vpc.id + count = var.public_subnet_id == "" ? 1 : 0 + vpc_id = local.arvados_vpc_id route { cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.internet_gw.id + gateway_id = aws_internet_gateway.internet_gw[0].id } } resource "aws_route_table_association" "public_subnet_assoc" { - subnet_id = aws_subnet.public_subnet.id - route_table_id = aws_route_table.public_subnet_rt.id + count = var.public_subnet_id == "" ? 1 : 0 + subnet_id = aws_subnet.public_subnet[0].id + route_table_id = aws_route_table.public_subnet_rt[0].id } # # Internet access for Private IP instances # resource "aws_eip" "nat_gw_eip" { + count = var.private_subnet_id == "" ? 1 : 0 depends_on = [ - aws_internet_gateway.internet_gw + aws_internet_gateway.internet_gw[0] ] } resource "aws_nat_gateway" "nat_gw" { + count = var.private_subnet_id == "" ? 1 : 0 # A NAT gateway should be placed on a subnet with an internet gateway - subnet_id = aws_subnet.public_subnet.id - allocation_id = aws_eip.nat_gw_eip.id + subnet_id = aws_subnet.public_subnet[0].id + allocation_id = aws_eip.nat_gw_eip[0].id } resource "aws_route_table" "private_subnet_rt" { - vpc_id = aws_vpc.arvados_vpc.id + count = var.private_subnet_id == "" ? 1 : 0 + vpc_id = local.arvados_vpc_id route { cidr_block = "0.0.0.0/0" - nat_gateway_id = aws_nat_gateway.nat_gw.id + nat_gateway_id = aws_nat_gateway.nat_gw[0].id } } resource "aws_route_table_association" "private_subnet_assoc" { - subnet_id = aws_subnet.private_subnet.id - route_table_id = aws_route_table.private_subnet_rt.id + count = var.private_subnet_id == "" ? 1 : 0 + subnet_id = aws_subnet.private_subnet[0].id + route_table_id = aws_route_table.private_subnet_rt[0].id } resource "aws_security_group" "arvados_sg" { name = "arvados_sg" - vpc_id = aws_vpc.arvados_vpc.id + count = var.sg_id == "" ? 1 : 0 + vpc_id = aws_vpc.arvados_vpc[0].id + + lifecycle { + precondition { + condition = (var.vpc_id == "") + error_message = "sg_id should be set if vpc_id is set" + } + } dynamic "ingress" { for_each = local.allowed_ports @@ -116,7 +177,7 @@ resource "aws_security_group" "arvados_sg" { from_port = 0 to_port = 0 protocol = "-1" - cidr_blocks = [ aws_vpc.arvados_vpc.cidr_block ] + cidr_blocks = [ aws_vpc.arvados_vpc[0].cidr_block ] } # Even though AWS auto-creates an "allow all" egress rule, # Terraform deletes it, so we add it explicitly. @@ -135,10 +196,11 @@ resource "aws_security_group" "arvados_sg" { # PUBLIC DNS resource "aws_route53_zone" "public_zone" { - name = local.arvados_dns_zone + count = var.private_only ? 0 : 1 + name = var.domain_name } resource "aws_route53_record" "public_a_record" { - zone_id = aws_route53_zone.public_zone.id + zone_id = try(local.route53_public_zone.id, "") for_each = local.public_ip name = each.key type = "A" @@ -146,15 +208,20 @@ resource "aws_route53_record" "public_a_record" { records = [ each.value ] } resource "aws_route53_record" "main_a_record" { - zone_id = aws_route53_zone.public_zone.id + count = var.private_only ? 0 : 1 + zone_id = try(local.route53_public_zone.id, "") name = "" type = "A" ttl = 300 records = [ local.public_ip["controller"] ] } resource "aws_route53_record" "public_cname_record" { - zone_id = aws_route53_zone.public_zone.id - for_each = {for i in local.cname_by_host: i.record => "${i.cname}.${local.arvados_dns_zone}" } + zone_id = try(local.route53_public_zone.id, "") + for_each = { + for i in local.cname_by_host: i.record => + "${i.cname}.${var.domain_name}" + if var.private_only == false + } name = each.key type = "CNAME" ttl = 300 @@ -163,9 +230,9 @@ resource "aws_route53_record" "public_cname_record" { # PRIVATE DNS resource "aws_route53_zone" "private_zone" { - name = local.arvados_dns_zone + name = var.domain_name vpc { - vpc_id = aws_vpc.arvados_vpc.id + vpc_id = local.arvados_vpc_id } } resource "aws_route53_record" "private_a_record" { @@ -185,7 +252,7 @@ resource "aws_route53_record" "private_main_a_record" { } resource "aws_route53_record" "private_cname_record" { zone_id = aws_route53_zone.private_zone.id - for_each = {for i in local.cname_by_host: i.record => "${i.cname}.${local.arvados_dns_zone}" } + for_each = {for i in local.cname_by_host: i.record => "${i.cname}.${var.domain_name}" } name = each.key type = "CNAME" ttl = 300 @@ -196,16 +263,19 @@ resource "aws_route53_record" "private_cname_record" { # Route53's credentials for Let's Encrypt # resource "aws_iam_user" "letsencrypt" { + count = var.private_only ? 0 : 1 name = "${var.cluster_name}-letsencrypt" path = "/" } resource "aws_iam_access_key" "letsencrypt" { - user = aws_iam_user.letsencrypt.name + count = var.private_only ? 0 : 1 + user = local.iam_user_letsencrypt.name } resource "aws_iam_user_policy" "letsencrypt_iam_policy" { + count = var.private_only ? 0 : 1 name = "${var.cluster_name}-letsencrypt_iam_policy" - user = aws_iam_user.letsencrypt.name + user = local.iam_user_letsencrypt.name policy = jsonencode({ "Version": "2012-10-17", "Statement": [{ @@ -223,7 +293,7 @@ resource "aws_iam_user_policy" "letsencrypt_iam_policy" { "route53:ChangeResourceRecordSets" ], "Resource" : [ - "arn:aws:route53:::hostedzone/${aws_route53_zone.public_zone.id}" + "arn:aws:route53:::hostedzone/${local.route53_public_zone.id}" ] }] })