‹ All study guides

IAM users, roles and policies on AWS

Updated 12 October 2026 · 8 min read

Almost every AWS security question comes down to the same two things: who is making the request, and which policies are allowed to say yes or no to it. The answer options usually all sound plausible. One hands out access keys, one uses a role, one edits a bucket policy and one adds an organization-wide guardrail. Only one of them fits the constraint in the question.

The exams care about IAM because it decides whether a design is secure and whether it can be run at scale. Cloud Practitioner checks that you know a role from a user and why long-lived keys are a bad idea. Solutions Architect Associate adds cross-account access, resource-based policies and SCPs. Solutions Architect Professional asks how all of these combine across dozens of accounts, including the edge cases.

Users, groups and roles

An IAM user is an identity with long-term credentials: a console password, access keys, or both. Those credentials stay valid until someone rotates or deletes them. AWS now recommends IAM users only for the cases federation can't cover, such as a third-party tool that can only take an access key, or a tightly controlled break-glass account for when your identity provider is down. For people, the recommended route is federation, usually through IAM Identity Center, which hands out temporary credentials for a role in each account.

An IAM group is just a collection of users that share attached policies. It is not an identity: you can't sign in as a group, and a resource-based policy can't name a group as a principal. Groups exist to make permissions manageable when people join and leave.

An IAM role is an identity with permissions but no long-term credentials. Something assumes the role and gets temporary credentials through AWS STS that expire on their own. A role can be assumed by IAM users or roles in the same or another account, by AWS services (an EC2 instance through its instance profile, a Lambda function through its execution role), and by people signed in through a SAML 2.0 or OpenID Connect identity provider. A role has two policies that matter:

  • The trust policy says who may assume the role. It is a resource-based policy attached to the role, and you can't put a wildcard inside an ARN in its principal element.
  • The permissions policy says what the role can do once assumed.

Session length is configurable. A single AssumeRole call can ask for up to 12 hours if the role's maximum session duration allows it. Role chaining, which means using one role's temporary credentials to assume a second role, is capped at one hour no matter what either role allows.

Identity-based and resource-based policies

An identity-based policy is attached to a user, group or role and says what that identity can do. It can be AWS managed, customer managed, or inline. It has no Principal element, because the principal is whoever it is attached to.

A resource-based policy is attached to the resource itself: an S3 bucket policy, an SQS queue policy, an SNS topic policy, a KMS key policy, a Lambda function policy, or a role's trust policy. It has a Principal element naming who is allowed in, and that principal can be in another account.

Every request starts as an implicit deny. Within one account, the identity-based and resource-based policies are combined as a union: if either allows the action and nothing explicitly denies it, the request goes through. An explicit deny anywhere always wins.

Cross-account access

There are two ways to let a principal in account A reach a resource in account B.

  1. Assume a role in account B. Account B creates a role whose trust policy names account A (or a specific role in it). Account A gives its principal permission to call sts:AssumeRole on that role. The caller temporarily takes on the role's permissions and gives up its own for that session. This works for any service and lets account B revoke access by editing the trust policy.
  2. Use a resource-based policy in account B that names the principal in account A. The caller keeps its own identity, which matters when it also needs to write to something in its own account during the same operation.

With the second pattern, the request is evaluated in both accounts. Account A's identity-based policy must allow the action on the resource's ARN, and account B's resource-based policy must allow the caller. If either side doesn't say yes, the request fails. The union rule from the previous section only applies within one account.

KMS adds a twist the exams love. If an object in account B is encrypted with a customer managed KMS key, the caller from account A needs permission on the key as well as on the bucket. That means the key policy in account B must allow account A, and account A's identity policy must allow the KMS actions on that key. A bucket policy alone isn't enough.

For third parties, the trust policy should also require an external ID, which protects you against the confused deputy problem when a vendor assumes roles in many customers' accounts.

Guardrails: SCPs and permissions boundaries

Both of these set a maximum. Neither grants anything on its own.

Service control policies

An SCP is an AWS Organizations policy attached to the root, an OU or an account. It limits what IAM users and roles in member accounts can do, including the member account's root user. Even a principal with AdministratorAccess can't use an action an SCP blocks. Points to remember:

  • SCPs don't affect users or roles in the management account.
  • They don't affect service-linked roles.
  • They limit principals in your organization, not the resource. A bucket policy that lets an outside account in isn't restricted by your SCPs; resource control policies (RCPs) cover that side.
  • Removing the default FullAWSAccess policy without replacing it blocks every action in the affected accounts.

Permissions boundaries

A permissions boundary is a managed policy set on a single user or role that caps what its identity-based policies can grant. The effective permissions are the intersection of the two. Its classic use is safe delegation. You let developers create roles, but only if each new role carries a specific boundary, and you deny them the ability to change or remove that boundary. A developer can then attach AdministratorAccess to a new role and it still can't exceed the boundary.

When an SCP, a boundary and an identity-based policy all apply, an action must be allowed by all three. An explicit deny in any of them ends the evaluation.

How to choose

  • An application on EC2, Lambda, ECS or any AWS compute needs AWS access: use a role attached to the compute, never access keys in a file or environment variable.
  • People need console or CLI access: federation through IAM Identity Center, so they get temporary role credentials. Use IAM users only where federation can't work.
  • Many users need the same permissions: attach the policy to a group, not to each user.
  • Another account needs access to many kinds of resource, or you want to revoke it from one place: a role in your account that trusts theirs.
  • Another account needs one bucket, queue or key, and must keep its own identity: a resource-based policy plus an allow in their identity policy.
  • No one in the organization may ever do something, account admins included: an SCP.
  • Someone may create identities, but only up to a fixed ceiling: a permissions boundary.

Common exam traps

  • Treating an SCP as a grant. An SCP that "allows S3" gives nobody access to S3. The user still needs an identity-based policy, and the SCP only stops it being exceeded.
  • Expecting an SCP to restrict the management account. It doesn't. Questions that need a control over every account usually also say to keep workloads out of the management account.
  • Using a group as a principal. A bucket policy can't name an IAM group. Name a role or user, or grant the group an identity-based policy instead.
  • Fixing only one side of a cross-account request. Editing the bucket policy while the caller's own identity policy has no allow, or the KMS key policy says nothing, still ends in access denied.
  • Asking for a long session through a role chain. A second hop is limited to one hour, so the fix is to remove the chain, not to raise the maximum session duration.
  • Detective instead of preventive. AWS Config or a daily audit reports a bad policy after it exists. When a question says "prevent", look for an SCP, a boundary or an explicit deny.

A worked example

A company has 30 member accounts in AWS Organizations. Developers in each account must be able to create IAM roles for their own Lambda functions. Security says no such role may ever reach anything beyond S3, DynamoDB and CloudWatch Logs. Separately, nobody in any member account may disable CloudTrail, including account administrators.

These are two different requirements, so they need two different tools. Stopping CloudTrail from being turned off has to bind account administrators, who can edit any IAM policy in their own account. Only something outside the account can do that, so it is an SCP that denies cloudtrail:StopLogging and cloudtrail:DeleteTrail, attached at the root or the workload OU. It applies to every member account, including ones added later.

The role-creation requirement can't use an SCP alone. An SCP limits every principal in the account, and here the limit should apply only to roles developers create. The fit is a permissions boundary policy that allows only the three services. The developers' own policy allows iam:CreateRole only when iam:PermissionsBoundary equals that policy's ARN, and explicitly denies deleting or replacing boundaries and editing the boundary policy. A role created this way can carry any permissions policy, yet its effective permissions never exceed the boundary.

Practice questions

Further reading

Practice questions