2.1 IAM for Developers

Key Takeaways

  • IAM evaluation always follows the same order: an explicit Deny overrides every Allow, and with no matching Allow the default is an implicit deny
  • Identity-based policies attach to users, groups, or roles; resource-based policies (S3 bucket, SQS queue, KMS key, Lambda) attach to the resource and name a Principal
  • Grant AWS access to running code with roles (EC2 instance profiles, Lambda execution roles, ECS task roles), never long-lived access keys baked into the app
  • STS AssumeRole returns short-lived credentials and is the basis for cross-account access; use an External ID to prevent the confused-deputy problem with third parties
  • Permission boundaries, SCPs, and session policies set a ceiling on permissions but never grant access on their own
Last updated: June 2026

Why IAM Matters on DVA-C02

Security accounts for 26% of the DVA-C02 exam (the second-largest domain, behind Development with AWS Services at 32%, on a 65-question, 130-minute test scored 100–1000 with a 720 passing line), and Identity and Access Management (IAM) questions dominate it. Most are scenarios: an application throws an AccessDeniedException, or you must pick the most secure way to grant a permission. The correct answer almost always involves an IAM role with least privilege, not a hard-coded access key.

Identities: Users, Groups, Roles

  • IAM user — a long-term identity (a person or service) with a console password and/or access keys. Discouraged for application code because the keys are static and easily leaked.
  • IAM group — a collection of users; attach a policy once and every member inherits it. Groups cannot be assumed and cannot be nested inside other groups.
  • IAM role — an identity assumed temporarily that hands out short-lived credentials with no embedded secret. This is the preferred mechanism for EC2, Lambda, ECS, and any cross-account access.

Anatomy of a Policy Statement

Every JSON policy statement combines Effect (Allow/Deny), Action (e.g. s3:GetObject), Resource (an ARN), and optional Principal and Condition blocks. Wildcards (s3:*, arn:aws:s3:::bucket/*) widen scope; least privilege narrows it. The exam expects you to read a statement and predict the outcome.

Identity Policy vs Resource Policy

This distinction is a favorite trap. Both are JSON, but they answer different questions.

Identity-based policyResource-based policy
Attached toUser, group, or roleThe resource (S3 bucket, SQS queue, KMS key, Lambda)
Names a Principal?NoYes — defines who may act
Cross-accountNeeds a role + AssumeRoleCan grant another account directly

For same-account access you only need an Allow on either side. Across accounts you typically need an Allow on both sides — the resource policy permits the external principal, and the principal's identity policy permits the action.

Policy Evaluation: Deny Wins

IAM gathers every applicable policy — identity, resource, permission boundary, Service Control Policy (SCP), and session policy — and applies one rule:

  1. Explicit Deny anywhere → request denied. Nothing overrides it.
  2. No explicit Deny + at least one Allow → request allowed.
  3. No Allow at all → implicit deny (the default starting state).

Roles, STS, and Least Privilege

AWS Security Token Service (STS) issues temporary credentials when an identity calls AssumeRole. A role carries two policies: a trust policy (the Principal allowed to assume it) and a permissions policy (what the session may do). EC2 uses an instance profile, Lambda an execution role, and ECS a task role — the SDK fetches and auto-rotates the credentials, so no keys touch your code.

For third-party (cross-account) access, add an External ID as a Condition (sts:ExternalId) in the trust policy to block the confused-deputy problem. The confused deputy occurs when a trusted intermediary (for example, a monitoring SaaS) is tricked into using its access on behalf of an attacker; the External ID is a secret only you and the legitimate partner know, so a third party cannot impersonate them even if they learn your role ARN. Use policy variables like ${aws:username} and Condition keys such as aws:SourceIp, aws:SecureTransport, or aws:MultiFactorAuthPresent to scope access tightly.

Permission Boundaries vs SCPs vs Session Policies

The exam often layers several guardrails and asks for the effective permission. Keep them straight:

  • Permission boundary — an advanced policy attached to a user or role that caps its maximum permissions. Effective permission is the intersection of the identity policy and the boundary. It grants nothing on its own.
  • Service Control Policy (SCP) — an AWS Organizations guardrail applied to whole accounts/OUs. It also only filters; it never grants. An action must be allowed by the identity policy and not blocked by any SCP.
  • Session policy — passed inline during AssumeRole/GetFederationToken to further restrict that one session.

The golden rule across all of them: a guardrail can only narrow, never widen. For an action to succeed it must be Allowed by an identity (or resource) policy and survive every boundary, SCP, and session policy, with no explicit Deny anywhere.

Practical Least-Privilege Workflow

Developers are expected to start narrow and widen only as needed. Use IAM Access Analyzer to generate a policy from CloudTrail activity, scope Resource to specific ARNs instead of *, prefer roles over users, and rotate or eliminate any long-lived access keys. When code runs on AWS compute, the SDK's default credential provider chain automatically discovers role credentials from the instance profile, ECS task metadata endpoint, or Lambda environment — so correct code never needs an embedded key at all.

Debugging AccessDenied Errors

Many DVA-C02 questions hand you an AccessDeniedException and a set of policies, then ask which fix is correct. Work the evaluation logic in order: first scan every attached policy (identity, resource, boundary, SCP, session) for an explicit Deny — if one matches the action and resource, that is the cause, and no Allow can save it. If there is no Deny, confirm at least one Allow matches the exact Action and Resource ARN; a wildcard mismatch (granting s3:GetObject on bucket but not bucket/*) is a frequent trap. For cross-account calls, verify the Allow exists on both the identity side and the resource side.

Finally, confirm the request satisfies every Condition (such as a required source IP, MFA, or SecureTransport) — a failed condition turns an apparent Allow into an effective deny.

Test Your Knowledge

A Lambda function's identity-based execution role contains an Allow for s3:GetObject on a bucket. The bucket policy contains an explicit Deny for that same Lambda role. Can the function read the object?

A
B
C
D
Test Your Knowledge

A developer must let a partner's separate AWS account assume a role in your account, but only when the partner supplies a shared secret value. Which element of the role's trust policy addresses the confused-deputy risk?

A
B
C
D
Test Your Knowledge

An EC2-based application authenticates to DynamoDB using an IAM user's access keys stored in a config file. What is the most secure way to grant the same access?

A
B
C
D