Cross-Account Access
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks and see fewer ads — read each lesson on a single page with Pro
Lesson: Mastering Cross-Account Access in Secure Architectures
Introduction: The Necessity of Cross-Account Access
In modern cloud computing environments, organizations rarely rely on a single, monolithic account to manage their entire infrastructure. Instead, they distribute workloads across multiple accounts to isolate environments (such as development, staging, and production), segregate sensitive data, or comply with regulatory requirements. While this multi-account strategy is excellent for limiting the blast radius of a security incident, it introduces a significant engineering challenge: how do you allow authorized users or services in one account to interact with resources in another account securely?
Cross-account access is the architectural practice of granting permission for an identity in one account (the "source" or "trusting" account) to perform actions on resources located in another account (the "target" or "trusted" account). If implemented poorly, this practice can become the single greatest vulnerability in your cloud perimeter. If implemented correctly, it provides a granular, auditable, and temporary way to manage resources without the need for static credentials or shared account passwords.
This lesson explores the mechanics of cross-account access, the security principles that govern it, and the practical implementation strategies you need to build a hardened, multi-account architecture. By the end of this module, you will understand how to move away from long-lived credentials and toward a model of identity-based, temporary authorization.
The Core Concept: Trust Relationships
At the heart of cross-account access lies the concept of a "Trust Relationship." In most cloud environments, an identity (like a user or a role) exists only within the boundaries of a specific account. To grant access to someone from outside that boundary, you must explicitly tell your account to trust the external entity.
Think of it like a physical building. If you have an office in Building A, your badge works there. If you need to enter Building B, you don't just walk in; the security team at Building B must create a record that says, "We recognize the badge system of Building A, and specifically, we allow this individual to enter our lobby."
The Two-Part Authentication Dance
Cross-account access always requires two distinct steps to be successful:
- The Target Account (Trusting): You must define a policy that allows the external entity to assume a role within your account. This is known as a Trust Policy or an Identity-based Policy that permits
sts:AssumeRole. - The Source Account (Trusted): You must define a policy that allows your local identity (user or role) to perform the
sts:AssumeRoleaction on the target account’s role.
Without both sides of this configuration, access will be denied. This two-way validation is a critical security feature because it prevents a malicious actor from simply "pointing" to a role they don't own.
Callout: The Principle of Least Privilege in Cross-Account Access Cross-account access is often treated as a "blank check." Engineers sometimes create a cross-account role with
AdministratorAccessto make things "easier." This is a fundamental error. When designing cross-account roles, you must scope the permissions to the specific resources and actions required for the task. If a service in Account A only needs to read from an S3 bucket in Account B, the cross-account role must only haves3:GetObjectpermissions for that specific bucket.
Practical Implementation: Role-Based Access
The standard way to implement cross-account access is through Role Assumption. An identity in the source account requests temporary credentials from the Security Token Service (STS) by assuming a role in the target account.
Step-by-Step: Configuring the Target Account
First, you must create a role in the target account that specifies which external accounts are allowed to assume it.
- Navigate to the IAM console in the target account.
- Create a new role and select "Another AWS Account" (or the equivalent identity provider option).
- Enter the ID of the source account.
- Optionally, require an "External ID." This is a secret string that acts as a password for the role assumption process, which is critical when using third-party services to access your account.
- Attach the specific permissions policy required for the task.
Step-by-Step: Configuring the Source Account
Once the target role exists, you must authorize your local user or service to request those credentials.
- Locate the user or service role in the source account.
- Add an inline policy or managed policy that allows the
sts:AssumeRoleaction. - Specify the Amazon Resource Name (ARN) of the target role you created in the previous step.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::TARGET_ACCOUNT_ID:role/CrossAccountAccessRole"
}
]
}
Note: The
Resourcefield in the policy above must point to the specific role ARN in the target account. If you use a wildcard (*), you are potentially allowing your users to assume any role in that target account, which is a significant security risk.
Common Pitfalls and Security Risks
Even experienced architects often make mistakes when implementing cross-account access. Understanding these pitfalls is the first step toward building a robust architecture.
The "Wildcard" Trap
The most common mistake is using wildcards in the Resource or Principal fields. If you configure a trust policy to allow Principal: "*", you are essentially opening your role to every account in the cloud provider’s ecosystem. Always explicitly define the account ID or the specific ARN.
Ignoring the External ID
The External ID is a mechanism designed to prevent the "Confused Deputy" problem. If you are using a third-party SaaS tool to manage your resources, they might ask you to grant them access to your account. If you use a generic role, they might be able to access your account using the same role they use for other customers. By requiring an External ID, you ensure that the role can only be assumed if the requester provides the unique secret you shared with that specific vendor.
Lack of Auditing
Cross-account access can become a "black box." If you don't enable CloudTrail logging in both the source and target accounts, you will have no way of knowing who assumed the role or what actions they performed. Always ensure that AssumeRole events are captured in your logs and forwarded to a centralized security account for analysis.
| Feature | Best Practice | Risk of Ignoring |
|---|---|---|
| Account IDs | Use exact IDs in Trust Policies | Unauthorized access from other accounts |
| External ID | Use for 3rd-party integrations | Confused Deputy attacks |
| Permissions | Least privilege (specific actions) | Escalation of privilege |
| Logging | Enable CloudTrail in both accounts | Lack of forensic visibility |
| Session Duration | Set to minimum required time | Longer window for potential misuse |
Advanced Architecture: Using IAM Roles for Service Accounts (IRSA)
In containerized environments like Kubernetes, cross-account access takes on a different form. Instead of users manually assuming roles, the infrastructure handles it automatically. This is often implemented using OIDC (OpenID Connect) providers.
When a pod in a Kubernetes cluster in Account A needs to access a database in Account B, you configure the Kubernetes cluster to act as an OIDC provider. You then create an IAM role in Account B that trusts the OIDC provider (the cluster) rather than a specific account.
Why this is superior:
- Granularity: You can grant access to individual pods rather than an entire node.
- Automatic Rotation: The OIDC tokens are short-lived and automatically rotated by the orchestration layer.
- No Static Credentials: There are no access keys stored in environment variables or configuration files.
Warning: Never store access keys or secret keys in your code, container images, or CI/CD pipelines. Even with cross-account access, the temptation to "hardcode" credentials for convenience is high. Always use the native identity provider mechanisms (like IAM Roles or OIDC) to facilitate access.
Establishing a Secure Workflow: Step-by-Step
To implement cross-account access properly, follow this structured workflow. This approach ensures that you maintain control, visibility, and security at every stage.
Phase 1: Planning and Scoping
Before touching any configuration, identify exactly what needs to be accessed. Ask yourself:
- Who (or what service) needs access?
- What specific resources do they need to interact with?
- What is the minimum set of permissions (actions) required?
- How long does this access need to last?
Phase 2: Building the Target Role
In the target account, create a role that follows the naming convention of your organization (e.g., CrossAccount-Readonly-S3). Set the Trust Policy to only allow the specific account ID of the source account.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::SOURCE_ACCOUNT_ID:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "SecretUniqueString"
}
}
}
]
}
Phase 3: Granting Permission in the Source Account
In the source account, apply a policy to the entity (user, group, or role) that allows them to assume the target role. Test this using the Command Line Interface (CLI) to ensure the handshake is successful.
# Example command to assume the role
aws sts assume-role \
--role-arn arn:aws:iam::TARGET_ACCOUNT_ID:role/CrossAccount-Readonly-S3 \
--role-session-name MySessionName
Phase 4: Verification and Monitoring
Once configured, use the target account’s CloudTrail logs to verify that the AssumeRole call was successful. Check the userIdentity section of the log to confirm the correct source account and user performed the action.
Handling the "Confused Deputy" Problem
The "Confused Deputy" problem is a classic security vulnerability where an entity with higher privileges (the deputy) is tricked by an entity with lower privileges into performing an action that the lower-privileged entity should not be able to perform.
In the context of cross-account access, imagine a scenario where a third-party backup service has a role in your account. If you don't use an External ID, the backup service might be tricked into backing up data from one of their other customers into your account, or vice versa, because they don't know which customer "owns" the request.
By implementing the sts:ExternalId condition, you provide a unique, non-guessable secret that acts as a cryptographic proof of ownership. The service must present this ID when assuming the role. Since only you and the service know this ID, the risk of a confused deputy attack is effectively neutralized.
Callout: Why Not Use Access Keys? Many beginners ask, "Why not just create an IAM user in the target account and give the source account the Access Key ID and Secret Access Key?" This is a dangerous practice. Long-lived credentials are easily leaked, difficult to rotate, and impossible to revoke without potentially breaking services. Role assumption uses temporary security tokens that automatically expire, significantly reducing the window of opportunity for an attacker if a credential is compromised.
Best Practices for Enterprise Environments
1. Centralized Identity Management
Ideally, you should have a single "Identity Account" where all your users reside. You then grant these users permissions to assume roles in other accounts. This avoids the need to create individual IAM users in every single account, which is an administrative nightmare and a security risk.
2. Standardized Naming Conventions
Use a consistent naming convention for your cross-account roles. For example, use CrossAccount-Admin, CrossAccount-ReadOnly, or CrossAccount-SecurityAuditor. This makes it easy to identify the purpose of a role at a glance and simplifies the process of auditing permissions across the organization.
3. Automated Auditing
Use automated tools to scan your IAM policies for over-privileged roles. Many cloud providers offer tools that can detect if a role has more permissions than it actually uses based on access patterns. Regularly prune unused roles and tighten policies that are too broad.
4. Enforce MFA for Sensitive Roles
For roles that grant broad administrative access, enforce Multi-Factor Authentication (MFA) in the trust policy. You can add a condition that requires the session to be authenticated with an MFA device before the AssumeRole action is permitted.
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
5. Use Service Control Policies (SCPs)
If you are using an organization-level hierarchy, use Service Control Policies (SCPs) to set guardrails. For example, you can create an SCP that prevents any account in your organization from assuming a role that doesn't belong to your organization. This prevents data exfiltration to accounts you don't control.
Troubleshooting Common Issues
When setting up cross-account access, you will inevitably run into "Access Denied" errors. Here is a systematic way to troubleshoot:
- Check the Trust Policy: Does the target role's trust policy explicitly list the source account ID?
- Check the Permissions Policy: Does the source user/role have an explicit
Allowfor thests:AssumeRoleaction? - Check the Resource ARN: Is the ARN in the source policy exactly correct? A single typo in the account ID will cause the request to fail.
- Check for Deny Policies: Remember that in most cloud IAM systems, an explicit
Denyoverrides anyAllow. Check for any SCPs or boundary policies that might be blocking the action. - Check External ID: If the target role requires an External ID, ensure it is being passed in the API call or CLI command.
- Check Time Skew: If using OIDC or other time-sensitive tokens, ensure the system clocks on your servers are synchronized.
Summary and Key Takeaways
Cross-account access is the foundation of secure, scalable multi-account architectures. By moving away from static credentials and embracing temporary, role-based access, you drastically reduce your attack surface and simplify identity management.
Key Takeaways:
- Trust is Bidirectional: Cross-account access requires configuration in both the source (trusted) and target (trusting) accounts. Neither side can grant access without the other.
- Avoid Long-Lived Credentials: Always prefer IAM roles and temporary security tokens over static access keys. Roles provide the necessary isolation and automatic credential rotation.
- The Power of Least Privilege: Never use
AdministratorAccessfor cross-account roles. Define the exact actions and resources required for the specific task at hand. - Use External IDs: When working with third-party vendors, always use the External ID feature to prevent confused deputy attacks and ensure that your roles are not misused by other customers of that vendor.
- Visibility is Mandatory: Enable logging (such as CloudTrail) in both the source and target accounts. Without logs, you cannot audit access or perform forensics if a security incident occurs.
- Standardize and Automate: Use naming conventions and infrastructure-as-code (IaC) to manage your roles. This ensures consistency and makes it easier to audit your architecture as it grows.
- Implement Guardrails: Use organization-level policies (like SCPs) to prevent unauthorized cross-account access and enforce security standards across your entire environment.
By adhering to these principles, you create an environment where access is controlled, transparent, and aligned with modern security best practices. As you move forward in your architecture design, always evaluate whether a cross-account role can solve a problem before resorting to more complex or less secure alternatives.
Frequently Asked Questions (FAQ)
Q: Can I use cross-account access for users who don't have an IAM account? A: Yes, if you use an identity provider (IdP) like Okta or Azure AD, you can federate those identities into your cloud environment. The federation process acts similarly to role assumption, where the IdP provides a token that the cloud environment validates before granting access.
Q: How often should I rotate my cross-account roles? A: Because roles use temporary credentials generated by STS, you don't need to "rotate" the role itself in the same way you rotate a password. However, you should periodically audit the trust policies and permission policies of your roles to ensure they are still necessary and correctly scoped.
Q: What if I need to access a resource in a different region?
A: Cross-account access is independent of regions. You can assume a role in an account in the us-east-1 region even if you are originating the request from eu-west-1. The IAM service is global, meaning your trust policies and roles are available across all regions.
Q: Can I limit cross-account access to specific IP addresses?
A: Yes, you can add a Condition block to your trust policy that restricts the sts:AssumeRole action to a specific range of IP addresses (the aws:SourceIp condition). This adds an extra layer of defense, ensuring that the role can only be assumed from your corporate network or VPN.
Q: What happens if the target account is deleted?
A: If the target account is deleted, any roles within it are also deleted. Any ongoing sessions will be terminated, and no further AssumeRole calls will succeed. It is important to have a lifecycle management process for your accounts to ensure that cross-account dependencies are cleaned up appropriately.
Continue the course
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons