Skip to content
Linuxbeast
Subscribe
  • Home
  • Today in Tech
  • Who is Hiring?
  • About Me
  • Work With Me
  • Lab
    • DevOps Onboarding
    • Tag Network
    • Tools
      • VPC Subnet Planner
  • Contact
Subscribe
Home › AWS › How to Access AWS Secrets Manager from Another Account
AWS

How to Access AWS Secrets Manager from Another Account

Sometimes you need a Lambda function or EC2 instance in one AWS account to read a secret stored in a different account. This is…

Linuxbeast Developer Aug 16, 2024 6 min read 678 views
How to Access AWS Secrets Manager from Another Account
Share:
In This Article
How It Works› Prerequisites› Step 1: Create the Cross-Account Role in Account A› Step 2: Update the KMS Key Policy (If Using a Custom Key)›

How to Access AWS Secrets Manager from Another Account

March 9, 2026August 16, 2024 by Linuxbeast Developer
6 min read
678 views

Sometimes you need a Lambda function or EC2 instance in one AWS account to read a secret stored in a different account. This is a common setup in multi-account environments — you might keep shared credentials (database passwords, API keys) in a central account and have workloads in other accounts pull them as needed.

This guide covers how to set up cross-account access to AWS Secrets Manager using the AssumeRole pattern. We’ll configure both accounts, handle KMS encryption, and test it with Python and the AWS CLI.

Advertisement

How It Works

Two accounts are involved:

  • Account A (111111111111) — owns the secret in Secrets Manager
  • Account B (222222222222) — has the EC2 instance or Lambda that needs the secret

The recommended approach is the AssumeRole pattern: create an IAM role in Account A that Account B can assume. The flow goes like this:

  1. Account B’s Lambda/EC2 calls sts:AssumeRole to assume a role in Account A
  2. STS returns temporary credentials scoped to Account A
  3. Using those credentials, the code calls secretsmanager:GetSecretValue in Account A
  4. The secret is returned

You could also do this with just a resource-based policy on the secret (no role assumption), but the AssumeRole approach gives you better audit trails in CloudTrail and finer-grained control. If you’re new to AssumeRole, check out How to Set Up Cross-Account Access in AWS with AssumeRole for the fundamentals.

Advertisement

Prerequisites

  • Two AWS accounts with admin or IAM management access
  • A secret already created in Account A’s Secrets Manager
  • AWS CLI configured — see How to Install AWS CLI v2 on Ubuntu 22.04 if needed

Step 1: Create the Cross-Account Role in Account A

In Account A, create an IAM role that Account B is allowed to assume. This role will have permissions to read the secret.

Trust Policy (Who Can Assume This Role)

This trust policy allows a specific role in Account B to assume the role. Replace the account ID and role name with your own:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::222222222222:role/AccountB-LambdaRole"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:PrincipalOrgID": "o-your-org-id"
        }
      }
    }
  ]
}

The aws:PrincipalOrgID condition is optional but recommended if both accounts are in the same AWS Organization. It prevents any account outside your org from assuming the role, even if the account ID somehow gets into the trust policy by mistake.

Permissions Policy (What the Role Can Do)

Attach this inline or managed policy to the role. It grants permission to read a specific secret:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "arn:aws:secretsmanager:ap-southeast-1:111111111111:secret:my-shared-secret-*"
    }
  ]
}

Note the -* at the end of the secret ARN — Secrets Manager appends a random suffix to secret ARNs, so you need the wildcard to match it. You can find the full ARN in the Secrets Manager console.

Step 2: Update the KMS Key Policy (If Using a Custom Key)

If your secret is encrypted with the default aws/secretsmanager key, you can skip this step — AWS-managed keys handle cross-account access automatically when using the AssumeRole pattern (since you’re operating as a role within Account A).

But if you’re using a customer-managed KMS key (CMK) to encrypt the secret, you need to update the key policy to allow the cross-account role to decrypt:

{
  "Sid": "AllowCrossAccountDecrypt",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::111111111111:role/CrossAccountSecretsRole"
  },
  "Action": [
    "kms:Decrypt",
    "kms:DescribeKey"
  ],
  "Resource": "*"
}

Add this as a statement to your existing KMS key policy in Account A. The Resource: "*" here is fine because this policy is attached to the key itself — it’s saying “allow this role to use this key,” not “allow access to all keys.”

Step 3: Configure the Role in Account B

The EC2 instance or Lambda function in Account B needs an IAM role with permission to assume the cross-account role in Account A.

Attach this policy to the Account B role (the one assigned to your Lambda or EC2 instance profile):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::111111111111:role/CrossAccountSecretsRole"
    }
  ]
}

This is the only permission Account B needs. The actual Secrets Manager access comes from the assumed role in Account A.

Step 4: Retrieve the Secret with Python

Here’s a Python function that assumes the cross-account role and retrieves the secret. This works the same in Lambda, on EC2, or locally with configured credentials:

import boto3
import json
import os

def get_cross_account_secret():
    role_arn = os.environ["ROLE_ARN"]
    secret_name = os.environ["SECRET_NAME"]
    region = os.environ.get("AWS_REGION", "ap-southeast-1")

    # Step 1: Assume the cross-account role
    sts_client = boto3.client("sts")
    assumed = sts_client.assume_role(
        RoleArn=role_arn,
        RoleSessionName="cross-account-secrets"
    )
    credentials = assumed["Credentials"]

    # Step 2: Create a Secrets Manager client using the assumed credentials
    sm_client = boto3.client(
        "secretsmanager",
        region_name=region,
        aws_access_key_id=credentials["AccessKeyId"],
        aws_secret_access_key=credentials["SecretAccessKey"],
        aws_session_token=credentials["SessionToken"],
    )

    # Step 3: Get the secret
    response = sm_client.get_secret_value(SecretId=secret_name)
    secret = json.loads(response["SecretString"])

    return secret


if __name__ == "__main__":
    secret = get_cross_account_secret()
    print("Secret keys:", list(secret.keys()))

Set the environment variables before running:

export ROLE_ARN="arn:aws:iam::111111111111:role/CrossAccountSecretsRole"
export SECRET_NAME="my-shared-secret"
python3 get_secret.py

The script prints the secret’s keys (not the values) to verify it works without exposing anything in logs. In production, you’d obviously use the values directly in your application instead of printing them.

Testing with the AWS CLI

You can also test this flow from the CLI without writing any code. First, assume the role:

aws sts assume-role \
  --role-arn "arn:aws:iam::111111111111:role/CrossAccountSecretsRole" \
  --role-session-name "test-session"

This returns temporary credentials. Export them:

export AWS_ACCESS_KEY_ID="returned-access-key"
export AWS_SECRET_ACCESS_KEY="returned-secret-key"
export AWS_SESSION_TOKEN="returned-session-token"

Now fetch the secret:

aws secretsmanager get-secret-value \
  --secret-id "my-shared-secret" \
  --region ap-southeast-1

If you get the secret back, your cross-account setup is working. Don’t forget to unset the environment variables after testing so you switch back to your default credentials:

unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

Troubleshooting

AccessDeniedException on AssumeRole

Check two things: the trust policy on the Account A role must list Account B’s role ARN as a principal, and Account B’s role must have sts:AssumeRole permission targeting the Account A role ARN. Both sides need to agree.

AccessDeniedException on GetSecretValue

The assumed role probably doesn’t have secretsmanager:GetSecretValue permission, or the secret ARN in the policy doesn’t match. Double-check the wildcard suffix (-*) on the ARN.

KMS Decrypt Error

If you see AccessDeniedException mentioning KMS, the secret uses a customer-managed key and the key policy is missing the decrypt permissions. Go back to Step 2 and add the KMS policy statement.

Summary of What Goes Where

Component Account What It Does
Cross-account IAM role A Allows Account B to assume it; has permission to read the secret
KMS key policy update A Allows the cross-account role to decrypt (only if using CMK)
Lambda/EC2 role policy B Allows sts:AssumeRole targeting the Account A role
Application code B Assumes role, then calls GetSecretValue with temporary credentials

Conclusion

Cross-account Secrets Manager access comes down to three pieces: a role in Account A that Account B can assume, the right permissions on that role, and KMS key access if you’re using a customer-managed key. Once it’s set up, the actual code is a handful of boto3 calls.

If you’re working on more cross-account patterns, How to Copy S3 Bucket Objects Across AWS Accounts uses a similar AssumeRole setup for S3. And if you need to send emails cross-account, check out How to Send Email Using AWS SES with Cross-Account Secrets Manager — it builds directly on what we covered here.

Advertisement

On This Page
How It Works Prerequisites Step 1: Create the Cross-Account Role in Account A Trust Policy (Who Can Assume This Role) Permissions Policy (What the Role Can Do) Step 2: Update the KMS Key Policy (If Using a Custom Key) Step 3: Configure the Role in Account B Step 4: Retrieve the Secret with Python Testing with the AWS CLI Troubleshooting AccessDeniedException on AssumeRole AccessDeniedException on GetSecretValue KMS Decrypt Error Summary of What Goes Where Conclusion

Key Takeaways

  • Two AWS accounts with admin or IAM management access
  • A secret already created in Account A's Secrets Manager
  • AWS CLI configured — see How to Install AWS CLI v2 on Ubuntu 22.04 if needed

Tags

AssumeRole AWS Cross-Account IAM KMS Python Secrets Manager

Level Up Your DevOps Skills

Practical guides, tutorials, and real-world best practices delivered weekly.

No spam, ever. Unsubscribe anytime.

Popular Articles

How to Mount S3 Bucket on Ubuntu with s3fs-fuse How to Mount S3 Bucket on Ubuntu 22.04 with S3FS Fuse 9.9K views How to Fix WSL CreateVm/HCS/ERROR_FILE_NOT_FOUND on Windows How to Fix WSL CreateVm/HCS/ERROR_FILE_NOT_FOUND on Windows 5.9K views How to Install and Configure Claude Code CLI on Windows PowerShell How to Install and Configure Claude Code CLI on Windows PowerShell 5.4K views How to Install Ubuntu in WSL 2 on Windows 10 and 11 How to Install Ubuntu in WSL 2 on Windows 10 and Windows 11 5.2K views How to Configure MCP Servers in VS Code, Claude Desktop, and Claude Code on WSL How to Configure MCP Servers in VS Code, Claude Desktop, and Claude Code on WSL 4.4K views
Advertisement
How to Use SQL Joins and Conditional Statements in PostgreSQL← PreviousHow to Use SQL Joins and Conditional Statements in PostgreSQLNext →How to Connect AWS Lambda to Microsoft SQL Server Using PyODBCHow to Connect AWS Lambda to Microsoft SQL Server Using PyODBC

Related Articles

How to Mount S3 Bucket on Ubuntu with s3fs-fuse
AWS

How to Mount S3 Bucket on Ubuntu 22.04 with S3FS Fuse

9.9K views  •  Apr 13, 2024
How to Install WordPress on EC2 Ubuntu 22.04
AWS

How to Install WordPress on EC2 Ubuntu 22.04 (Complete Linux Guide)

2.2K views  •  Apr 6, 2024
How to Avoid AWS Lambda Timeout When Processing HubSpot Records
AWS

How to Avoid AWS Lambda Timeout When Processing HubSpot Records

216 views  •  Aug 4, 2025
linuxbeast-logo

Built for DevOps, Cloud & Automation.

Popular Topics

  • AWS
  • WSL & Windows
  • Git
  • DevOps
  • Developer Tools
  • Programming

Resources

  • Home
  • Today in Tech
  • Who is Hiring?
  • About Me
  • Work With Me
  • Contact

Legal

  • Privacy Policy
  • Cookie Policy

Stay updated with LinuxBeast

Get the best Linux, DevOps, and Cloud content delivered to your inbox.

No spam, ever. Unsubscribe anytime.

© 2026 LinuxBeast. All rights reserved. Made with ♥ for the DevOps community.
© 2026 Linuxbeast · All rights reserved.
Manage Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
View preferences
  • {title}
  • {title}
  • {title}
Esc to closeCtrl+K to open