Systems Manager Automation enables you to run a sequence of workflows (AWS API calls, provisioning instances, creating buckets, and triggering Lambda functions) through the convenience of a single SSM Automation document.
One of the major benefits you are getting is you no longer need to maintain tooling servers or run scripts locally on your computer. You can automate or schedule most of the maintenance and deployment tasks as a runbook style SSM documents that define the actions to perform.
In this hands-on post, we’ll create a custom AWS SSM Automation document to create an AMI of 1 instance or more and copy the AMI cross regions.
1./ Create a Iam role
1- Navigate to the IAM Console and create a role for System Manager with the below JSON policy. This policy grants the System Manager, the ability to Describe Tags, create and copy Images.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"ec2:CreateSnapshot",
"ec2:CopySnapshot",
"ec2:CreateTags",
"ec2:ModifySnapshotAttribute",
"ec2:CreateImage",
"ec2:CopyImage",
"ec2:RegisterImage"
],
"Resource": "*"
}
]
}
2./ Create SSM Automation Document
1- From the AWS console, select Systems Manager.
2- When you get to the front page of the service, use the left hand panel and go down to the bottom of the menu to select Documents
3- From the main page, select the Create Automation button to build an automation document
4- Enter the name of the automation document and select the Editor option to enter a the document directly into the console
5- Copy the below code:
description: ''
schemaVersion: '0.3'
assumeRole: '{{ AutomationAssumeRole }}'
parameters:
InstanceId:
type: String
description: ' (Required) Target EC2 InstanceId'
allowedPattern: '^i-[a-z0-9]{8,17}$'
AutomationAssumeRole:
type: String
description: (Required) The ARN of the role that allows Automation to perform the actions on your behalf.
ImagePrefix:
type: String
description: Choose Prefixes from one of the choices below.
allowedValues:
- ManualBackup
- DEPLOY
TargetRegion:
type: String
description: Region to copy the Ami to
default: us-west-2
mainSteps:
- name: RecordStartTime
action: 'aws:executeScript'
inputs:
Runtime: python3.8
Handler: script_handler
Script: |
from datetime import datetime, timezone
def script_handler(params: dict, context):
return get_current_time().strftime('%Y%m%d_%H%M')
def get_current_time():
return datetime.now(timezone.utc)
InputPayload: {}
outputs:
- Name: StartTime
Selector: $.Payload
Type: String
- name: GetInstanceName
action: 'aws:executeScript'
inputs:
Runtime: python3.8
Handler: script_handler
Script: |
import boto3
def script_handler(events, context):
instanceId = events["InstanceId"]
ec2 = boto3.client('ec2')
tags = ec2.describe_tags(
Filters=[{'Name': 'resource-id', 'Values': [instanceId]}])['Tags']
if not tags:
return (instanceId)
for tag in tags:
if (tag['Key']) == "Name":
result = tag['Value']
return (result)
InputPayload:
InstanceId: '{{InstanceId}}'
outputs:
- Name: result
Selector: $.Payload
Type: String
- name: CreateImage
action: 'aws:createImage'
inputs:
InstanceId: '{{InstanceId}}'
ImageName: '{{RecordStartTime.StartTime}}_{{GetInstanceName.result}}_{{ImagePrefix}}'
NoReboot: true
- name: CreateTagsImage
action: 'aws:createTags'
maxAttempts: 1
onFailure: Continue
inputs:
ResourceType: EC2
ResourceIds:
- '{{ CreateImage.ImageId }}'
Tags:
- Key: Name
Value: '{{RecordStartTime.StartTime}}_{{GetInstanceName.result}}_{{ImagePrefix}}'
- Key: Automation-Id
Value: '{{automation:EXECUTION_ID}}'
- Key: Owner
Value: YallaLabs
- Key: SourceInstanceName
Value: '{{GetInstanceName.result}}'
- Key: Amazon-SSM
Value: 'true'
- name: CrossRegionImageCopy
action: 'aws:executeScript'
inputs:
Runtime: python3.8
Handler: script_handler
Script: |
import boto3
def script_handler(events, context):
newImageId = events['newImageId']
sourceregion = events['sourceregion']
targetregion = events['targetregion']
creationtime = events['creationtime']
instancename = events['instancename']
imageprefix = events['imageprefix']
ec2 = boto3.client('ec2', region_name=targetregion)
result= ec2.copy_image(
Name=creationtime + "_" + instancename + "_" + imageprefix,
SourceImageId=newImageId,
SourceRegion=sourceregion
)
new_ami= result['ImageId']
ec2.create_tags(
Resources=[new_ami],
Tags=[
{'Key': 'Name', 'Value': creationtime + "_" + instancename + "_" + imageprefix},
{'Key': 'CreatedOn', 'Value': str(creationtime)},
{'Key': 'SourceImageId', 'Value': str(newImageId)},
{'Key': 'SourceInstanceName', 'Value': str(instancename)},
{'Key': 'SourceRegion', 'Value': str(sourceregion)}
]
)
return (new_ami)
InputPayload:
newImageId: '{{ CreateImage.ImageId }}'
sourceregion: '{{ global:REGION }}'
targetregion: '{{ TargetRegion }}'
creationtime: '{{RecordStartTime.StartTime}}'
instancename: '{{GetInstanceName.result}}'
imageprefix: '{{ImagePrefix}}'
outputs:
- Name: ImageId
Selector: $.Payload
Type: String
6- Once that’s done click Create Automation
3./ Execute the Automation Document
1- Navigate to Systems Manager > Change Management > Automation
2- Select Execute Automation
3- In Choose document go to Owned by me

4- Pick the one we just created, new Windows will open. Click Execute automation button
5- Fill out the details for Execute automation document
- AutomationAssumeRole: The ARN of the role that allows Automation to perform the actions on your behalf
- InstanceId: Toggle Show Interactive instance picker on and select your instance
- ImagePrefix: Choose a prefix for image, or you can set yours
- TargetRegion: Region to copy the Ami to

6- Select Execute
New window will open to check the status of the currently running automation executions.

Conclusion
In this post, we demonstrated how to create an AMI and copy it to another region using AWS Systems Manager auomation document. You might want to check the following guides:


