From 46cc975a9b5ef69e01d77a97a3b20d98acda0c31 Mon Sep 17 00:00:00 2001 From: dillanb-hashi Date: Fri, 16 Jan 2026 10:53:05 -0700 Subject: [PATCH] test(e2e): Created enos scenario for https testing (#6324) * test(e2e): Created enos scenario for https testing --- enos/README.md | 26 +++++++++++++++ enos/ci/service-user-iam/main.tf | 4 +++ enos/enos-scenario-e2e-ui-aws.hcl | 5 ++- enos/modules/aws_boundary/alb.tf | 46 ++++++++++++++++++++++++-- enos/modules/aws_boundary/outputs.tf | 7 +++- enos/modules/aws_boundary/variables.tf | 6 ++++ enos/modules/test_e2e_ui/main.tf | 6 ++++ 7 files changed, 96 insertions(+), 4 deletions(-) diff --git a/enos/README.md b/enos/README.md index 9ecc555977..7a8bfe5162 100644 --- a/enos/README.md +++ b/enos/README.md @@ -185,3 +185,29 @@ Once the workspace has been created, changes to the bootstrap module will automa the GitHub PR workflow. Each time a PR is created for changes to files within that module the module will be planned via the workflow described above. If the plan is ok and the PR is merged, the module will automatically be applied via the same workflow. + +### Trust certificate for HTTPS testing + +The scenario e2e_ui_aws has the options for setting up using HTTPS. When you do this, additional steps +need to be taken in order to trust the certificate locally and fully enable HTTPS. The certificate is +in the enos scenario output as `E2E_ALB_CERT`. + +#### Trusting on Mac + +1. **Save the certificate** - Save the output of the certificate in a file e.g. `mycert.crt` +2. **Trust the certificate** - Double click the certificate to open keychain access. Right click the +certificate in the list. Click `get info`. Under `Trust` select `Always Trust` under the +`When using this certificate:` option. +3. **Restart your computer** - Restart computer to complete the trusting process +4. **Firefox trusting** - For firefox you additionally need to trust the cert in the browser. +This can be done under `Firefox Settings > Privacy & Security > View Certificates > Authorities > Import` + +#### Trusting on linux + +1. **Save the certificate** - Save the output of the certificate in a file e.g. `mycert.crt` +2. **Trust the certificate** - Run the following commands + +```shell +> sudo cp mycert.crt /usr/local/share/ca-certificates/ +> sudo update-ca-certificates +``` \ No newline at end of file diff --git a/enos/ci/service-user-iam/main.tf b/enos/ci/service-user-iam/main.tf index 98c4afbc2b..1309d8c726 100644 --- a/enos/ci/service-user-iam/main.tf +++ b/enos/ci/service-user-iam/main.tf @@ -65,6 +65,10 @@ data "aws_iam_policy_document" "enos_policy_document" { statement { effect = "Allow" actions = [ + "acm:ImportCertificate", + "acm:DeleteCertificate", + "acm:DescribeCertificate", + "acm:ListTagsForCertificate", "ec2:AssociateRouteTable", "ec2:AttachInternetGateway", "ec2:AuthorizeSecurityGroupEgress", diff --git a/enos/enos-scenario-e2e-ui-aws.hcl b/enos/enos-scenario-e2e-ui-aws.hcl index 69f204599a..73a29da62c 100644 --- a/enos/enos-scenario-e2e-ui-aws.hcl +++ b/enos/enos-scenario-e2e-ui-aws.hcl @@ -10,7 +10,8 @@ scenario "e2e_ui_aws" { ] matrix { - builder = ["local", "crt"] + builder = ["local", "crt"] + protocol = ["http", "https"] } locals { @@ -106,6 +107,7 @@ scenario "e2e_ui_aws" { worker_instance_type = var.worker_instance_type worker_type_tags = [local.egress_tag] aws_region = var.aws_region + protocol = matrix.protocol } } @@ -212,6 +214,7 @@ scenario "e2e_ui_aws" { aws_host_set_ips = step.create_targets_with_tag.target_private_ips worker_tag_egress = local.egress_tag aws_region = var.aws_region + alb_cert = matrix.protocol == "https" ? step.create_boundary_cluster.alb_cert : "" } } diff --git a/enos/modules/aws_boundary/alb.tf b/enos/modules/aws_boundary/alb.tf index ab436c46e6..45782a951c 100644 --- a/enos/modules/aws_boundary/alb.tf +++ b/enos/modules/aws_boundary/alb.tf @@ -24,10 +24,48 @@ resource "aws_alb" "boundary_alb" { ) } +resource "tls_private_key" "private_key" { + depends_on = [aws_alb.boundary_alb] + count = var.protocol == "https" ? 1 : 0 + + algorithm = "RSA" + rsa_bits = 2048 +} + +resource "tls_self_signed_cert" "certificate" { + depends_on = [aws_alb.boundary_alb] + count = var.protocol == "https" ? 1 : 0 + + private_key_pem = tls_private_key.private_key[0].private_key_pem + + subject { + common_name = aws_alb.boundary_alb.dns_name + } + + dns_names = [aws_alb.boundary_alb.dns_name] + + validity_period_hours = 8760 + + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth", + ] +} + +resource "aws_acm_certificate" "cert" { + depends_on = [aws_alb.boundary_alb] + count = var.protocol == "https" ? 1 : 0 + + private_key = tls_private_key.private_key[0].private_key_pem + certificate_body = tls_self_signed_cert.certificate[0].cert_pem +} + resource "aws_alb_target_group" "boundary_tg" { + depends_on = [aws_acm_certificate.cert] name = "boundary-tg-${random_string.cluster_id.result}" - port = var.listener_api_port protocol = "HTTP" + port = var.listener_api_port vpc_id = var.vpc_id ip_address_type = var.ip_version == "6" ? "ipv6" : "ipv4" @@ -57,7 +95,11 @@ resource "aws_lb_target_group_attachment" "boundary" { resource "aws_alb_listener" "boundary" { load_balancer_arn = aws_alb.boundary_alb.arn port = var.alb_listener_api_port - protocol = "HTTP" + protocol = var.protocol == "https" ? "HTTPS" : "HTTP" + + # These MUST be null if protocol is HTTP + ssl_policy = var.protocol == "https" ? "ELBSecurityPolicy-2016-08" : null + certificate_arn = var.protocol == "https" ? aws_acm_certificate.cert[0].arn : null default_action { target_group_arn = aws_alb_target_group.boundary_tg.arn diff --git a/enos/modules/aws_boundary/outputs.tf b/enos/modules/aws_boundary/outputs.tf index d36524ba9a..88b72c642d 100644 --- a/enos/modules/aws_boundary/outputs.tf +++ b/enos/modules/aws_boundary/outputs.tf @@ -38,7 +38,7 @@ output "rds_db_name" { output "alb_boundary_api_addr" { description = "The address of the boundary API" - value = "http://${aws_alb.boundary_alb.dns_name}:${var.alb_listener_api_port}" + value = var.protocol == "https" ? "https://${aws_alb.boundary_alb.dns_name}:${var.alb_listener_api_port}" : "http://${aws_alb.boundary_alb.dns_name}:${var.alb_listener_api_port}" } // Boundary init outputs @@ -252,3 +252,8 @@ output "worker_ipv6_cidr" { description = "List of ipv6 subnets of all workers" value = distinct([for ip in flatten(aws_instance.worker.*.ipv6_addresses) : cidrsubnet("${ip}/64", 0, 0)]) } + +output "alb_cert" { + description = "Public cert for the alb" + value = try(tls_self_signed_cert.certificate[0].cert_pem, null) +} \ No newline at end of file diff --git a/enos/modules/aws_boundary/variables.tf b/enos/modules/aws_boundary/variables.tf index 5a55a00a6e..a8dc81e341 100644 --- a/enos/modules/aws_boundary/variables.tf +++ b/enos/modules/aws_boundary/variables.tf @@ -401,3 +401,9 @@ variable "vault_transit_token" { type = string default = "" } + +variable "protocol" { + description = "http protocol (http/https)" + type = string + default = "http" +} \ No newline at end of file diff --git a/enos/modules/test_e2e_ui/main.tf b/enos/modules/test_e2e_ui/main.tf index f026c04c3f..c08c4cc17f 100644 --- a/enos/modules/test_e2e_ui/main.tf +++ b/enos/modules/test_e2e_ui/main.tf @@ -194,6 +194,11 @@ variable "worker_tag_egress" { type = string default = "" } +variable "alb_cert" { + description = "public cert for the alb" + type = string + default = "" +} locals { aws_ssh_private_key_path = abspath(var.aws_ssh_private_key_path) @@ -236,6 +241,7 @@ resource "enos_local_exec" "run_e2e_test" { E2E_LDAP_GROUP_NAME = var.ldap_group_name E2E_WORKER_TOKEN = var.worker_token E2E_WORKER_TAG_EGRESS = var.worker_tag_egress + E2E_ALB_CERT = var.alb_cert } inline = var.debug_no_run ? [""] : ["set -o pipefail; PATH=\"${var.local_boundary_dir}:$PATH\" pnpm --cwd ${var.local_boundary_ui_src_dir}/ui/admin run e2e 2>&1 | tee ${path.module}/../../test-e2e-ui.log"]