StudyToCert

All certifications / Solutions Architect Associate / Lessons

AWS Certified Solutions Architect – Associate SAA-C03 · Domain 1: Design Secure Architectures

IAM users, groups, roles and policies: least privilege, identity-based vs resource-based policies and policy evaluation logic

▶ Watch the overview video

Last reviewed September 30, 2026 · Leer en español

AWS Identity and Access Management (IAM) decides who can do what in an AWS account. Every API call, whether it comes from the console, the command line interface (CLI), a software development kit (SDK) or another AWS service, is checked by IAM before anything happens. Getting IAM right is the foundation of every secure architecture on the Solutions Architect Associate (SAA-C03) exam, and many questions that look like they are about S3, EC2 or Lambda are really asking whether you understand identities and policies. There are three kinds of identity to know. An IAM user is a long-term identity for one person or application, with an optional console password and optional access keys for the API. An IAM group is a collection of users that share permissions; groups cannot sign in, cannot be nested inside other groups and cannot be named as a principal in a policy. An IAM role is an identity with no long-term credentials: a trusted principal (a user, an AWS service such as EC2 or Lambda, another account, or a federated user) assumes it and receives temporary credentials from AWS Security Token Service (STS). For workloads, roles are almost always the right answer, because there are no keys to leak or rotate. An EC2 instance gets a role through an instance profile, and a Lambda function gets one as its execution role. The account root user, created with the account, can do almost everything and should be locked away with multi-factor authentication (MFA) and used only for the few tasks that require it.

Requestprincipal · action · resourceExplicit Deny anywhere?any policy that appliesyesDENYexplicit, finalnoGuardrails allow it?SCP, permissions boundarynoDenyoutside limitsyesExplicit Allow?identity or resource policyyesALLOWrequest runsnoImplicit denythe default for everythingExplicit deny > Allow > implicit deny
IAM policy evaluation: explicit deny, allow, implicit deny

Permissions come from policies, which are JSON documents made of statements. Each statement has an Effect (Allow or Deny), an Action (for example s3:GetObject), a Resource (an ARN, the Amazon Resource Name) and optional Condition blocks using keys such as aws:SourceIp or aws:MultiFactorAuthPresent. Least privilege means granting only the actions and resources a job needs, then widening only when there is a proven need. AWS managed policies are convenient starting points but are often broad; customer managed policies let you tighten scope and reuse the result; inline policies are embedded in one identity and deleted with it.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["s3:GetObject"],
    "Resource": "arn:aws:s3:::reports-bucket/*"
  }]
}

Identity-based policies attach to users, groups and roles and say what that identity can do. Resource-based policies attach to a resource, such as an S3 bucket policy, an SQS queue policy or a KMS key policy, and include a Principal element naming who may access it. Resource-based policies are how you grant another account access without that account assuming a role. A role's trust policy is itself a resource-based policy: it says who may assume the role, while the role's permissions policies say what the role can do once assumed.

Policy evaluation follows a fixed logic. Every request starts as an implicit deny. AWS collects every applicable policy: service control policies (SCPs) from AWS Organizations, resource-based policies, permissions boundaries, session policies and identity-based policies. If any of them contains an explicit Deny that matches, the request is denied, full stop. Otherwise the request needs an Allow, and every guardrail layer that applies (SCPs, a permissions boundary, a session policy) must also allow it. Within one account, an Allow in either the identity policy or the resource policy is usually enough; across accounts, both the caller's identity policy and the resource policy must allow. A permissions boundary is a managed policy set on a user or role that caps the maximum permissions its identity policies can grant; it grants nothing by itself. Boundaries let developers create roles for their applications without being able to create a role more powerful than they are. The IAM policy simulator and IAM Access Analyzer help you test policies and find unintended external access.

Consider a worked example. An application on EC2 needs to read one S3 bucket, and a developer suggests pasting an access key into a configuration file. Instead, the architect creates a role whose trust policy allows ec2.amazonaws.com, attaches a customer managed policy allowing only s3:GetObject on that bucket's objects, and attaches the role to the instance through an instance profile. The SDK on the instance finds temporary credentials automatically through the instance metadata service and refreshes them before they expire. Later, security adds a bucket policy that explicitly denies all access unless the request uses TLS; the application still works because its requests are encrypted, and any plain HTTP request is refused regardless of the role's Allow.

Common mistakes: storing access keys on instances or in code instead of using roles; thinking a permissions boundary or SCP grants access (they only limit it); forgetting that an explicit Deny beats any Allow; trying to put a group in a policy's Principal element; and using the root user for daily work. Another trap is assuming an AWS managed policy is least privilege; it is a starting point you should narrow once you know what the workload actually calls.

Exam questions usually describe a symptom or a goal. 'Access denied despite an Allow' points to an explicit Deny, an SCP or a permissions boundary. 'Give an EC2 instance or Lambda function access to a service' points to an IAM role, never stored keys. 'Let developers create roles but cap what those roles can do' points to a permissions boundary, and 'grant another account access to a bucket without a role' points to a resource-based bucket policy.

Key terms

IAM role
An identity with permissions but no long-term credentials, assumed by a trusted principal to receive temporary credentials.
IAM group
A collection of IAM users that share attached policies; it cannot sign in, be nested or be a policy principal.
Identity-based policy
A policy attached to a user, group or role that states what that identity may do.
Resource-based policy
A policy attached to a resource, such as an S3 bucket policy, that names the principals allowed to access it.
Explicit deny
A Deny statement that matches a request; it overrides any Allow in any policy.
Permissions boundary
A managed policy that sets the maximum permissions an IAM user or role can have, without granting any itself.
Instance profile
The container that passes an IAM role to an EC2 instance so software on it receives temporary credentials.
Real-world example

A development team keeps asking the cloud team to create IAM roles for their Lambda functions. The cloud team lets them create roles themselves, but only if each new role has a permissions boundary attached that allows DynamoDB, S3 and CloudWatch Logs actions in the development account. A developer then creates a role with AdministratorAccess by mistake; because of the boundary, the function can still only use those three services, and an attempt to call IAM is denied.

Exam tip: When a question asks why access is denied despite an Allow, look for an explicit Deny, an SCP or a permissions boundary. When it asks how to give an EC2 instance or Lambda function access, the answer is a role, never access keys stored on the instance.

Check yourself

A user's identity policy allows s3:DeleteObject, but the bucket policy explicitly denies it to that user. What happens?

The request is denied. An explicit Deny in any applicable policy overrides every Allow.

What does a permissions boundary do on its own?

It grants nothing. It only limits the maximum permissions that the identity-based policies of that user or role can make effective.

Can you nest an IAM group inside another group or name it as a principal?

No. IAM groups cannot be nested and cannot be a principal in a policy; attach policies to the group or use roles instead.

An account B user needs to read a bucket in account A without assuming a role. What must be true?

Account A's bucket policy must allow the account B principal, and the user's identity policy in account B must also allow the S3 action, because cross-account access needs both sides.

Study Solutions Architect Associate for free
A week-by-week plan with every lesson, quizzes, checkpoint tests, a practice exam and hands-on labs.
Open the Solutions Architect Associate study plan