Table of Contents
- 1 Introduction: Mastering Ansible Cross-Account Role Assumption
- 2 The War Story: The Danger of Hardcoded Credentials
- 3 Core Architecture: Deconstructing the Cross-Account Flow
- 4 Step-by-Step Implementation: Automating Role Assumption in Ansible
- 5 Advanced Scenarios and Real-World Use Cases
- 6 Troubleshooting: Common Cross-Account Pitfalls
- 7 Frequently Asked Questions
- 8 Conclusion
Introduction: Mastering Ansible Cross-Account Role Assumption
Managing identity and access across multiple AWS environments is perhaps the most complex challenge in modern DevOps. When you need to perform tasks—like deploying infrastructure or managing secrets-in a target AWS account without having permanent administrative credentials, you must leverage Ansible Cross-Account Role Assumption. This technique allows an executing identity (your machine or CI/CD runner) to temporarily assume a designated role in a separate, protected AWS account. This capability is foundational to building scalable, secure, and multi-tenant cloud architectures.
Automating AWS cross-account role assumption in Ansible requires utilizing the AWS Security Token Service (STS) via the aws sts assume-role command. The secure, production-grade method involves retrieving source credentials from a secrets manager like Vault and passing the resulting temporary session tokens to the Ansible playbook for subsequent module execution.
The War Story: The Danger of Hardcoded Credentials
I recall a project early in my career where the team, under immense pressure, opted for the simplest solution: hardcoding AWS access keys into the Ansible inventory file. The result was predictable and catastrophic. These credentials, which had maximum permissions, were committed to a Git repository, exposed via a public mirror, and spent weeks in the hands of various developers. When the breach was discovered, the immediate operational paralysis was severe.
The problem wasn’t the automation; the problem was the identity management. We needed a mechanism that enforced the principle of least privilege, ensuring that the credentials used for deployment in the Staging account were completely isolated and temporary when interacting with the Production account. Simply passing credentials around was not enough.
The solution demanded a shift in architecture: we had to treat credentials as a runtime artifact, not a static variable. This realization drove the adoption of sophisticated role assumption patterns, making Ansible Cross-Account Role Assumption the central pillar of our deployment pipeline.
Core Architecture: Deconstructing the Cross-Account Flow
To understand how Ansible performs cross-account operations, you must first grasp the underlying AWS mechanics. The process relies entirely on the AWS Security Token Service (STS). STS provides the programmatic means to obtain temporary security credentials for an AWS resource assuming a specific IAM role.
The standard flow looks like this:
- Source Identity: The entity running Ansible (e.g., CI/CD runner) must possess credentials (the source identity).
- Trust Policy: The target AWS account’s IAM Role must have a Trust Policy that explicitly allows the Source Identity’s ARN to assume it.
- Assumption: The playbook executes
aws sts assume-role, providing the target Role ARN and the Source Identity’s credentials. - Temporary Credentials: AWS returns a set of temporary credentials:
AccessKeyId,SecretAccessKey, andSessionToken. - Execution: Ansible must then utilize these temporary credentials for all subsequent module calls targeting the remote resource.
This separation of concerns—using temporary, scoped credentials—is what makes Ansible Cross-Account Role Assumption inherently secure and compliant with modern security standards.
The Role of Vault and Dynamic Secrets
In a high-security environment, even the source credentials used to initiate the role assumption must be protected. This is where HashiCorp Vault comes into play. Vault acts as the central, secure vault, providing source credentials dynamically upon request. By integrating Vault into the pre-playbook setup, we ensure that the source identity is never exposed in plain text or stored in the inventory.
This combination—Vault for source credentials and STS for target role assumption—is the gold standard for secure automation, dramatically minimizing the blast radius of any potential credential leak.
Step-by-Step Implementation: Automating Role Assumption in Ansible
Implementing this requires a combination of AWS CLI commands executed via Ansible’s shell module and the use of set_fact to inject the temporary credentials into the playbook’s runtime variables.
Phase 1: The Role Assumption Playbook Block
We must first capture the output of the assume-role command. Since the output is a structured block of text, we use Ansible’s regex_search filter to reliably parse the required key-value pairs.
- name: Assume AWS Role in Target Account
ansible.builtin.shell:
cmd: |
aws sts assume-role \
--role-arn "arn:aws:iam::{{ target_account_id }}:role/TargetRoleName" \
--role-session-arn "arn:aws:iam::{{ target_account_id }}:role/TargetRoleName" \
--duration-seconds 3600
register: assumed_role_creds
changed_when: false
Phase 2: Parsing and Injecting Temporary Credentials
The output of the shell command is captured in assumed_role_creds.stdout. We must parse this to extract the three critical values and save them as facts for the entire playbook run.
- name: Set temporary credentials for subsequent tasks
ansible.builtin.set_fact:
aws_access_key_id: "{{ assumed_role_creds.stdout | regex_search('AccessKeyId: ([a-zA-Z0-9]+)') | firstgroup }}"
aws_secret_access_key: "{{ assumed_role_creds.stdout | regex_search('SecretAccessKey: ([a-zA-Z0-9]+)') | firstgroup }}"
aws_session_token: "{{ assumed_role_creds.stdout | regex_search('SessionToken: ([a-zA-Z0-9]+)') | firstgroup }}"
Phase 3: Utilizing the Temporary Credentials
Finally, any subsequent module—be it community.aws.ec2_keypair or community.aws.s3_object—must be explicitly told to use these newly created temporary credentials. While some modules support direct credential passing, the most robust method is often to set environment variables or use the ansible.builtin.environment module before the final task.
- name: Deploy resource using assumed role
community.aws.ec2_keypair:
key_name: production-key
key_content: "{{ aws_secret_access_key }}"
environment:
AWS_ACCESS_KEY_ID: "{{ aws_access_key_id }}"
AWS_SECRET_ACCESS_KEY: "{{ aws_secret_access_key }}"
AWS_SESSION_TOKEN: "{{ aws_session_token }}"
Advanced Scenarios and Real-World Use Cases
While the basic flow handles single-step role assumption, real-world infrastructure requires complex orchestration. Consider the scenario of a multi-tiered application:
- Database Migration: The CI/CD pipeline assumes Role A (read-only access) in Account 1 to pull the latest schema dump, then assumes Role B (write access) in Account 2 to execute the migration scripts.
- Network Changes: An Ansible playbook assumes a Networking Role to modify Security Groups, followed by assuming a Compute Role to restart affected instances, all within a single, transactional run.
- Handling Failure: Crucially, the entire sequence must be wrapped in robust
block/rescuehandlers. If the role assumption fails due to an expired session or permission error, the playbook must fail gracefully and report the exact STS failure code, preventing partial, dangerous deployments.
For deeper dives into AWS integration, always refer to the official AWS CLI documentation. This ensures your automation adheres to the latest service boundaries.
If your automation strategy involves complex orchestration across various cloud providers, exploring best practices in advanced configuration management is vital. We recommend reviewing our comprehensive guide on devopsroles.com for pattern matching.
Troubleshooting: Common Cross-Account Pitfalls
The most common failures in Ansible Cross-Account Role Assumption fall into three categories:
- Trust Policy Misconfiguration: The target role’s Trust Policy (the JSON defining who can assume the role) must explicitly list the ARN of the source identity. If the source identity’s ARN is missing, the STS call will fail with an “Unauthorized Operation” error.
- Timeouts and Session Duration: Remember that temporary credentials have a limited lifespan (the
duration-secondsparameter). If the playbook takes longer than the session duration, subsequent tasks will fail. Design playbooks to assume roles near the start and execute all necessary tasks before the token expires. - Environment Variable Overwrite: If Ansible modules are running in an environment where AWS credentials are already set (e.g., by the CI/CD runner’s environment), the explicit passing of temporary credentials via
environmentblocks might be ignored. Always confirm that the temporary credentials are passed at the lowest possible level of the module call.
By understanding these failure points, you can build resilient, production-grade automation that handles the complexities of multi-account governance.
Frequently Asked Questions
- Can Ansible assume multiple roles sequentially in one run?Yes. You simply repeat the
assume-roleblock, registering the output each time, and passing the resulting temporary credentials to the next set of tasks. This is the core pattern for multi-account orchestration. - Is using the shell module to run
aws sts assume-roleconsidered best practice?It is the most reliable method for capturing the raw, structured output necessary to parse the temporary credentials. While native modules are preferred, the complexity of STS output often necessitates theshellmodule for initial credential acquisition. - What is the difference between assuming a role and using an IAM profile?An IAM profile is a static configuration block that bundles credentials. Role assumption is a dynamic, temporary mechanism that grants credentials based on a defined trust relationship and limited time scope, making it far more secure for automation.
Conclusion
Mastering Ansible Cross-Account Role Assumption is not just about running a command; it’s about adopting a comprehensive security mindset. By integrating Vault for source identity protection and STS for temporary, scoped credentials, your automation moves from a simple script to a robust, enterprise-grade control plane. Implementing these patterns ensures that your deployments are both highly efficient and compliant with the strictest governance policies.
