diff --git a/infrastructure/applications/.terraform.lock.hcl b/infrastructure/applications/.terraform.lock.hcl index 53d077e95f..0fe99186a2 100644 --- a/infrastructure/applications/.terraform.lock.hcl +++ b/infrastructure/applications/.terraform.lock.hcl @@ -2,25 +2,25 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "5.70.0" - constraints = "5.70.0" + version = "5.82.2" + constraints = "5.82.2" hashes = [ - "h1:LKnWZnujHcQPm3MAk4elP3H9VXNjlO6rNqlO5s330Yg=", - "zh:09cbec93c324e6f03a866244ecb2bae71fdf1f5d3d981e858b745c90606b6b6d", - "zh:19685d9f4c9ddcfa476a9a428c6c612be4a1b4e8e1198fbcbb76436b735284ee", - "zh:3358ee6a2b24c982b7c83fac0af6898644d1bbdabf9c4e0589e91e427641ba88", - "zh:34f9f2936de7384f8ed887abdbcb54aea1ce7b0cf2e85243a3fd3904d024747f", - "zh:4a99546cc2140304c90d9ccb9db01589d4145863605a0fcd90027a643ea3ec5d", - "zh:4da32fec0e10dab5aa3dea3c9fe57adc973cc73a71f5d59da3f65d85d925dc3f", - "zh:659cf94522bc38ce0af70f7b0371b2941a0e0bcad02d17c1a7b264575fe07224", - "zh:6f1c172c9b98bc86e4f0526872098ee3246c2620f7b323ce0c2ce6427987f7d2", - "zh:79bf8fb8f37c308742e287694a9de081ff8502b065a390d1bcfbd241b4eca203", + "h1:RuPaHbllUB8a2TGTyc149wJfoh6zhIEjUvFYKR6iP2E=", + "zh:0262fc96012fb7e173e1b7beadd46dfc25b1dc7eaef95b90e936fc454724f1c8", + "zh:397413613d27f4f54d16efcbf4f0a43c059bd8d827fe34287522ae182a992f9b", + "zh:436c0c5d56e1da4f0a4c13129e12a0b519d12ab116aed52029b183f9806866f3", + "zh:4d942d173a2553d8d532a333a0482a090f4e82a2238acf135578f163b6e68470", + "zh:624aebc549bfbce06cc2ecfd8631932eb874ac7c10eb8466ce5b9a2fbdfdc724", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:b7a5e1dfd9e179d70a169ddd4db44b56da90309060e27d36b329fe5fb3528e29", - "zh:c2cc728cb18ffd5c4814a10c203452c71f5ab0c46d68f9aa9183183fa60afd87", - "zh:c89bb37d2b8947c9a0d62b0b86ace51542f3327970f4e56a68bf81d9d0b8b65b", - "zh:ef2a61e8112c3b5e70095508aadaadf077e904b62b9cfc22030337f773bba041", - "zh:f714550b858d141ea88579f25247bda2a5ba461337975e77daceaf0bb7a9c358", + "zh:9e632dee2dfdf01b371cca7854b1ec63ceefa75790e619b0642b34d5514c6733", + "zh:a07567acb115b60a3df8f6048d12735b9b3bcf85ec92a62f77852e13d5a3c096", + "zh:ab7002df1a1be6432ac0eb1b9f6f0dd3db90973cd5b1b0b33d2dae54553dfbd7", + "zh:bc1ff65e2016b018b3e84db7249b2cd0433cb5c81dc81f9f6158f2197d6b9fde", + "zh:bcad84b1d767f87af6e1ba3dc97fdb8f2ad5de9224f192f1412b09aba798c0a8", + "zh:cf917dceaa0f9d55d9ff181b5dcc4d1e10af21b6671811b315ae2a6eda866a2a", + "zh:d8e90ecfb3216f3cc13ccde5a16da64307abb6e22453aed2ac3067bbf689313b", + "zh:d9054e0e40705df729682ad34c20db8695d57f182c65963abd151c6aba1ab0d3", + "zh:ecf3a4f3c57eb7e89f71b8559e2a71e4cdf94eea0118ec4f2cb37e4f4d71a069", ] } diff --git a/infrastructure/applications/applications.tf b/infrastructure/applications/applications.tf index 6963652c4c..a99c34c1f5 100644 --- a/infrastructure/applications/applications.tf +++ b/infrastructure/applications/applications.tf @@ -1,11 +1,5 @@ locals { is_prod = terraform.workspace == "production" - deploy_pretix = local.is_prod - - # AMI - # Built from https://github.com/aws/amazon-ecs-ami - # Using 8GB as storage. - ecs_arm_ami = "ami-0bd650c1ca04cc1a4" # make al2023arm } # Applications @@ -13,23 +7,25 @@ locals { module "pretix" { source = "./pretix" count = 1 - ecs_arm_ami = local.ecs_arm_ami server_ip = module.cluster.server_ip cluster_id = module.cluster.cluster_id logs_group_name = module.cluster.logs_group_name + database_settings = module.database.database_settings } module "pycon_backend" { source = "./pycon_backend" - ecs_arm_ami = local.ecs_arm_ami cluster_id = module.cluster.cluster_id security_group_id = module.cluster.security_group_id server_ip = module.cluster.server_ip logs_group_name = module.cluster.logs_group_name iam_role_arn = module.cluster.iam_role_arn + database_settings = module.database.database_settings + vpc_id = module.vpc.vpc_id + public_1a_subnet_id = module.vpc.public_1a_subnet_id + configuration_set_name = module.emails.configuration_set_name providers = { - aws = aws aws.us = aws.us } } @@ -41,49 +37,44 @@ module "pycon_frontend" { server_ip = module.cluster.server_ip cf_domain_name = module.cluster.cf_domain_name cf_hosted_zone_id = module.cluster.cf_hosted_zone_id - - providers = { - aws = aws - aws.us = aws.us - } } module "clamav" { source = "./clamav" cluster_id = module.cluster.cluster_id logs_group_name = module.cluster.logs_group_name - - providers = { - aws = aws - aws.us = aws.us - } } # Other resources module "database" { source = "./database" + private_subnets_ids = module.vpc.private_subnets_ids + vpc_id = module.vpc.vpc_id } module "emails" { source = "./emails" providers = { - aws = aws aws.us = aws.us } } module "cluster" { source = "./cluster" - ecs_arm_ami = local.ecs_arm_ami + vpc_id = module.vpc.vpc_id + public_1a_subnet_id = module.vpc.public_1a_subnet_id providers = { - aws = aws aws.us = aws.us } } +module "vpc" { + source = "./vpc" +} + output "server_public_ip" { value = module.cluster.server_public_ip } diff --git a/infrastructure/applications/cluster/cloudfront.tf b/infrastructure/applications/cluster/cloudfront.tf index cda03d1507..88a1da2d7a 100644 --- a/infrastructure/applications/cluster/cloudfront.tf +++ b/infrastructure/applications/cluster/cloudfront.tf @@ -73,9 +73,6 @@ resource "aws_cloudfront_distribution" "application" { cache_policy_id = data.aws_cloudfront_cache_policy.origin_cache_control_headers.id origin_request_policy_id = data.aws_cloudfront_origin_request_policy.all_viewer.id - min_ttl = 0 - default_ttl = 86400 - max_ttl = 31536000 compress = true viewer_protocol_policy = "redirect-to-https" } diff --git a/infrastructure/applications/cluster/providers.tf b/infrastructure/applications/cluster/providers.tf new file mode 100644 index 0000000000..2ec15ed060 --- /dev/null +++ b/infrastructure/applications/cluster/providers.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + configuration_aliases = [aws.us] + } + } +} diff --git a/infrastructure/applications/cluster/security.tf b/infrastructure/applications/cluster/security.tf index 72ac9029bb..9c050a3231 100644 --- a/infrastructure/applications/cluster/security.tf +++ b/infrastructure/applications/cluster/security.tf @@ -1,7 +1,11 @@ resource "aws_security_group" "server" { - name = "${terraform.workspace}-server" - description = "${terraform.workspace} server" - vpc_id = data.aws_vpc.default.id + name = "pythonit-${terraform.workspace}-server" + description = "pythonit-${terraform.workspace} server" + vpc_id = var.vpc_id + + tags = { + Name = "pythonit-${terraform.workspace}-server" + } } resource "aws_security_group_rule" "out_all" { diff --git a/infrastructure/applications/cluster/server.tf b/infrastructure/applications/cluster/server.tf index f204fb2164..47a23ac662 100644 --- a/infrastructure/applications/cluster/server.tf +++ b/infrastructure/applications/cluster/server.tf @@ -11,9 +11,9 @@ resource "aws_eip" "server" { } resource "aws_instance" "server" { - ami = "ami-0d683ccb0045afce1" + ami = "ami-0ce51086755ce7709" instance_type = local.is_prod ? "t4g.large" : "t4g.small" - subnet_id = data.aws_subnet.public_1a.id + subnet_id = var.public_1a_subnet_id availability_zone = "eu-central-1a" vpc_security_group_ids = [ aws_security_group.server.id, diff --git a/infrastructure/applications/cluster/variables.tf b/infrastructure/applications/cluster/variables.tf index 15b58209f2..1fe3b51d3d 100644 --- a/infrastructure/applications/cluster/variables.tf +++ b/infrastructure/applications/cluster/variables.tf @@ -1 +1,2 @@ -variable "ecs_arm_ami" {} +variable "vpc_id" {} +variable "public_1a_subnet_id" {} diff --git a/infrastructure/applications/cluster/vpc.tf b/infrastructure/applications/cluster/vpc.tf deleted file mode 100644 index 7162daf1c0..0000000000 --- a/infrastructure/applications/cluster/vpc.tf +++ /dev/null @@ -1,20 +0,0 @@ -data "aws_vpc" "default" { - filter { - name = "tag:Name" - values = ["pythonit-vpc"] - } -} - -data "aws_subnet" "public_1a" { - vpc_id = data.aws_vpc.default.id - - filter { - name = "tag:Type" - values = ["public"] - } - - filter { - name = "tag:AZ" - values = ["eu-central-1a"] - } -} diff --git a/infrastructure/applications/config.tf b/infrastructure/applications/config.tf index f123e44746..81bf4e6fa0 100644 --- a/infrastructure/applications/config.tf +++ b/infrastructure/applications/config.tf @@ -2,7 +2,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "5.70.0" + version = "5.82.2" configuration_aliases = [aws.us] } } diff --git a/infrastructure/applications/database/db.tf b/infrastructure/applications/database/db.tf index 71ac4858df..5b6141eb5f 100644 --- a/infrastructure/applications/database/db.tf +++ b/infrastructure/applications/database/db.tf @@ -3,14 +3,6 @@ locals { is_prod = terraform.workspace == "production" } -data "aws_db_subnet_group" "rds" { - name = "pythonit-rds-subnet" -} - -data "aws_security_group" "rds" { - name = "pythonit-rds-security-group" -} - resource "aws_db_instance" "database" { allocated_storage = 20 storage_type = "gp3" @@ -31,9 +23,19 @@ resource "aws_db_instance" "database" { deletion_protection = local.is_prod storage_encrypted = true - db_subnet_group_name = data.aws_db_subnet_group.rds.name - vpc_security_group_ids = [data.aws_security_group.rds.id] + db_subnet_group_name = aws_db_subnet_group.rds.name + vpc_security_group_ids = [aws_security_group.rds.id] performance_insights_enabled = true performance_insights_retention_period = 7 } + +output "database_settings" { + value = { + address = aws_db_instance.database.address + port = aws_db_instance.database.port + username = aws_db_instance.database.username + password = module.common_secrets.value.database_password + db_name = aws_db_instance.database.db_name + } +} diff --git a/infrastructure/applications/database/security_group.tf b/infrastructure/applications/database/security_group.tf new file mode 100644 index 0000000000..ef7194c17c --- /dev/null +++ b/infrastructure/applications/database/security_group.tf @@ -0,0 +1,23 @@ +resource "aws_security_group" "rds" { + vpc_id = var.vpc_id + name = "pythonit-${terraform.workspace}-rds-security-group" + description = "Allow inbound postgres traffic" +} + +resource "aws_security_group_rule" "allow_postgres" { + type = "ingress" + from_port = 5432 + to_port = 5432 + protocol = "tcp" + security_group_id = aws_security_group.rds.id + cidr_blocks = ["0.0.0.0/0"] +} + +resource "aws_security_group_rule" "allow_outbound_postgres" { + type = "egress" + from_port = 5432 + to_port = 5432 + protocol = "tcp" + security_group_id = aws_security_group.rds.id + source_security_group_id = aws_security_group.rds.id +} diff --git a/infrastructure/applications/database/subnet.tf b/infrastructure/applications/database/subnet.tf new file mode 100644 index 0000000000..c735ba6876 --- /dev/null +++ b/infrastructure/applications/database/subnet.tf @@ -0,0 +1,9 @@ +resource "aws_db_subnet_group" "rds" { + name = "pythonit-${terraform.workspace}-rds-subnet" + description = "pythonit ${terraform.workspace} rds subnet" + subnet_ids = var.private_subnets_ids + + tags = { + Name = "pythonit-${terraform.workspace}-rds-subnet" + } +} diff --git a/infrastructure/applications/database/variables.tf b/infrastructure/applications/database/variables.tf new file mode 100644 index 0000000000..beed670083 --- /dev/null +++ b/infrastructure/applications/database/variables.tf @@ -0,0 +1,2 @@ +variable "private_subnets_ids" {} +variable "vpc_id" {} diff --git a/infrastructure/applications/emails/main.tf b/infrastructure/applications/emails/main.tf index 01b0cfe73c..abb61d550d 100644 --- a/infrastructure/applications/emails/main.tf +++ b/infrastructure/applications/emails/main.tf @@ -7,6 +7,7 @@ resource "aws_sesv2_configuration_set" "main" { tracking_options { custom_redirect_domain = local.email_tracking_domain + https_policy = "OPTIONAL" } } @@ -33,3 +34,7 @@ resource "aws_sesv2_configuration_set_event_destination" "backend" { ] } } + +output "configuration_set_name" { + value = aws_sesv2_configuration_set.main.configuration_set_name +} diff --git a/infrastructure/applications/pretix/main.tf b/infrastructure/applications/pretix/main.tf index c1bef2a199..da6e1b8fd7 100644 --- a/infrastructure/applications/pretix/main.tf +++ b/infrastructure/applications/pretix/main.tf @@ -3,10 +3,6 @@ locals { alias = local.is_prod ? "tickets.pycon.it" : "${terraform.workspace}-tickets.pycon.it" } -data "aws_db_instance" "database" { - db_instance_identifier = "pythonit-${terraform.workspace}" -} - resource "aws_ecs_task_definition" "pretix" { family = "${terraform.workspace}-pretix" container_definitions = jsonencode([ @@ -87,19 +83,19 @@ resource "aws_ecs_task_definition" "pretix" { }, { name = "PRETIX_DATABASE_USER" - value = data.aws_db_instance.database.master_username + value = var.database_settings.username }, { name = "PRETIX_DATABASE_PASSWORD" - value = module.common_secrets.value.database_password + value = var.database_settings.password }, { name = "PRETIX_DATABASE_HOST" - value = data.aws_db_instance.database.address + value = var.database_settings.address }, { name = "PRETIX_DATABASE_PORT" - value = "5432" + value = tostring(var.database_settings.port) }, { name = "PRETIX_MAIL_USER" diff --git a/infrastructure/applications/pretix/variables.tf b/infrastructure/applications/pretix/variables.tf index 592a14ab97..df3caf78b1 100644 --- a/infrastructure/applications/pretix/variables.tf +++ b/infrastructure/applications/pretix/variables.tf @@ -1,4 +1,4 @@ -variable "ecs_arm_ami" {} variable "server_ip" {} variable "cluster_id" {} variable "logs_group_name" {} +variable "database_settings" {} diff --git a/infrastructure/applications/pycon_backend/main.tf b/infrastructure/applications/pycon_backend/main.tf index 4bac6239c2..e4ee917fe1 100644 --- a/infrastructure/applications/pycon_backend/main.tf +++ b/infrastructure/applications/pycon_backend/main.tf @@ -2,46 +2,12 @@ locals { is_prod = terraform.workspace == "production" admin_domain = "admin" full_admin_domain = local.is_prod ? "${local.admin_domain}.pycon.it" : "${terraform.workspace}-${local.admin_domain}.pycon.it" - db_connection = "postgres://${data.aws_db_instance.database.master_username}:${module.common_secrets.value.database_password}@${data.aws_db_instance.database.address}:${data.aws_db_instance.database.port}/pycon" + db_connection = "postgres://${var.database_settings.username}:${var.database_settings.password}@${var.database_settings.address}:${var.database_settings.port}/pycon" cdn_url = local.is_prod ? "cdn.pycon.it" : "${terraform.workspace}-cdn.pycon.it" } -data "aws_vpc" "default" { - filter { - name = "tag:Name" - values = ["pythonit-vpc"] - } -} - -data "aws_subnets" "private" { - filter { - name = "vpc-id" - values = [data.aws_vpc.default.id] - } - - tags = { - Type = "private" - } -} - -data "aws_security_group" "rds" { - name = "pythonit-rds-security-group" -} - -data "aws_security_group" "lambda" { - name = "pythonit-lambda-security-group" -} - -data "aws_db_instance" "database" { - db_instance_identifier = "pythonit-${terraform.workspace}" -} - data "aws_acm_certificate" "cert" { domain = "pycon.it" statuses = ["ISSUED"] provider = aws.us } - -data "aws_sesv2_configuration_set" "main" { - configuration_set_name = "pythonit-${terraform.workspace}" -} diff --git a/infrastructure/applications/pycon_backend/variables.tf b/infrastructure/applications/pycon_backend/variables.tf index 23f0956687..630dbb24dc 100644 --- a/infrastructure/applications/pycon_backend/variables.tf +++ b/infrastructure/applications/pycon_backend/variables.tf @@ -4,9 +4,12 @@ locals { local_path = "backend" } -variable "ecs_arm_ami" {} variable "cluster_id" {} variable "security_group_id" {} variable "server_ip" {} variable "logs_group_name" {} variable "iam_role_arn" {} +variable "database_settings" {} +variable "vpc_id" {} +variable "public_1a_subnet_id" {} +variable "configuration_set_name" {} diff --git a/infrastructure/applications/pycon_backend/worker.tf b/infrastructure/applications/pycon_backend/worker.tf index 81045d550c..33546dbbc8 100644 --- a/infrastructure/applications/pycon_backend/worker.tf +++ b/infrastructure/applications/pycon_backend/worker.tf @@ -171,7 +171,7 @@ locals { { name = "ECS_NETWORK_CONFIG", value = jsonencode({ - subnets = [data.aws_subnet.public_1a.id], + subnets = [var.public_1a_subnet_id], security_groups = [ var.security_group_id ], @@ -183,7 +183,7 @@ locals { }, { name = "AWS_SES_CONFIGURATION_SET" - value = data.aws_sesv2_configuration_set.main.configuration_set_name + value = var.configuration_set_name }, { name = "SNS_WEBHOOK_SECRET", @@ -209,34 +209,6 @@ resource "aws_iam_role" "ecs_service" { }) } -data "aws_subnet" "private_1a" { - vpc_id = data.aws_vpc.default.id - - filter { - name = "tag:Type" - values = ["private"] - } - - filter { - name = "tag:AZ" - values = ["eu-central-1a"] - } -} - -data "aws_subnet" "public_1a" { - vpc_id = data.aws_vpc.default.id - - filter { - name = "tag:Type" - values = ["public"] - } - - filter { - name = "tag:AZ" - values = ["eu-central-1a"] - } -} - resource "aws_ecs_task_definition" "worker" { family = "pythonit-${terraform.workspace}-worker" diff --git a/infrastructure/applications/vpc/endpoints.tf b/infrastructure/applications/vpc/endpoints.tf new file mode 100644 index 0000000000..77e7df7e12 --- /dev/null +++ b/infrastructure/applications/vpc/endpoints.tf @@ -0,0 +1,8 @@ +resource "aws_vpc_endpoint" "s3" { + vpc_id = aws_vpc.default.id + service_name = "com.amazonaws.eu-central-1.s3" + vpc_endpoint_type = "Gateway" + route_table_ids = concat( + [for route in aws_route_table.public : route.id] + ) +} diff --git a/infrastructure/applications/vpc/main.tf b/infrastructure/applications/vpc/main.tf new file mode 100644 index 0000000000..9d35297308 --- /dev/null +++ b/infrastructure/applications/vpc/main.tf @@ -0,0 +1,21 @@ +locals { + public_azs_cidr = { + "eu-central-1a" : "10.0.1.0/24", + "eu-central-1b" : "10.0.2.0/24", + "eu-central-1c" : "10.0.3.0/24", + } + private_azs_cidr = { + "eu-central-1a" : "10.0.4.0/24", + "eu-central-1b" : "10.0.5.0/24", + "eu-central-1c" : "10.0.6.0/24", + } +} + +resource "aws_vpc" "default" { + cidr_block = "10.0.0.0/16" + enable_dns_hostnames = true + + tags = { + Name = "pythonit-${terraform.workspace}-vpc" + } +} diff --git a/infrastructure/applications/vpc/outputs.tf b/infrastructure/applications/vpc/outputs.tf new file mode 100644 index 0000000000..01464c7a68 --- /dev/null +++ b/infrastructure/applications/vpc/outputs.tf @@ -0,0 +1,11 @@ +output "private_subnets_ids" { + value = [for subnet in aws_subnet.private : subnet.id] +} + +output "vpc_id" { + value = aws_vpc.default.id +} + +output "public_1a_subnet_id" { + value = aws_subnet.public["eu-central-1a"].id +} diff --git a/infrastructure/applications/vpc/private_subnet.tf b/infrastructure/applications/vpc/private_subnet.tf new file mode 100644 index 0000000000..43de323d45 --- /dev/null +++ b/infrastructure/applications/vpc/private_subnet.tf @@ -0,0 +1,12 @@ +resource "aws_subnet" "private" { + for_each = local.private_azs_cidr + vpc_id = aws_vpc.default.id + availability_zone = each.key + cidr_block = each.value + + tags = { + Name = "pythonit-${terraform.workspace}-private-subnet-${each.key}" + Type = "private" + AZ = each.key + } +} diff --git a/infrastructure/applications/vpc/public_subnet.tf b/infrastructure/applications/vpc/public_subnet.tf new file mode 100644 index 0000000000..6975238bdd --- /dev/null +++ b/infrastructure/applications/vpc/public_subnet.tf @@ -0,0 +1,41 @@ +resource "aws_subnet" "public" { + for_each = local.public_azs_cidr + vpc_id = aws_vpc.default.id + availability_zone = each.key + cidr_block = each.value + map_public_ip_on_launch = true + + tags = { + Name = "pythonit-${terraform.workspace}-public-subnet-${each.key}" + Type = "public" + AZ = each.key + } +} + +resource "aws_route_table" "public" { + for_each = toset(keys(local.public_azs_cidr)) + vpc_id = aws_vpc.default.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.default.id + } + + tags = { + Name = "pythonit-${terraform.workspace}-public-route-${each.value}" + } + + depends_on = [ + aws_internet_gateway.default + ] +} + +resource "aws_route_table_association" "public_subnet_to_public_route" { + for_each = toset(keys(local.public_azs_cidr)) + route_table_id = aws_route_table.public[each.value].id + subnet_id = aws_subnet.public[each.value].id +} + +resource "aws_internet_gateway" "default" { + vpc_id = aws_vpc.default.id +}