Déployer l'architecture VPC et les contrôleurs de domaine Microsoft Active Directory - AWS Systems Manager

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Déployer l'architecture VPC et les contrôleurs de domaine Microsoft Active Directory

Pour accroître l'efficacité et normaliser les tâches courantes, vous pouvez choisir d'automatiser les déploiements. C'est particulièrement utile si vous déployez régulièrement la même architecture sur plusieurs comptes et dans plusieurs Régions AWS. L'automatisation des déploiements d'architecture peut également réduire le risque d'erreurs humaines susceptibles de se produire lors du déploiement manuel de l'architecture. AWS Systems Manager Les actions d'automatisation peuvent vous aider à y parvenir. Automation est une fonctionnalité de AWS Systems Manager.

Dans l'exemple suivant, un runbook AWS Systems Manager exécute ces actions :

  • Récupère la dernière Amazon Machine Image (AMI) Windows Server 2016 avec Systems Manager Parameter Store à utiliser lors du lancement des instances EC2 qui seront configurées en tant que contrôleurs de domaine. Parameter Store est une fonctionnalité de AWS Systems Manager.

  • Utilise l'opération d'automatisation aws:executeAwsApi pour appeler plusieurs opérations d'API AWS pour créer l'architecture VPC. Les instances de contrôleur de domaine sont lancées dans des sous-réseaux privés et se connectent à Internet à l'aide d'une passerelle NAT. Cela permet à l'SSM Agent sur les instances d'accéder aux points de terminaison Systems Manager requis.

  • Il utilise l'action d'automatisation aws:waitForAwsResourceProperty pour confirmer que les instances lancées par l'action précédente sont Online pour AWS Systems Manager.

  • Il utilise l'action d'automatisation aws:runCommand pour configurer les instances lancées en tant que contrôleurs de domaine 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 $_", "}" ] } } } ] }