AWS Systems Architect Professional

AWS IAM Policy Structure: Actions, Resources, and JSON – SAP-C02 Study Guide

Learn how to read AWS IAM JSON policies, including statements, effects, API actions, resources, wildcards, S3 ARN scope, and DynamoDB permissions.

AWS Systems Architect ProfessionalAWS Systems Architect ProfessionalUpdated Sep 1, 2026
Study options
WatchComing later
ListenComing later
ReadAvailable
ReviewComing later

Study guide

Technical reference and lesson notes

Purpose of This Lesson

AWS Identity and Access Management (IAM) policies define which API operations a principal may perform against which AWS resources. Understanding policy structure is essential for creating least-privilege permissions and interpreting AWS security scenarios.

Every action performed through the AWS Management Console, AWS CLI, SDK, or another AWS service ultimately results in an AWS API call. IAM evaluates policies against those API calls.

Key Concepts

IAM policies use JSON

IAM policies are written in JavaScript Object Notation (JSON). A policy contains one or more statements. Each statement describes a permission or restriction.

A typical policy structure is:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::example-bucket"
      ]
    }
  ]
}

The Version field identifies the IAM policy language version. 2012-10-17 is the commonly used policy version and is not intended to represent the date the policy was created.

Statements

The Statement element contains the individual permission statements. A policy can contain multiple statements, allowing different actions, resources, or conditions to be expressed separately.

When a policy contains multiple JSON objects in the statement array, each object must be separated by a comma. Invalid JSON formatting prevents the policy from being accepted.

Effect

Effect determines whether the statement grants or removes permission. The valid values are:

  • Allow
  • Deny

The effect applies to the actions and resources specified in that statement.

Action

Action identifies the AWS API operations covered by the statement. Actions use the format:

service:api-operation

Examples include:

  • ec2:RunInstances
  • rds:StopDBInstance
  • s3:ListBucket
  • dynamodb:DescribeTable

A wildcard can broaden the action scope. For example:

"Action": "s3:*"

This represents all IAM actions in the Amazon S3 service. A narrower wildcard such as dynamodb:Describe* represents DynamoDB API actions whose names begin with Describe.

Use broad wildcards cautiously. service:* can grant substantially more access than an application needs and may violate least-privilege requirements.

Resource

Resource identifies the AWS resources to which the actions apply. Resources are normally specified using Amazon Resource Names (ARNs).

An ARN commonly includes information such as:

  • AWS service
  • Region, when applicable
  • AWS account ID, when applicable
  • Resource type and name

For example, a DynamoDB table ARN identifies a specific table in a specific Region and account:

arn:aws:dynamodb:us-east-1:123456789012:table/Orders

A wildcard in the resource can represent multiple resources, but the exact meaning depends on where it appears in the ARN.

S3 bucket and object resources are different

Amazon S3 distinguishes between bucket-level and object-level resources. These are different ARN scopes:

arn:aws:s3:::example-bucket
arn:aws:s3:::example-bucket/*

The first ARN identifies the bucket itself. The second identifies objects inside the bucket.

A statement that grants access to both the bucket and its objects generally needs both resource forms. For example:

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

The bucket ARN is used for bucket operations such as listing a bucket. The object ARN is used for operations against the files stored in the bucket, such as reading or uploading objects.

A common mistake is to specify only arn:aws:s3:::example-bucket while attempting to grant object access. That does not automatically include the objects beneath the bucket.

Exam-Relevant Takeaways

  • Console activity, CLI commands, and SDK calls invoke AWS API actions.
  • IAM Action values identify those API operations.
  • Effect can only be Allow or Deny.
  • A policy can contain multiple statements.
  • service:* is a wildcard for all actions in that service.
  • Describe* or a similar pattern can match multiple API actions with the same prefix.
  • Resource specifies the target ARN or ARNs.
  • S3 bucket-level and object-level permissions use different ARNs.
  • arn:aws:s3:::bucket-name refers to the bucket; arn:aws:s3:::bucket-name/* refers to objects within it.
  • A syntactically valid policy can still be logically incorrect if the action and resource types do not match.
  • Prefer narrowly scoped actions and resources instead of broad wildcards whenever the requirements permit.

Architecture Decision Guide

RequirementPolicy design approachImportant consideration
Permit one specific API operationSpecify the exact action, such as s3:GetObjectBest supports least privilege
Permit several related API operationsUse an explicit action list or a carefully scoped wildcard such as dynamodb:Describe*Verify that the wildcard does not include unintended operations
Permit all actions for a serviceUse service:*Broad permission; generally unsuitable for tightly scoped application roles
Permit an S3 bucket operationUse the bucket ARN, such as arn:aws:s3:::bucket-nameRequired for bucket-level APIs such as listing
Permit access to S3 objectsUse arn:aws:s3:::bucket-name/*Required for object-level APIs such as getting or putting objects
Permit access to a specific DynamoDB tableUse the table ARNInclude the correct Region, account, and table name
Grant different permissions to different targetsUse multiple statementsKeep each statement’s action/resource relationship clear

Common Exam Traps

Confusing a service wildcard with a resource wildcard

These are different:

  • s3:* means all S3 API actions.
  • arn:aws:s3:::example-bucket/* means all objects under one S3 bucket.

The first broadens the action set; the second broadens the resource set.

Using only the S3 bucket ARN for object access

The bucket ARN does not represent every object in the bucket. Object actions generally require the ARN ending in /*.

Assuming one statement must contain every permission

A policy can contain multiple statements. Separating bucket-level and object-level permissions is often clearer and necessary because they use different resources.

Overlooking API action names

IAM permissions are based on API actions, not console labels. A console task may invoke several API operations, and granting one obvious-looking action may not be sufficient for the complete workflow.

Treating Describe* as one action

A wildcard action pattern can match multiple API operations. Review the resulting permission scope rather than assuming it grants only one read operation.

Ignoring JSON syntax

Missing commas, braces, brackets, or quotation marks make the policy invalid. Use the IAM Policy editor or a JSON-aware editor to validate syntax before deployment.

Assuming an ARN format is universal

ARN formats vary by service. Some include Region and account information, while others do not. Use the documented ARN format for the specific AWS service and resource type.

Real-World Engineer Notes

  • Start with exact API actions and exact resource ARNs. Expand permissions only when a documented application requirement demands it.
  • Separate permissions by purpose, such as bucket listing versus object read/write access, to make review and troubleshooting easier.
  • Test policies with IAM policy validation and simulation tools where appropriate, but also verify the application workflow because a successful policy simulation may not cover every API call made by a service or SDK.
  • Be careful when copying examples between Regions, accounts, or environments. Account IDs, Regions, resource names, and ARN formats may need to change.
  • Broad permissions such as s3:* or Resource: "*" increase operational risk. They should be treated as deliberate exceptions rather than convenient defaults.
  • When a console workflow fails, identify the underlying API operation and compare it with the policy’s Action and Resource values.

Quick Reference Summary

ElementMeaningExample
VersionIAM policy language version"2012-10-17"
StatementOne or more permission definitions[ { ... } ]
EffectGrants or denies access"Allow"
ActionAWS API operation or operation pattern"ec2:RunInstances"
ResourceARN of the target resource"arn:aws:dynamodb:...:table/Orders"
* in an actionWildcard matching actions"s3:*"
S3 bucket ARNBucket-level targetarn:aws:s3:::example-bucket
S3 object ARNObject-level targetarn:aws:s3:::example-bucket/*

Flashcards

  1. Q: What does an IAM policy Action represent?

A: An AWS API operation, such as ec2:RunInstances or rds:StopDBInstance.

  1. Q: What values are valid for the IAM Effect element?

A: Allow and Deny.

  1. Q: Can one IAM policy contain multiple statements?

A: Yes. The Statement element can contain multiple permission statement objects.

  1. Q: What does s3:* mean in an IAM action field?

A: All IAM actions for the Amazon S3 service.

  1. Q: What does an action pattern such as dynamodb:Describe* do?

A: It matches DynamoDB API actions beginning with Describe.

  1. Q: What does arn:aws:s3:::example-bucket identify?

A: The S3 bucket itself.

  1. Q: What does arn:aws:s3:::example-bucket/* identify?

A: Objects stored within the bucket.

  1. Q: Why might an S3 policy need both a bucket ARN and an object ARN?

A: Bucket-level and object-level API operations use different resource scopes.

  1. Q: What does the Version field in an IAM policy indicate?

A: The version of the IAM policy language being used.

  1. Q: What is the difference between s3:* and an S3 ARN ending in /*?

A: s3:* broadens the API actions; the ARN ending in /* broadens the targeted objects within a bucket.

Practice Questions

Question 1

An application must list the contents of an S3 bucket named reports-prod. Which resource ARN should be used for the s3:ListBucket permission?

A. arn:aws:s3:::reports-prod/*
B. arn:aws:s3:::reports-prod
C. arn:aws:s3:*:*:reports-prod
D. arn:aws:iam:::reports-prod

Correct answer: B

Explanation: s3:ListBucket is a bucket-level operation, so it uses the bucket ARN without /*.

Question 2

A role can list an S3 bucket but receives AccessDenied when reading files from it. The policy allows s3:ListBucket on arn:aws:s3:::data-bucket but has no object resource. What is the most likely correction?

A. Change the action to s3:* on the bucket ARN only
B. Add s3:GetObject on arn:aws:s3:::data-bucket/*
C. Add s3:GetBucket on the object ARN
D. Replace the bucket ARN with an IAM role ARN

Correct answer: B

Explanation: Listing the bucket and reading objects are separate permission scopes. Object reads require s3:GetObject against the object ARN.

Question 3

A policy contains "Action": "dynamodb:Describe*". What does this permission represent?

A. Only the DescribeTable operation
B. All actions in DynamoDB
C. DynamoDB API actions whose names begin with Describe
D. All actions against every DynamoDB table

Correct answer: C

Explanation: The wildcard applies to the API operation name after the service prefix. It does not grant all DynamoDB actions or automatically define all resources.

Question 4

An engineer adds a second statement object to an IAM policy but forgets the comma between the two objects. What is the expected result?

A. AWS silently combines the statements
B. Only the first statement is evaluated
C. The policy is invalid JSON and cannot be accepted as written
D. The second statement becomes an implicit deny

Correct answer: C

Explanation: IAM policies must be valid JSON. Missing commas and other syntax errors prevent the policy from being parsed correctly.

Question 5

A security team wants a role to stop one RDS DB instance rather than all RDS resources. Which design best supports that requirement?

A. Allow rds:* on *
B. Allow rds:StopDBInstance and specify the target DB instance ARN where supported
C. Allow ec2:StopInstances on the DB instance ARN
D. Allow rds:Describe* only

Correct answer: B

Explanation: IAM policies should identify the required service API action and restrict the resource to the intended target whenever the service supports resource-level permissions.