Implantar a arquitetura da VPC e os controles de domínio do Microsoft Active Directory - AWS Systems Manager

Implantar a arquitetura da VPC e os controles de domínio do Microsoft Active Directory

Para aumentar a eficiência e padronizar tarefas comuns, é possível optar por automatizar implantações. Isso é útil se você implantar regularmente a mesma arquitetura em várias contas e Regiões da AWS. A automatização de implantações de arquitetura também pode reduzir o potencial de erro humano que pode ocorrer ao implantar a arquitetura manualmente. AWS Systems Manager As ações do Automation podem ajudar você a fazer isso. O Automation é um recurso do AWS Systems Manager.

O runbook AWS Systems Manager de exemplo a seguir realiza estas ações:

  • Recupera a Amazon Machine Image (AMI) mais recente do Windows Server 2016 usando o Parameter Store do Systems Manager para usar ao executar as instâncias do EC2 que serão configuradas como controladores de domínio. O Parameter Store é u m recurso do AWS Systems Manager.

  • Usa a ação de automação aws:executeAwsApi para chamar várias operações da API da AWS para criar a arquitetura da VPC. As instâncias do controlador de domínio são executadas em sub-redes privadas e se conectam à Internet usando um gateway NAT. Isso permite que o SSM Agent nas instâncias acessem os endpoints do Systems Manager necessários.

  • Usa a ação de automação aws:waitForAwsResourceProperty para confirmar se as instâncias executadas pela ação anterior estão Online para o AWS Systems Manager.

  • Usa a ação de automação aws:runCommand para configurar as instâncias executadas como controles de domínio do Microsoft Active Directory.

YAML
--- description: Custom Automation Deployment Example schemaVersion: '0.3' parameters: AutomationAssumeRole: type: String default: '' description: >- (Optional) The ARN of the role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to run this runbook. mainSteps: - name: getLatestWindowsAmi action: aws:executeAwsApi onFailure: Abort inputs: Service: ssm Api: GetParameter Name: >- /aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base outputs: - Name: amiId Selector: $.Parameter.Value Type: String nextStep: createSSMInstanceRole - name: createSSMInstanceRole action: aws:executeAwsApi onFailure: Abort inputs: Service: iam Api: CreateRole AssumeRolePolicyDocument: >- {"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":["ec2.amazonaws.com"]},"Action":["sts:AssumeRole"]}]} RoleName: sampleSSMInstanceRole nextStep: attachManagedSSMPolicy - name: attachManagedSSMPolicy action: aws:executeAwsApi onFailure: Abort inputs: Service: iam Api: AttachRolePolicy PolicyArn: 'arn:aws:iam::aws:policy/service-role/AmazonSSMManagedInstanceCore' RoleName: sampleSSMInstanceRole nextStep: createSSMInstanceProfile - name: createSSMInstanceProfile action: aws:executeAwsApi onFailure: Abort inputs: Service: iam Api: CreateInstanceProfile InstanceProfileName: sampleSSMInstanceRole outputs: - Name: instanceProfileArn Selector: $.InstanceProfile.Arn Type: String nextStep: addSSMInstanceRoleToProfile - name: addSSMInstanceRoleToProfile action: aws:executeAwsApi onFailure: Abort inputs: Service: iam Api: AddRoleToInstanceProfile InstanceProfileName: sampleSSMInstanceRole RoleName: sampleSSMInstanceRole nextStep: createVpc - name: createVpc action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateVpc CidrBlock: 10.0.100.0/22 outputs: - Name: vpcId Selector: $.Vpc.VpcId Type: String nextStep: getMainRtb - name: getMainRtb action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: DescribeRouteTables Filters: - Name: vpc-id Values: - '{{ createVpc.vpcId }}' outputs: - Name: mainRtbId Selector: '$.RouteTables[0].RouteTableId' Type: String nextStep: verifyMainRtb - name: verifyMainRtb action: aws:assertAwsResourceProperty onFailure: Abort inputs: Service: ec2 Api: DescribeRouteTables RouteTableIds: - '{{ getMainRtb.mainRtbId }}' PropertySelector: '$.RouteTables[0].Associations[0].Main' DesiredValues: - 'True' nextStep: createPubSubnet - name: createPubSubnet action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateSubnet CidrBlock: 10.0.103.0/24 AvailabilityZone: us-west-2c VpcId: '{{ createVpc.vpcId }}' outputs: - Name: pubSubnetId Selector: $.Subnet.SubnetId Type: String nextStep: createPubRtb - name: createPubRtb action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateRouteTable VpcId: '{{ createVpc.vpcId }}' outputs: - Name: pubRtbId Selector: $.RouteTable.RouteTableId Type: String nextStep: createIgw - name: createIgw action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateInternetGateway outputs: - Name: igwId Selector: $.InternetGateway.InternetGatewayId Type: String nextStep: attachIgw - name: attachIgw action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: AttachInternetGateway InternetGatewayId: '{{ createIgw.igwId }}' VpcId: '{{ createVpc.vpcId }}' nextStep: allocateEip - name: allocateEip action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: AllocateAddress Domain: vpc outputs: - Name: eipAllocationId Selector: $.AllocationId Type: String nextStep: createNatGw - name: createNatGw action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateNatGateway AllocationId: '{{ allocateEip.eipAllocationId }}' SubnetId: '{{ createPubSubnet.pubSubnetId }}' outputs: - Name: natGwId Selector: $.NatGateway.NatGatewayId Type: String nextStep: verifyNatGwAvailable - name: verifyNatGwAvailable action: aws:waitForAwsResourceProperty timeoutSeconds: 150 inputs: Service: ec2 Api: DescribeNatGateways NatGatewayIds: - '{{ createNatGw.natGwId }}' PropertySelector: '$.NatGateways[0].State' DesiredValues: - available nextStep: createNatRoute - name: createNatRoute action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateRoute DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: '{{ createNatGw.natGwId }}' RouteTableId: '{{ getMainRtb.mainRtbId }}' nextStep: createPubRoute - name: createPubRoute action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateRoute DestinationCidrBlock: 0.0.0.0/0 GatewayId: '{{ createIgw.igwId }}' RouteTableId: '{{ createPubRtb.pubRtbId }}' nextStep: setPubSubAssoc - name: setPubSubAssoc action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: AssociateRouteTable RouteTableId: '{{ createPubRtb.pubRtbId }}' SubnetId: '{{ createPubSubnet.pubSubnetId }}' - name: createDhcpOptions action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateDhcpOptions DhcpConfigurations: - Key: domain-name-servers Values: - '10.0.100.50,10.0.101.50' - Key: domain-name Values: - sample.com outputs: - Name: dhcpOptionsId Selector: $.DhcpOptions.DhcpOptionsId Type: String nextStep: createDCSubnet1 - name: createDCSubnet1 action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateSubnet CidrBlock: 10.0.100.0/24 AvailabilityZone: us-west-2a VpcId: '{{ createVpc.vpcId }}' outputs: - Name: firstSubnetId Selector: $.Subnet.SubnetId Type: String nextStep: createDCSubnet2 - name: createDCSubnet2 action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateSubnet CidrBlock: 10.0.101.0/24 AvailabilityZone: us-west-2b VpcId: '{{ createVpc.vpcId }}' outputs: - Name: secondSubnetId Selector: $.Subnet.SubnetId Type: String nextStep: createDCSecGroup - name: createDCSecGroup action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateSecurityGroup GroupName: SampleDCSecGroup Description: Security Group for Sample Domain Controllers VpcId: '{{ createVpc.vpcId }}' outputs: - Name: dcSecGroupId Selector: $.GroupId Type: String nextStep: authIngressDCTraffic - name: authIngressDCTraffic action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: AuthorizeSecurityGroupIngress GroupId: '{{ createDCSecGroup.dcSecGroupId }}' IpPermissions: - FromPort: -1 IpProtocol: '-1' IpRanges: - CidrIp: 0.0.0.0/0 Description: Allow all traffic between Domain Controllers nextStep: verifyInstanceProfile - name: verifyInstanceProfile action: aws:waitForAwsResourceProperty maxAttempts: 5 onFailure: Abort inputs: Service: iam Api: ListInstanceProfilesForRole RoleName: sampleSSMInstanceRole PropertySelector: '$.InstanceProfiles[0].Arn' DesiredValues: - '{{ createSSMInstanceProfile.instanceProfileArn }}' nextStep: iamEventualConsistency - name: iamEventualConsistency action: aws:sleep inputs: Duration: PT2M nextStep: launchDC1 - name: launchDC1 action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: RunInstances BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: DeleteOnTermination: true VolumeSize: 50 VolumeType: gp2 - DeviceName: xvdf Ebs: DeleteOnTermination: true VolumeSize: 100 VolumeType: gp2 IamInstanceProfile: Arn: '{{ createSSMInstanceProfile.instanceProfileArn }}' ImageId: '{{ getLatestWindowsAmi.amiId }}' InstanceType: t2.micro MaxCount: 1 MinCount: 1 PrivateIpAddress: 10.0.100.50 SecurityGroupIds: - '{{ createDCSecGroup.dcSecGroupId }}' SubnetId: '{{ createDCSubnet1.firstSubnetId }}' TagSpecifications: - ResourceType: instance Tags: - Key: Name Value: SampleDC1 outputs: - Name: pdcInstanceId Selector: '$.Instances[0].InstanceId' Type: String nextStep: launchDC2 - name: launchDC2 action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: RunInstances BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: DeleteOnTermination: true VolumeSize: 50 VolumeType: gp2 - DeviceName: xvdf Ebs: DeleteOnTermination: true VolumeSize: 100 VolumeType: gp2 IamInstanceProfile: Arn: '{{ createSSMInstanceProfile.instanceProfileArn }}' ImageId: '{{ getLatestWindowsAmi.amiId }}' InstanceType: t2.micro MaxCount: 1 MinCount: 1 PrivateIpAddress: 10.0.101.50 SecurityGroupIds: - '{{ createDCSecGroup.dcSecGroupId }}' SubnetId: '{{ createDCSubnet2.secondSubnetId }}' TagSpecifications: - ResourceType: instance Tags: - Key: Name Value: SampleDC2 outputs: - Name: adcInstanceId Selector: '$.Instances[0].InstanceId' Type: String nextStep: verifyDCInstanceState - name: verifyDCInstanceState action: aws:waitForAwsResourceProperty inputs: Service: ec2 Api: DescribeInstanceStatus IncludeAllInstances: true InstanceIds: - '{{ launchDC1.pdcInstanceId }}' - '{{ launchDC2.adcInstanceId }}' PropertySelector: '$.InstanceStatuses[0].InstanceState.Name' DesiredValues: - running nextStep: verifyInstancesOnlineSSM - name: verifyInstancesOnlineSSM action: aws:waitForAwsResourceProperty timeoutSeconds: 600 inputs: Service: ssm Api: DescribeInstanceInformation InstanceInformationFilterList: - key: InstanceIds valueSet: - '{{ launchDC1.pdcInstanceId }}' - '{{ launchDC2.adcInstanceId }}' PropertySelector: '$.InstanceInformationList[0].PingStatus' DesiredValues: - Online nextStep: installADRoles - name: installADRoles action: aws:runCommand inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{ launchDC1.pdcInstanceId }}' - '{{ launchDC2.adcInstanceId }}' Parameters: commands: |- try { Install-WindowsFeature -Name AD-Domain-Services -IncludeManagementTools } catch { Write-Error "Failed to install ADDS Role." } nextStep: setAdminPassword - name: setAdminPassword action: aws:runCommand inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{ launchDC1.pdcInstanceId }}' Parameters: commands: - net user Administrator "sampleAdminPass123!" nextStep: createForest - name: createForest action: aws:runCommand inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{ launchDC1.pdcInstanceId }}' Parameters: commands: |- $dsrmPass = 'sample123!' | ConvertTo-SecureString -asPlainText -Force try { Install-ADDSForest -DomainName "sample.com" -DomainMode 6 -ForestMode 6 -InstallDNS -DatabasePath "D:\NTDS" -SysvolPath "D:\SYSVOL" -SafeModeAdministratorPassword $dsrmPass -Force } catch { Write-Error $_ } try { Add-DnsServerForwarder -IPAddress "10.0.100.2" } catch { Write-Error $_ } nextStep: associateDhcpOptions - name: associateDhcpOptions action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: AssociateDhcpOptions DhcpOptionsId: '{{ createDhcpOptions.dhcpOptionsId }}' VpcId: '{{ createVpc.vpcId }}' nextStep: waitForADServices - name: waitForADServices action: aws:sleep inputs: Duration: PT1M nextStep: promoteADC - name: promoteADC action: aws:runCommand inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{ launchDC2.adcInstanceId }}' Parameters: commands: |- ipconfig /renew $dsrmPass = 'sample123!' | ConvertTo-SecureString -asPlainText -Force $domAdminUser = "sample\Administrator" $domAdminPass = "sampleAdminPass123!" | ConvertTo-SecureString -asPlainText -Force $domAdminCred = New-Object System.Management.Automation.PSCredential($domAdminUser,$domAdminPass) try { Install-ADDSDomainController -DomainName "sample.com" -InstallDNS -DatabasePath "D:\NTDS" -SysvolPath "D:\SYSVOL" -SafeModeAdministratorPassword $dsrmPass -Credential $domAdminCred -Force } catch { Write-Error $_ }
JSON
{ "description": "Custom Automation Deployment Example", "schemaVersion": "0.3", "assumeRole": "{{ AutomationAssumeRole }}", "parameters": { "AutomationAssumeRole": { "type": "String", "description": "(Optional) The ARN of the role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to run this runbook.", "default": "" } }, "mainSteps": [ { "name": "getLatestWindowsAmi", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ssm", "Api": "GetParameter", "Name": "/aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base" }, "outputs": [ { "Name": "amiId", "Selector": "$.Parameter.Value", "Type": "String" } ], "nextStep": "createSSMInstanceRole" }, { "name": "createSSMInstanceRole", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "iam", "Api": "CreateRole", "AssumeRolePolicyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":[\"ec2.amazonaws.com\"]},\"Action\":[\"sts:AssumeRole\"]}]}", "RoleName": "sampleSSMInstanceRole" }, "nextStep": "attachManagedSSMPolicy" }, { "name": "attachManagedSSMPolicy", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "iam", "Api": "AttachRolePolicy", "PolicyArn": "arn:aws:iam::aws:policy/service-role/AmazonSSMManagedInstanceCore", "RoleName": "sampleSSMInstanceRole" }, "nextStep": "createSSMInstanceProfile" }, { "name": "createSSMInstanceProfile", "action":"aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "iam", "Api": "CreateInstanceProfile", "InstanceProfileName": "sampleSSMInstanceRole" }, "outputs": [ { "Name": "instanceProfileArn", "Selector": "$.InstanceProfile.Arn", "Type": "String" } ], "nextStep": "addSSMInstanceRoleToProfile" }, { "name": "addSSMInstanceRoleToProfile", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "iam", "Api": "AddRoleToInstanceProfile", "InstanceProfileName": "sampleSSMInstanceRole", "RoleName": "sampleSSMInstanceRole" }, "nextStep": "createVpc" }, { "name": "createVpc", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateVpc", "CidrBlock": "10.0.100.0/22" }, "outputs": [ { "Name": "vpcId", "Selector": "$.Vpc.VpcId", "Type": "String" } "nextStep": "getMainRtb" }, { "name": "getMainRtb", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "DescribeRouteTables", "Filters": [ { "Name": "vpc-id", "Values": ["{{ createVpc.vpcId }}"] } ] }, "outputs": [ { "Name": "mainRtbId", "Selector": "$.RouteTables[0].RouteTableId", "Type": "String" } ], "nextStep": "verifyMainRtb" }, { "name": "verifyMainRtb", "action": "aws:assertAwsResourceProperty", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "DescribeRouteTables", "RouteTableIds": ["{{ getMainRtb.mainRtbId }}"], "PropertySelector": "$.RouteTables[0].Associations[0].Main", "DesiredValues": ["True"] }, "nextStep": "createPubSubnet" }, { "name": "createPubSubnet", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateSubnet", "CidrBlock": "10.0.103.0/24", "AvailabilityZone": "us-west-2c", "VpcId": "{{ createVpc.vpcId }}" }, "outputs":[ { "Name": "pubSubnetId", "Selector": "$.Subnet.SubnetId", "Type": "String" } ], "nextStep": "createPubRtb" }, { "name": "createPubRtb", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateRouteTable", "VpcId": "{{ createVpc.vpcId }}" }, "outputs": [ { "Name": "pubRtbId", "Selector": "$.RouteTable.RouteTableId", "Type": "String" } ], "nextStep": "createIgw" }, { "name": "createIgw", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateInternetGateway" }, "outputs": [ { "Name": "igwId", "Selector": "$.InternetGateway.InternetGatewayId", "Type": "String" } ], "nextStep": "attachIgw" }, { "name": "attachIgw", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "AttachInternetGateway", "InternetGatewayId": "{{ createIgw.igwId }}", "VpcId": "{{ createVpc.vpcId }}" }, "nextStep": "allocateEip" }, { "name": "allocateEip", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "AllocateAddress", "Domain": "vpc" }, "outputs": [ { "Name": "eipAllocationId", "Selector": "$.AllocationId", "Type": "String" } ], "nextStep": "createNatGw" }, { "name": "createNatGw", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateNatGateway", "AllocationId": "{{ allocateEip.eipAllocationId }}", "SubnetId": "{{ createPubSubnet.pubSubnetId }}" }, "outputs":[ { "Name": "natGwId", "Selector": "$.NatGateway.NatGatewayId", "Type": "String" } ], "nextStep": "verifyNatGwAvailable" }, { "name": "verifyNatGwAvailable", "action": "aws:waitForAwsResourceProperty", "timeoutSeconds": 150, "inputs": { "Service": "ec2", "Api": "DescribeNatGateways", "NatGatewayIds": [ "{{ createNatGw.natGwId }}" ], "PropertySelector": "$.NatGateways[0].State", "DesiredValues": [ "available" ] }, "nextStep": "createNatRoute" }, { "name": "createNatRoute", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateRoute", "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": "{{ createNatGw.natGwId }}", "RouteTableId": "{{ getMainRtb.mainRtbId }}" }, "nextStep": "createPubRoute" }, { "name": "createPubRoute", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateRoute", "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": "{{ createIgw.igwId }}", "RouteTableId": "{{ createPubRtb.pubRtbId }}" }, "nextStep": "setPubSubAssoc" }, { "name": "setPubSubAssoc", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "AssociateRouteTable", "RouteTableId": "{{ createPubRtb.pubRtbId }}", "SubnetId": "{{ createPubSubnet.pubSubnetId }}" } }, { "name": "createDhcpOptions", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateDhcpOptions", "DhcpConfigurations": [ { "Key": "domain-name-servers", "Values": ["10.0.100.50,10.0.101.50"] }, { "Key": "domain-name", "Values": ["sample.com"] } ] }, "outputs": [ { "Name": "dhcpOptionsId", "Selector": "$.DhcpOptions.DhcpOptionsId", "Type": "String" } ], "nextStep": "createDCSubnet1" }, { "name": "createDCSubnet1", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateSubnet", "CidrBlock": "10.0.100.0/24", "AvailabilityZone": "us-west-2a", "VpcId": "{{ createVpc.vpcId }}" }, "outputs": [ { "Name": "firstSubnetId", "Selector": "$.Subnet.SubnetId", "Type": "String" } ], "nextStep": "createDCSubnet2" }, { "name": "createDCSubnet2", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateSubnet", "CidrBlock": "10.0.101.0/24", "AvailabilityZone": "us-west-2b", "VpcId": "{{ createVpc.vpcId }}" }, "outputs": [ { "Name": "secondSubnetId", "Selector": "$.Subnet.SubnetId", "Type": "String" } ], "nextStep": "createDCSecGroup" }, { "name": "createDCSecGroup", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateSecurityGroup", "GroupName": "SampleDCSecGroup", "Description": "Security Group for Example Domain Controllers", "VpcId": "{{ createVpc.vpcId }}" }, "outputs": [ { "Name": "dcSecGroupId", "Selector": "$.GroupId", "Type": "String" } ], "nextStep": "authIngressDCTraffic" }, { "name": "authIngressDCTraffic", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "AuthorizeSecurityGroupIngress", "GroupId": "{{ createDCSecGroup.dcSecGroupId }}", "IpPermissions": [ { "FromPort": -1, "IpProtocol": "-1", "IpRanges": [ { "CidrIp": "0.0.0.0/0", "Description": "Allow all traffic between Domain Controllers" } ] } ] }, "nextStep": "verifyInstanceProfile" }, { "name": "verifyInstanceProfile", "action": "aws:waitForAwsResourceProperty", "maxAttempts": 5, "onFailure": "Abort", "inputs": { "Service": "iam", "Api": "ListInstanceProfilesForRole", "RoleName": "sampleSSMInstanceRole", "PropertySelector": "$.InstanceProfiles[0].Arn", "DesiredValues": [ "{{ createSSMInstanceProfile.instanceProfileArn }}" ] }, "nextStep": "iamEventualConsistency" }, { "name": "iamEventualConsistency", "action": "aws:sleep", "inputs": { "Duration": "PT2M" }, "nextStep": "launchDC1" }, { "name": "launchDC1", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "RunInstances", "BlockDeviceMappings": [ { "DeviceName": "/dev/sda1", "Ebs": { "DeleteOnTermination": true, "VolumeSize": 50, "VolumeType": "gp2" } }, { "DeviceName": "xvdf", "Ebs": { "DeleteOnTermination": true, "VolumeSize": 100, "VolumeType": "gp2" } } ], "IamInstanceProfile": { "Arn": "{{ createSSMInstanceProfile.instanceProfileArn }}" }, "ImageId": "{{ getLatestWindowsAmi.amiId }}", "InstanceType": "t2.micro", "MaxCount": 1, "MinCount": 1, "PrivateIpAddress": "10.0.100.50", "SecurityGroupIds": [ "{{ createDCSecGroup.dcSecGroupId }}" ], "SubnetId": "{{ createDCSubnet1.firstSubnetId }}", "TagSpecifications": [ { "ResourceType": "instance", "Tags": [ { "Key": "Name", "Value": "SampleDC1" } ] } ] }, "outputs": [ { "Name": "pdcInstanceId", "Selector": "$.Instances[0].InstanceId", "Type": "String" } ], "nextStep": "launchDC2" }, { "name": "launchDC2", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "RunInstances", "BlockDeviceMappings": [ { "DeviceName": "/dev/sda1", "Ebs": { "DeleteOnTermination": true, "VolumeSize": 50, "VolumeType": "gp2" } }, { "DeviceName": "xvdf", "Ebs": { "DeleteOnTermination": true, "VolumeSize": 100, "VolumeType": "gp2" } } ], "IamInstanceProfile": { "Arn": "{{ createSSMInstanceProfile.instanceProfileArn }}" }, "ImageId": "{{ getLatestWindowsAmi.amiId }}", "InstanceType": "t2.micro", "MaxCount": 1, "MinCount": 1, "PrivateIpAddress": "10.0.101.50", "SecurityGroupIds": [ "{{ createDCSecGroup.dcSecGroupId }}" ], "SubnetId": "{{ createDCSubnet2.secondSubnetId }}", "TagSpecifications": [ { "ResourceType": "instance", "Tags": [ { "Key": "Name", "Value": "SampleDC2" } ] } ] }, "outputs": [ { "Name": "adcInstanceId", "Selector": "$.Instances[0].InstanceId", "Type": "String" } ], "nextStep": "verifyDCInstanceState" }, { "name": "verifyDCInstanceState", "action": "aws:waitForAwsResourceProperty", "inputs": { "Service": "ec2", "Api": "DescribeInstanceStatus", "IncludeAllInstances": true, "InstanceIds": [ "{{ launchDC1.pdcInstanceId }}", "{{ launchDC2.adcInstanceId }}" ], "PropertySelector": "$.InstanceStatuses[0].InstanceState.Name", "DesiredValues": [ "running" ] }, "nextStep": "verifyInstancesOnlineSSM" }, { "name": "verifyInstancesOnlineSSM", "action": "aws:waitForAwsResourceProperty", "timeoutSeconds": 600, "inputs": { "Service": "ssm", "Api": "DescribeInstanceInformation", "InstanceInformationFilterList": [ { "key": "InstanceIds", "valueSet": [ "{{ launchDC1.pdcInstanceId }}", "{{ launchDC2.adcInstanceId }}" ] } ], "PropertySelector": "$.InstanceInformationList[0].PingStatus", "DesiredValues": [ "Online" ] }, "nextStep": "installADRoles" }, { "name": "installADRoles", "action": "aws:runCommand", "inputs": { "DocumentName": "AWS-RunPowerShellScript", "InstanceIds": [ "{{ launchDC1.pdcInstanceId }}", "{{ launchDC2.adcInstanceId }}" ], "Parameters": { "commands": [ "try {", " Install-WindowsFeature -Name AD-Domain-Services -IncludeManagementTools", "}", "catch {", " Write-Error \"Failed to install ADDS Role.\"", "}" ] } }, "nextStep": "setAdminPassword" }, { "name": "setAdminPassword", "action": "aws:runCommand", "inputs": { "DocumentName": "AWS-RunPowerShellScript", "InstanceIds": [ "{{ launchDC1.pdcInstanceId }}" ], "Parameters": { "commands": [ "net user Administrator \"sampleAdminPass123!\"" ] } }, "nextStep": "createForest" }, { "name": "createForest", "action": "aws:runCommand", "inputs": { "DocumentName": "AWS-RunPowerShellScript", "InstanceIds": [ "{{ launchDC1.pdcInstanceId }}" ], "Parameters": { "commands": [ "$dsrmPass = 'sample123!' | ConvertTo-SecureString -asPlainText -Force", "try {", " Install-ADDSForest -DomainName \"sample.com\" -DomainMode 6 -ForestMode 6 -InstallDNS -DatabasePath \"D:\\NTDS\" -SysvolPath \"D:\\SYSVOL\" -SafeModeAdministratorPassword $dsrmPass -Force", "}", "catch {", " Write-Error $_", "}", "try {", " Add-DnsServerForwarder -IPAddress \"10.0.100.2\"", "}", "catch {", " Write-Error $_", "}" ] } }, "nextStep": "associateDhcpOptions" }, { "name": "associateDhcpOptions", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "AssociateDhcpOptions", "DhcpOptionsId": "{{ createDhcpOptions.dhcpOptionsId }}", "VpcId": "{{ createVpc.vpcId }}" }, "nextStep": "waitForADServices" }, { "name": "waitForADServices", "action": "aws:sleep", "inputs": { "Duration": "PT1M" }, "nextStep": "promoteADC" }, { "name": "promoteADC", "action": "aws:runCommand", "inputs": { "DocumentName": "AWS-RunPowerShellScript", "InstanceIds": [ "{{ launchDC2.adcInstanceId }}" ], "Parameters": { "commands": [ "ipconfig /renew", "$dsrmPass = 'sample123!' | ConvertTo-SecureString -asPlainText -Force", "$domAdminUser = \"sample\\Administrator\"", "$domAdminPass = \"sampleAdminPass123!\" | ConvertTo-SecureString -asPlainText -Force", "$domAdminCred = New-Object System.Management.Automation.PSCredential($domAdminUser,$domAdminPass)", "try {", " Install-ADDSDomainController -DomainName \"sample.com\" -InstallDNS -DatabasePath \"D:\\NTDS\" -SysvolPath \"D:\\SYSVOL\" -SafeModeAdministratorPassword $dsrmPass -Credential $domAdminCred -Force", "}", "catch {", " Write-Error $_", "}" ] } } } ] }