SAA-C03Chapter 11 of 189Objective 1.1

AWS IAM Advanced: Roles, Policies, STS

This chapter covers advanced IAM concepts critical for the SAA-C03 exam: IAM roles, policies (identity-based and resource-based), and AWS Security Token Service (STS). These topics appear in roughly 20-25% of exam questions, often interleaved with S3, Lambda, EC2, and cross-account access scenarios. You will learn the internal mechanisms of role assumption, policy evaluation logic, and STS token generation — knowledge essential for designing secure, scalable AWS architectures and passing the exam.

25 min read
Intermediate
Updated May 31, 2026

IAM Roles: The Hotel Key Card System

Think of an IAM role like a hotel key card system. A hotel has many rooms (AWS resources) and guests (AWS services or users). Instead of giving each guest a permanent key to every room (long-term credentials), the hotel issues a key card at check-in that is valid only for their stay and only for their assigned room. When a guest wants to enter their room, they swipe the card at the door. The door lock checks the card's validity against a central system (STS) — the card must not be expired and must have the correct permissions. The lock then grants access. The hotel can issue many such cards without changing the locks. If a card is lost, it can be revoked centrally by deactivating that card's ID. Similarly, an IAM role provides temporary credentials (key card) that an AWS service (guest) can assume to perform actions. The role's policy (room assignment) defines what actions are allowed. AWS STS (the hotel's key card machine) issues the temporary credentials, which include an expiration time. Once expired, the credentials cannot be used, just like a checkout time. This eliminates the need to embed long-term keys in code or manage user credentials for services.

How It Actually Works

What Are IAM Roles and Why Do They Exist?

An IAM role is an AWS identity with permission policies that determine what the role can do, but it is not uniquely associated with one person or service. Instead, trusted entities — such as IAM users, AWS services (EC2, Lambda), or users from another AWS account — assume the role to obtain temporary security credentials. Roles eliminate the need to share or embed long-term access keys. They are the foundation of secure credential management in AWS.

How Role Assumption Works Internally

When an entity assumes a role, the following occurs:

1. The entity calls the AWS STS AssumeRole API (or AssumeRoleWithWebIdentity, AssumeRoleWithSAML, etc.). 2. AWS STS validates that the entity has permission to assume the role (checked via the entity's IAM policy and the role's trust policy). 3. STS generates a temporary security credential set consisting of: - Access Key ID (string) - Secret Access Key (string) - Session Token (string) - Expiration (timestamp, default 1 hour, max 12 hours for most roles) 4. These credentials are returned to the entity, which can then use them to make AWS API calls. The credentials are valid until the expiration time.

Key Components and Values

Trust Policy: A JSON policy document attached to the role that specifies which principals (users, services, accounts) are allowed to assume the role. The Principal element can be an AWS account, IAM user, role, or federated user. Example:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"AWS": "arn:aws:iam::123456789012:root"},
    "Action": "sts:AssumeRole"
  }]
}

Permissions Policy: A JSON policy attached to the role that defines what actions the role can perform on which resources. This is the same as an IAM user policy.

Maximum session duration: Set when creating the role, from 1 hour (3600 seconds) to 12 hours (43200 seconds). Default is 1 hour. The actual session duration can be less if the caller specifies a shorter duration.

Role ARN: Unique identifier for the role, e.g., arn:aws:iam::123456789012:role/MyRole.

Policy Evaluation Logic

When a request is made using temporary credentials, AWS evaluates all applicable policies:

1.

Identity-based policies of the role (permissions policy).

2.

Resource-based policies on the target resource (e.g., S3 bucket policy).

3.

Organizations SCPs (if applicable).

4.

Session policies (if passed during AssumeRole call).

The decision is based on an explicit deny override: if any policy explicitly denies the action, the request is denied. If no policy explicitly allows and no explicit deny, the request is denied by default (implicit deny).

STS APIs and Token Types

AssumeRole: Used by IAM users or roles to assume another role within the same or different account.

AssumeRoleWithWebIdentity: For users authenticated by a web identity provider (e.g., Amazon Cognito, Login with Amazon, Google, Facebook). No AWS credentials needed.

AssumeRoleWithSAML: For users authenticated via SAML 2.0.

GetFederationToken: Returns temporary credentials for a federated user, with a custom session name.

GetSessionToken: Returns temporary credentials for an IAM user or AWS account root user, typically for MFA-protected API calls.

Role for EC2 (Instance Profile)

An EC2 instance can assume a role by launching it with an IAM instance profile. The instance profile is a container for a role. AWS automatically rotates the temporary credentials inside the instance via the instance metadata service (IMDS). The instance retrieves credentials from http://169.254.169.254/latest/meta-data/iam/security-credentials/rolename. These credentials are automatically renewed before expiration.

Cross-Account Roles

To grant access to resources in Account A from Account B:

1.

In Account A, create a role with a trust policy that allows Account B's root user or a specific role to assume it.

2.

Attach a permissions policy granting access to Account A's resources.

3.

In Account B, an admin grants the user or role permission to call sts:AssumeRole with the ARN of the role in Account A.

4.

The user in Account B assumes the role and gets temporary credentials to access Account A's resources.

Service-Linked Roles

These are predefined roles linked directly to an AWS service. The service defines the trust policy and permissions. You cannot modify them, but you can create and delete them as needed. Example: Amazon Redshift uses a service-linked role to access S3 for data loading.

PassRole Permission

To allow a user to pass a role to an AWS service (e.g., when launching an EC2 instance with a role), the user must have iam:PassRole permission on that role. This prevents privilege escalation.

Role Chaining

You can assume a role, then use the resulting temporary credentials to assume another role. This is called role chaining. However, the maximum chain depth is limited by AWS (usually not recommended due to complexity and security concerns).

Session Tags and Transitive Keys

When assuming a role, you can pass session tags that are propagated to the role's session. These tags can be used in attribute-based access control (ABAC). The role's trust policy must allow sts:TagSession for the principal to pass tags.

Verification Commands

Use AWS CLI to test role assumption:

aws sts assume-role --role-arn "arn:aws:iam::123456789012:role/MyRole" --role-session-name "TestSession"

Output:

{
    "Credentials": {
        "AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
        "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        "SessionToken": "FwoGZXIvYXdzEH...",
        "Expiration": "2025-03-20T12:00:00Z"
    }
}

To use these credentials, set environment variables:

export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
export AWS_SESSION_TOKEN=FwoGZXIvYXdzEH...

Interaction with Other Services

AWS Lambda: Lambda functions can assume a role (execution role) to access other services. The role's permissions policy defines what the function can do.

AWS CloudFormation: Uses a service role to perform stack operations.

AWS Organizations: SCPs can restrict what roles can do even if the role's permissions allow it.

Defaults and Limits

Maximum session duration: 1 hour default, configurable up to 12 hours.

Maximum number of roles per account: 5000 (soft limit, can be increased).

Maximum trust policy size: 2048 characters.

Maximum permissions policy size: 6144 characters (for most services).

STS endpoints: Global endpoint (sts.amazonaws.com) and regional endpoints for better latency and availability.

Security Best Practices

Use roles instead of access keys for EC2, Lambda, etc.

Scope down permissions using least privilege.

Use conditions in policies (e.g., aws:SourceIp, aws:MultiFactorAuthPresent).

Rotate temporary credentials automatically (they expire).

Use aws:SourceArn and aws:SourceAccount in trust policies to prevent confused deputy problem.

Confused Deputy Problem

When a service assumes a role on behalf of a user, another service could trick it into accessing resources. To prevent this, use the aws:SourceArn condition key in the trust policy to restrict which resource can assume the role.

Policy Types Summary

Identity-based: Attached to IAM users, groups, or roles.

Resource-based: Attached to resources (S3 bucket, SQS queue, etc.).

Permissions boundary: Set on a user or role to limit maximum permissions.

SCP: Applied to an AWS organization unit to restrict permissions.

Session policy: Passed during role assumption to further restrict permissions for that session.

Evaluation Logic Example

If a role has a permissions policy allowing s3:GetObject on bucket1/*, and the bucket has a resource-based policy denying s3:GetObject for that role, the request is denied (explicit deny overrides allow).

Walk-Through

1

Create the IAM Role

In the AWS Management Console, navigate to IAM > Roles > Create role. Select the trusted entity type (e.g., AWS service, Another AWS account, Web identity, SAML). For an EC2 role, choose 'AWS service' then 'EC2'. Attach a permissions policy that defines what actions the role can perform, e.g., AmazonS3ReadOnlyAccess. Optionally set a tags and maximum session duration (default 1 hour). The role is created with a trust policy that allows the selected entity to assume it.

2

Attach Trust Policy

The trust policy is a JSON document that specifies who can assume the role. For cross-account access, the Principal element includes the AWS account ID of the trusting account. For an EC2 role, the trust policy allows the EC2 service to assume the role. Example: {"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ec2.amazonaws.com"},"Action":"sts:AssumeRole"}]}. This policy is stored with the role and evaluated when an entity calls AssumeRole.

3

Entity Calls STS AssumeRole

The entity (e.g., an IAM user or EC2 instance) makes an API call to AWS STS (e.g., via CLI: `aws sts assume-role`). The request includes the role ARN and a session name. STS checks the entity's identity and verifies that it has permission to call `sts:AssumeRole` on the role. This check involves evaluating the entity's IAM policy (must allow `sts:AssumeRole` on the role ARN) and the role's trust policy (must allow the entity's principal). If both allow, STS proceeds.

4

STS Generates Temporary Credentials

STS generates a set of temporary security credentials: an access key ID, a secret access key, and a session token. These credentials have an expiration time (default 1 hour, up to 12 hours). The session token is unique to this session and must be included in all subsequent AWS API calls. The credentials are cryptographically signed and tied to the role's permissions. STS returns these to the caller in the API response.

5

Entity Uses Temporary Credentials

The entity uses the temporary credentials to make AWS API calls. For example, an EC2 instance uses credentials from the instance metadata service. Each API request includes the access key ID, secret access key, and session token. AWS validates the session token and checks the role's permissions policy for authorization. If the action is allowed and the credentials are not expired, the request succeeds. The credentials are automatically rotated if the entity is an AWS service (e.g., EC2) before expiration.

What This Looks Like on the Job

Enterprise Scenario 1: Cross-Account Access for Centralized Logging

A large enterprise has multiple AWS accounts (Dev, Test, Prod) and a central logging account. They want EC2 instances in each account to send logs to an S3 bucket in the logging account. Solution: In the logging account, create an IAM role with a trust policy that allows the root user of each member account to assume it. Attach a permissions policy granting s3:PutObject on the central bucket. In each member account, create an IAM instance profile using that role. Launch EC2 instances with the instance profile. The instances automatically assume the cross-account role via STS and write logs. This avoids embedding keys and centralizes control. Common misconfiguration: forgetting to update the trust policy when adding a new account, leading to access denied errors. Performance: STS calls are low-latency; credentials are cached by the instance metadata service and renewed automatically, so no performance impact.

Enterprise Scenario 2: Federated Access for Third-Party Contractors

A company uses Okta for identity management. They want to grant temporary access to AWS resources (e.g., a specific S3 bucket) to external contractors. Solution: Create an IAM role with a trust policy that allows sts:AssumeRoleWithSAML from the Okta SAML provider. Attach a permissions policy scoped to the bucket. Contractors authenticate via Okta, which generates a SAML assertion. The assertion is exchanged with STS for temporary credentials. The contractors then access the bucket via AWS CLI or console. This provides fine-grained, time-limited access without creating IAM users. Common issue: the SAML assertion must include the correct role ARN and session duration; otherwise, STS rejects the request. Scale: can support thousands of federated users.

Enterprise Scenario 3: EC2 Role for Auto-Scaling Application

A web application runs on an Auto Scaling group of EC2 instances. The instances need to read from DynamoDB and write to SQS. Instead of embedding access keys in the AMI or user data, attach an IAM role to the launch configuration. The role's permissions policy grants dynamodb:GetItem and sqs:SendMessage. As instances scale up, they automatically assume the role via the instance profile. No manual key management. Misconfiguration: if the role's permissions are too broad (e.g., dynamodb:*), an attacker who compromises an instance could delete tables. Best practice: use the most restrictive policy and use condition keys like aws:ResourceTag to limit access to specific tables. Performance: credential rotation is handled by the EC2 metadata service with no application impact.

How SAA-C03 Actually Tests This

SAA-C03 Exam Coverage

This topic falls under Domain 1: Secure Architectures (Objective 1.1: Design secure access to AWS resources). Expect 2-4 questions directly on roles, STS, or policy evaluation. The exam tests your ability to choose the correct mechanism for granting temporary access, cross-account access, or service-to-service permissions.

Common Wrong Answers and Why

1.

Using IAM user access keys for EC2: Many candidates think embedding keys in user data or AMI is acceptable. Wrong — AWS recommends roles for EC2 because keys are long-term and can be exposed. The exam expects you to choose a role with an instance profile.

2.

Creating a role without a trust policy: A role without a trust policy cannot be assumed by anyone. Candidates often forget the trust policy and wonder why AssumeRole fails. The exam tests that the trust policy is required.

3.

Using resource-based policies for cross-account access when a role is needed: For some services (S3, SQS, SNS), you can use resource-based policies to grant cross-account access directly. But for services like EC2 or Lambda, you must use roles. The exam will test which method applies.

4.

Assuming a role without session token: Temporary credentials include a session token. Calls without the session token are denied. Candidates might think only access key and secret key are needed.

Specific Numbers and Terms

Maximum session duration: 12 hours (43200 seconds). Default 1 hour.

STS API actions: AssumeRole, AssumeRoleWithWebIdentity, AssumeRoleWithSAML, GetFederationToken, GetSessionToken.

Instance metadata service IP: 169.254.169.254.

Role trust policy principal: "Service": "ec2.amazonaws.com" for EC2.

PassRole permission: Required to pass a role to an AWS service.

Edge Cases and Exceptions

Role chaining: You can chain up to 5 roles in some scenarios, but the exam typically avoids deep chains. Know that each assume reduces the session duration.

Service-linked roles: Cannot be modified; the service controls the policy.

Permissions boundaries: They limit the maximum permissions a role can have, even if the permissions policy allows more. The exam may ask about boundary vs. policy.

Confused deputy: Use aws:SourceArn or aws:SourceAccount in trust policies to prevent a service from being tricked into assuming a role on behalf of an unintended resource.

How to Eliminate Wrong Answers

If the question involves a service (EC2, Lambda) needing access to other services, the answer must involve a role (instance profile or execution role). Eliminate any answer using access keys.

If the question involves cross-account access and the resource supports resource-based policies (S3, SQS, SNS), both roles and resource policies are possible. Choose the one that fits the scenario (e.g., if the resource is S3 bucket, a bucket policy might be simpler). For services that don't support resource policies, you must use a role.

If the question mentions temporary credentials or federation, think STS. Eliminate options that use IAM users with long-term keys.

If the question involves MFA, use GetSessionToken with MFA or condition key aws:MultiFactorAuthPresent.

Key Takeaways

IAM roles provide temporary security credentials via AWS STS, eliminating the need for long-term access keys.

A role has two policies: a trust policy (who can assume) and a permissions policy (what actions allowed).

Default session duration is 1 hour, configurable up to 12 hours.

EC2 instances assume roles via instance profiles; credentials are retrieved from instance metadata at 169.254.169.254.

Cross-account access uses roles; resource-based policies are an alternative for S3, SQS, SNS.

Use `iam:PassRole` to control which users can pass roles to AWS services.

The confused deputy problem is mitigated using `aws:SourceArn` or `aws:SourceAccount` condition keys.

STS APIs include AssumeRole, AssumeRoleWithWebIdentity, AssumeRoleWithSAML, GetFederationToken, GetSessionToken.

Permissions boundaries can limit the maximum permissions a role can have, overriding the permissions policy.

Service-linked roles are predefined by AWS services and cannot be modified.

Easy to Mix Up

These come up on the exam all the time. Here's how to tell them apart.

IAM Role

No long-term credentials (access key/secret key).

Assumed by trusted entities for temporary access.

Permissions defined by attached policies.

Used primarily for services and cross-account access.

Credentials are automatically rotated (via STS).

IAM User

Has long-term credentials (access key/secret key or password).

Directly authenticated as a principal.

Permissions defined by attached policies.

Used for individual human users or applications with static credentials.

Credentials must be manually rotated.

Watch Out for These

Mistake

IAM roles can be directly assigned to users like groups.

Correct

Roles are not assigned to users permanently; users assume roles to get temporary credentials. A role is an identity that can be assumed by trusted entities, not a container for users.

Mistake

A role's trust policy and permissions policy are the same thing.

Correct

The trust policy defines who can assume the role. The permissions policy defines what actions the role can perform once assumed. They are separate JSON documents.

Mistake

Temporary credentials from STS never expire.

Correct

Temporary credentials have a configurable expiration (1-12 hours). After expiration, they are invalid and must be renewed by assuming the role again.

Mistake

You can attach a role directly to an EC2 instance after launch.

Correct

A role can only be attached at launch via an instance profile. To change the role, you must stop the instance, modify the instance profile, and restart it. You cannot change the role on a running instance.

Mistake

Cross-account access always requires a role.

Correct

Some services (S3, SQS, SNS) support resource-based policies that grant cross-account access without roles. For other services (EC2, Lambda), you must use roles.

Do You Actually Know This?

Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.

Frequently Asked Questions

What is the difference between an IAM role and an IAM user?

An IAM user has permanent credentials (password or access keys) and is associated with a specific person or application. An IAM role does not have permanent credentials; it is assumed by a trusted entity (user, service, or federated identity) to obtain temporary credentials. Roles are used for granting permissions to AWS services (e.g., EC2) or for cross-account access. Users are for direct human or application authentication.

How do I grant an EC2 instance access to an S3 bucket?

Create an IAM role with a permissions policy that allows the required S3 actions (e.g., s3:GetObject). Attach a trust policy that allows the EC2 service to assume the role (Principal: ec2.amazonaws.com). When launching the EC2 instance, assign the role via an instance profile. The instance will automatically retrieve temporary credentials from the instance metadata service and use them to access S3.

Can I use a role to give a user in another AWS account access to my resources?

Yes. Create a role in your account with a trust policy that allows the other account's root user or a specific role to assume it. Attach a permissions policy granting access to your resources. The user in the other account must have permission to call sts:AssumeRole on your role's ARN. They then assume the role and get temporary credentials to access your resources.

What happens when temporary credentials expire?

When temporary credentials expire, any API calls made with them will be denied with an 'Access Denied' error. The entity must obtain new credentials by assuming the role again. AWS services like EC2 automatically refresh credentials before expiration via the instance metadata service, so applications typically do not need to handle expiration manually.

What is the difference between identity-based and resource-based policies?

Identity-based policies are attached to IAM users, groups, or roles and define what actions the identity can perform. Resource-based policies are attached to resources (e.g., S3 bucket, SQS queue) and define who can access that resource and what actions they can perform. For cross-account access, resource-based policies can grant access directly without needing a role, but only for services that support them.

How do I pass a role to an AWS service?

To pass a role to an AWS service (e.g., when launching an EC2 instance with a role), the user must have the `iam:PassRole` permission on that role. This is a separate permission from `iam:CreateRole` or `sts:AssumeRole`. It prevents users from escalating privileges by passing a high-permission role to a service they control.

What is the confused deputy problem and how do I prevent it?

The confused deputy problem occurs when a service (e.g., AWS Lambda) is tricked into assuming a role on behalf of an unintended resource. To prevent it, use the `aws:SourceArn` condition key in the role's trust policy to restrict which resource can assume the role. For example, a Lambda function's execution role can have a condition that the source ARN must match the function's ARN.

Terms Worth Knowing

Ready to put this to the test?

You've just covered AWS IAM Advanced: Roles, Policies, STS — now see how well it sticks with free SAA-C03 practice questions. Full explanations included, no account needed.

Done with this chapter?