My last blog post explored the service IAM, which stands for Identity and Access Management, as a Cloud architect for AWS infrastructure. We weren't looking at IAM as a System Administrator. Instead, we were examining IAM to gain a conceptual understanding of how AWS enforces security in its cloud using users, groups, roles and associated security policies.
One of the realities of the AWS Certified Solutions Architect Associate exam material is that, in many cases, we need complex topics to be explained in simple terms that we can then apply when answering multiple-choice questions.
The first step when learning about every AWS service is to reduce the job of the service to a one or two-sentence explanation.
IAM (AWS Identity and Access Management) is a service that securely manages access to AWS resources by defining users, roles, and permissions through JSON-based policies.
Regarding IAM policies, we do need some additional information to complete the big picture.
This blog post aims to simplify the complexity of IAM policies down to a simple understanding of the topic, complete with a couple of examples that will help you answer the IAM test questions that you may get. There’s also the reality that you may not get any IAM questions at all when you sit the exam.
IAM Policies
AWS Identity and Access Management (IAM) policies are JSON documents that define permissions for AWS resources. JSON stands for JavaScript Object Notation. It’s described as a “lightweight data-interchange format,” meaning “easy to process”. Easy for humans to read and write, and simple for computers to parse and generate.
You may disagree with the description of easy-to-read and write, but once you understand the basic syntax, you'll be able to understand the documents. I mean, you're not going to write a novel in JSON, but then again, that would be quite the mystery novel, wouldn't it?
Every IAM policy document controls who (or what) can access specific AWS services and resources, and under what conditions. As we know, IAM policies are used to grant or deny access to all AWS services. IAM policies adhere to the principle of least privilege, where only the necessary permissions are granted.
Exhibit A
Let's start with a straightforward policy document.
Figure 1: A simple JSON policy document
This policy grants full access to all S3 buckets and the objects stored in all S3 buckets in an AWS account.
This policy by itself does nothing unless it is attached to an IAM User, an IAM Group (of IAM users), or an IAM role. Policies have no power until they are linked or attached to a user, group, or role.
Note that the policy starts with a left curly bracket. Since the policy begins with a left curly bracket, it must end with a right curly bracket. When a computer reads a policy statement, the left and right brackets signify the start and the end of the policy. If you forget a bracket, the error-checking system will usually decide to tease you by letting you know that on line 0 or line 14, there's a problem.
Solving errors requires a Spock level of humour and detachment.
Figure 2: Even Spock would pretend to show emotions when faced with JSON errors
Take a look at the policy statement again, and locate Effect, Action, and Resource.
Figure 3: Statements contains Effect, Action, and Resource values.
In this policy statement, the Effect is to Allow, the Action in this policy is to to allow, or, grant access to the S3 storage service, the Resource is all objects (files) in any S3 bucket. The star, or asterisk (*) is a wild-card providing full access in this policy to “any S3 bucket, and, any object contained in any S3 bucket.
Effect, Action, and Resource are nouns used when making a statement in a policy document.
Each statement describes a permission that will be either allowed or denied. Statements begin and end with square brackets.
Within each statement, Effect, Action, and Resource are contained within curly brackets.
The Action statement itself is contained within square brackets.
Figure 4: Note the starting and ending brackets, how they are grouped, and where they are used.
At this point, your head is supposed to hurt.
For our purposes of understanding this policy document for the exam, all we need to focus on is Effect, Action, and Resource. The rest we can leave as noise. But, just in case you’re wondering……
The Version 2012 – 10 – 17 is the AWS version number that starts every policy document. It has to be there. That’s all we have to know.
SID is an optional “unique identifier” description statement. If SID is appropriately used, it will describe what the statement does and potentially save you many hours of frustration trying to figure out what a statement without a helpful SID actually does.
Policy Evaluation Logic
AWS evaluates IAM policies attached to an IAM User, IAM Group, or IAM Role, using the following logic:
Default Deny: By default, all requests are implicitly denied unless explicitly allowed. (We aren’t running Windows 11 with full read access.)
Explicit Allow: Allow grants access to the specified actions and resources. When you create a policy using the IAM Dashboard, the default is to create an allow policy.
Figure 5: Creating a new JSON policy starts with a version and sample entries to get you started.
Explicit Deny: Deny overrides any Allow for the same action and resource.
Three Simple IAM Policy Examples
Below are three IAM policy examples tailored to the requested scenarios: access to S3 storage, access to a specific S3 bucket called global_logs, and access to global_logs restricted to one particular IP address range and time window.
IAM Policy 1. Access to S3 Storage
Figure 6: This policy grants a user or role full access to all S3 buckets and their objects in an AWS account.
We've seen this example earlier. Hopefully, when you look at this policy document again, you'll be able to quickly read it and understand what it would allow once attached to an IAM user, group, or role.
Effect: Allow, or grants permission.
Action: s3:* allows all S3 actions (for example: GetObject, PutObject, ListBucket).
Resource: * applies to all S3 resources (all S3 buckets and objects).
Use Case: Suitable for an admin who needs unrestricted S3 access. Note: This violates least privilege and should be used cautiously. Always scope permissions to the minimum required actions and resources. For example, please don't use s3:* or * unless absolutely necessary.
IAM Policy 2. Access to S3 Bucket global_logs
Figure 7: This policy grants specific permissions to interact with an S3 bucket named global_logs.
Effect: Allow grants permission.
Action: s3:GetObject: Allows retrieving objects from the global_logs bucket.
s3:PutObject: Allows uploading objects to the global_logs bucket.
s3:ListBucket: Allows listing the global_logs bucket's contents.
Resource:
arn:aws:s3:::global_logs applies to the bucket itself (for actions like ListBucket).
arn:aws:s3:::global_logs/* applies to all objects in the global_logs bucket.
Use Case: Suitable for an application or user that needs to read, write, and list objects in the global_logs bucket.
arn stands for “Amazon Resource Name”. Every resource created in an AWS account has a unique arn applied. These unique variables enable us to create highly effective security policies tailored to specific situations.
IAM Policy 3. Access to global_logs from a Specific IP Address Range (8 PM to 12 AM)
Figure 8: This policy restricts access to the global_logs bucket to requests originating from a specific IP address range (e.g., 192.168.1.0/24) and only between 8 PM and 12 AM.
Conditions are optional and specify conditions for when the policy is in effect (e.g., IP address, time, or MFA requirements).
If a Condition is specified, the policy applies only when the condition is met (e.g., a specific IP range or time constraint). AWS supports many other conditions, such as MFA, VPC endpoints, or specific tags.
Effect: Allow grants permission.
Action: Same as the previous example (GetObject, PutObject, ListBucket).
Resource: Same as the previous example (global_logs bucket and its objects).
Condition:
IpAddress: Restricts access to requests from the IP range 192.168.1.0/24.
DateGreaterThan and DateLessThan: Restricts access to the time window between 8 PM (20:00:00 UTC) and 12 AM (00:00:00 UTC the next day). The date specified is June 9, 2025
Use Case: Suitable for a scenario where access to the global_logs bucket is restricted to a specific network (e.g., a corporate VPN) during one particular time window, such as a nightly batch process.
Understanding IAM policy logic and the usage of Effect, Action, Resource, and Conditions will help you successfully answer any IAM policy question on the AWS Certified Solutions Architect Associate (SAA C03) exam.