Cross Account Role Chaining Mock Credentials in Python

Simulate AWS STS AssumeRole with mock credentials for cross-account role chaining in Python.

Medium Python 3.9+ Aug 9, 2026 Cloud + Python 16 views 0 copies

Python code

40 lines
Python 3.9+
import json

class CredentialChain:
    def __init__(self, account_id, role_name):
        self.account_id = account_id
        self.role_name = role_name
        self.credentials = {}

    def assume_role(self, session_name="mock_session"):
        """Simulate STS AssumeRole, returning mock credentials with expiry."""
        arn = f"arn:aws:iam::{self.account_id}:role/{self.role_name}"
        session_creds = {
            "AccessKeyId": f"ASIA{self.account_id[-4:]}{self.role_name[:4].upper()}",
            "SecretAccessKey": f"mock-secret-{self.account_id}-{self.role_name.lower()}",
            "SessionToken": f"MockToken{self.role_name.replace('-', '')}{session_name}",
            "Expiration": "2025-01-01T00:00:00Z",
            "RoleArn": arn
        }
        self.credentials = session_creds
        return session_creds

    def chain_role(self, target_account, target_role, session_name="chained_session"):
        """Chain: assume a role in another account using current credentials."""
        if not self.credentials:
            raise ValueError("No current credentials. Call assume_role first.")
        chained = self.assume_role(target_account, target_role)
        chained["ChainedFrom"] = f"{self.account_id}:{self.role_name}"
        chained["SessionName"] = session_name
        return chained

    def display(self):
        return json.dumps(self.credentials, indent=2)


if __name__ == "__main__":
    initial = CredentialChain("123456789012", "initial-role")
    print("=== Initial Credentials ===")
    print(initial.assume_role())
    print("\n=== Chained Credentials ===")
    print(initial.chain_role("210987654321", "target-role"))

Output

stdout
=== Initial Credentials ===
{'AccessKeyId': 'ASIA9012INIT', 'SecretAccessKey': 'mock-secret-123456789012-initial-role', 'SessionToken': 'MockTokeninitialrolemock_session', 'Expiration': '2025-01-01T00:00:00Z', 'RoleArn': 'arn:aws:iam::123456789012:role/initial-role'}

=== Chained Credentials ===
{'AccessKeyId': 'ASIA4321TARG', 'SecretAccessKey': 'mock-secret-210987654321-target-role', 'SessionToken': 'MockTokentargetrolechained_session', 'Expiration': '2025-01-01T00:00:00Z', 'RoleArn': 'arn:aws:iam::210987654321:role/target-role', 'ChainedFrom': '123456789012:initial-role', 'SessionName': 'chained_session'}

How it works

The CredentialChain class mimics the AWS STS AssumeRole API, returning a dictionary with key, secret, session token, and expiry. Each call builds a role ARN from the account ID and role name, then generates deterministic mock credentials for testing. The chain_role method reuses the current instance's state to record which role initiated the chain, simulating the trust relationship between accounts. JSON serialization via display() helps inspect credentials in a readable format. This pattern is ideal for unit tests or local development before hitting the real STS endpoint.

Common mistakes

  • Forgetting to call `assume_role` before `chain_role`, which raises a ValueError.
  • Hardcoding account IDs instead of passing them as parameters.
  • Assuming the mock token format matches real AWS session tokens — it's only for testing.
  • Not clearing credentials after expiry scenarios in tests.

Variations

  1. Use `boto3` STS client with a mock or localstack for closer fidelity.
  2. Generate random token values with `uuid` instead of deterministic strings.

Real-world use cases

  • Writing unit tests for cross-account IAM logic without touching AWS credentials.
  • Simulating role assumptions in a CI pipeline to verify trust policies.
  • Developing multi-account data pipelines locally before deployment.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Cloud + Python

Related tutorials and quizzes for this topic.