DEV Community

Nicolás
Nicolás

Posted on

Part 1: Understanding AWS Identity and Access Management (IAM)

Identity and Access Management (IAM) is one of the most essential services in the AWS ecosystem. It handles authentication (who you are), authorization (what you’re allowed to do) across your AWS environment.

Every request to AWS is evaluated by IAM before it’s allowed or denied. In other words — IAM is the security gatekeeper for your AWS account.

The AWS Root User

Every AWS account starts with a single root user — the credentials created when you first set up your account. This is the most priviveled user in the account because it has unrestricted access to every resource.

As best security practice, avoid using the root user for daily operations.
Instead, create IAM users or roles with just the permissions they need.

Four Key IAM Concepts

As mentioned in one of my previous blogs, IAM is built around four fundamental building blocks:

IAM User

IAM Users are individual user user accounts, similar to those you’d find on any website that requires a username and password for authentication. They represent specific people or applications that need direct access to AWS.

IAM Role

IAM Roles represent a set of permissions associated with a specific function, for example, an Administrator or Security Engineer role. These roles define what actions an entity can perform. Roles are often used to delegate access without sharing long-term credentials.

IAM Group

IAM Groups are simply a collection of IAM Users. It allows you to manage permissions for multiple users at once instead of assigning policies individually.

IAM Policy

IAM Policies are documents written in JSON that explicitly define which actions are allowed or denied for a given user or role. A single policy can be attached to multiple users or roles.

Structure of an IAM Policy

Let's first see how an IAM policy looks like and break it down:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CrossAccountRead",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::shared-reports/*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode
  • "Version": "2012-10-17"

This specifies the policy language version — always use 2012-10-17 unless you have a very old AWS environment.

  • "Statement": [...]

Each item inside "Statement" is an individual permission rule.
A policy can have one or many statements.

Here, there’s only one statement (the one with "Sid": "CrossAccountRead").

  • "Sid": "CrossAccountRead"

Sid (Statement ID) is optional — it’s like a label or comment for readability.

  • "Effect": "Allow"

Specifies whether to allow or deny the action specified in the "Action" field, so the only two possible values are "Allow" and "Deny".

  • "Action": "s3:GetObject"

    Defines what the Principal is allowed to do. In our case, the IAM user, group, or role this policy is attached to will allow them to download (read) objects from S3.

  • "Resource": "arn:aws:s3:::shared-reports/*"

Defines which AWS resource(s) the permission applies to.

This mean that the action "s3:GetObject" is scoped to only the shared-reports bucket.

🧠 How IAM Evaluates Access

Every request made to AWS (for example, listing S3 buckets or starting an EC2 instance) goes through IAM’s evaluation logic:

  1. Default Deny – Everything is denied unless explicitly allowed.
  2. Explicit Allow – If a policy allows the action, IAM grants it.
  3. Explicit Deny – If a policy explicitly denies something, it overrides any allow.

Imagine we add the following DenyAllS3Actions statement to our policy:

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

Enter fullscreen mode Exit fullscreen mode

Even though the policy explicity grants the s3:GetObject operation over the shared-reports bucket, it will be denied because there is an explicit deny in the DenyAllS3Actions statement that blocks every single S3 action.

There are some caveats to this as there are other controls that could be in place to further restrict permissions like Service Control Policies (SCPs). However, for simplicity's sake, we will assume that permissions are only controlled via default IAM policies and we will cover other controls in next blogs.

Resource-Based vs. Identity-Based Policies

Depending on which entity a policy is attached to, IAM policies are categorized as:

  • Identity-based policies: Attached to IAM users, groups, or roles.
  • Resource-based policies: Attached directly to AWS resources such as S3 buckets, SQS queues, or SNS topics.

They work similarly, but resource-based policies include a Principal field specifying who the policy applies to. These are also what enable cross-account access.

For example, suppose we have an S3 bucket we want to make public so everyone can access it:

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

Enter fullscreen mode Exit fullscreen mode

We didn’t include the Principal element in our earlier examples because it wasn’t needed — in identity-based policies, the principal is implicitly the IAM user, group, or role the policy is attached to.

Managed, Inline, and Customer Policies

Other than the identity based and resource based policies, IAM policies are further categorized in:

  • AWS Managed Policies – Pre-built and maintained by AWS. Available to all customers.
  • Customer-Managed Policies – Custom policies you create and manage. They are reusable and often preferred over Inline policies.
  • Inline Policies – Policies embedded directly in a specific user, group, or role.

What’s Next

In Part 2, we’ll dive deeper into IAM policies — exploring:

  • Policy conditions and wildcards (*)
  • How AWS evaluates multiple overlapping policies

Top comments (0)