DEV Community

Cover image for Cross-Account Parameter Sharing in AWS with RAM using Terraform: A Practical Guide
Olumuyiwa Kolayemi for AWS Community Builders

Posted on • Edited on

7

Cross-Account Parameter Sharing in AWS with RAM using Terraform: A Practical Guide

Introduction

Many organizations maintain common system configuration parameters that are stored centrally and shared across different cloud environments. For instance, an organization's security team might be tasked with creating a golden AMI that is compliant and certified for use across their AWS environments and accounts. While AMI IDs themselves are not inherently sensitive, they can become a concern in specific contexts—such as when they point to proprietary, internal, or specially configured images that reveal details about the organization's infrastructure. Managing multiple AWS accounts often involves securely sharing such sensitive configuration data—like AMI IDs in these contexts, along with API keys, database credentials, or application secrets—across accounts. If exposed, these configurations could compromise security or critical infrastructure. The key players for this implementation are SSM Parameter Store and RAM.

AWS Resource Access Manager (RAM) allows for the secure sharing of AWS resources, such as subnets, transit gateways, and Systems Manager (SSM) parameters, across accounts in your organization or with specific AWS accounts. By enabling centralized access to shared resources, RAM reduces duplication and improves efficiency in multi-account setups. When integrated with SSM, RAM facilitates the secure sharing of advanced parameters, making it easier to manage sensitive configuration data across accounts while maintaining security and scalability.

AWS Systems Manager (SSM) Parameter Store is a secure and scalable solution for managing configuration data and secrets. One of its standout features is the ability to organize parameters using a hierarchical naming structure (e.g., /prod/app1/db-password), which makes it easier to logically group and retrieve related configurations. This structured approach simplifies parameter management across multiple environments and applications. Moreover, SSM Parameter Store supports cross-account sharing of parameters, enhancing collaboration in multi-account setups. Something to keep in mind for this use case is that the SSM parameter being shared must meet a few key requirements. Specifically, it must be an Advanced Tier SSM parameter and must be encrypted with a customer-managed key if you are sharing secured strings.

If you are very familiar with AWS, I know you must be thinking that yes, you can use AWS Secrets Manager for this. To clarify your options, here’s a comparison of SSM Parameter Store (Advanced Tier) and AWS Secrets Manager, two services that can handle configuration data effectively in AWS:

Comparison between SSM Parameter Store (Advanced Tier) & Secrets Manager
Fig 1: Comparison between SSM Parameter Store (Advanced Tier) & Secrets Manager

With this comparison and requirements in mind, you can better understand which service aligns with your use case as we dive into implementing a solution for securely sharing AWS Systems Manager parameters.

Architecture Overview

Cross-Account Parameter Sharing Architecture
Fig 2: Cross-Account Parameter Sharing Architecture

The solution involves two AWS accounts:

  1. Security Account: Acts as the source of truth for sensitive parameters. It stores and shares parameters securely using AWS SSM Parameter Store and AWS RAM.
  2. Development Account: Consumes the shared parameters to deploy resources, such as EC2 instances, using Terraform.

Key AWS Services Used:

  • AWS Systems Manager Parameter Store: For storing and managing parameters.
  • AWS Resource Access Manager (RAM): For securely sharing resources across accounts.
  • AWS Key Management Service (KMS): For encrypting sensitive parameters.
  • AWS EC2: For deploying resources that consume shared parameters.

Prerequisite set up:

For my developer environment set up, I use VSCode with AWS CLI that is configured with an Admin User profile in the AWS Security account. I created two separate folders - security_account and dev_account to have separate terraform states for resources deployed to these different environments/accounts. See folder structure below.

Implementation Folder Structure
Fig 3: Implementation Folder Structure

Provider configuration of the security account:

This file ensures that Terraform is properly authenticated and authorized to create and manage resources in the security account.
Key details to note;

  • Profile: Indicates the AWS CLI profile to use for authentication. In this case, the profile Muyi-Admin is used, which corresponds to an IAM user with administrative privileges in the security account.

Terraform User for Security Account Deployments
Fig 4: Terraform User for Security Account Deployments

Provider configuration of the dev account:

For the dev account, I used the AssumeRole method of authentication for terraform deployments.

In this setup, the Development Account does not have direct access to resources (e.g., SSM parameters) in the Security Account. To securely retrieve these resources, the Development Account assumes an IAM role in the Security Account that has the necessary permissions. This is achieved using the assume_role block in the AWS provider configuration. See image below.

# AWS Provider configuration for dev account
provider "aws" {
  region = "us-west-2"
  assume_role {
    role_arn     = "arn:aws:iam::${dev_account_id}:role/TerraformAssumeRole"
    session_name = "dev-muykol"
  }
}
Enter fullscreen mode Exit fullscreen mode

AWS generates temporary security credentials (access key, secret key, and session token) for the assumed role, which Terraform uses to interact with resources in the Security Account. The Development Account does not need long-term credentials for the Security Account. Instead, it uses temporary credentials generated by the assumed role. See figure 6 below for details.

STS Test Session for the Terraform AssumedRole
Fig 6: STS Test Session for the Terraform AssumedRole

Now that we have our developer environment set up, let’s get to the implementation proper.

Part A: Configure the Security Account

  1. Set up a KMS Key:
    • A KMS key is created in the security account to encrypt sensitive parameters stored in the SSM Parameter Store. This ensures that the parameters are protected at rest.
    • Key rotation is enabled to enhance security by periodically updating the encryption key.
    • The KMS key is configured to allow access only to authorized users and services, ensuring that only the intended accounts and roles can decrypt the parameters.
resource "aws_kms_key" "shared_params_key" {
  description             = "KMS key for shared parameters"
  deletion_window_in_days = 30
  enable_key_rotation     = true
  multi_region            = true
}

resource "aws_kms_alias" "shared_params_alias" {
  name          = "alias/${var.key_alias}"
  target_key_id = aws_kms_key.shared_params_key.key_id
}

resource "aws_kms_key_policy" "shared_params_key_policy" {
  key_id     = aws_kms_key.shared_params_key.key_id
  policy     = data.aws_iam_policy_document.shared_params_key_policy.json
  depends_on = [aws_kms_key.shared_params_key]
}
Enter fullscreen mode Exit fullscreen mode

Terraform Plan for KMS Deployment
Fig 7: Terraform Plan for KMS Deployment

  1. Create SSM Parameters:
    • Parameters are stored in the SSM Parameter Store using the SecureString type, which ensures that the values are encrypted.
    • The KMS key created earlier is associated with the parameters to provide encryption.
    • Parameters are named using a consistent naming convention (e.g., /golden-ami/latest) to make them easily identifiable and manageable.
resource "random_string" "random_params" {
  length  = 8
  special = false
}

# Create SSM Parameter for AMI ID
resource "aws_ssm_parameter" "golden_ami" {
  name       = "/golden-ami/latest"
  tier       = "Advanced"
  type       = "SecureString"
  value      = "REPLACEPLEASE-${random_string.random_params.result}"
  key_id     = aws_kms_key.shared_params_key.key_id
  depends_on = [aws_kms_key.shared_params_key]

  lifecycle {
    ignore_changes = [value]
  }

  tags = {
    Environment = "shared"
    Purpose     = "Golden AMI Reference"
  }
}
Enter fullscreen mode Exit fullscreen mode

Shared Parameter Deployed
Fig 8: Shared Parameter Deployed

  1. Set Up RAM Resource Sharing:
    • AWS Resource Access Manager (RAM) is used to share the SSM parameters with the development account.
    • A RAM resource share is created, and the SSM parameter is added as a shared resource.
    • The development account is specified as the principal in the resource share, granting it access to the shared parameter.
    • This setup ensures that the parameter is securely shared without duplicating it in the development account.
# Create RAM Resource Share
resource "aws_ram_resource_share" "ssm_share" {
  name                      = "golden-ami-parameter-share"
  allow_external_principals = true

  tags = {
    Environment = "shared"
  }
}

# Associate SSM Parameter with RAM Share
resource "aws_ram_resource_association" "ssm_association" {
  resource_arn       = aws_ssm_parameter.golden_ami.arn
  resource_share_arn = aws_ram_resource_share.ssm_share.arn
}

# Share with Dev Account
resource "aws_ram_principal_association" "dev_shared_params" {
  principal          = var.dev_account_id
  resource_share_arn = aws_ram_resource_share.ssm_share.arn
}
Enter fullscreen mode Exit fullscreen mode

Resource Shares Deployed
Fig 9: Resource Shares Deployed

Part B: Configure the Development Account

  1. Access the Shared Parameter:
    • Terraform AssumedRole was used to retrieve the shared parameter value dynamically using its ARN, ensuring that the latest version of the parameter is always used and necessary IAM permissions were granted to access the shared parameter through the RAM resource share.

Shared Parameter Policy
Fig 10: Shared Parameter Policy

Dev Account Trust Policy Updated
Fig 11: Dev Account Trust Policy Updated

  1. Validate the Shared Parameter in AWS RAM on Dev Account: In the Shared with me Resource shares on Dev Account, you should be able to see the resource share arn that is pointing to the /golden-ami/latest parameter stored in the RAM on Security Account.

Successful Resource Shares
Fig 12: Resource share Validation on Dev Account

  1. Deploy Resources Using Shared Parameters: To test the retrieved parameter value, I updated the golden-ami value to one of the available AMI-ID in the US-West-2 region for demo purpose. This will correspond to the AMI-ID of the golden-image baked by the Security team in an enterprise setup. The retrieved parameter value was used by Terraform to deploy EC2 instances on Dev Account.
# Retrieve the shared SSM parameter
data "aws_ssm_parameter" "shared_ami" {
  name = "arn:aws:ssm:us-west-2:${local.security_account_id}:parameter/golden-ami/latest"
}
Enter fullscreen mode Exit fullscreen mode
locals {
  security_account_id = "724604039557"
}
# Create EC2 instance using the shared AMI ID
resource "aws_instance" "web_instance" {
  ami           = data.aws_ssm_parameter.shared_ami.value
  instance_type = "t2.micro"

  tags = {
    Name        = "Fikol Instance"
    Environment = "dev"
  }
}
Enter fullscreen mode Exit fullscreen mode

Shared Parameter Updated
Fig 13: Shared Parameter Updated

Successful EC2 Instance Launched
Fig 14: Successful EC2 Instance Launched

Benefits of This Approach

  1. Security: Parameters are encrypted and securely shared using AWS RAM.
  2. Scalability: Easily extend the solution to share parameters with additional accounts or regions.
  3. Centralized Management: Simplifies parameter management by consolidating it in a single account.
  4. Automation: Terraform ensures consistent and repeatable deployments across accounts.
  5. Cost Efficiency: Reduces duplication of resources by sharing parameters instead of recreating them in each account.

Possible Improvement for this implementation;

  • Configure OIDC role and deploy using GitHub Action (deploy using an OIDC secured CICD Pipeline)

Conclusion

This implementation demonstrates a secure and scalable way to share sensitive configuration data across AWS accounts using Terraform. By leveraging AWS SSM Parameter Store, RAM, and KMS, you can centralize parameter management while maintaining strict security controls.

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (0)

Best Practices for Running  Container WordPress on AWS (ECS, EFS, RDS, ELB) using CDK cover image

Best Practices for Running Container WordPress on AWS (ECS, EFS, RDS, ELB) using CDK

This post discusses the process of migrating a growing WordPress eShop business to AWS using AWS CDK for an easily scalable, high availability architecture. The detailed structure encompasses several pillars: Compute, Storage, Database, Cache, CDN, DNS, Security, and Backup.

Read full post

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay