Parameter sharing across an organisation with AWS RAM and SSM Parameter Store integration.

Tech Community • 10 min read

Introduction

Managing Amazon Machine Image (AMI) IDs within an AWS environment can quickly become a heavy task, especially when dealing with frequently updated images. One of our customers recently faced this challenge, struggling to keep their infrastructure up-to-date with the latest AMI IDs and sharing them organisation wide.

The Challenge

Whether using standard AMIs provided by AWS or custom AMIs designed for specific needs, keeping the infrastructure updated can be challenging. Typically, updating EC2 launch templates with new AMI IDs requires manual intervention, which can be both time consuming and prone to errors.

A Better Solution

However, AWS Systems Manager (SSM) Parameter Store offers a more efficient solution. By storing AMI IDs as parameters in SSM, these IDs can be easily referenced across the infrastructure and accounts without constant manual updates. This is particularly useful for Auto Scaling Groups, where the AMI ID needs to be kept current to maintain the integrity and security of instances.

Centralised Management with AWS RAM

In environments with a centralised architecture, such as those using a Shared Services account and multiple member accounts, AWS Resource Access Manager (RAM) is essential. RAM allows us to securely share SSM Parameters, including AMI IDs, across different AWS accounts within the organisation. This ensures that all member accounts consistently use the same up-to-date AMI IDs, reducing discrepancies and the risk of outdated images being used.

By centralising AMI ID management in the Shared Services account and using RAM to share them with member accounts, we make sure that all accounts use verified and company approved AMIs across the infrastructure. This approach aligns with best practices for managing multi-account environments, offering a scalable solution that improves efficiency and security.

Considerations and Limitations

While this solution offers significant benefits, it’s important to consider some limitations:

  • Regional constraints: SSM Parameters and RAM can only share resources within the same AWS Region. If your infrastructure spans multiple regions, you'll need to replicate SSM Parameters in each region and set up corresponding RAM resource shares. This adds complexity but ensures that AMIs are available where they are needed.
  • Partition differences: AWS operates in several distinct partitions, including Commercial, China, and GovCloud regions. AMIs and SSM Parameters cannot be shared across these partitions, so a separate setup is required for each partition. This is especially important for organisations operating in multiple regulatory environments.
  • AMI sharing across accounts: When sharing AMIs between accounts, especially organisation-wide, it’s essential to remember that AMIs themselves need to be explicitly shared, as SSM Parameter sharing via RAM does not automatically share the underlying AMI. AMI sharing must be done per account and per region.

Cost and Well-Architected Considerations

While this serverless solution leveraging AWS-managed services like SSM and RAM minimises operational overhead, there are still some cost considerations:

  • Cost impact: The cost associated with SSM Parameter Store is generally negligible, as charges are based on the number of “advanced parameters” and API interactions. However, frequent updates to AMIs (and thus parameters) could increase API call charges, though this would still likely be minimal.
  • Well-Architected Framework: This solution aligns well with the AWS Well-Architected Framework. By using managed services, the reliability, scalability, and security aspects are largely handled by AWS. However, it's crucial to ensure that IAM permissions are correctly configured to avoid unauthorised access to shared parameters and AMIs. Additionally, monitoring and logging via AWS CloudTrail and Amazon CloudWatch should be implemented to maintain visibility into operations.

What to expect from this blog post

I will explain how to use AWS SSM Parameter Store and AWS RAM to manage AMI IDs effectively. We’ll cover how to distribute and dynamically build these parameters and reference custom AMIs, ensuring that the infrastructure remains robust and adaptable to changes.

Note: The creation of the AMIs themselves is out of scope for this post. We assume that we have AMIs already created (i.e. by AWS EC2 Image Builder or third- party tool), available and properly named in an automated fashion. Also, this post will not address the complexities associated with cross-region or cross-partition sharing of AMIs, but these are important considerations to keep in mind.

Architecture

Parameter sharing with AWS RAM

Step 1: Create SSM parameters and related RAM resources

To enable our Lambda function to update SSM Parameters in case a new AMI gets created, we first need to create these parameters and the related RAM resources within the Shared Services Account. This can be done via the AWS console or by using Infrastructure as Code (IaC).

SSM parameter

Creating an AWS SSM parameter via the console

  1. Open the AWS console and go to https://console.aws.amazon.com/systems-manager/.
  2. In the navigation pane, choose Parameter Store, and then choose Create parameter.
  3. Enter a Name according to your defined naming convention and an optional Description for your SSM Parameter.
  4. Choose Advanced as Tier.
  5. Type should be String.
  6. Under Data type, choose aws:ec2:image.
  7. Put the AMI ID (i.e. ami-123example456) in the Value field.
  8. Add Tags if necessary and create the parameter.
  9. Change to tab History, choose the current Version and Manage labels.
  10. In our case we set label to ‘latest’.

Creating an AWS SSM parameter using Terraform

In case you prefer the above steps as Terraform configuration. Please adjust where necessary:
ssm-parameter.tf

RAM resources

Creating RAM resources via the console

Each AMI ID SSM Parameter is associated with this resource share, ensuring they are available across the organisation. The RAM resource share is linked to the AWS Organizations principal, providing access to all accounts within the organisation.

  1. Open the AWS Console and go to https://console.aws.amazon.com/ram/home.
  2. In the navigation pane, choose Resource shares and then Create resource share.
  3. Enter a Name for your resource share. Use a name that reflects its purpose, such as "SSM Parameters for AMI ID".
  4. Choose the resources to share. In this case, select SSM Parameters from the list of available resource types.
  5. Select the parameters you wish to share and click on Next.
  6. Choose the managed permission to use for ssm:Parameter or create a new customer-managed permission.
  7. Specify the principals with whom to share the resources. You can select accounts or organisations, depending on your requirements.
  8. Review the details of your resource share. Ensure that the resource types, parameters, and principals are correctly configured.
  9. Create the resource share by clicking Create resource share.

Creating RAM resources using Terraform

ram.tf

resource "aws_ram_resource_share" "ram" {
  name = "SSM Parameters for AMI ID"
  allow_external_principals = false
  tags        = var.tags

  depends_on = [aws_ssm_parameter.ami-id]
}

resource "aws_ram_resource_association" "ram" {
  count = length(aws_ssm_parameter.ami-id)
  resource_arn       = "arn:aws:ssm:${var.region}:${var.account}:parameter${aws_ssm_parameter.ami-id[count.index].name}"
  resource_share_arn = aws_ram_resource_share.ram.arn
}

resource "aws_ram_principal_association" "ram" {
  principal          = data.aws_organizations_organization.org.arn
  resource_share_arn = aws_ram_resource_share.ram.arn
}

data "aws_organizations_organization" "org" {}

Step 2: SSM parameter gets updated by Lambda

After the SSM Parameter is created, whenever a new AMI is generated, an Amazon EventBridge rule in the Shared Service Account captures the relevant event. Specifically, this rule listens for the CreateImage API call made by ec2.amazonaws.com through CloudTrail:

{
    "source": ["aws.ec2"],
    "detail-type": ["AWS API Call via CloudTrail"],
    "detail": {
        "eventSource": ["ec2.amazonaws.com"],
        "eventName": ["CreateImage"]
    }
}

When the event occurs, it triggers a Lambda function designed to update the SSM Parameter by re-labeling it to reflect the latest version:

try:
    # Get latest version
    response = ssm_client.get_parameter(Name=param_name,)
    param_latest_version = response['Parameter']['Version']
    
    # Set label to latest version
    response = ssm_client.label_parameter_version(
      Name=param_name,
      ParameterVersion=param_latest_version,
      Labels=[
          'latest',
      ]
    )
    logger.info(f"Latest SSM Parameter v{param_latest_version} has been labelled.")
  except Exception as e:
    logger.error(f"Error labeling SSM Parameter {param_name} v{param_latest_version}...!")
    raise(e)
    
  return {
    'statusCode': 200,
    'body': json.dumps('Lambda function finished successfully')
  }

This part of the function ensures that the SSM Parameter version is always automatically labelled as the latest version whenever a new AMI is created.

Caution: The above lambda function is a code snippet and only for illustration purposes.

Step 3: Configure EC2 or Launch Templates

For EC2 Instances

Currently, the AWS Console does not offer an option to specify a Systems Manager (SSM) Parameter directly when launching an EC2 instance, unlike the “Launch Template” UI, which provides a “Specify custom value/Systems Manager parameter” option. We've submitted a feature request to AWS to address this limitation.

Parameter sharing with AWS RAM

As a workaround, you can create an EC2 instance using the AWS CLI. Below is an example command:

aws ec2 run-instances \
    --image-id "resolve:ssm:arn:aws:ssm:<AWS_REGION>:<AWS_ACCOUNT>:parameter/<CUSTOM-PARAM-NAME>:latest" \
    --instance-type "t2.small" \
    --subnet-id "<SUBNET-ID>" \
    --security-group-ids "<SECURITYGROUP-ID>" \
    --iam-instance-profile "Arn=<INSTANCE-PROFILE-ARN>"

In the example above, the image-id attribute references the ARN of the SSM Parameter, allowing us to dynamically resolve the AMI ID at runtime using the latest version of the specified parameter.

For Launch Templates

Steps to create a new launch template using the AMI parameter

  1. Open the Amazon EC2 console at https://console.aws.amazon.com/ec2/.
  2. In the navigation pane, choose Launch Templates, and then choose Create launch template.
  3. For Launch template name enter a name according to your defined naming convention and an optional Description.
  4. Under Application and OS Images (Amazon Machine Image), choose Browse more AMIs.
  5. Choose the arrow button to the right of the search bar, and then choose Specify custom value/Systems Manager parameter.
Parameter sharing with AWS RAM

6. In the Specify custom value or Systems Manager parameter dialog box, enter the parameter name as follow:

a) To reference the latest parameter from shared-tooling account it needs to be in the format:

  • resolve:ssm:parameter-ARN:label
  • Example: resolve:ssm:arn:aws:ssm:<AWS_REGION>:<AWS_ACCOUNT>:parameter/<CUSTOM-PARAM-NAME>:latest

b) To reference a particular version of the parameter, in case of i.e. rollback, it needs to be in the format:

  • resolve:ssm:parameter-ARN:version-number
  • Example: resolve:ssm:arn:aws:ssm:<AWS_REGION>:<AWS_ACCOUNT>:parameter/<CUSTOM-PARAM-NAME>:

7. Choose Save.
8. Configure any other launch template settings as needed, and then choose Create launch template

Note: Make sure that your EC2 instance profile role has the proper permission to read the parameters.

Example:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "GetAmiSSMParameter",
            "Effect": "Allow",
            "Action": [
              "ssm:DescribeParameters",
              "ssm:GetParameter",
              "ssm:GetParameters",
              "ssm:GetParameterHistory"
            ],
            "Resource": [
                "arn:aws:ssm:<AWS_REGION>:<SHARED_SERVICE_ACCOUNT_ID>:parameter/<CUSTOM-PARAM-NAME>"
            ]
        }
    ]
}

Integrating AMI Parameters with Launch Templates

To use the AMI parameter with an existing launch template, navigate to the Amazon EC2 console and select your launch template. Modify the template by creating a new version and applying the AMI parameter as described earlier.

Conclusion

Using AWS Systems Manager and RAM for Better AMI Management

Managing AMI IDs can be tough, especially with frequent updates. Instead of using shared AMIs directly, using SSM Parameter Store and RAM can make things easier. By storing AMI IDs in SSM and sharing them securely with RAM, you make sure that all accounts use the same, updated AMIs without constant manual work.

In the end, using SSM Parameters with RAM makes your AMI management smoother, safer, and more efficient. While there are some regional and partition-related limitations, this solution fits well with best practices for managing multiple AWS accounts and keeping your AWS environment in good shape.

Reference

For additional information, please also refer to other related pages or the AWS documentation:

Get in Touch.

Let’s discuss how we can help with your cloud journey. Our experts are standing by to talk about your migration, modernisation, development and skills challenges.

Ilja Summala
Ilja’s passion and tech knowledge help customers transform how they manage infrastructure and develop apps in cloud.
Ilja Summala LinkedIn
Group CTO