diff --git a/enos/enos-scenario-e2e-aws-windows.hcl b/enos/enos-scenario-e2e-aws-rdp-base.hcl similarity index 92% rename from enos/enos-scenario-e2e-aws-windows.hcl rename to enos/enos-scenario-e2e-aws-rdp-base.hcl index eed9b49c23..5cc974d759 100644 --- a/enos/enos-scenario-e2e-aws-windows.hcl +++ b/enos/enos-scenario-e2e-aws-rdp-base.hcl @@ -1,7 +1,11 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: BUSL-1.1 -scenario "e2e_aws_windows" { +# This scenario creates a complete end-to-end test environment for Boundary to +# test RDP functionality. It includes a Windows client, a Boundary controller +# and worker, a domain controller, a member server, and another member server +# with a worker running on it. +scenario "e2e_aws_rdp_base" { terraform_cli = terraform_cli.default terraform = terraform.default providers = [ @@ -10,8 +14,11 @@ scenario "e2e_aws_windows" { ] matrix { - builder = ["local", "crt"] - client = ["win10", "win11"] + builder = ["local", "crt"] + client = ["win10", "win11"] + # Windows Server 2016 does not support OpenSSH, but it's relied on for some + # parts of setup. If 2016 is selected, the member server will be created as + # 2016, but the domain controller and worker will be 2019. rdp_server = ["2016", "2019", "2022", "2025"] } @@ -150,7 +157,7 @@ scenario "e2e_aws_windows" { variables { vpc_id = step.create_base_infra.vpc_id - server_version = matrix.rdp_server + server_version = matrix.rdp_server == "2016" ? "2019" : matrix.rdp_server } } @@ -233,7 +240,7 @@ scenario "e2e_aws_windows" { variables { vpc_id = step.create_base_infra.vpc_id - server_version = matrix.rdp_server + server_version = matrix.rdp_server == "2016" ? "2019" : matrix.rdp_server boundary_cli_zip_path = step.build_boundary_windows.artifact_path kms_key_arn = step.create_base_infra.kms_key_arn controller_ip = step.create_boundary_cluster.public_controller_addresses[0] @@ -245,6 +252,7 @@ scenario "e2e_aws_windows" { domain_admin_password = step.create_rdp_domain_controller.password domain_controller_private_key = step.create_rdp_domain_controller.ssh_private_key domain_controller_sec_group_id_list = step.create_rdp_domain_controller.security_group_id_list + aws_region = var.aws_region } } @@ -303,6 +311,9 @@ scenario "e2e_aws_windows" { client_username = step.create_windows_client.test_username client_password = step.create_windows_client.test_password client_test_dir = step.create_windows_client.test_dir + vault_addr_public = step.create_vault_cluster.instance_public_ips_ipv4[0] + vault_addr_private = step.create_vault_cluster.instance_private_ips[0] + vault_root_token = step.create_vault_cluster.vault_root_token } } @@ -389,4 +400,4 @@ scenario "e2e_aws_windows" { output "windows_worker_private_ip" { value = step.create_windows_worker.private_ip } -} \ No newline at end of file +} diff --git a/enos/enos-scenario-e2e-aws-rdp-target.hcl b/enos/enos-scenario-e2e-aws-rdp-target.hcl index 04fbf3f531..1393329c61 100644 --- a/enos/enos-scenario-e2e-aws-rdp-target.hcl +++ b/enos/enos-scenario-e2e-aws-rdp-target.hcl @@ -1,6 +1,8 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: BUSL-1.1 +# This scenario creates a single Windows ec2 instance that acts as a domain +# controller. This can be used as an RDP target for boundary. scenario "e2e_aws_rdp_target" { terraform_cli = terraform_cli.default terraform = terraform.default diff --git a/enos/modules/aws_rdp_member_server/main.tf b/enos/modules/aws_rdp_member_server/main.tf index d231460c56..128b7883f8 100644 --- a/enos/modules/aws_rdp_member_server/main.tf +++ b/enos/modules/aws_rdp_member_server/main.tf @@ -61,14 +61,15 @@ resource "aws_instance" "member_server" { user_data = < + %{if var.server_version != "2016"~} # set variables for retry loops $timeout = 300 $interval = 30 # Set up SSH so we can remotely manage the instance ## Install OpenSSH Server and Client - # Loop to make sure that SSH installs correctly - $elapsed = 0 + # Loop to make sure that SSH installs correctly + $elapsed = 0 do { try { Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 @@ -129,6 +130,7 @@ resource "aws_instance" "member_server" { ## Open the firewall for SSH connections New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 + %{endif~} # Adds member server to the domain [int]$intix = Get-NetAdapter | % { Process { If ( $_.Status -eq "up" ) { $_.ifIndex } }} @@ -160,7 +162,7 @@ ${var.domain_admin_password} Write-Host "Resovling domain after 5 minutes. Exiting." exit 1 } - } while ($true) + } while ($true) #logging to troubleshoot domain issues Resolve-DnsName -Name "${var.active_directory_domain}" -Server "${var.domain_controller_ip}" -ErrorAction SilentlyContinue @@ -222,6 +224,7 @@ resource "time_sleep" "wait_2_minutes" { # BatchMode=Yes to prevent SSH from prompting for a password to ensure that we # can just SSH using the private key resource "enos_local_exec" "wait_for_ssh" { + count = var.server_version != "2016" ? 1 : 0 depends_on = [time_sleep.wait_2_minutes] inline = ["timeout 600s bash -c 'until ssh -i ${local.private_key} -o BatchMode=Yes -o IdentitiesOnly=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no Administrator@${aws_instance.member_server.public_ip} \"echo ready\"; do sleep 10; done'"] } @@ -229,6 +232,7 @@ resource "enos_local_exec" "wait_for_ssh" { # Retrieve the domain hostname of the member server, which will be used in # Kerberos resource "enos_local_exec" "get_hostname" { + count = var.server_version != "2016" ? 1 : 0 depends_on = [ enos_local_exec.wait_for_ssh, ] diff --git a/enos/modules/aws_rdp_member_server/outputs.tf b/enos/modules/aws_rdp_member_server/outputs.tf index b09e4ee836..50e1247d03 100644 --- a/enos/modules/aws_rdp_member_server/outputs.tf +++ b/enos/modules/aws_rdp_member_server/outputs.tf @@ -29,6 +29,6 @@ output "password" { } output "domain_hostname" { - description = "The hostname of the domain controller" - value = trimspace(enos_local_exec.get_hostname.stdout) + description = "The hostname of the member server" + value = var.server_version != "2016" ? trimspace(enos_local_exec.get_hostname[0].stdout) : "" } diff --git a/enos/modules/aws_rdp_member_server_with_worker/main.tf b/enos/modules/aws_rdp_member_server_with_worker/main.tf index 21f5ad3c35..a1c87f1d39 100644 --- a/enos/modules/aws_rdp_member_server_with_worker/main.tf +++ b/enos/modules/aws_rdp_member_server_with_worker/main.tf @@ -93,8 +93,8 @@ resource "aws_instance" "worker" { # Set up SSH so we can remotely manage the instance ## Install OpenSSH Server and Client - # Loop to make sure that SSH installs correctly - $elapsed = 0 + # Loop to make sure that SSH installs correctly + $elapsed = 0 do { try { Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 @@ -158,14 +158,14 @@ resource "aws_instance" "worker" { New-NetFirewallRule -Name boundary_in -DisplayName 'Boundary inbound' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 9202 New-NetFirewallRule -Name boundary_out -DisplayName 'Boundary outbound' -Enabled True -Direction Outbound -Protocol TCP -Action Allow -LocalPort 9202 - ## Add computer to the domain + # Add computer to the domain [int]$intix = Get-NetAdapter | % { Process { If ( $_.Status -eq "up" ) { $_.ifIndex } }} Set-DNSClientServerAddress -interfaceIndex $intix -ServerAddresses ("${var.domain_controller_ip}","127.0.0.1") $here_string_password = @' ${var.domain_admin_password} '@ $password = ConvertTo-SecureString $here_string_password -AsPlainText -Force - $username = "${local.domain_sld}\Administrator" + $username = "${local.domain_sld}\Administrator" $credential = New-Object System.Management.Automation.PSCredential($username,$password) # check that domain can be reached @@ -184,7 +184,7 @@ ${var.domain_admin_password} Write-Host "Resolving domain after 5 minutes. Exiting." exit 1 } - } while ($true) + } while ($true) #logging to troubleshoot domain issues Resolve-DnsName -Name "${var.active_directory_domain}" -Server "${var.domain_controller_ip}" -ErrorAction SilentlyContinue diff --git a/enos/modules/aws_rdp_member_server_with_worker/scripts/setup.ps1 b/enos/modules/aws_rdp_member_server_with_worker/scripts/setup.ps1 index 47f734af95..2e36a12187 100644 --- a/enos/modules/aws_rdp_member_server_with_worker/scripts/setup.ps1 +++ b/enos/modules/aws_rdp_member_server_with_worker/scripts/setup.ps1 @@ -26,4 +26,4 @@ $command = "boundary server -config `"$configPath`" *> $jobLog" Register-ScheduledJob boundary -ScriptBlock ([ScriptBlock]::Create($command)) -Trigger $trigger # Restart the computer to apply changes -shutdown -r -t 10 \ No newline at end of file +shutdown -r -t 10 diff --git a/enos/modules/aws_vault/outputs.tf b/enos/modules/aws_vault/outputs.tf index 1947ab1073..525c811ebc 100644 --- a/enos/modules/aws_vault/outputs.tf +++ b/enos/modules/aws_vault/outputs.tf @@ -11,6 +11,11 @@ output "instance_public_ips" { value = var.ip_version == "4" ? [for instance in aws_instance.vault_instance : instance.public_ip] : flatten([for instance in aws_instance.vault_instance : instance.ipv6_addresses]) } +output "instance_public_ips_ipv4" { + description = "Public IPv4 addresses of Vault instances" + value = [for instance in aws_instance.vault_instance : instance.public_ip if instance.public_ip != null] +} + output "instance_private_ips" { description = "Private IPs of Vault instances" value = [for instance in aws_instance.vault_instance : instance.private_ip] diff --git a/enos/modules/aws_vpc_ipv6/main.tf b/enos/modules/aws_vpc_ipv6/main.tf index 1ba48517eb..f34496f3f3 100644 --- a/enos/modules/aws_vpc_ipv6/main.tf +++ b/enos/modules/aws_vpc_ipv6/main.tf @@ -71,6 +71,8 @@ variable "ip_version" { } } +data "aws_caller_identity" "current" {} + data "enos_environment" "localhost" {} check "ipv6_connection" { @@ -174,7 +176,7 @@ resource "aws_vpc" "vpc" { tags = merge( local.common_tags, { - "Name" = var.name + "Name" = "${var.name}-${split(":", data.aws_caller_identity.current.user_id)[1]}" }, ) }