効率を高め、一般的なタスクを標準化するために、デプロイを自動化することができます。これは、定期的に複数のアカウントと に同じアーキテクチャをデプロイする場合に便利ですAWS リージョン また、アーキテクチャのデプロイを自動化することで、アーキテクチャを手動でデプロイするときに発生する人為的エラーの発生率を減らすことができます。AWS Systems Managerオートメーションアクションが、これを実現するのに役立ちます。Automation は AWS Systems Manager のツールです。
次の AWS Systems Manager ランブックの例では、これらのアクションを実行します。
-
ドメインコントローラーとして設定して EC2 インスタンスを起動する際に、Systems Manager Parameter Store を使用して、最新の Windows Server 2016 Amazon Machine Image (AMI) を取得します。Parameter Store は AWS Systems Manager のツールです。
-
aws:executeAwsApi
オートメーションアクションを使用して、複数の AWS API オペレーションを呼び出して VPC アーキテクチャを作成します。ドメインコントローラーインスタンスはプライベートサブネットで起動され、NAT ゲートウェイを使用してインターネットに接続されます。これにより、インスタンスの SSM Agent は、必要な Systems Manager エンドポイントにアクセスできるようになります。 -
aws:waitForAwsResourceProperty
オートメーションアクションを使用して、前のアクションによって起動されたインスタンスがOnline
に対してAWS Systems Manager であることを確認します。 -
aws:runCommand
オートメーションアクションを使用して、Microsoft Active Directory ドメインコントローラーとして起動されるインスタンスを設定します。
---
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..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..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 $_
}