From 8a2dbe4bcb9a92bf6dbce1806f79733291e01ec8 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Tue, 16 Jun 2026 12:29:32 +0100 Subject: [PATCH 01/26] improve infra providers --- infrastructure/blocks/auth/main.tf | 10 ++--- infrastructure/blocks/s3/main.tf | 4 +- infrastructure/modules/app-cluster/db.tf | 6 +-- .../modules/app-cluster/providers.tf | 8 ++++ infrastructure/modules/auth/db.tf | 6 +-- infrastructure/modules/auth/providers.tf | 8 ++++ .../modules/data-workflow/dynamodb.tf | 6 +-- .../modules/data-workflow/providers.tf | 8 ++++ infrastructure/modules/rapid/main.tf | 37 +++++++++++++++++++ infrastructure/modules/rapid/providers.tf | 9 +++++ infrastructure/modules/ui/cloudfront.tf | 3 +- infrastructure/modules/ui/lambda.tf | 2 + infrastructure/modules/ui/providers.tf | 9 +++++ infrastructure/modules/ui/waf.tf | 9 ----- 14 files changed, 99 insertions(+), 26 deletions(-) create mode 100644 infrastructure/modules/app-cluster/providers.tf create mode 100644 infrastructure/modules/auth/providers.tf create mode 100644 infrastructure/modules/data-workflow/providers.tf create mode 100644 infrastructure/modules/rapid/providers.tf create mode 100644 infrastructure/modules/ui/providers.tf diff --git a/infrastructure/blocks/auth/main.tf b/infrastructure/blocks/auth/main.tf index f417fa48..42cfd92a 100644 --- a/infrastructure/blocks/auth/main.tf +++ b/infrastructure/blocks/auth/main.tf @@ -5,9 +5,9 @@ terraform { } module "auth" { - source = "../../modules/auth" - tags = var.tags - domain_name = var.domain_name - resource-name-prefix = var.resource-name-prefix - layers = var.layers + source = "../../modules/auth" + tags = var.tags + domain_name = var.domain_name + resource-name-prefix = var.resource-name-prefix + layers = var.layers } diff --git a/infrastructure/blocks/s3/main.tf b/infrastructure/blocks/s3/main.tf index 2ab51ad6..8c6a340d 100644 --- a/infrastructure/blocks/s3/main.tf +++ b/infrastructure/blocks/s3/main.tf @@ -19,7 +19,7 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "rapid_data_storag rule { apply_server_side_encryption_by_default { - sse_algorithm = "aws:kms" + sse_algorithm = "aws:kms" } } } @@ -84,7 +84,7 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "logs" { rule { apply_server_side_encryption_by_default { - sse_algorithm = "aws:kms" + sse_algorithm = "aws:kms" } } } diff --git a/infrastructure/modules/app-cluster/db.tf b/infrastructure/modules/app-cluster/db.tf index 28339d1e..0d40feeb 100644 --- a/infrastructure/modules/app-cluster/db.tf +++ b/infrastructure/modules/app-cluster/db.tf @@ -3,9 +3,9 @@ data "aws_caller_identity" "current" {} resource "aws_dynamodb_table" "service_table" { # checkov:skip=CKV_AWS_119:No need for customer managed keys - name = "${var.resource-name-prefix}_service_table" - hash_key = "PK" - range_key = "SK" + name = "${var.resource-name-prefix}_service_table" + hash_key = "PK" + range_key = "SK" billing_mode = "PAY_PER_REQUEST" deletion_protection_enabled = true diff --git a/infrastructure/modules/app-cluster/providers.tf b/infrastructure/modules/app-cluster/providers.tf new file mode 100644 index 00000000..ed160fde --- /dev/null +++ b/infrastructure/modules/app-cluster/providers.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 2.7.0" + } + } +} diff --git a/infrastructure/modules/auth/db.tf b/infrastructure/modules/auth/db.tf index c1e8cb8e..e0ecfcba 100644 --- a/infrastructure/modules/auth/db.tf +++ b/infrastructure/modules/auth/db.tf @@ -3,9 +3,9 @@ data "aws_caller_identity" "current" {} resource "aws_dynamodb_table" "permissions_table" { # checkov:skip=CKV_AWS_119:No need for customer managed keys - name = "${var.resource-name-prefix}_${var.permissions_table_name}" - hash_key = "PK" - range_key = "SK" + name = "${var.resource-name-prefix}_${var.permissions_table_name}" + hash_key = "PK" + range_key = "SK" billing_mode = "PAY_PER_REQUEST" deletion_protection_enabled = true diff --git a/infrastructure/modules/auth/providers.tf b/infrastructure/modules/auth/providers.tf new file mode 100644 index 00000000..ed160fde --- /dev/null +++ b/infrastructure/modules/auth/providers.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 2.7.0" + } + } +} diff --git a/infrastructure/modules/data-workflow/dynamodb.tf b/infrastructure/modules/data-workflow/dynamodb.tf index 0d818888..ddcaee78 100644 --- a/infrastructure/modules/data-workflow/dynamodb.tf +++ b/infrastructure/modules/data-workflow/dynamodb.tf @@ -1,8 +1,8 @@ resource "aws_dynamodb_table" "schema_table" { # checkov:skip=CKV_AWS_119:No need for customer managed keys - name = "${var.resource-name-prefix}_schema_table" - hash_key = "PK" - range_key = "SK" + name = "${var.resource-name-prefix}_schema_table" + hash_key = "PK" + range_key = "SK" billing_mode = "PAY_PER_REQUEST" deletion_protection_enabled = true diff --git a/infrastructure/modules/data-workflow/providers.tf b/infrastructure/modules/data-workflow/providers.tf new file mode 100644 index 00000000..ed160fde --- /dev/null +++ b/infrastructure/modules/data-workflow/providers.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 2.7.0" + } + } +} diff --git a/infrastructure/modules/rapid/main.tf b/infrastructure/modules/rapid/main.tf index bcc7ff00..5f030c1f 100644 --- a/infrastructure/modules/rapid/main.tf +++ b/infrastructure/modules/rapid/main.tf @@ -1,4 +1,7 @@ module "app_cluster" { + providers = { + aws = aws.default + } source = "../app-cluster" app-replica-count-desired = var.app-replica-count-desired app-replica-count-max = var.app-replica-count-max @@ -37,6 +40,9 @@ module "app_cluster" { } module "auth" { + providers = { + aws = aws.default + } source = "../auth" tags = var.tags domain_name = var.domain_name @@ -48,6 +54,9 @@ module "auth" { } module "data_workflow" { + providers = { + aws = aws.default + } source = "../data-workflow" resource-name-prefix = var.resource-name-prefix aws_account = var.aws_account @@ -55,6 +64,10 @@ module "data_workflow" { } module "ui" { + providers = { + aws.default = aws.default + aws.us_east = aws.us_east + } source = "../ui" tags = var.tags log_bucket_name = aws_s3_bucket.logs.id @@ -77,6 +90,8 @@ resource "aws_s3_bucket" "this" { #checkov:skip=CKV2_AWS_62:No need for event notifications #checkov:skip=CKV2_AWS_61:No need for lifecycle configuration + provider = aws.default + bucket = var.resource-name-prefix force_destroy = false @@ -85,6 +100,8 @@ resource "aws_s3_bucket" "this" { } resource "aws_s3_bucket_server_side_encryption_configuration" "this" { + provider = aws.default + bucket = aws_s3_bucket.this.id rule { @@ -96,6 +113,8 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "this" { } resource "aws_s3_bucket_versioning" "this" { + provider = aws.default + bucket = aws_s3_bucket.this.id versioning_configuration { status = "Enabled" @@ -103,6 +122,8 @@ resource "aws_s3_bucket_versioning" "this" { } resource "aws_s3_bucket_logging" "this" { + provider = aws.default + bucket = aws_s3_bucket.this.id target_bucket = aws_s3_bucket.logs.bucket @@ -110,11 +131,15 @@ resource "aws_s3_bucket_logging" "this" { } resource "aws_s3_bucket_notification" "this" { + provider = aws.default + bucket = aws_s3_bucket.this.id eventbridge = true } resource "aws_s3_bucket_public_access_block" "this" { + provider = aws.default + bucket = aws_s3_bucket.this.id ignore_public_acls = true block_public_acls = true @@ -129,6 +154,8 @@ resource "aws_s3_bucket" "logs" { #checkov:skip=CKV_AWS_21:No need to version log bucket #checkov:skip=CKV2_AWS_62:No need for event notifications #checkov:skip=CKV2_AWS_61:No need for lifecycle configuration + provider = aws.default + bucket = "${var.resource-name-prefix}-logs" force_destroy = false @@ -136,11 +163,15 @@ resource "aws_s3_bucket" "logs" { } resource "aws_s3_bucket_acl" "logs" { + provider = aws.default + bucket = aws_s3_bucket.logs.id acl = "private" } resource "aws_s3_bucket_server_side_encryption_configuration" "logs" { + provider = aws.default + bucket = aws_s3_bucket.logs.id rule { @@ -153,6 +184,8 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "logs" { # Resource to avoid error "AccessControlListNotSupported: The bucket does not allow ACLs" resource "aws_s3_bucket_ownership_controls" "logs" { + provider = aws.default + bucket = aws_s3_bucket.logs.id rule { object_ownership = "BucketOwnerPreferred" @@ -160,6 +193,8 @@ resource "aws_s3_bucket_ownership_controls" "logs" { } resource "aws_s3_bucket_public_access_block" "logs" { + provider = aws.default + bucket = aws_s3_bucket.logs.id ignore_public_acls = true block_public_acls = true @@ -169,6 +204,8 @@ resource "aws_s3_bucket_public_access_block" "logs" { } resource "aws_s3_bucket_policy" "log_bucket_policy" { + provider = aws.default + bucket = aws_s3_bucket.this.id policy = < Date: Tue, 16 Jun 2026 13:15:13 +0100 Subject: [PATCH 02/26] add kms perm to delete key --- infrastructure/modules/app-cluster/cloudtrail.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/infrastructure/modules/app-cluster/cloudtrail.tf b/infrastructure/modules/app-cluster/cloudtrail.tf index 878dd5ec..5b81e016 100644 --- a/infrastructure/modules/app-cluster/cloudtrail.tf +++ b/infrastructure/modules/app-cluster/cloudtrail.tf @@ -19,6 +19,7 @@ data "aws_iam_policy_document" "access_logs_key_policy" { "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", + "kms:ScheduleKeyDeletion" ] resources = [ From 44522916cdde86f02101b6ac1862580df4e0f753 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Tue, 16 Jun 2026 13:19:30 +0100 Subject: [PATCH 03/26] add kms perm to enable key rotation --- infrastructure/modules/app-cluster/cloudtrail.tf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/infrastructure/modules/app-cluster/cloudtrail.tf b/infrastructure/modules/app-cluster/cloudtrail.tf index 5b81e016..24b24938 100644 --- a/infrastructure/modules/app-cluster/cloudtrail.tf +++ b/infrastructure/modules/app-cluster/cloudtrail.tf @@ -19,7 +19,8 @@ data "aws_iam_policy_document" "access_logs_key_policy" { "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", - "kms:ScheduleKeyDeletion" + "kms:ScheduleKeyDeletion", + "kms:EnableKeyRotation" ] resources = [ From 469a9494e5770bf116508f67408b03b20fa920ff Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Tue, 16 Jun 2026 13:25:15 +0100 Subject: [PATCH 04/26] random password generation fix --- infrastructure/modules/auth/users.tf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/infrastructure/modules/auth/users.tf b/infrastructure/modules/auth/users.tf index b9698877..50160682 100644 --- a/infrastructure/modules/auth/users.tf +++ b/infrastructure/modules/auth/users.tf @@ -158,6 +158,10 @@ resource "aws_secretsmanager_secret_version" "e2e_test_client_write_all_secrets_ # UI_TEST_USER resource "random_password" "password" { length = 16 + min_lower = 1 + min_numeric = 1 + min_special = 1 + min_upper = 1 special = true override_special = "!#$%&*()-_=+[]{}<>:?" } From 7c712591c616c7565a9e429c31ac95668998df54 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Tue, 16 Jun 2026 13:51:17 +0100 Subject: [PATCH 05/26] update terraform --- infrastructure/modules/app-cluster/cloudtrail.tf | 2 +- infrastructure/modules/app-cluster/routing.tf | 10 ++++++++++ infrastructure/modules/app-cluster/variables.tf | 6 ++++++ infrastructure/modules/rapid/main.tf | 1 + infrastructure/modules/rapid/variables.tf | 6 ++++++ 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/infrastructure/modules/app-cluster/cloudtrail.tf b/infrastructure/modules/app-cluster/cloudtrail.tf index 24b24938..1076cf9b 100644 --- a/infrastructure/modules/app-cluster/cloudtrail.tf +++ b/infrastructure/modules/app-cluster/cloudtrail.tf @@ -35,7 +35,7 @@ data "aws_iam_policy_document" "access_logs_key_policy" { principals { type = "Service" - identifiers = ["logs.${data.aws_region.region.name}.amazonaws.com"] + identifiers = ["logs.${data.aws_region.region.region}.amazonaws.com"] } actions = [ diff --git a/infrastructure/modules/app-cluster/routing.tf b/infrastructure/modules/app-cluster/routing.tf index 65bc5248..3b59a45a 100644 --- a/infrastructure/modules/app-cluster/routing.tf +++ b/infrastructure/modules/app-cluster/routing.tf @@ -6,6 +6,16 @@ resource "aws_route53_zone" "primary-hosted-zone" { tags = var.tags } +resource "aws_route53_record" "copy-ns-records" { + count = var.parent_hosted_zone_id == "" ? 0 : 1 + + zone_id = var.parent_hosted_zone_id + name = aws_route53_zone.primary-hosted-zone[0].name + type = "NS" + ttl = "30" + records = aws_route53_zone.primary-hosted-zone[0].name_servers +} + # Create the certificate resource "aws_acm_certificate" "rapid-certificate" { count = var.certificate_validation_arn == "" ? 1 : 0 diff --git a/infrastructure/modules/app-cluster/variables.tf b/infrastructure/modules/app-cluster/variables.tf index 9232c48f..5b739d3e 100644 --- a/infrastructure/modules/app-cluster/variables.tf +++ b/infrastructure/modules/app-cluster/variables.tf @@ -102,6 +102,12 @@ variable "hosted_zone_id" { description = "Hosted Zone ID with the domain Name Servers, pass quotes to create a new one from scratch" } +variable "parent_hosted_zone_id" { + type = string + description = "Parent hosted Zone ID, if domain you use is aws subdomain. This will copy NS records to parent hosted zone" + default = "" +} + variable "certificate_validation_arn" { type = string description = "Arn of the certificate used by the domain" diff --git a/infrastructure/modules/rapid/main.tf b/infrastructure/modules/rapid/main.tf index 5f030c1f..10ec454f 100644 --- a/infrastructure/modules/rapid/main.tf +++ b/infrastructure/modules/rapid/main.tf @@ -19,6 +19,7 @@ module "app_cluster" { rapid_ecr_url = var.rapid_ecr_url certificate_validation_arn = var.certificate_validation_arn hosted_zone_id = var.hosted_zone_id + parent_hosted_zone_id = var.parent_hosted_zone_id aws_account = var.aws_account aws_region = var.aws_region data_s3_bucket_arn = aws_s3_bucket.this.arn diff --git a/infrastructure/modules/rapid/variables.tf b/infrastructure/modules/rapid/variables.tf index 6187a52e..41e9f842 100644 --- a/infrastructure/modules/rapid/variables.tf +++ b/infrastructure/modules/rapid/variables.tf @@ -66,6 +66,12 @@ variable "hosted_zone_id" { default = "" } +variable "parent_hosted_zone_id" { + type = string + description = "Parent hosted Zone ID, if domain you use is aws subdomain. This will copy NS records to parent hosted zone" + default = "" +} + variable "ip_whitelist" { type = list(string) description = "A list of IPs to whitelist for access to the service" From 265fee17dcf3c416621f12267446cd7012abdcc5 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Tue, 16 Jun 2026 13:59:25 +0100 Subject: [PATCH 06/26] update terraform --- infrastructure/modules/app-cluster/cloudtrail.tf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/infrastructure/modules/app-cluster/cloudtrail.tf b/infrastructure/modules/app-cluster/cloudtrail.tf index 1076cf9b..f0f1c401 100644 --- a/infrastructure/modules/app-cluster/cloudtrail.tf +++ b/infrastructure/modules/app-cluster/cloudtrail.tf @@ -24,7 +24,7 @@ data "aws_iam_policy_document" "access_logs_key_policy" { ] resources = [ - "arn:aws:kms:${data.aws_region.region.name}:${data.aws_caller_identity.current.account_id}:key/*", + "arn:aws:kms:${data.aws_region.region.region}:${data.aws_caller_identity.current.account_id}:key/*", ] } @@ -47,14 +47,14 @@ data "aws_iam_policy_document" "access_logs_key_policy" { ] resources = [ - "arn:aws:kms:${data.aws_region.region.name}:${data.aws_caller_identity.current.account_id}:key/*", + "arn:aws:kms:${data.aws_region.region.region}:${data.aws_caller_identity.current.account_id}:key/*", ] condition { test = "ArnEquals" variable = "kms:EncryptionContext:aws:logs:arn" values = [ - "arn:aws:logs:${data.aws_region.region.name}:${data.aws_caller_identity.current.account_id}:log-group:${var.resource-name-prefix}_access_logs" + "arn:aws:logs:${data.aws_region.region.region}:${data.aws_caller_identity.current.account_id}:log-group:${var.resource-name-prefix}_access_logs" ] } } @@ -78,7 +78,7 @@ data "aws_iam_policy_document" "access_logs_key_policy" { ] resources = [ - "arn:aws:kms:${data.aws_region.region.name}:${data.aws_caller_identity.current.account_id}:key/*", + "arn:aws:kms:${data.aws_region.region.region}:${data.aws_caller_identity.current.account_id}:key/*", ] } } From 973a5164434caa357f16ea14c1aaec0fdb12a9fb Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Tue, 16 Jun 2026 21:50:20 +0100 Subject: [PATCH 07/26] update terraform --- infrastructure/modules/rapid/providers.tf | 4 ++ infrastructure/modules/ui/providers.tf | 3 + infrastructure/modules/ui/s3.tf | 74 +++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/infrastructure/modules/rapid/providers.tf b/infrastructure/modules/rapid/providers.tf index 19be1c08..e3d4d186 100644 --- a/infrastructure/modules/rapid/providers.tf +++ b/infrastructure/modules/rapid/providers.tf @@ -5,5 +5,9 @@ terraform { version = ">= 2.7.0" configuration_aliases = [aws.default, aws.us_east] } + github = { + source = "integrations/github" + version = "~> 6.0" + } } } diff --git a/infrastructure/modules/ui/providers.tf b/infrastructure/modules/ui/providers.tf index 19be1c08..74b8b7b3 100644 --- a/infrastructure/modules/ui/providers.tf +++ b/infrastructure/modules/ui/providers.tf @@ -5,5 +5,8 @@ terraform { version = ">= 2.7.0" configuration_aliases = [aws.default, aws.us_east] } + github = { + source = "integrations/github" + } } } diff --git a/infrastructure/modules/ui/s3.tf b/infrastructure/modules/ui/s3.tf index 4b712a2f..bdc9773d 100644 --- a/infrastructure/modules/ui/s3.tf +++ b/infrastructure/modules/ui/s3.tf @@ -57,6 +57,79 @@ resource "aws_s3_bucket_website_configuration" "rapid_ui_website" { } } +data "github_release" "this" { + repository = "rapid" + owner = "no10ds" + retrieve_by = "tag" + release_tag = var.ui_version +} + +data "github_release_asset" "router_lambda" { + repository = "rapid" + owner = "no10ds" + asset_id = data.github_release.this.assets[index(data.github_release.this.assets.*.name, "${var.ui_version}-router-lambda.zip")] + download_file = true +} + +resource "local_file" "router_lambda" { + content_base64 = github_release_asset.router_lambda.file_contents + filename = "${var.ui_version}-router-lambda.zip" +} + +data "github_release_asset" "static_ui" { + repository = "rapid" + owner = "no10ds" + asset_id = data.github_release.this.assets[index(data.github_release.this.assets.*.name, "${var.ui_version}.zip")] + download_file = true +} + +resource "local_file" "static_ui" { + content_base64 = github_release_asset.static_ui.file_contents + filename = "${var.ui_version}.zip" +} + +resource "terraform_data" "static_ui" { + input = { + version = var.ui_version, + bucket = aws_s3_bucket.rapid_ui.id + } + + triggers_replace = [ + var.ui_version, + aws_s3_bucket.rapid_ui.id + ] + + provisioner "local-exec" { + interpreter = local.interpreter + + command = <<-EOT + unzip -o "${var.ui_version}.zip" + EOT + + } + +} + +resource "aws_s3_object" "static_ui" { + for_each = fileset("out", "**") + + key = each.value + bucket = aws_s3_bucket.rapid_ui.id + source = "out/${each.value}" + etag = filemd5("out/${each.value}") + + lifecycle { + ignore_changes = [ + source, etag + ] + replace_triggered_by = [ + terraform_data.static_ui.output.version, + terraform_data.static_ui.output.bucket + ] + } +} + +/* locals { ui_registry_url = "https://github.com/no10ds/rapid/releases/download/${var.ui_version}" } @@ -79,6 +152,7 @@ resource "null_resource" "download_static_ui" { }) } } +*/ data "aws_iam_policy_document" "s3" { statement { From c68e26b4a72723d354b37519179fe2a66f4a1027 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Tue, 16 Jun 2026 22:02:33 +0100 Subject: [PATCH 08/26] update terraform --- infrastructure/modules/ui/lambda.tf | 2 +- infrastructure/modules/ui/s3.tf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/infrastructure/modules/ui/lambda.tf b/infrastructure/modules/ui/lambda.tf index 3429d7e2..d04fab7a 100644 --- a/infrastructure/modules/ui/lambda.tf +++ b/infrastructure/modules/ui/lambda.tf @@ -61,6 +61,6 @@ resource "aws_lambda_function" "this" { publish = true depends_on = [ - null_resource.download_static_ui + local_file.router_lambda ] } diff --git a/infrastructure/modules/ui/s3.tf b/infrastructure/modules/ui/s3.tf index bdc9773d..9b50b37c 100644 --- a/infrastructure/modules/ui/s3.tf +++ b/infrastructure/modules/ui/s3.tf @@ -72,7 +72,7 @@ data "github_release_asset" "router_lambda" { } resource "local_file" "router_lambda" { - content_base64 = github_release_asset.router_lambda.file_contents + content_base64 = data.github_release_asset.router_lambda.file_contents filename = "${var.ui_version}-router-lambda.zip" } @@ -84,7 +84,7 @@ data "github_release_asset" "static_ui" { } resource "local_file" "static_ui" { - content_base64 = github_release_asset.static_ui.file_contents + content_base64 = data.github_release_asset.static_ui.file_contents filename = "${var.ui_version}.zip" } From 5a2099566b788d65440ef7872c19d1625927f1ca Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Tue, 16 Jun 2026 22:10:12 +0100 Subject: [PATCH 09/26] update terraform --- infrastructure/modules/ui/s3.tf | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/infrastructure/modules/ui/s3.tf b/infrastructure/modules/ui/s3.tf index 9b50b37c..7c5e8ad7 100644 --- a/infrastructure/modules/ui/s3.tf +++ b/infrastructure/modules/ui/s3.tf @@ -65,10 +65,10 @@ data "github_release" "this" { } data "github_release_asset" "router_lambda" { - repository = "rapid" - owner = "no10ds" - asset_id = data.github_release.this.assets[index(data.github_release.this.assets.*.name, "${var.ui_version}-router-lambda.zip")] - download_file = true + repository = "rapid" + owner = "no10ds" + asset_id = data.github_release.this.assets[index(data.github_release.this.assets.*.name, "${var.ui_version}-router-lambda.zip")].id + download_file_contents = true } resource "local_file" "router_lambda" { @@ -77,10 +77,10 @@ resource "local_file" "router_lambda" { } data "github_release_asset" "static_ui" { - repository = "rapid" - owner = "no10ds" - asset_id = data.github_release.this.assets[index(data.github_release.this.assets.*.name, "${var.ui_version}.zip")] - download_file = true + repository = "rapid" + owner = "no10ds" + asset_id = data.github_release.this.assets[index(data.github_release.this.assets.*.name, "${var.ui_version}.zip")].id + download_file_contents = true } resource "local_file" "static_ui" { @@ -100,7 +100,6 @@ resource "terraform_data" "static_ui" { ] provisioner "local-exec" { - interpreter = local.interpreter command = <<-EOT unzip -o "${var.ui_version}.zip" From 59c245b2fd919bb269ce2f2497bb617d1c662e4e Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Tue, 16 Jun 2026 22:12:48 +0100 Subject: [PATCH 10/26] update terraform --- infrastructure/modules/ui/s3.tf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/infrastructure/modules/ui/s3.tf b/infrastructure/modules/ui/s3.tf index 7c5e8ad7..36f03609 100644 --- a/infrastructure/modules/ui/s3.tf +++ b/infrastructure/modules/ui/s3.tf @@ -126,6 +126,8 @@ resource "aws_s3_object" "static_ui" { terraform_data.static_ui.output.bucket ] } + + depends_on = [terraform_data.static_ui] } /* From 5e8c6e82c87538bbe58ecd2c856ecc2219a7e4b2 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Wed, 17 Jun 2026 09:05:04 +0100 Subject: [PATCH 11/26] update terraform --- infrastructure/modules/ui/s3.tf | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/infrastructure/modules/ui/s3.tf b/infrastructure/modules/ui/s3.tf index 36f03609..30ffe6a9 100644 --- a/infrastructure/modules/ui/s3.tf +++ b/infrastructure/modules/ui/s3.tf @@ -57,6 +57,7 @@ resource "aws_s3_bucket_website_configuration" "rapid_ui_website" { } } +/* data "github_release" "this" { repository = "rapid" owner = "no10ds" @@ -70,22 +71,31 @@ data "github_release_asset" "router_lambda" { asset_id = data.github_release.this.assets[index(data.github_release.this.assets.*.name, "${var.ui_version}-router-lambda.zip")].id download_file_contents = true } - +*/ resource "local_file" "router_lambda" { content_base64 = data.github_release_asset.router_lambda.file_contents filename = "${var.ui_version}-router-lambda.zip" -} + depends_on = [terraform_data.static_ui] +} +/* data "github_release_asset" "static_ui" { repository = "rapid" owner = "no10ds" asset_id = data.github_release.this.assets[index(data.github_release.this.assets.*.name, "${var.ui_version}.zip")].id download_file_contents = true } +*/ resource "local_file" "static_ui" { content_base64 = data.github_release_asset.static_ui.file_contents filename = "${var.ui_version}.zip" + + depends_on = [terraform_data.static_ui] +} + +locals { + ui_registry_url = "https://github.com/no10ds/rapid/releases/download/${var.ui_version}" } resource "terraform_data" "static_ui" { @@ -102,6 +112,12 @@ resource "terraform_data" "static_ui" { provisioner "local-exec" { command = <<-EOT + url="${local.ui_registry_url}/${var.ui_version}.zip" + router_url="${local.ui_registry_url}/${var.ui_version}-router-lambda.zip" + + wget $url + wget $router_url + unzip -o "${var.ui_version}.zip" EOT From d6d1d7d62533262b73620a36e8e9f8160e5f6302 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Wed, 17 Jun 2026 09:08:10 +0100 Subject: [PATCH 12/26] update terraform --- infrastructure/modules/ui/lambda.tf | 2 +- infrastructure/modules/ui/s3.tf | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/infrastructure/modules/ui/lambda.tf b/infrastructure/modules/ui/lambda.tf index d04fab7a..4437c1ea 100644 --- a/infrastructure/modules/ui/lambda.tf +++ b/infrastructure/modules/ui/lambda.tf @@ -61,6 +61,6 @@ resource "aws_lambda_function" "this" { publish = true depends_on = [ - local_file.router_lambda + data.local_file.router_lambda ] } diff --git a/infrastructure/modules/ui/s3.tf b/infrastructure/modules/ui/s3.tf index 30ffe6a9..bf8005f1 100644 --- a/infrastructure/modules/ui/s3.tf +++ b/infrastructure/modules/ui/s3.tf @@ -72,9 +72,8 @@ data "github_release_asset" "router_lambda" { download_file_contents = true } */ -resource "local_file" "router_lambda" { - content_base64 = data.github_release_asset.router_lambda.file_contents - filename = "${var.ui_version}-router-lambda.zip" +data "local_file" "router_lambda" { + filename = "${var.ui_version}-router-lambda.zip" depends_on = [terraform_data.static_ui] } @@ -85,14 +84,13 @@ data "github_release_asset" "static_ui" { asset_id = data.github_release.this.assets[index(data.github_release.this.assets.*.name, "${var.ui_version}.zip")].id download_file_contents = true } -*/ -resource "local_file" "static_ui" { - content_base64 = data.github_release_asset.static_ui.file_contents +data "local_file" "static_ui" { filename = "${var.ui_version}.zip" depends_on = [terraform_data.static_ui] } +*/ locals { ui_registry_url = "https://github.com/no10ds/rapid/releases/download/${var.ui_version}" From 3bec449f3bb7c59a82b5e30ccbcffdc605ef8e89 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Wed, 17 Jun 2026 09:25:39 +0100 Subject: [PATCH 13/26] update terraform --- infrastructure/modules/ui/s3.tf | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/infrastructure/modules/ui/s3.tf b/infrastructure/modules/ui/s3.tf index bf8005f1..933a6bb0 100644 --- a/infrastructure/modules/ui/s3.tf +++ b/infrastructure/modules/ui/s3.tf @@ -123,6 +123,12 @@ resource "terraform_data" "static_ui" { } +resource "time_sleep" "wait_5_seconds" { + depends_on = [terraform_data.static_ui] + + create_duration = "5s" +} + resource "aws_s3_object" "static_ui" { for_each = fileset("out", "**") @@ -141,7 +147,7 @@ resource "aws_s3_object" "static_ui" { ] } - depends_on = [terraform_data.static_ui] + depends_on = [time_sleep.wait_5_seconds] } /* From 1952b8305f26e7193f5c56917919ade3c2f32150 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Wed, 17 Jun 2026 10:57:29 +0100 Subject: [PATCH 14/26] update terraform --- infrastructure/modules/rapid/main.tf | 1 + infrastructure/modules/rapid/providers.tf | 4 - infrastructure/modules/rapid/variables.tf | 6 ++ infrastructure/modules/ui/lambda.tf | 4 +- infrastructure/modules/ui/providers.tf | 3 - infrastructure/modules/ui/s3.tf | 104 ++------------------ infrastructure/modules/ui/scripts/ui.sh.tpl | 5 + infrastructure/modules/ui/variables.tf | 6 ++ 8 files changed, 28 insertions(+), 105 deletions(-) mode change 100644 => 100755 infrastructure/modules/ui/scripts/ui.sh.tpl diff --git a/infrastructure/modules/rapid/main.tf b/infrastructure/modules/rapid/main.tf index 10ec454f..8b730980 100644 --- a/infrastructure/modules/rapid/main.tf +++ b/infrastructure/modules/rapid/main.tf @@ -83,6 +83,7 @@ module "ui" { route_53_validation_record_fqdns = module.app_cluster.route_53_validation_record_fqdns geo_restriction_locations = var.geo_restriction_locations sql_injection_protection = var.sql_injection_protection + aws_role_arn_to_assume = var.aws_role_arn_to_assume } resource "aws_s3_bucket" "this" { diff --git a/infrastructure/modules/rapid/providers.tf b/infrastructure/modules/rapid/providers.tf index e3d4d186..19be1c08 100644 --- a/infrastructure/modules/rapid/providers.tf +++ b/infrastructure/modules/rapid/providers.tf @@ -5,9 +5,5 @@ terraform { version = ">= 2.7.0" configuration_aliases = [aws.default, aws.us_east] } - github = { - source = "integrations/github" - version = "~> 6.0" - } } } diff --git a/infrastructure/modules/rapid/variables.tf b/infrastructure/modules/rapid/variables.tf index 41e9f842..48f5becc 100644 --- a/infrastructure/modules/rapid/variables.tf +++ b/infrastructure/modules/rapid/variables.tf @@ -208,3 +208,9 @@ variable "task_cpu" { description = "rAPId ecs task cpu" default = 256 } + +variable "aws_role_arn_to_assume" { + description = "AWS Role ARN to assume for aws cli commands" + type = string + default = "" +} diff --git a/infrastructure/modules/ui/lambda.tf b/infrastructure/modules/ui/lambda.tf index 4437c1ea..f4691087 100644 --- a/infrastructure/modules/ui/lambda.tf +++ b/infrastructure/modules/ui/lambda.tf @@ -60,7 +60,5 @@ resource "aws_lambda_function" "this" { publish = true - depends_on = [ - data.local_file.router_lambda - ] + depends_on = [terraform_data.static_ui] } diff --git a/infrastructure/modules/ui/providers.tf b/infrastructure/modules/ui/providers.tf index 74b8b7b3..19be1c08 100644 --- a/infrastructure/modules/ui/providers.tf +++ b/infrastructure/modules/ui/providers.tf @@ -5,8 +5,5 @@ terraform { version = ">= 2.7.0" configuration_aliases = [aws.default, aws.us_east] } - github = { - source = "integrations/github" - } } } diff --git a/infrastructure/modules/ui/s3.tf b/infrastructure/modules/ui/s3.tf index 933a6bb0..7c705143 100644 --- a/infrastructure/modules/ui/s3.tf +++ b/infrastructure/modules/ui/s3.tf @@ -57,41 +57,6 @@ resource "aws_s3_bucket_website_configuration" "rapid_ui_website" { } } -/* -data "github_release" "this" { - repository = "rapid" - owner = "no10ds" - retrieve_by = "tag" - release_tag = var.ui_version -} - -data "github_release_asset" "router_lambda" { - repository = "rapid" - owner = "no10ds" - asset_id = data.github_release.this.assets[index(data.github_release.this.assets.*.name, "${var.ui_version}-router-lambda.zip")].id - download_file_contents = true -} -*/ -data "local_file" "router_lambda" { - filename = "${var.ui_version}-router-lambda.zip" - - depends_on = [terraform_data.static_ui] -} -/* -data "github_release_asset" "static_ui" { - repository = "rapid" - owner = "no10ds" - asset_id = data.github_release.this.assets[index(data.github_release.this.assets.*.name, "${var.ui_version}.zip")].id - download_file_contents = true -} - -data "local_file" "static_ui" { - filename = "${var.ui_version}.zip" - - depends_on = [terraform_data.static_ui] -} -*/ - locals { ui_registry_url = "https://github.com/no10ds/rapid/releases/download/${var.ui_version}" } @@ -108,72 +73,21 @@ resource "terraform_data" "static_ui" { ] provisioner "local-exec" { - - command = <<-EOT - url="${local.ui_registry_url}/${var.ui_version}.zip" - router_url="${local.ui_registry_url}/${var.ui_version}-router-lambda.zip" - - wget $url - wget $router_url - - unzip -o "${var.ui_version}.zip" - EOT - - } - -} - -resource "time_sleep" "wait_5_seconds" { - depends_on = [terraform_data.static_ui] - - create_duration = "5s" -} - -resource "aws_s3_object" "static_ui" { - for_each = fileset("out", "**") - - key = each.value - bucket = aws_s3_bucket.rapid_ui.id - source = "out/${each.value}" - etag = filemd5("out/${each.value}") - - lifecycle { - ignore_changes = [ - source, etag - ] - replace_triggered_by = [ - terraform_data.static_ui.output.version, - terraform_data.static_ui.output.bucket - ] + command = templatefile("${path.module}/scripts/ui.sh.tpl", { + REGISTRY_URL = local.ui_registry_url, + VERSION = var.ui_version, + BUCKET_ID = aws_s3_bucket.rapid_ui.id + ROLE_TO_ASSUME = var.aws_role_arn_to_assume + }) } - depends_on = [time_sleep.wait_5_seconds] } -/* -locals { - ui_registry_url = "https://github.com/no10ds/rapid/releases/download/${var.ui_version}" -} - -resource "null_resource" "download_static_ui" { - depends_on = [ - aws_s3_bucket.rapid_ui - ] - - triggers = { - ui_version = var.ui_version - bucket = aws_s3_bucket.rapid_ui.id - } +data "local_file" "router_lambda" { + filename = "${var.ui_version}-router-lambda.zip" - provisioner "local-exec" { - command = templatefile("${path.module}/scripts/ui.sh.tpl", { - REGISTRY_URL = local.ui_registry_url, - VERSION = var.ui_version, - BUCKET_ID = aws_s3_bucket.rapid_ui.id - }) - } + depends_on = [terraform_data.static_ui] } -*/ data "aws_iam_policy_document" "s3" { statement { diff --git a/infrastructure/modules/ui/scripts/ui.sh.tpl b/infrastructure/modules/ui/scripts/ui.sh.tpl old mode 100644 new mode 100755 index d9e9568b..80a8f2e4 --- a/infrastructure/modules/ui/scripts/ui.sh.tpl +++ b/infrastructure/modules/ui/scripts/ui.sh.tpl @@ -1,5 +1,10 @@ #!/bin/bash +if [ ! -z "${ROLE_TO_ASSUME}" ]; then +echo "assume aws role ${ROLE_TO_ASSUME}" +eval $(aws sts assume-role --role-arn arn:aws:iam::992382722318:role/${ROLE_TO_ASSUME} --role-session-name rapid-cli | jq -r '.Credentials | "export AWS_ACCESS_KEY_ID=\(.AccessKeyId)\nexport AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey)\nexport AWS_SESSION_TOKEN=\(.SessionToken)\n"') +fi + url="${REGISTRY_URL}/${VERSION}.zip" router_url="${REGISTRY_URL}/${VERSION}-router-lambda.zip" diff --git a/infrastructure/modules/ui/variables.tf b/infrastructure/modules/ui/variables.tf index e0dcc904..bb7e7baf 100644 --- a/infrastructure/modules/ui/variables.tf +++ b/infrastructure/modules/ui/variables.tf @@ -65,3 +65,9 @@ variable "sql_injection_protection" { type = bool default = true } + +variable "aws_role_arn_to_assume" { + description = "AWS Role ARN to assume for aws cli commands" + type = string + default = "" +} From fba8bfd70e81d220c507e5efc29cd6399d8f5335 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Wed, 17 Jun 2026 11:10:31 +0100 Subject: [PATCH 15/26] update terraform --- infrastructure/modules/ui/s3.tf | 6 ------ 1 file changed, 6 deletions(-) diff --git a/infrastructure/modules/ui/s3.tf b/infrastructure/modules/ui/s3.tf index 7c705143..0a3d084d 100644 --- a/infrastructure/modules/ui/s3.tf +++ b/infrastructure/modules/ui/s3.tf @@ -83,12 +83,6 @@ resource "terraform_data" "static_ui" { } -data "local_file" "router_lambda" { - filename = "${var.ui_version}-router-lambda.zip" - - depends_on = [terraform_data.static_ui] -} - data "aws_iam_policy_document" "s3" { statement { effect = "Allow" From 6decdc8208acc14c2c35310d3537a4ae04882b9d Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Wed, 17 Jun 2026 11:27:34 +0100 Subject: [PATCH 16/26] fix script --- infrastructure/modules/ui/scripts/ui.sh.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/infrastructure/modules/ui/scripts/ui.sh.tpl b/infrastructure/modules/ui/scripts/ui.sh.tpl index 80a8f2e4..f91623b3 100755 --- a/infrastructure/modules/ui/scripts/ui.sh.tpl +++ b/infrastructure/modules/ui/scripts/ui.sh.tpl @@ -1,8 +1,8 @@ #!/bin/bash -if [ ! -z "${ROLE_TO_ASSUME}" ]; then -echo "assume aws role ${ROLE_TO_ASSUME}" -eval $(aws sts assume-role --role-arn arn:aws:iam::992382722318:role/${ROLE_TO_ASSUME} --role-session-name rapid-cli | jq -r '.Credentials | "export AWS_ACCESS_KEY_ID=\(.AccessKeyId)\nexport AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey)\nexport AWS_SESSION_TOKEN=\(.SessionToken)\n"') +if [ ! -z "${AWS_ROLE_ARN_TO_ASSUME}" ]; then +echo "assume aws role ${AWS_ROLE_ARN_TO_ASSUME}" +eval $(aws sts assume-role --role-arn ${AWS_ROLE_ARN_TO_ASSUME} --role-session-name rapid-cli | jq -r '.Credentials | "export AWS_ACCESS_KEY_ID=\(.AccessKeyId)\nexport AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey)\nexport AWS_SESSION_TOKEN=\(.SessionToken)\n"') fi url="${REGISTRY_URL}/${VERSION}.zip" From 8d812a4a712479c2f4e03b0a90298ff90e063e73 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Wed, 17 Jun 2026 11:28:54 +0100 Subject: [PATCH 17/26] update terraform --- infrastructure/modules/ui/s3.tf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/infrastructure/modules/ui/s3.tf b/infrastructure/modules/ui/s3.tf index 0a3d084d..040de9f9 100644 --- a/infrastructure/modules/ui/s3.tf +++ b/infrastructure/modules/ui/s3.tf @@ -74,10 +74,10 @@ resource "terraform_data" "static_ui" { provisioner "local-exec" { command = templatefile("${path.module}/scripts/ui.sh.tpl", { - REGISTRY_URL = local.ui_registry_url, - VERSION = var.ui_version, - BUCKET_ID = aws_s3_bucket.rapid_ui.id - ROLE_TO_ASSUME = var.aws_role_arn_to_assume + REGISTRY_URL = local.ui_registry_url, + VERSION = var.ui_version, + BUCKET_ID = aws_s3_bucket.rapid_ui.id + AWS_ROLE_ARN_TO_ASSUME = var.aws_role_arn_to_assume }) } From 4bf63b35198af5c492dfe42dbd349b2aaa56ea2f Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Wed, 17 Jun 2026 11:30:38 +0100 Subject: [PATCH 18/26] update terraform --- infrastructure/modules/ui/s3.tf | 5 ----- 1 file changed, 5 deletions(-) diff --git a/infrastructure/modules/ui/s3.tf b/infrastructure/modules/ui/s3.tf index 040de9f9..6ce5da48 100644 --- a/infrastructure/modules/ui/s3.tf +++ b/infrastructure/modules/ui/s3.tf @@ -62,11 +62,6 @@ locals { } resource "terraform_data" "static_ui" { - input = { - version = var.ui_version, - bucket = aws_s3_bucket.rapid_ui.id - } - triggers_replace = [ var.ui_version, aws_s3_bucket.rapid_ui.id From 945e35fc01b9df208c91125ad233d8dce6ef80c6 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Thu, 25 Jun 2026 03:35:44 +0100 Subject: [PATCH 19/26] add email message tf variable --- infrastructure/modules/auth/main.tf | 8 +++++ infrastructure/modules/auth/variables.tf | 42 +++++++++++++++++++++++ infrastructure/modules/rapid/main.tf | 21 +++++++----- infrastructure/modules/rapid/variables.tf | 42 +++++++++++++++++++++++ 4 files changed, 105 insertions(+), 8 deletions(-) diff --git a/infrastructure/modules/auth/main.tf b/infrastructure/modules/auth/main.tf index b95ecfd7..4be387f1 100644 --- a/infrastructure/modules/auth/main.tf +++ b/infrastructure/modules/auth/main.tf @@ -37,6 +37,14 @@ resource "aws_cognito_user_pool" "rapid_user_pool" { source_arn = var.ses_domain_identity_arn } } + + verification_message_template { + default_email_option = var.verification_message_email_option + email_message = var.verification_message_email_message_by_code == "" ? null : var.verification_message_email_message_by_code + email_subject = var.verification_message_email_subject_by_code + email_message_by_link = var.verification_message_email_message_by_link == "" ? null : var.verification_message_email_message_by_link + email_subject_by_link = var.verification_message_email_subject_by_link + } } resource "aws_cognito_resource_server" "rapid_resource_server" { diff --git a/infrastructure/modules/auth/variables.tf b/infrastructure/modules/auth/variables.tf index 46801ed5..4e6d2f4c 100644 --- a/infrastructure/modules/auth/variables.tf +++ b/infrastructure/modules/auth/variables.tf @@ -119,3 +119,45 @@ variable "ses_email_domain" { description = "The domain to use for the SES email 'from' address (e.g., no-reply@). Defaults to domain_name if not specified." default = null } + +variable "verification_message_email_option" { + description = "Verification message email option" + type = string + validation { + condition = contains(["CONFIRM_WITH_CODE", "CONFIRM_WITH_LINK"], var.verification_message_email_option) + error_message = "Must be either CONFIRM_WITH_CODE or CONFIRM_WITH_LINK. Defaults to CONFIRM_WITH_CODE." + } + default = "CONFIRM_WITH_CODE" +} + +variable "verification_message_email_message_by_code" { + description = "Verification message email message by code" + type = string + validation { + condition = var.verification_message_email_message_by_code == "" || strcontains(var.verification_message_email_message_by_code, "{####}") + error_message = "Email message template. Must contain the {####} placeholder. Conflicts with email_verification_message argument." + } + default = "" +} + +variable "verification_message_email_subject_by_code" { + description = "Verification message email subject by code" + type = string + default = null +} + +variable "verification_message_email_message_by_link" { + description = "Verification message email message by link" + type = string + validation { + condition = var.verification_message_email_message_by_link == "" || strcontains(var.verification_message_email_message_by_link, "{##Click Here##}") + error_message = "Email message template for sending a confirmation link to the user, it must contain the {##Click Here##} placeholder." + } + default = "" +} + +variable "verification_message_email_subject_by_link" { + description = "Verification message email subject by link" + type = string + default = null +} \ No newline at end of file diff --git a/infrastructure/modules/rapid/main.tf b/infrastructure/modules/rapid/main.tf index 8b730980..b3cc9c5e 100644 --- a/infrastructure/modules/rapid/main.tf +++ b/infrastructure/modules/rapid/main.tf @@ -44,14 +44,19 @@ module "auth" { providers = { aws = aws.default } - source = "../auth" - tags = var.tags - domain_name = var.domain_name - resource-name-prefix = var.resource-name-prefix - password_policy = var.password_policy - layers = var.layers - ses_domain_identity_arn = var.ses_domain_identity_arn - ses_email_domain = var.ses_email_domain + source = "../auth" + tags = var.tags + domain_name = var.domain_name + resource-name-prefix = var.resource-name-prefix + password_policy = var.password_policy + layers = var.layers + ses_domain_identity_arn = var.ses_domain_identity_arn + ses_email_domain = var.ses_email_domain + verification_message_email_option = var.verification_message_email_option + verification_message_email_subject_by_code = var.verification_message_email_subject_by_code + verification_message_email_message_by_code = var.verification_message_email_message_by_code + verification_message_email_subject_by_link = var.verification_message_email_subject_by_link + verification_message_email_message_by_link = var.verification_message_email_message_by_link } module "data_workflow" { diff --git a/infrastructure/modules/rapid/variables.tf b/infrastructure/modules/rapid/variables.tf index 48f5becc..91728907 100644 --- a/infrastructure/modules/rapid/variables.tf +++ b/infrastructure/modules/rapid/variables.tf @@ -214,3 +214,45 @@ variable "aws_role_arn_to_assume" { type = string default = "" } + +variable "verification_message_email_option" { + description = "Verification message email option" + type = string + validation { + condition = contains(["CONFIRM_WITH_CODE", "CONFIRM_WITH_LINK"], var.verification_message_email_option) + error_message = "Must be either CONFIRM_WITH_CODE or CONFIRM_WITH_LINK. Defaults to CONFIRM_WITH_CODE." + } + default = "CONFIRM_WITH_CODE" +} + +variable "verification_message_email_message_by_code" { + description = "Verification message email message by code" + type = string + validation { + condition = var.verification_message_email_message_by_code == "" || strcontains(var.verification_message_email_message_by_code, "{####}") + error_message = "Email message template. Must contain the {####} placeholder. Conflicts with email_verification_message argument." + } + default = "" +} + +variable "verification_message_email_subject_by_code" { + description = "Verification message email subject by code" + type = string + default = null +} + +variable "verification_message_email_message_by_link" { + description = "Verification message email message by link" + type = string + validation { + condition = var.verification_message_email_message_by_link == "" || strcontains(var.verification_message_email_message_by_link, "{##Click Here##}") + error_message = "Email message template for sending a confirmation link to the user, it must contain the {##Click Here##} placeholder." + } + default = "" +} + +variable "verification_message_email_subject_by_link" { + description = "Verification message email subject by link" + type = string + default = null +} From e90120504c6d36f4fb4bbbbdc69dc31ad18d21eb Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Thu, 25 Jun 2026 09:27:10 +0100 Subject: [PATCH 20/26] update email configuration --- infrastructure/modules/auth/main.tf | 28 ++++++++--------- infrastructure/modules/auth/variables.tf | 38 +++++++++-------------- infrastructure/modules/rapid/main.tf | 25 +++++++-------- infrastructure/modules/rapid/variables.tf | 38 +++++++---------------- 4 files changed, 53 insertions(+), 76 deletions(-) diff --git a/infrastructure/modules/auth/main.tf b/infrastructure/modules/auth/main.tf index 4be387f1..8ab53900 100644 --- a/infrastructure/modules/auth/main.tf +++ b/infrastructure/modules/auth/main.tf @@ -6,6 +6,11 @@ resource "aws_cognito_user_pool" "rapid_user_pool" { admin_create_user_config { allow_admin_create_user_only = true + + invite_message_template { + email_message = var.invite_message_email_message + email_subject = var.invite_message_email_subject + } } mfa_configuration = "OPTIONAL" @@ -29,22 +34,17 @@ resource "aws_cognito_user_pool" "rapid_user_pool" { advanced_security_mode = "ENFORCED" } - dynamic "email_configuration" { - for_each = var.ses_domain_identity_arn != null ? [1] : [] - content { - email_sending_account = "DEVELOPER" - from_email_address = "no-reply@${coalesce(var.ses_email_domain, var.domain_name)}" - source_arn = var.ses_domain_identity_arn - } + email_configuration { + email_sending_account = var.ses_domain_identity_arn != null ? "DEVELOPER" : "COGNITO_DEFAULT" + from_email_address = ( + var.ses_domain_identity_arn != null ? + "\"${var.sender_display_name}\" " : + "\"${var.sender_display_name}\" " + ) + source_arn = var.ses_domain_identity_arn + reply_to_email_address = var.reply_to_email_address } - verification_message_template { - default_email_option = var.verification_message_email_option - email_message = var.verification_message_email_message_by_code == "" ? null : var.verification_message_email_message_by_code - email_subject = var.verification_message_email_subject_by_code - email_message_by_link = var.verification_message_email_message_by_link == "" ? null : var.verification_message_email_message_by_link - email_subject_by_link = var.verification_message_email_subject_by_link - } } resource "aws_cognito_resource_server" "rapid_resource_server" { diff --git a/infrastructure/modules/auth/variables.tf b/infrastructure/modules/auth/variables.tf index 4e6d2f4c..8d2aa1db 100644 --- a/infrastructure/modules/auth/variables.tf +++ b/infrastructure/modules/auth/variables.tf @@ -120,44 +120,36 @@ variable "ses_email_domain" { default = null } -variable "verification_message_email_option" { - description = "Verification message email option" +variable "invite_message_email_message" { + description = "Invite message email message" type = string validation { - condition = contains(["CONFIRM_WITH_CODE", "CONFIRM_WITH_LINK"], var.verification_message_email_option) - error_message = "Must be either CONFIRM_WITH_CODE or CONFIRM_WITH_LINK. Defaults to CONFIRM_WITH_CODE." + condition = strcontains(var.invite_message_email_message, "{username}") && strcontains(var.invite_message_email_message, "{####}") + error_message = "Email message template. Must contain {username} and {####} placeholders, for username and temporary password, respectively." } - default = "CONFIRM_WITH_CODE" + default = null } -variable "verification_message_email_message_by_code" { - description = "Verification message email message by code" +variable "invite_message_email_subject" { + description = "Invite message email subject" type = string - validation { - condition = var.verification_message_email_message_by_code == "" || strcontains(var.verification_message_email_message_by_code, "{####}") - error_message = "Email message template. Must contain the {####} placeholder. Conflicts with email_verification_message argument." - } - default = "" + default = null } -variable "verification_message_email_subject_by_code" { - description = "Verification message email subject by code" +variable "sender_display_name" { + description = "Invite message email sender display name" type = string default = null } -variable "verification_message_email_message_by_link" { - description = "Verification message email message by link" +variable "sender_display_name" { + description = "Email sender display name" type = string - validation { - condition = var.verification_message_email_message_by_link == "" || strcontains(var.verification_message_email_message_by_link, "{##Click Here##}") - error_message = "Email message template for sending a confirmation link to the user, it must contain the {##Click Here##} placeholder." - } - default = "" + default = null } -variable "verification_message_email_subject_by_link" { - description = "Verification message email subject by link" +variable "reply_to_email_address" { + description = "Email REPLY-TO email address" type = string default = null } \ No newline at end of file diff --git a/infrastructure/modules/rapid/main.tf b/infrastructure/modules/rapid/main.tf index b3cc9c5e..2599ea85 100644 --- a/infrastructure/modules/rapid/main.tf +++ b/infrastructure/modules/rapid/main.tf @@ -44,19 +44,18 @@ module "auth" { providers = { aws = aws.default } - source = "../auth" - tags = var.tags - domain_name = var.domain_name - resource-name-prefix = var.resource-name-prefix - password_policy = var.password_policy - layers = var.layers - ses_domain_identity_arn = var.ses_domain_identity_arn - ses_email_domain = var.ses_email_domain - verification_message_email_option = var.verification_message_email_option - verification_message_email_subject_by_code = var.verification_message_email_subject_by_code - verification_message_email_message_by_code = var.verification_message_email_message_by_code - verification_message_email_subject_by_link = var.verification_message_email_subject_by_link - verification_message_email_message_by_link = var.verification_message_email_message_by_link + source = "../auth" + tags = var.tags + domain_name = var.domain_name + resource-name-prefix = var.resource-name-prefix + password_policy = var.password_policy + layers = var.layers + ses_domain_identity_arn = var.ses_domain_identity_arn + ses_email_domain = var.ses_email_domain + invite_message_email_subject = var.invite_message_email_subject + invite_message_email_message = var.invite_message_email_message + sender_display_name = var.sender_display_name + reply_to_email_address = var.reply_to_email_address } module "data_workflow" { diff --git a/infrastructure/modules/rapid/variables.tf b/infrastructure/modules/rapid/variables.tf index 91728907..19d4104f 100644 --- a/infrastructure/modules/rapid/variables.tf +++ b/infrastructure/modules/rapid/variables.tf @@ -215,44 +215,30 @@ variable "aws_role_arn_to_assume" { default = "" } -variable "verification_message_email_option" { - description = "Verification message email option" +variable "invite_message_email_message" { + description = "Invite message email message" type = string validation { - condition = contains(["CONFIRM_WITH_CODE", "CONFIRM_WITH_LINK"], var.verification_message_email_option) - error_message = "Must be either CONFIRM_WITH_CODE or CONFIRM_WITH_LINK. Defaults to CONFIRM_WITH_CODE." + condition = strcontains(var.invite_message_email_message, "{username}") && strcontains(var.invite_message_email_message, "{####}") + error_message = "Email message template. Must contain {username} and {####} placeholders, for username and temporary password, respectively." } - default = "CONFIRM_WITH_CODE" + default = null } -variable "verification_message_email_message_by_code" { - description = "Verification message email message by code" - type = string - validation { - condition = var.verification_message_email_message_by_code == "" || strcontains(var.verification_message_email_message_by_code, "{####}") - error_message = "Email message template. Must contain the {####} placeholder. Conflicts with email_verification_message argument." - } - default = "" -} - -variable "verification_message_email_subject_by_code" { - description = "Verification message email subject by code" +variable "invite_message_email_subject" { + description = "Invite message email subject" type = string default = null } -variable "verification_message_email_message_by_link" { - description = "Verification message email message by link" +variable "sender_display_name" { + description = "Email sender display name" type = string - validation { - condition = var.verification_message_email_message_by_link == "" || strcontains(var.verification_message_email_message_by_link, "{##Click Here##}") - error_message = "Email message template for sending a confirmation link to the user, it must contain the {##Click Here##} placeholder." - } - default = "" + default = null } -variable "verification_message_email_subject_by_link" { - description = "Verification message email subject by link" +variable "reply_to_email_address" { + description = "Email REPLY-TO email address" type = string default = null } From 0a3c15147aabfe7791a80acc5dcf75fdf7dd3184 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Thu, 25 Jun 2026 09:33:19 +0100 Subject: [PATCH 21/26] update email configuration --- infrastructure/modules/auth/variables.tf | 6 ------ 1 file changed, 6 deletions(-) diff --git a/infrastructure/modules/auth/variables.tf b/infrastructure/modules/auth/variables.tf index 8d2aa1db..7016d9fa 100644 --- a/infrastructure/modules/auth/variables.tf +++ b/infrastructure/modules/auth/variables.tf @@ -136,12 +136,6 @@ variable "invite_message_email_subject" { default = null } -variable "sender_display_name" { - description = "Invite message email sender display name" - type = string - default = null -} - variable "sender_display_name" { description = "Email sender display name" type = string From b15b8b3d8f36536e4bed6ecba8984f14ffcec43a Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Thu, 25 Jun 2026 09:46:09 +0100 Subject: [PATCH 22/26] update email configuration --- infrastructure/modules/auth/main.tf | 1 + infrastructure/modules/auth/variables.tf | 8 ++++---- infrastructure/modules/rapid/variables.tf | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/infrastructure/modules/auth/main.tf b/infrastructure/modules/auth/main.tf index 8ab53900..7d6b473f 100644 --- a/infrastructure/modules/auth/main.tf +++ b/infrastructure/modules/auth/main.tf @@ -10,6 +10,7 @@ resource "aws_cognito_user_pool" "rapid_user_pool" { invite_message_template { email_message = var.invite_message_email_message email_subject = var.invite_message_email_subject + sms_message = "Your username is {username} and temporary password is {####}." } } diff --git a/infrastructure/modules/auth/variables.tf b/infrastructure/modules/auth/variables.tf index 7016d9fa..1b4708cb 100644 --- a/infrastructure/modules/auth/variables.tf +++ b/infrastructure/modules/auth/variables.tf @@ -127,23 +127,23 @@ variable "invite_message_email_message" { condition = strcontains(var.invite_message_email_message, "{username}") && strcontains(var.invite_message_email_message, "{####}") error_message = "Email message template. Must contain {username} and {####} placeholders, for username and temporary password, respectively." } - default = null + default = "Your username is {username} and temporary password is {####}." } variable "invite_message_email_subject" { description = "Invite message email subject" type = string - default = null + default = "Your temporary password" } variable "sender_display_name" { description = "Email sender display name" type = string - default = null + default = "" } variable "reply_to_email_address" { description = "Email REPLY-TO email address" type = string - default = null + default = "" } \ No newline at end of file diff --git a/infrastructure/modules/rapid/variables.tf b/infrastructure/modules/rapid/variables.tf index 19d4104f..b37fba9f 100644 --- a/infrastructure/modules/rapid/variables.tf +++ b/infrastructure/modules/rapid/variables.tf @@ -222,23 +222,23 @@ variable "invite_message_email_message" { condition = strcontains(var.invite_message_email_message, "{username}") && strcontains(var.invite_message_email_message, "{####}") error_message = "Email message template. Must contain {username} and {####} placeholders, for username and temporary password, respectively." } - default = null + default = "Your username is {username} and temporary password is {####}." } variable "invite_message_email_subject" { description = "Invite message email subject" type = string - default = null + default = "Your temporary password" } variable "sender_display_name" { description = "Email sender display name" type = string - default = null + default = "" } variable "reply_to_email_address" { description = "Email REPLY-TO email address" type = string - default = null + default = "" } From e8dd172a2d24fc949b6498c8b9ef115217ebaac3 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Thu, 25 Jun 2026 09:51:20 +0100 Subject: [PATCH 23/26] update email configuration --- infrastructure/modules/auth/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/modules/auth/main.tf b/infrastructure/modules/auth/main.tf index 7d6b473f..e9ae7ff3 100644 --- a/infrastructure/modules/auth/main.tf +++ b/infrastructure/modules/auth/main.tf @@ -40,7 +40,7 @@ resource "aws_cognito_user_pool" "rapid_user_pool" { from_email_address = ( var.ses_domain_identity_arn != null ? "\"${var.sender_display_name}\" " : - "\"${var.sender_display_name}\" " + null ) source_arn = var.ses_domain_identity_arn reply_to_email_address = var.reply_to_email_address From 7cf52f34790766841e43701d9c1e88e2924fb8d2 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Thu, 25 Jun 2026 10:10:14 +0100 Subject: [PATCH 24/26] update email configuration --- infrastructure/modules/auth/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/modules/auth/variables.tf b/infrastructure/modules/auth/variables.tf index 1b4708cb..ba0ddc81 100644 --- a/infrastructure/modules/auth/variables.tf +++ b/infrastructure/modules/auth/variables.tf @@ -137,7 +137,7 @@ variable "invite_message_email_subject" { } variable "sender_display_name" { - description = "Email sender display name" + description = "Email sender display name. Applicable only if ses_domain_identity_arn is configured." type = string default = "" } From f896d8d9ef9fbf6aaede64c8ef6b7939d7c6c1e9 Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Thu, 2 Jul 2026 13:39:46 +0100 Subject: [PATCH 25/26] security group create before destroy --- infrastructure/modules/app-cluster/main.tf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/infrastructure/modules/app-cluster/main.tf b/infrastructure/modules/app-cluster/main.tf index 6940c209..c4283822 100644 --- a/infrastructure/modules/app-cluster/main.tf +++ b/infrastructure/modules/app-cluster/main.tf @@ -409,4 +409,8 @@ resource "aws_security_group" "service_security_group" { } tags = var.tags + + lifecycle { + create_before_destroy = true + } } From bc9297df982951edebedfaadb408600ddd5b939e Mon Sep 17 00:00:00 2001 From: Jarek-Rolski Date: Thu, 2 Jul 2026 13:43:42 +0100 Subject: [PATCH 26/26] update terraform --- infrastructure/modules/app-cluster/cloudtrail.tf | 3 ++- infrastructure/modules/app-cluster/load_balancer.tf | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/infrastructure/modules/app-cluster/cloudtrail.tf b/infrastructure/modules/app-cluster/cloudtrail.tf index f0f1c401..6f9adf8e 100644 --- a/infrastructure/modules/app-cluster/cloudtrail.tf +++ b/infrastructure/modules/app-cluster/cloudtrail.tf @@ -20,7 +20,8 @@ data "aws_iam_policy_document" "access_logs_key_policy" { "kms:Decrypt", "kms:ReEncrypt*", "kms:ScheduleKeyDeletion", - "kms:EnableKeyRotation" + "kms:EnableKeyRotation", + "kms:TagResource" ] resources = [ diff --git a/infrastructure/modules/app-cluster/load_balancer.tf b/infrastructure/modules/app-cluster/load_balancer.tf index 8b220637..747c40c8 100644 --- a/infrastructure/modules/app-cluster/load_balancer.tf +++ b/infrastructure/modules/app-cluster/load_balancer.tf @@ -130,7 +130,6 @@ resource "aws_security_group_rule" "load_balancer_security_group_rule_egress_htt } resource "aws_lb_target_group" "target_group" { - name = "${var.resource-name-prefix}-tg" port = 80 protocol = "HTTP" target_type = "ip"