From a8c2a50def19156217dacd03bdf6c8fb515e1c1b Mon Sep 17 00:00:00 2001 From: Robert Sweetman Date: Thu, 14 Sep 2023 11:28:04 +0100 Subject: [PATCH] Csr/dsos 2171/fix ad connectivity (#3356) * add domain controller sg to asg * add ec2 instance for testing in dev * fix casing and name * add kerberos ports to domain-controller sg * increase domain-controller range to all of fixngo * add port 389 to ports list * add test linux asg * allow ldap global catalog * add tcp ldap secure port 636 * add TCP and UDP netbios sg rules * add second test instance without any local hacks * add turn off schedule for asg's in dev * tidy up --- .../corporate-staff-rostering/ec2_common.tf | 14 +++ .../corporate-staff-rostering/locals.tf | 1 + .../locals_development.tf | 71 ++++++++++++- .../locals_security_groups.tf | 100 ++++++++++++++---- .../ssm-documents/windows-domain-join.yaml | 43 ++++++++ .../templates/test-user-data.yaml | 32 +++++- 6 files changed, 234 insertions(+), 27 deletions(-) create mode 100644 terraform/environments/corporate-staff-rostering/ssm-documents/windows-domain-join.yaml diff --git a/terraform/environments/corporate-staff-rostering/ec2_common.tf b/terraform/environments/corporate-staff-rostering/ec2_common.tf index 9f4fcb8831f..50b35685ebb 100644 --- a/terraform/environments/corporate-staff-rostering/ec2_common.tf +++ b/terraform/environments/corporate-staff-rostering/ec2_common.tf @@ -10,4 +10,18 @@ resource "aws_ssm_document" "csr_server_config" { Name = "csr-server-config" }, ) +} + +resource "aws_ssm_document" "windows_domain_join" { + name = "windows-domain-join" + document_type = "Command" + document_format = "YAML" + content = file("./ssm-documents/windows-domain-join.yaml") + + tags = merge( + local.tags, + { + Name = "windows-domain-join" + }, + ) } \ No newline at end of file diff --git a/terraform/environments/corporate-staff-rostering/locals.tf b/terraform/environments/corporate-staff-rostering/locals.tf index e0af20ad736..f597c8a9f20 100644 --- a/terraform/environments/corporate-staff-rostering/locals.tf +++ b/terraform/environments/corporate-staff-rostering/locals.tf @@ -40,6 +40,7 @@ locals { actions = [ "ec2-instance-connect:SendSerialConsoleSSHPublicKey", "ssm:SendCommand", + "ds:describeDirectories", ] resources = ["*"] }] diff --git a/terraform/environments/corporate-staff-rostering/locals_development.tf b/terraform/environments/corporate-staff-rostering/locals_development.tf index 374276f910e..6198425da62 100644 --- a/terraform/environments/corporate-staff-rostering/locals_development.tf +++ b/terraform/environments/corporate-staff-rostering/locals_development.tf @@ -21,7 +21,7 @@ locals { autoscaling_group = merge(module.baseline_presets.ec2_autoscaling_group.default, { desired_capacity = 0 }) - # autoscaling_schedules = module.baseline_presets.ec2_autoscaling_schedules.working_hours + autoscaling_schedules = module.baseline_presets.ec2_autoscaling_schedules.working_hours tags = { description = "For testing our base OL8.5 base image" ami = "base_ol_8_5" @@ -41,12 +41,13 @@ locals { }) instance = merge(module.baseline_presets.ec2_instance.instance.default, { - vpc_security_group_ids = ["migration-app-sg"] + vpc_security_group_ids = ["migration-app-sg","domain-controller"] instance_type = "t3.medium" }) autoscaling_group = merge(module.baseline_presets.ec2_autoscaling_group.default, { desired_capacity = 0 # set to 0 while testing }) + autoscaling_schedules = module.baseline_presets.ec2_autoscaling_schedules.working_hours ebs_volumes = { "/dev/sda1" = { type = "gp3", size = 192 } # minimum size has to be 128 due to snapshot sizes } @@ -125,6 +126,72 @@ locals { server-type = "csr-db" } } + /* dev-tst-3 = { + config = merge(module.baseline_presets.ec2_instance.config.default, { + ami_name = "base_windows_server_2012_r2_release_2023-*" + ami_owner = "374269020027" + ebs_volumes_copy_all_from_ami = false + user_data_raw = base64encode(file("./templates/test-user-data.yaml")) + instance_profile_policies = concat(module.baseline_presets.ec2_instance.config.default.instance_profile_policies, ["CSRWebServerPolicy"]) + }) + + instance = merge(module.baseline_presets.ec2_instance.instance.default, { + vpc_security_group_ids = ["migration-app-sg","domain-controller"] + instance_type = "t3.medium" + }) + ebs_volumes = { + "/dev/sda1" = { type = "gp3", size = 192 } # minimum size has to be 128 due to snapshot sizes + } + tags = { + description = "Test AWS AMI Windows Server 2012 R2" + os-type = "Windows" + component = "appserver" + server-type = "test-server" + } + } */ + /* dev-base-rhel85 = { + config = merge(module.baseline_presets.ec2_instance.config.default, { + ami_name = "base_rhel_8_5_*" + }) + instance = merge(module.baseline_presets.ec2_instance.instance.default, { + vpc_security_group_ids = ["migration-app-sg","domain-controller"] + }) + user_data_cloud_init = module.baseline_presets.ec2_instance.user_data_cloud_init.ssm_agent_and_ansible + autoscaling_group = merge(module.baseline_presets.ec2_autoscaling_group.default, { + desired_capacity = 0 + }) + autoscaling_schedules = module.baseline_presets.ec2_autoscaling_schedules.working_hours + tags = { + description = "For testing our base RHEL8.5 base image" + ami = "base_rhel_8_5" + os-type = "Linux" + component = "test" + server-type = "base-rhel85" + } + } */ + /* dev-tst-4 = { + config = merge(module.baseline_presets.ec2_instance.config.default, { + ami_name = "base_windows_server_2012_r2_release_2023-*" + ami_owner = "374269020027" + ebs_volumes_copy_all_from_ami = false + user_data_raw = base64encode(file("./templates/test-user-data.yaml")) + instance_profile_policies = concat(module.baseline_presets.ec2_instance.config.default.instance_profile_policies, ["CSRWebServerPolicy"]) + }) + + instance = merge(module.baseline_presets.ec2_instance.instance.default, { + vpc_security_group_ids = ["migration-app-sg","domain-controller"] + instance_type = "t3.medium" + }) + ebs_volumes = { + "/dev/sda1" = { type = "gp3", size = 192 } # minimum size has to be 128 due to snapshot sizes + } + tags = { + description = "Test AWS AMI Windows Server 2012 R2" + os-type = "Windows" + component = "appserver" + server-type = "test-server" + } + } */ } baseline_route53_zones = { diff --git a/terraform/environments/corporate-staff-rostering/locals_security_groups.tf b/terraform/environments/corporate-staff-rostering/locals_security_groups.tf index 12ffe5857e1..73651e5d4ac 100644 --- a/terraform/environments/corporate-staff-rostering/locals_security_groups.tf +++ b/terraform/environments/corporate-staff-rostering/locals_security_groups.tf @@ -422,12 +422,44 @@ locals { cidr_blocks = [for ip in module.ip_addresses.azure_fixngo_ips.devtest.domain_controllers : "${ip}/32"] security_groups = [] } */ + kerberos_tcp = { + description = "88: TCP Allow Kerberos ingress from Azure DC" + from_port = 88 + to_port = 88 + protocol = "TCP" + cidr_blocks = ["10.102.0.0/16"] + security_groups = [] + } + kerberos_udp = { + description = "88: UDP Allow Kerberos ingress from Azure DC" + from_port = 88 + to_port = 88 + protocol = "UDP" + cidr_blocks = ["10.102.0.0/16"] + security_groups = [] + } + kerberos_tcp_pwd = { + description = "464: TCP Allow Kerberos Password Change ingress from Azure DC" + from_port = 464 + to_port = 464 + protocol = "TCP" + cidr_blocks = ["10.102.0.0/16"] + security_groups = [] + } + kerberos_udp_pwd = { + description = "464: UDP Allow Kerberos Password Change ingress from Azure DC" + from_port = 464 + to_port = 464 + protocol = "UDP" + cidr_blocks = ["10.102.0.0/16"] + security_groups = [] + } rpc_udp = { description = "135: UDP MS-RPC AD connect ingress from Azure DC" from_port = 135 to_port = 135 protocol = "UDP" - cidr_blocks = [for ip in module.ip_addresses.azure_fixngo_ips.devtest.domain_controllers : "${ip}/32"] + cidr_blocks = ["10.102.0.0/16"] security_groups = [] } rpc_tcp = { @@ -435,31 +467,47 @@ locals { from_port = 135 to_port = 135 protocol = "TCP" - cidr_blocks = [for ip in module.ip_addresses.azure_fixngo_ips.devtest.domain_controllers : "${ip}/32"] + cidr_blocks = ["10.102.0.0/16"] security_groups = [] } - netbios = { - description = "139: NetBIOS ingress from Azure DC" - from_port = 139 + netbios_tcp = { + description = "137-139: TCP NetBIOS ingress from Azure DC" + from_port = 137 to_port = 139 protocol = "TCP" - cidr_blocks = [for ip in module.ip_addresses.azure_fixngo_ips.devtest.domain_controllers : "${ip}/32"] + cidr_blocks = ["10.102.0.0/16"] security_groups = [] } - /* ldap = { - description = "389: Allow LDAP ingress from Azure DC" + netbios_udp = { + description = "137-139: UDP NetBIOS ingress from Azure DC" + from_port = 137 + to_port = 139 + protocol = "UDP" + cidr_blocks = ["10.102.0.0/16"] + security_groups = [] + } + ldap_tcp = { + description = "389: TCP Allow LDAP ingress from Azure DC" from_port = 389 to_port = 389 - protocol = -1 - cidr_blocks = [for ip in module.ip_addresses.azure_fixngo_ips.devtest.domain_controllers : "${ip}/32"] + protocol = "TCP" + cidr_blocks = ["10.0.0.0/8"] security_groups = [] - } */ + } + ldap_udp = { + description = "389: UDP Allow LDAP ingress from Azure DC" + from_port = 389 + to_port = 389 + protocol = "UDP" + cidr_blocks = ["10.0.0.0/8"] + security_groups = [] + } smb_udp = { description = "445: UDP SMB ingress from Azure DC" from_port = 445 to_port = 445 protocol = "UDP" - cidr_blocks = [for ip in module.ip_addresses.azure_fixngo_ips.devtest.domain_controllers : "${ip}/32"] + cidr_blocks = ["10.102.0.0/16"] # cidr_blocks = var.modules.ip_addresses.azure_fixngo_ips.devtest.domain_controllers # cidr_blocks = ["10.102.0.196/32"] security_groups = [] @@ -469,26 +517,34 @@ locals { from_port = 445 to_port = 445 protocol = "TCP" - cidr_blocks = [for ip in module.ip_addresses.azure_fixngo_ips.devtest.domain_controllers : "${ip}/32"] + cidr_blocks = ["10.102.0.0/16"] # cidr_blocks = var.modules.ip_addresses.azure_fixngo_ips.devtest.domain_controllers # cidr_blocks = [" } - /* ldap_ssl = { - description = "636: Allow LDAP SSL ingress from Azure DC" + ldap_ssl = { + description = "636: TCP LDAP SSL ingress from Azure DC" from_port = 636 to_port = 636 protocol = "TCP" - cidr_blocks = [for ip in module.ip_addresses.azure_fixngo_ips.devtest.domain_controllers : "${ip}/32"] + cidr_blocks = ["10.0.0.0/8"] security_groups = [] - } */ - /* global_catalog_3268_3269 = { + } + ldap_ssl_udp = { + description = "636: UDP LDAP SSL ingress from Azure DC" + from_port = 636 + to_port = 636 + protocol = "UDP" + cidr_blocks = ["10.0.0.0/8"] + security_groups = [] + } + global_catalog_3268_3269 = { description = "3268-3269: Allow LDAP connection to Global Catalog over plain text and SSL" from_port = 3268 to_port = 3269 protocol = "TCP" - cidr_blocks = [for ip in module.ip_addresses.azure_fixngo_ips.devtest.domain_controllers : "${ip}/32"] + cidr_blocks = ["10.102.0.0/16"] security_groups = [] - } */ + } /* active_directory_web_services = { description = "9389: Allow Active Directory Web Services ingress from Azure DC" from_port = 9389 @@ -502,7 +558,7 @@ locals { from_port = 49152 to_port = 65535 protocol = "UDP" - cidr_blocks = [for ip in module.ip_addresses.azure_fixngo_ips.devtest.domain_controllers : "${ip}/32"] + cidr_blocks = ["10.102.0.0/16"] security_groups = [] } rpc_dynamic_tcp = { @@ -510,7 +566,7 @@ locals { from_port = 49152 to_port = 65535 protocol = "TCP" - cidr_blocks = [for ip in module.ip_addresses.azure_fixngo_ips.devtest.domain_controllers : "${ip}/32"] + cidr_blocks = ["10.102.0.0/16"] security_groups = [] } } diff --git a/terraform/environments/corporate-staff-rostering/ssm-documents/windows-domain-join.yaml b/terraform/environments/corporate-staff-rostering/ssm-documents/windows-domain-join.yaml new file mode 100644 index 00000000000..20ef1070e49 --- /dev/null +++ b/terraform/environments/corporate-staff-rostering/ssm-documents/windows-domain-join.yaml @@ -0,0 +1,43 @@ +--- +schemaVersion: "2.2" +description: "SSM Document for creating local configs on Windows Server" +parameters: + domainJoinUsername: + type: "String" + description: "username for the domain join credentials" + domainJoinPassword: + type: "String" + description: "password for the domain join credentials" + hostname: + type: "String" + description: "hostname for the new instance" + domain: + type: "String" + description: "domain to join" +mainSteps: + - name: JoinDomain + action: aws:runPowerShellScript + inputs: + runCommand: + - | + $ErrorActionPreference = "Stop" # all errors will terminate the script + + $domainUsername = "{{domainJoinUsername}}" + $domainPassword = "{{domainJoinPassword}}" + $hostname = "{{hostname}}" + $domain = "{{domain}}" + + # TODO: set up the domain join pre-requisites here + + # TODO: check if the proposed hostname is already in use + + # TODO: check if the instance is part of an ASG and terminate if it is since reboot may just result in another instance being spawned which won't be joined to the domain + + $secpasswd = ConvertTo-SecureString $domainPassword -AsPlainText -Force + $mycreds = New-Object System.Management.Automation.PSCredential ($domainUsername, $secpasswd) + + # TODO: check this next command is in a fit state to be run before the domain join + + # TODO: check to what extent we need to rename the instance and add it to the domain + + Add-Computer -DomainName $domain -Credential $mycreds -NewName $hostname -Restart diff --git a/terraform/environments/corporate-staff-rostering/templates/test-user-data.yaml b/terraform/environments/corporate-staff-rostering/templates/test-user-data.yaml index 44a33f5af15..8d3a222f70d 100644 --- a/terraform/environments/corporate-staff-rostering/templates/test-user-data.yaml +++ b/terraform/environments/corporate-staff-rostering/templates/test-user-data.yaml @@ -8,6 +8,7 @@ tasks: - frequency: always type: powershell runAs: admin + # debug AmazonSSMAgent service start content: |- $aws_ssm_status = (Get-Service -Name "AmazonSSMAgent").Status @@ -40,6 +41,7 @@ tasks: - frequency: once type: powershell runAs: admin + # run SSM test document content: |- # Install AWS PowerShell module if not already installed if (-Not (Get-Module -ListAvailable -Name "AWSPowerShell")) { @@ -76,6 +78,12 @@ tasks: Start-Sleep -Seconds 10 } } while ((Get-Date) -lt $startTime.AddMinutes(10)) + - frequency: once + type: powershell + runAs: admin # or localSystem + # install AD commands + content: |- + Install-WindowsFeature -Name RSAT-AD-PowerShell # - frequency: always # type: powershell # runAs: admin # or localSystem @@ -85,9 +93,27 @@ tasks: # # Set-TimeZone "GMT Standard Time" # does not work for Server 2012 R2 version of PowerShell # Set-WinSystemLocale "en-GB" - # - frequency: always + # IGNORE THIS - WIP + + # - frequency: once # type: powershell # runAs: admin # or localSystem - # # install AD commands + # # join domain calling SSM document # content: |- - # Install-WindowsFeature -Name RSAT-AD-PowerShell -IncludeAllSubFeature -IncludeManagementTools + # $parameters = @{ + # domainUsername = "domain-join-user" + # domainPassword = "domain-join-password" + # hostname = "test-hostname" + # primaryDC = "test-primary-dc" + # domain = "test-domain" + # } + # + # Function Execute-SSMCommand { + # $instanceId = Get-EC2InstanceMetadata -Category InstanceId + # $documentName = "windows-domain-join" + # + # + # $commandId = Send-SSMCommand -InstanceId $instanceId -DocumentName $documentName -Force -Parameter $parameters + # Write-Host "Executed SSM command with Command ID: $($commandId.CommandId)" + # } +