IAM identity and access control is the layer of AWS that decides who can call an AWS API, which resources they can touch, and under what conditions. Every other security topic in SAA-C03 — VPC security, KMS encryption, S3 data protection, cross-account architectures — ultimately resolves to one AWS IAM evaluation: Allow or Deny. Task Statement 1.1 of the SAA-C03 exam guide, "Design secure access to AWS resources", leans heavily on IAM identity and access control because it is the single most frequently mistaken family of topics on the test. Miss the evaluation logic, miss the cross-account pattern, miss the identity-based vs resource-based distinction, and you can lose a full domain's worth of points.
At SAA-C03 depth this topic is not only about vocabulary — "an IAM role is temporary, an IAM user is permanent" — it is about designing access. Which policy type do I attach to an S3 bucket vs an EC2 instance profile? What exactly happens when an explicit deny sits inside an SCP while an identity policy tries to allow? How does a Lambda in Account A write to a DynamoDB table in Account B using the smallest safe IAM footprint? This guide walks through IAM identity and access control one building block at a time, with plain-language analogies, must-memorize numbers, and the trap-first scenarios SAA-C03 loves.
What is IAM Identity and Access Control and Why It Matters for SAA-C03
IAM identity and access control is the combination of AWS IAM constructs (users, groups, roles, policies, permissions boundaries, session policies) and AWS Organizations constructs (service control policies, resource control policies) that together form the authorization plane for every request to every AWS service. IAM identity and access control is a global AWS service (not region-scoped), is free to use, and its decision — Allow or Deny — is the gate every API call must pass before AWS touches a resource.
SAA-C03 expects architects to design IAM identity and access control end-to-end. That means picking the right primitive (IAM user vs IAM role vs federated identity), picking the right policy type (identity-based vs resource-based vs session policy), applying least privilege without breaking the workload, and debugging why a seemingly correct IAM policy is still returning AccessDenied. The SAA-C03 Exam Guide explicitly lists "policy evaluation logic", "cross-account access patterns", and "least privilege" as tested skills under Task 1.1.
- IAM user: a long-lived identity inside one AWS account with optional console password and up to two access keys.
- IAM group: a container for IAM users that lets you attach identity-based policies once.
- IAM role: an identity with policies but no long-term credentials — principals assume it and receive short-term credentials from AWS STS.
- IAM policy: a JSON document listing allowed or denied API actions on specific resources, optionally under conditions.
- Trust policy: the resource-based policy attached to an IAM role that controls who may assume the role.
- AWS STS: the AWS Security Token Service, which mints temporary security credentials for assumed roles and federated identities.
- Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html
Where IAM identity and access control sits in SAA-C03
Task 1.1 is the primary home for IAM identity and access control, but the same knowledge shows up inside other domains: Domain 2 high-availability questions assume you know how service-linked roles and EC2 instance profiles work, Domain 3 analytics scenarios (Lake Formation, Athena, Glue) test fine-grained IAM identity and access control, and Domain 4 cost scenarios sometimes test how least-privilege IAM policies keep accidental spend under control. If you master IAM identity and access control here, you lower the difficulty of roughly a third of the entire exam.
Plain-Language Explanation: — IAM Identity and Access Control in Plain English
SAA-C03 terminology gets easier once you attach it to something from everyday life. Here are three distinct analogies that cover every major IAM identity and access control concept the exam tests.
Analogy 1: The office building with badge readers
Picture a corporate office. An IAM user is an employee badge with the employee's photo — it belongs to one specific person, has a long-lasting PIN, and opens the doors that person is allowed through. An IAM group is a team-level door code configured once for everyone with a specific role, so every engineer's badge inherits "rooms 3, 4, 5". An IAM role is the visitor lanyard kept at the front desk — anyone (or any AWS service) can check one out by asking the security guard (AWS STS), wear it for a set duration, and hand it back with no long-term keys left behind. The root user is the building owner who holds the master key — powerful enough to re-key every lock, which is exactly why you lock the master key in a vault (MFA on, access keys deleted) and only use it for one-of-a-kind tasks.
MFA is the second turnstile after the badge reader: even with a stolen badge you can't get past the second barrier without the physical token. Identity-based policies are rules taped to your badge (this badge may open rooms 3, 4, 5). Resource-based policies are rules taped to the door itself (this door opens for badges in Engineering, or for visitor lanyards issued in Account B). An explicit deny is the big red "DO NOT ENTER" sign — no matter what your badge says, a deny always wins.
Analogy 2: The open-book exam with a proctor
Imagine taking a certification exam with strict rules. The proctor is IAM — they check your ID (authentication) and then look at the rulebook (authorization) for exactly what you can and can't do. The rulebook is your IAM policy. Least privilege means the rulebook says "you may use these three reference books" not "you may use every book in the library" — the smaller the allowed surface, the less damage if your seat is compromised. An explicit deny is the proctor's red-penned "NO" — even if the Allow list says you can open a book, a red NO trumps it. The default deny at the top of the page means if the rulebook never mentions an action, you cannot do it. That is the IAM policy evaluation logic in one mental image: default deny, union of allows, any explicit deny wins.
Analogy 3: The hotel front desk and room keys
A hotel captures IAM identity and access control perfectly. The root user is the hotel owner — universal override, the only person who can close the hotel or change the name on the lease. The front desk clerk is IAM — they issue room keys (IAM users, IAM roles) with specific access (room 305 only, pool only, gym only). A keycard that expires at checkout is an IAM role — temporary access that self-deactivates, so a forgotten keycard isn't a long-term risk. MFA is the signature at check-in plus the scanned ID — two factors that prove you are really the reservation holder. The hotel's door locks also have their own list ("this door opens for keys in the wedding-party block") — that is a resource-based policy attached to the door, evaluated in addition to what your key says.
When you see "IAM role" in an SAA-C03 question, mentally picture a visitor lanyard or a keycard that expires at checkout — that simple mental move stops you from confusing IAM roles with IAM users, which is the #1 IAM identity and access control trap on the exam. Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html
IAM Building Blocks: Users, Groups, Roles, and Policies
AWS IAM has four primitives. Every SAA-C03 IAM identity and access control question is built from them, and the exam rewards architects who know what each one is and what each one is not.
IAM users
An IAM user is a single identity in one AWS account. It can have a console password (for sign-in to the AWS Management Console), up to two active access keys (for AWS CLI, SDK, PowerShell — two so you can rotate without downtime), and optional MFA devices. IAM users are long-term by design, which is exactly why modern AWS best practice for IAM identity and access control pushes you away from them. Every IAM user added is one more credential to rotate, one more human to offboard, one more access key that can leak to GitHub.
AWS guidance for SAA-C03-era architectures: minimize IAM user count, and prefer IAM Identity Center for humans and IAM roles for services.
IAM groups
An IAM group is a convenience container. You attach IAM policies to the group, and every member IAM user inherits them. A group cannot be a principal — you cannot "sign in as a group", there is no GroupArn in a trust policy, and groups cannot be nested. Their only job is to make IAM policy management scalable when you do have IAM users.
IAM roles
An IAM role is the most important construct for IAM identity and access control at the SAA-C03 level. A role has policies attached but no long-term credentials. A principal — an AWS service (EC2, Lambda, ECS task), an IAM user in the same account, an IAM user in another AWS account, or a federated identity — assumes the role and AWS STS mints temporary security credentials in return. Those credentials consist of an access key ID, a secret access key, and a session token, all three of which must be present on every API call. They expire automatically.
IAM roles are the correct IAM identity and access control construct for:
- Granting an Amazon EC2 instance access to S3 via an instance profile (rotating credentials delivered by IMDS).
- Letting an AWS Lambda function, ECS task, or EKS pod access other AWS services (execution role / task role / IRSA).
- Cross-account access — a user or service in Account A assumes an IAM role in Account B via
sts:AssumeRole. - Identity federation — SAML 2.0, OIDC, or web identity; the external identity is exchanged for an IAM role session.
- Service-linked roles — pre-defined roles that AWS services (Auto Scaling, Organizations, Trusted Advisor, etc.) create to manage resources on your behalf.
IAM policies (managed vs inline)
An IAM policy is a JSON document with Version, one or more Statements, and each statement containing Effect (Allow/Deny), Action, Resource, and optional Condition and Principal blocks. Delivery formats:
- AWS-managed policy — maintained by AWS (
AmazonS3ReadOnlyAccess,AmazonDynamoDBFullAccess). Use these for standard job functions. - Customer-managed policy — authored by you, reusable, versioned (up to 5 versions retained). Prefer these for bespoke least-privilege policies that multiple identities share.
- Inline policy — embedded directly in one IAM user, group, or role. Lives and dies with that identity. Use only when a 1:1 tie is actually desirable (for example, a role that only ever serves one workload and must not have stray policies attached later).
Inline IAM policies couple tightly to one identity and are hard to audit in bulk. Customer-managed IAM policies are reusable, versioned (5 versions retained), and far easier to review through IAM Access Analyzer. At SAA-C03 level, "prefer managed over inline" is the recommended default for IAM identity and access control design. Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html
Identity-Based vs Resource-Based Policies — When Each Applies
The identity-based vs resource-based distinction is the SAA-C03 concept most architects under-study. Many cross-account questions hinge on it entirely.
Identity-based policies
An identity-based policy is attached to an identity — an IAM user, IAM group, or IAM role — and says "this identity may do X on Y". Identity-based policies are evaluated against every request the identity makes. They are the most common form of IAM policy.
Resource-based policies
A resource-based policy is attached to a resource — an S3 bucket, a Lambda function, an SNS topic, an SQS queue, an ECR repository, a KMS key, an API Gateway REST API, an OpenSearch domain, a Secrets Manager secret — and says "these principals may do X on this resource". Unlike identity-based policies, resource-based policies always contain a Principal element specifying who the policy applies to.
Only some AWS services support resource-based policies. The SAA-C03-relevant ones you should recognize:
- Amazon S3 — bucket policies and, on objects, ACLs (largely deprecated in favor of policies + Block Public Access).
- AWS KMS — key policies, which are mandatory on every KMS key and are the primary access control for encryption keys.
- AWS Lambda — resource-based policies on functions control which accounts/services can invoke them.
- Amazon SNS, Amazon SQS — topic and queue policies control who can publish or consume.
- AWS Secrets Manager — resource policies on individual secrets.
- Amazon ECR — repository policies for container images.
- API Gateway — resource policies restricting which VPC endpoints or source IPs can invoke APIs.
Why cross-account access needs both (usually)
For cross-account IAM identity and access control, the general rule is: both the identity-based policy in the caller's account and the resource-based policy in the resource's account must allow the action. A principal in Account A calling s3:GetObject on a bucket in Account B needs:
- An identity-based IAM policy in Account A allowing
s3:GetObjecton that bucket ARN. - A resource-based bucket policy in Account B allowing Account A (or a principal in Account A) to call
s3:GetObject.
The important exception: when a principal assumes an IAM role in Account B, the resource-based policy is often unnecessary because the principal is now acting inside Account B. The trust policy on the role in Account B already controlled who may assume it.
- Identity-based policy = rules taped to the principal's badge. Answers: "what may this caller do?"
- Resource-based policy = rules taped to the resource's door. Answers: "who may touch this resource?"
- Cross-account without role assumption → need both policies to allow.
- Cross-account via AssumeRole → the trust policy on the role is the cross-account gate; inside Account B the role uses ordinary identity-based policy.
- KMS key policies and S3 bucket policies are the two resource-based policies SAA-C03 tests most often.
- Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html
Policy Evaluation Logic — Explicit Deny Always Wins
This is the most tested algorithm in IAM identity and access control. Memorize it and a whole class of SAA-C03 scenario questions becomes trivial.
The evaluation pipeline
When a request arrives, AWS collects every applicable policy for the principal and the resource. The set may include:
- AWS Organizations SCPs (service control policies) — guardrails at the OU/account level.
- AWS Organizations RCPs (resource control policies) — newer guardrails that restrict what resource-based policies can grant (for supported services).
- Resource-based policies — on the target resource.
- Identity-based policies — on the calling principal.
- Permissions boundaries — the cap attached to the principal (if any).
- Session policies — inline policies passed on
AssumeRoleorGetFederationToken.
Evaluation rules across the full set:
- Start from an implicit deny (default).
- Any explicit Deny in any applicable policy → final answer Deny. Full stop.
- Otherwise, if at least one of the applicable policies contains an explicit Allow for the action, the final answer is Allow.
- If no policy contains an explicit Allow, the implicit deny stands and the final answer is Deny.
Within an AWS Organizations context with SCPs, the SCP must also allow the action; if the SCP denies or doesn't allow it, no identity-based policy can make the action succeed.
Diagram in words
Imagine a chain of filters. A request passes only if every applicable filter says "no explicit deny, and at least one allow exists somewhere in the relevant scope":
- SCP allows (or no SCP present) → pass
- Resource policy: no explicit deny → pass
- Identity policy: no explicit deny → pass
- Permissions boundary: no explicit deny and the action is allowed within the cap → pass
- Session policy (if present): no explicit deny and the action is within the cap → pass
- Somewhere in the above, an explicit Allow exists → final Allow
Any single link that contains an explicit Deny, or that fails to contain an Allow when required (identity policy + permissions boundary + session policy all must allow the action if they exist), causes the request to fail.
Commit this sequence to memory for SAA-C03:
- If any applicable policy contains an explicit Deny for this action on this resource, the request is denied. Nothing overrides an explicit deny.
- If no explicit deny exists and at least one applicable policy contains an explicit Allow, the request is allowed.
- If no explicit deny exists and no explicit allow exists, the implicit (default) deny wins — the request is denied.
This is the core of IAM identity and access control policy evaluation logic and is tested in almost every SAA-C03 exam form. Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html
Worked example
A developer's IAM user in Account A has AmazonS3FullAccess. Their IAM user belongs to an IAM group with an inline policy Deny s3:DeleteObject on bucket logs-critical. They call DeleteObject on an object in logs-critical.
- AWS-managed policy on user: Allow
s3:*. - Inline group policy: Deny
s3:DeleteObjectonlogs-critical. - Final decision: Deny, because the explicit deny overrides the allow.
Now change the bucket: DeleteObject on logs-noncritical:
- AWS-managed policy on user: Allow
s3:*. - Inline group policy: no match (different bucket).
- Final decision: Allow, because no applicable deny exists and an allow does.
IAM Roles vs IAM Users — When to Use Each at SAA-C03 Depth
At Cloud Practitioner depth, "role = temporary, user = permanent" is enough. At SAA-C03 depth, you need to pick between them in design scenarios.
Choose an IAM role when
- An AWS service needs access to another AWS service (EC2 → S3, Lambda → DynamoDB, ECS task → SQS). Always use the service-native role pattern: EC2 instance profile, Lambda execution role, ECS task role, EKS IRSA (IAM Roles for Service Accounts).
- A workload in one AWS account needs access to resources in another AWS account. Use cross-account role assumption.
- Corporate employees sign in through a SAML 2.0 or OIDC identity provider. Use federation that maps to IAM roles (directly or via IAM Identity Center).
- A mobile/web app needs short-lived AWS credentials for end users. Use Amazon Cognito identity pools → IAM role.
Choose an IAM user only when
- A legacy or third-party tool absolutely cannot assume roles.
- An on-premises script is genuinely outside any federation story.
- Even then, apply MFA, tight least-privilege IAM policies, regular access key rotation, and consider IAM Roles Anywhere for on-prem workloads with an X.509 certificate.
Side-by-side
| Aspect | IAM User | IAM Role |
|---|---|---|
| Credential lifetime | Long-term (password + access keys) | Short-term STS session credentials |
| Password? | Optional | Never |
| Session token? | No (long-term access keys) | Always (access key ID + secret + session token) |
| Default session duration | N/A | 1 hour (configurable 15 min – 12 h for most flows) |
| Who can use it? | A specific person or external system | Any principal allowed by the role's trust policy |
| Best SAA-C03 fit | Rare — only true long-term external identities | The default for AWS services, cross-account, federation |
| Exam clue words | "long-term", "console login", "individual user" | "EC2 instance needs...", "cross-account", "temporary", "federation", "Lambda role" |
A SAA-C03 trap pattern: an answer choice that describes "an IAM user with temporary credentials issued by STS" or "an IAM role with a console password". Neither exists in IAM identity and access control. IAM users always carry long-term credentials and optionally a password; IAM roles never have a password, never hold long-term credentials, and always return a short-term access key ID + secret access key + session token triple when assumed. If the scenario mentions EC2 needing S3, Lambda needing DynamoDB, or Account A reaching Account B for 1 hour — answer is an IAM role. Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html
Cross-Account Access via Role Assumption and AWS STS
Cross-account access is the single most-tested IAM identity and access control scenario on SAA-C03. Expect two or three variants per exam form.
The pattern
Suppose a Lambda function in Account A (account ID 111111111111) needs to read objects from an S3 bucket in Account B (account ID 222222222222).
- In Account B, create an IAM role
CrossAccountS3Reader:- Trust policy (who may assume): allows principal
arn:aws:iam::111111111111:root(or a narrower principal such as the Lambda execution role ARN) to callsts:AssumeRole. - Permissions policy (what the role can do once assumed): allows
s3:GetObjecton the bucket.
- Trust policy (who may assume): allows principal
- In Account A, the Lambda execution role has an identity-based policy allowing
sts:AssumeRoleon the role ARNarn:aws:iam::222222222222:role/CrossAccountS3Reader. - At runtime, the Lambda code calls
sts:AssumeRolewith the target role ARN. AWS STS returns short-term credentials. The Lambda uses those credentials to calls3:GetObject. - Inside Account B, the request is now made by the assumed role, so the role's own identity-based policy is what matters. No additional bucket policy is required.
sts:AssumeRole essentials
- Default session duration: 1 hour.
- Maximum session duration on the role: 1 – 12 hours (configurable on the role itself).
- External ID: an optional string required by the trust policy to prevent the "confused deputy" problem when a third-party AWS account assumes a role in your account.
- MFA required: a trust policy condition
aws:MultiFactorAuthPresent: trueforces the assuming principal to present an MFA token. - Session policies: you can pass an inline IAM policy on AssumeRole to further narrow the role's effective permissions for that session — never to expand them.
Other STS APIs worth knowing
- AssumeRoleWithSAML — for SAML 2.0 identity federation (Microsoft Entra ID, ADFS, Okta).
- AssumeRoleWithWebIdentity — for OIDC/web identity federation (Amazon Cognito identity pools, Google, Facebook).
- GetFederationToken — legacy, for proxy applications that manage federated users without using a true IdP.
- GetSessionToken — returns temporary credentials for an IAM user, typically to satisfy an MFA requirement for CLI access.
- Trust policy on the role in Account B says who may assume (uses a
Principalelement — this is a resource-based policy). - Identity-based policy on the caller in Account A allows
sts:AssumeRoleon the role ARN. - Permissions policy on the role in Account B grants what the role can do once assumed.
All three must align. Default session 1 hour, max 12 hours. Use an External ID for third-party vendor trust. Reference: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html
The confused deputy problem and External ID
A third-party SaaS tool asks you to grant it an IAM role in your AWS account so it can monitor your resources. Without protection, another customer of that same SaaS vendor could trick it into using your role. The External ID is a secret string that the trust policy requires on every AssumeRole call; the SaaS vendor passes the right External ID per customer, which binds the assumption to that specific customer relationship. This is a classic SAA-C03 scenario.
Principle of Least Privilege — Managed Policies, Inline Policies, Boundaries, Sessions
Least privilege is the foundational IAM identity and access control principle: grant each principal only the permissions required for the task, for the shortest time necessary. It is the best practice AWS cites most often and it appears in scenario questions throughout SAA-C03.
Start narrow and widen as needed
Begin every customer-managed IAM policy with the minimum set of API actions on specific resource ARNs. Avoid starting from Action: "*" and "peeling back". Use AWS-managed policies as a baseline only if they closely match the job function; otherwise write your own customer-managed policy.
Permissions boundaries
A permissions boundary is an advanced IAM feature that attaches a second policy to an IAM user or IAM role. That second policy does not grant anything — it caps what identity-based policies can grant. The effective permission is the intersection of the identity-based policy and the permissions boundary.
Permissions boundaries are used when a team lead needs to delegate IAM user/role creation to a developer, but wants to guarantee the developer can never create a role with admin powers. The boundary enforces "whatever you grant, it cannot exceed this cap".
Session policies
A session policy is an inline IAM policy passed at the moment a role is assumed (via sts:AssumeRole or GetFederationToken). It can only narrow the role's permissions for the specific session, never widen them. Useful for handing a shorter-lived, lower-privilege scope to a sub-workflow.
IAM Access Analyzer
AWS IAM Access Analyzer is the feature you reach for when SAA-C03 asks "how do I find over-permissioned policies?" or "how do I generate a least-privilege policy?". It has three main capabilities:
- External access findings — continuously scans resource-based policies (S3, KMS, Lambda, SQS, SNS, Secrets Manager, and more) for grants to principals outside a zone of trust.
- Unused access findings — identifies IAM users/roles that haven't been used, and specific permissions on policies that are unused.
- Policy generation from CloudTrail — observes real API activity for an identity and generates a refined IAM policy containing only the actions it actually used.
When SAA-C03 asks "how does an organization ensure IAM policies grant only necessary permissions?" or "how do we find cross-account shares that weren't intended?", the expected answer is AWS IAM Access Analyzer. It's the AWS IAM feature explicitly named in best-practice documentation. Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html
Root Account Security — MFA, Access Keys, and What Only Root Can Do
The root user is the original email-address-based owner of the AWS account. It has unconditional, unrestricted access to every resource and every billing setting. That power is also why the root user is the biggest risk on the account and a frequent SAA-C03 topic.
Tasks only the root user can perform
- Change the AWS account's root email address or root password.
- Change the AWS account name.
- Close the AWS account.
- Change or cancel AWS Support plans.
- Restore IAM permissions if every administrator IAM user has been locked out.
- Register as a seller in AWS Marketplace.
- Enable invoice tax settings and some billing configurations.
Best practices for root
- Enable MFA on the root user immediately. Passkeys or hardware MFA (FIDO2) preferred; virtual MFA acceptable.
- Delete any root access keys. Programmatic use of root is strongly discouraged; use an IAM user or role instead.
- Use a strong, unique password.
- Use root only for one-time setup and root-only tasks. Create an administrator IAM user or an IAM Identity Center user with AdministratorAccess for day-to-day admin.
- Don't share root credentials. Every admin should have their own identity.
Root is not subject to IAM policies the way other identities are. Attaching a policy to the root user that denies actions is not an effective control — root bypasses it. Even AWS Organizations SCPs do not restrict the root user of the management account (they can restrict root in member accounts). The only effective root protection is not using the root user — MFA on, credentials locked away. Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html
Authentication Methods: MFA Types, Access Keys, Password Policies
IAM identity and access control supports multiple authentication factors. SAA-C03 expects you to tell them apart.
Console password + password policy
Every IAM user can optionally have a console password. A per-account IAM password policy enforces minimum length, character complexity, rotation windows, reuse prevention, and whether users can change their own passwords. The password policy applies to all IAM users in the account but does not apply to the root user (root has its own unchangeable minimum requirements).
Access keys
Access keys are the long-term credentials used by AWS CLI, AWS SDKs, and AWS PowerShell. Each IAM user can have up to 2 active access keys at a time to support rotation — provision a new key, cut the workload over, then delete the old key with zero downtime. Programmatic workloads should use IAM roles (EC2 instance profile, Lambda execution role, ECS task role, IAM Roles Anywhere for on-prem) instead of long-term access keys whenever possible.
MFA — virtual, hardware, and passkeys
Multi-factor authentication adds a second factor on top of the password. IAM supports:
- Virtual MFA device — an authenticator app (Google Authenticator, Authy, 1Password, Duo) producing a rotating 6-digit TOTP. Cheapest and most common.
- Hardware MFA device — a physical key fob (Gemalto/SafeNet) or a FIDO2 security key (YubiKey). Secret cannot be copied off the device.
- Passkey / FIDO2 authenticator — iOS, Android, macOS, Windows Hello, and hardware security keys. Phishing-resistant and the preferred modern factor for both IAM users and the root user.
MFA is free — there is no AWS charge to enable it. You only pay if you buy a physical hardware token.
- Root user: MFA mandatory as a design default; passkey or hardware MFA preferred.
- IAM users with elevated privileges: MFA required.
- Up to 2 active access keys per IAM user (for rotation).
- Default session token duration for assumed roles: 1 hour; max 12 hours for most flows (15 min min).
- Password policy applies to IAM users, not the root user.
- Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa.html
Key Numbers to Memorize for IAM Identity and Access Control
Numbers are easy points on SAA-C03 if you have them memorized. This list covers the IAM identity and access control numeric traps the exam leans on.
- IAM is global, not region-scoped. IAM is free to use.
- 2 active access keys per IAM user (for rotation).
- 5 versions kept per customer-managed IAM policy.
- 6,144 characters maximum size for a managed IAM policy (JSON).
- 2,048 characters maximum size for an inline IAM user policy.
- 10,240 characters maximum size for an inline IAM role or group policy.
- 10 managed policies attached per IAM user/role/group by default (increase available).
- 1 hour default AssumeRole session duration; 15 min – 12 hours configurable.
- 1 hour default for AssumeRoleWithSAML and AssumeRoleWithWebIdentity.
- Up to 12 hours maximum role session duration (per-role max session setting).
- 300 IAM roles per AWS account by default (service quota, increase available).
- 5,000 IAM users per AWS account by default.
- 300 IAM groups per AWS account by default.
- Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html
Common Exam Traps — IAM Identity and Access Control
Expect several of these per SAA-C03 exam form. Learning to spot the pattern before reading the answers is half the battle.
Trap 1: IAM role vs IAM user
Any answer choice describing "an IAM user with STS temporary credentials" or "an IAM role with a password and long-term access keys" is a distractor. Users = long-term credentials, optional password. Roles = short-term STS credentials (access key + secret + session token), no password, no persistent access keys.
Trap 2: Explicit deny vs no permission
A scenario says "a user has s3:* in one policy but still cannot delete an object. Why?" Possible answers include "policy is misconfigured", "bucket policy missing", etc. The winner is usually an explicit deny exists somewhere — an SCP denies, the bucket policy denies, a permissions boundary denies, or a group policy denies. Explicit deny always wins over explicit allow.
Trap 3: Cross-account — which side hosts the role?
A common confusion: "Account A needs to read S3 in Account B. Where do I create the IAM role?" The role lives in Account B (the account that owns the resource). Account A gets an identity-based policy allowing sts:AssumeRole on the role ARN in Account B. The trust policy on the role in B allows A to assume it.
Trap 4: Resource-based policy vs identity-based policy
If the exam asks about KMS keys (which require a key policy) or S3 bucket policies being the right place to grant cross-account access, that is a resource-based policy question. If it is about "what can this user do generally", that is identity-based. KMS is especially strict: without the key policy allowing access, no IAM policy can grant it.
Trap 5: IAM is NOT region-scoped
Any answer describing creating IAM users per region, replicating IAM policies across regions, or picking a region for IAM is wrong. IAM is a global service. STS, however, has regional endpoints (and a legacy global endpoint). Favor regional STS endpoints for latency and resilience.
Trap 6: SCPs restrict; they never grant
An SCP allowing s3:DeleteBucket does not by itself grant that permission — an IAM policy in the member account still has to grant it. Conversely, an SCP denying an action blocks it regardless of any IAM policy below. On SAA-C03: when the user "has an admin policy but still can't do X", SCPs are a prime suspect.
Trap 7: Permissions boundaries don't grant either
A permissions boundary is a cap, not a grant. A principal with a boundary but no identity-based policy has no permissions — the boundary only limits how much an identity-based policy can grant.
Trap 8: Session policies only narrow
When you pass a session policy on AssumeRole, it can only restrict the role's effective permissions for that session. You cannot widen permissions at assume time.
Trap 9: Trust policy is a resource-based policy
The trust policy attached to an IAM role is technically a resource-based policy — the role itself is the resource, and the trust policy specifies which principals can assume it. This matters because editing the trust policy is how you change cross-account access.
Trap 10: Service-linked roles are special
Service-linked roles (SLRs) are pre-defined roles created by AWS services (Auto Scaling, Organizations, Trusted Advisor) for themselves. They are tied to the service, often cannot be deleted while the service is in use, and have pre-authored permissions you should not edit. If a scenario asks about Auto Scaling automatically managing EC2, the SLR story is "already set up for you".
IAM vs Resource-Based Policy for Cross-Account — A Decision Tree
Here is the decision flow SAA-C03 expects you to internalize.
- Is the workload crossing AWS account boundaries?
- No → identity-based policy on the caller is enough.
- Yes → continue.
- Is the target resource a service that supports resource-based policies (S3, KMS, Lambda, SNS, SQS, Secrets Manager, ECR, API Gateway, OpenSearch)?
- Yes → you can do it two ways.
- Option A — resource-based policy on the target resource allowing the principal in the other account, plus identity-based policy in the caller's account. No role assumption needed. Great for simple, read-only cross-account shares.
- Option B — cross-account IAM role in the target account with a trust policy allowing the caller. Cleaner audit trail, tighter least privilege, required when the target doesn't support a resource-based policy or when you want to enforce MFA/ExternalId on assumption.
- No → you must use Option B (role assumption).
- Yes → you can do it two ways.
- Is a third-party vendor involved?
- Yes → use cross-account role with External ID in the trust policy to prevent confused deputy.
- Do you need MFA on cross-account access?
- Yes → add
aws:MultiFactorAuthPresent: truecondition to the trust policy.
- Yes → add
IAM Identity and Access Control vs VPC and Encryption — Where IAM Stops
IAM identity and access control is one layer of defense. It decides whether an API call is allowed. It does not decide whether network traffic can reach the resource (that's VPC security groups, NACLs, and endpoints) and it does not decide whether data at rest is unreadable if exfiltrated (that's KMS encryption and S3 bucket encryption settings).
A secure design uses all three: IAM identity and access control to authorize API calls, VPC constructs to limit network paths, and encryption with key policies to protect data even if the other layers fail. SAA-C03 scenarios often reward answers that combine multiple layers — for example, "least-privilege IAM role + VPC endpoint with endpoint policy + SSE-KMS with key policy restricting decrypt".
IAM Identity Center — The Workforce Upgrade Above AWS IAM
While the deep mechanics of IAM Identity Center (SSO) belong to the multi-account-federation topic, you should know the boundary for this one:
- AWS IAM is the in-account, global primitive that handles IAM users, IAM roles, IAM policies, and STS-issued credentials.
- IAM Identity Center sits on top of AWS Organizations, federates workforce identities across many AWS accounts, and materializes permission sets as IAM roles inside each target account automatically.
If SAA-C03 asks about giving employees single sign-on across many accounts with SAML/OIDC, that's IAM Identity Center. If it asks about granting an EC2 instance access to S3, that's an IAM role attached as an instance profile. Those are different tools for different jobs.
FAQ — IAM Identity and Access Control Top 6 Questions
Q1: How exactly does IAM policy evaluation logic resolve conflicts between an Allow and a Deny?
IAM identity and access control starts every evaluation from an implicit deny. It then collects every applicable policy: SCPs, resource-based policies, identity-based policies, permissions boundaries, and session policies. If any applicable policy contains an explicit Deny for this action on this resource, the final answer is Deny. If no explicit Deny exists and at least one applicable policy contains an explicit Allow (and all required scopes like permissions boundaries also allow it), the final answer is Allow. Otherwise the implicit deny stands. The single most important takeaway: an explicit Deny always overrides an explicit Allow, no matter where the Deny came from.
Q2: When do I need a resource-based policy in addition to an identity-based policy?
For same-account access, an identity-based policy on the caller is enough for almost every AWS service. For cross-account access, you need both an identity-based policy in the caller's account and a resource-based policy in the target account — unless you use the role assumption pattern, in which case the role's trust policy (itself a resource-based policy on the role) replaces the need for a resource-based policy on the target resource. Two AWS services are exceptions where a resource-based policy is effectively always required: AWS KMS (every key has a mandatory key policy) and AWS Lambda invocation from cross-account principals (resource-based policy on the function).
Q3: What is the cleanest way to let a Lambda in Account A write to an S3 bucket in Account B?
Two clean options. Option A — bucket policy: add a resource-based S3 bucket policy in Account B allowing s3:PutObject from the Lambda's execution role ARN in Account A, plus an identity-based policy on the Lambda execution role allowing s3:PutObject on that bucket. Option B — cross-account role: create an IAM role in Account B with a trust policy allowing the Lambda execution role to assume it, and a permissions policy allowing s3:PutObject; have the Lambda call sts:AssumeRole and use the returned credentials. Option B has tighter auditability and lets you add MFA/ExternalId conditions; Option A is simpler for low-complexity, one-way writes. If SSE-KMS is involved, the KMS key policy in Account B must also allow the Lambda role — KMS is a frequent SAA-C03 gotcha.
Q4: How should I protect the root user for a new AWS account?
Enable MFA on the root user immediately — a hardware FIDO2 key or passkey is ideal, a virtual MFA device is acceptable. Delete any existing root access keys. Set a strong, unique password and lock the credentials in a secure vault. Create a dedicated administrator identity (an IAM Identity Center user is the modern best practice; an IAM user with the AdministratorAccess managed policy is acceptable) for every day-to-day admin task. Use the root user only for the handful of root-only actions like closing the account, changing the root email, or registering in AWS Marketplace. Never embed root credentials in scripts, CI/CD, or applications.
Q5: What's the difference between a permissions boundary and a session policy?
A permissions boundary is an IAM policy attached to an IAM user or IAM role that caps the maximum permissions identity-based policies can grant to that principal. It doesn't grant anything itself — the effective permission is the intersection of identity-based policies and the boundary. A session policy is an inline IAM policy passed on sts:AssumeRole (or GetFederationToken) that further narrows the permissions of that specific session, without modifying the underlying IAM role or user. Boundaries persist on the identity; session policies live only for the one STS session. Both are ways to enforce least privilege — boundaries for delegation (a team lead capping what a developer-created role can do) and session policies for fine-grained per-session narrowing.
Q6: How do I pick between AWS-managed, customer-managed, and inline IAM policies?
AWS-managed policies are maintained by AWS (ReadOnlyAccess, AmazonS3FullAccess). Use them as a starting point when the job function matches closely and you don't need to tune wording. Customer-managed policies are authored by you, reusable across identities, versioned (5 versions retained), and are the sweet spot for IAM identity and access control: most production workloads should live here with least-privilege phrasing. Inline policies are embedded directly in one identity and cannot be reused. Use them only when you want a strict 1:1 tie between an identity and its permissions (for example, a single-purpose IAM role that must never grow unrelated permissions). SAA-C03 best-practice guidance: prefer managed over inline, prefer customer-managed over AWS-managed when a bespoke least-privilege policy is needed.