Update Suse Linux AMI With AWS System Manager
March 9, 2018
AWS Systems Manager provides a lot of flexibility to the users by providing an unified interface that allows you to automate tasks across all you AWS resources. Automation instructions are written in JSON or YAML format and they are called Documents. AWS provides myriad of documents for Automation and Run Command to perform most of the day-to-day admin requirements for both Linux and Windows.
Even though the SSM agent can be installed on several Linux distributions like Ubuntu, RHEL, CentOS etc, but it looks like one of the most popular AWS managed SSM document AWS-UpdateLinuxAmi
doesn’t work for SUSE Linux Enterprise Server (SLES) 12 platform yet. So, I decided to make few tweaks to the AWS-UpdateLinuxAmi
document which will allow us to AWS-UpdateLinuxAmi like functionalities for SUSE Linux.
The first thing we will need is a Role to allow SSM agent manage our instance. This can be done via AWS web console as well, but just to avoid taking lots of screenshots, I will just provide the CLI commands.
At first, create an assume role policy document to setup the trusted entities, call it assumerole-document.json
,
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"",
"Effect":"Allow",
"Principal":{
"Service":[
"ec2.amazonaws.com",
"ssm.amazonaws.com"
]
},
"Action":"sts:AssumeRole"
}
]
}
Create SSM Managed Instance Role
aws iam create-role --role-name DemoManagedInstanceRole --assume-role-policy-document file://assumerole-document.json
Then attach the AmazonEC2RoleforSSM
managed policy to the role,
aws iam attach-role-policy --role-name DemoManagedInstanceRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
Copy the Role role Arn from the output.
If we were doing this via AWS Console, AWS would automatically suggest the AmazonEC2RoleforSSM
when we selected EC2 Role for Simple Systems Manager.
Create Instance Profile
Create instance profile with the DemoManagedInstanceRole
, so that the SSM agent in our instance has the necessary permission.
aws iam create-instance-profile --instance-profile-name DemoManagedInstanceProfile
aws iam add-role-to-instance-profile --instance-profile-name DemoManagedInstanceProfile --role-name DemoManagedInstanceRole
Create Automation Service Role
Create an instance profile role with the JSON policy document,
aws iam create-role --role-name DemoAutomationServiceRole --assume-role-policy-document file://assumerole-document.json
Then attach the AmazonEC2RoleforSSM
managed policy to the role,
aws iam attach-role-policy --role-name DemoAutomationServiceRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole
Create a Pass Role policy with the DemoManagedInstanceRole
Arn that we copied in the last step, call it passRole.json
.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"iam:PassRole"
],
"Resource": [
"<DemoManagedInstanceRole Arn Goes Here!!!>"
],
"Effect": "Allow"
}
]
}
Attach it to the DemoAutomationServiceRole
automation role,
aws iam put-role-policy --role-name DemoAutomationServiceRole --policy-name passRole --policy-document file://passRole.json
Download The Helper Files
When we execute the AWS provided AWS-UpdateLinuxAmi
automation document, it uses pre-defined user-data to get the SSM agent install file. Then, in the update OS software step of the automation, it uses aws-update-linux-instance
file to update the running instance.
I will provide the updated file, but I am also going to provide the location of the files, so that you can update them as necessary.
User Data
Go to EC2 Dashboard -> SYSTEMS MANAGER SHARED RESOURCES -> Documents . From the table find AWS-UpdateLinuxAmi
document. Select the Content tab below, and copy the value of UserData from the JSON document.
Decode the base64 encoded user-data file and save them in a file called user-data.sh
,
echo IyEvYmluL2Jhc2gNCg0..... | base64 -D > user-data.sh
In the user-data.sh
file, look for the following lines,
readonly SCRIPT_NAME="aws-install-ssm-agent"
SCRIPT_URL="https://aws-ssm-downloads-$REGION.s3.amazonaws.com/scripts/$SCRIPT_NAME"
Here you should change the SCRIPT_URL
pointing to another bucket where you are going to host the SSM installer file. I have also removed the REGION
since I am not going to host the installer file in all the regions for now.
My updated user-data file can be found here. I also got rid of couple of other lines related to REGION
.
SSM Agent Installer
In the user-data script, we found out the location of the aws-install-ssm-agent
script. This script installs the SSM agent on the EC2 instances. With a very simple fix, this file can be used on SUSE Linux to install SSM agent. Basically, we will be adding a function that just checks if it knows the platform enough to fetch the right package.
function is_suse() {
if [ -f "/etc/os-release" ] ||
[ -f "/etc/SuSE-release" ]; then
echo "true"
else
echo "false"
fi
}
Like, if it’s SUSE, don’t use yum
or dpkg
.
Here is what the file looks like after I updated. I added few checks using the is_suse
function above and again, removed some region specific stuffs.
AWS Update Linux Instance Script
Now, we will need to update the aws-update-linux-instance
script. Here we will add a similar is_suse()
function, that we added to the other file. In addition to that, we will need to make sure to use the right commands to update the SUSE operating system.
function zypper_upgrade() {
exec_cmd 'zypper refresh'
zypper_cmd='zypper update -y'
for package in $EXCLUDE_PACKAGES; do
yum_cmd="zypper al $package"
done
exec_cmd "$zypper_cmd"
for package in $EXCLUDE_PACKAGES; do
yum_cmd="zypper rl $package"
done
}
Here is the modified file.
Upload The Files To S3
Upload the aws-install-ssm-agent
and aws-update-linux-instance
files to a bucket and make a note of the bucket name and path. We will use this information in the user-data script. Set appropriate permission for the files.
Modify The UpdateLinuxAmi Document
Finally, we need to modify the AWS-UpdateLinuxAmi
document to actually update the instance and create an image from it. We will call it My-UpdateSuseAmi.json
.
The first think we want to update in the document is the UserData
by replacing it with the one that we modified. To do so, we need to convert the user-data.sh
script back to base64
with the following command,
base64 -i user-data.sh
Then, look for the step that says updateOSSoftware
and change the following line to point to your bucket where the aws-update-linux-instance
is located.
eval $get_contents https://aws-ssm-downloads-{{global:REGION}}.s3.amazonaws.com/scripts/aws-update-linux-instance > /tmp/aws-update-linux-instance
Change the URL to your uploaded aws-update-linux-instance
location.
(Optional) Output To S3 Bucket
Sometimes it’s a good idea to send the command outputs to a S3 buckets, as the long AWS console outputs are often truncated.
Add the following lines in the updateOSSoftware step of the automation document,
"OutputS3BucketName": "demo-ssm-update-outputs",
"OutputS3KeyPrefix": "suse-update-{{global:DATE_TIME}}",
Create SUSE Linux AMIs using SSM Automation
Finally we are ready to create updated SUSE Linux AMIs using SSM automation.
Create Automation Document
aws ssm create-document --content file://My-UpdateSuseAmi.json --name My-UpdateSuseAmi --document-type Automation
Execute Automation
At this point you should have an automation document created. For this demo purpose, it would be better to go to the console and checkout the automation document we just created, so that we can visualize the parameters.
But in case you are feeling too geeky, follow the AWS CLI doc to do it via command line, https://docs.aws.amazon.com/cli/latest/reference/ssm/start-automation-execution.html
To do so, go to EC2 Dashboard -> SYSTEMS MANAGER SHARED RESOURCES -> Documents
If you can’t find the document we just created, set filter to Owned By Me.
To execute an Automation using the document, go to EC2 Dashboard -> SYSTEMS MANAGER SERVICES -> Automations and follow the instructions. Provide the following parameters:
- SourceAmiId: This should be a SUSE image.
- InstanceIamRole: Name of the instance profile that we created above,
DemoManagedInstanceProfile
. - AutomationAssumeRole: The resource name (Arn) of the automation service role that we created.
If everything works, we should see the execution status set to InProgress
.
Feel free to let me know if you have any questions, comments or suggestions.