部署 VPC 架构和 Microsoft Active Directory 域控制器 - Amazon Systems Manager
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

部署 VPC 架构和 Microsoft Active Directory 域控制器

要提高效率并标准化常见任务,可以选择自动执行部署。如果您定期在多个账户中部署相同的架构,此操作会很有帮助。 Amazon Web Services 区域 。自动化架构部署还可以降低在手动部署架构时发生人为错误的可能性。Amazon Systems ManagerAutomation 操作可帮助您做到这一点。自动化是Amazon Systems Manager。

以下示例Amazon Systems Managerrunbook 执行以下操作:

  • 检索最新的 Windows Server 2012R2Amazon Machine Image(AMI),使用 Systems Manager 参数存储以在启动将配置为域控制器的 EC2 实例时使用。参数存储是Amazon Systems Manager。

  • 使用aws:executeAwsApi自动化操作来调用多个AmazonAPI 操作来创建 VPC 架构。域控制器实例在私有子网中启动,使用 NAT 网关连接到 Internet。这使得实例上的 SSM Agent 可以访问必需的 Systems Manager 终端节点。

  • 使用aws:waitForAwsResourcePropertyAutomation 操作以确认上一个操作所启动的实例是Online对于 来说为Amazon Systems Manager。

  • 使用aws:runCommand自动化操作配置作为 Microsoft Active Directory 域控制器启动的实例。

YAML
--- description: Custom Automation Deployment Sample 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-2012-R2_RTM-English-64Bit-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 Sample", "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-2012-R2_RTM-English-64Bit-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 $_", "}" ] } } } ] }