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.


comments powered by Disqus