a practical guide to understanding iam policies
Tags: aws, iam
Published: 2023-06-28 23:41:18


### _TLDR_

AWS Identity and Access Management (IAM) policies regulate access to AWS resources. Policies can be attached to identities (users, groups, or roles) or resources. Each policy consists of statements with key elements: Principal, Action, Resource, Effect, and optional Conditions.

Policies can either be **identity-based**, attached to an IAM identity, or **resource-based**, attached directly to a resource. The policy defines permissions for an identity or specifies what actions a principal can perform on a resource.

Each policy statement has the following elements:

- **Principal**: In identity-based policies, the principal is the attached IAM identity. In resource-based policies, the principal is an entity granted or denied access.
- **Action**: Defines specific tasks that the policy allows or denies.
- **Resource**: Specifies the AWS resource that the policy governs.
- **Effect**: Can be **`Allow`** or **`Deny`**. If **`Allow`**, the principal is permitted to perform the action on the resource unless another policy denies it. If **`Deny`**, it overrides any **`Allow`**.
- **Condition** (optional): Specifies any conditions for the policy statement to take effect.

Policies are evaluated as follows: an explicit **`Deny`** overrides any **`Allow`**. If there's no explicit **`Deny`**, an explicit **`Allow`** permits the request. If neither **`Allow`** nor **`Deny`** is present, the request is denied by default.

Principals in a policy can be of different types, including **`AWS`** for IAM users or roles, **`Service`** for AWS services, **`Federated Users`** for federated identities, **`Anonymous`** for unauthenticated access, and **`AWS Organizations`** for the entire organization or an organizational unit (OU).

The blog post includes numerous examples of IAM policies with different conditions, multiple principals, and different principle types to demonstrate the flexibility and complexity of IAM policy creation. Remember, the key rule in IAM policy creation is to grant the least amount of access necessary.

## **Introduction**

AWS Identity and Access Management (IAM) policies are the cornerstone of managing access to AWS resources. A policy is an entity that, when attached to an identity or resource, defines their permissions. This blog post will help you understand the core components of IAM policies and the pivotal role they play in AWS's access control capabilities.

## **Understanding IAM Policy Types**

There are two main types of IAM policies:

1. **Identity-based policies:** These policies attach to an IAM identity (a user, group, or role). They control what actions the identity can perform, on which resources, and under what conditions.
2. **Resource-based policies:** These policies attach directly to a resource. They define what actions a specified principal (which could be in another account) can perform on that resource.

## **Deep Dive into IAM Policy Components**

IAM policies are composed of one or more statements, and each statement includes these elements:

1. **Principal:** In an identity-based policy, the principal is the IAM identity to which it's attached. In a resource-based policy, the principal is the entity that is allowed or denied access to the resource. The principal can be specified as a single string or a list of strings.
2. **Action:** This is the specific task the policy allows or denies. For instance, **`s3:PutObject`** permits an entity to upload an object to an S3 bucket. Actions can be specified as a single string or a list of strings.
3. **Resource:** The resource is the specific AWS asset that the policy allows or denies actions upon. Resources are defined using Amazon Resource Names (ARNs), and can be specified as a single string or a list of strings.
4. **Effect:** The effect can be either **`Allow`** or **`Deny`**. If the effect is **`Allow`**, the principal is permitted to perform the action on the resource, assuming no other policies deny it. If the effect is **`Deny`**, it overrides any **`Allow`**.
5. **Condition:** The condition is an optional field specifying any conditions for the policy statement to take effect. Conditions might include IP address range, time of day, whether MFA is enabled, and more.

## **IAM Policy Evaluation Logic**

IAM employs the following logic to evaluate policies:

1. An explicit **`Deny`** in any policy trumps any **`Allow`**.
2. If there's no explicit **`Deny`**, an explicit **`Allow`** in any policy permits the request.
3. If neither **`Allow`** nor **`Deny`** is present, the default decision is to deny the request.

## **Examples of IAM Policies**

**Example 1: IAM policy that includes a list for each of these elements:**

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ExampleStatement",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::123456789012:user/Alice",
                    "arn:aws:iam::123456789012:user/Bob"
                ]
            },
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::my_bucket/example1",
                "arn:aws:s3:::my_bucket/example2"
            ]
        }
    ]
}
```

This policy grants both Alice and Bob the ability to upload, download, and delete the **`example1`** and **`example2`** objects in **`my_bucket`**.

**Example 2: Allow Access Only From Specific IP Addresses**

The following IAM policy allows the principal to perform any Amazon S3 action (**`s3:*`**) on the bucket named **`my_bucket`** but only if the request originates from the range of IP addresses specified in the condition:

```json
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "s3:*",
        "Resource": "arn:aws:s3:::my_bucket/*",
        "Condition": {
            "IpAddress": {
                "aws:SourceIp": "192.0.2.0/24"
            }
        }
    }
}
```

In this policy, the **`aws:SourceIp`** condition key is used to match the IP address from where the request originates.

**Example 3: Allow Access Only During Specific Times**

The following IAM policy allows the principal to perform any Amazon DynamoDB action (**`dynamodb:*`**) but only during a specific time of day:

```json
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "dynamodb:*",
        "Resource": "*",
        "Condition": {
            "DateGreaterThan": {
                "aws:CurrentTime": "09:00:00Z"
            },
            "DateLessThan": {
                "aws:CurrentTime": "17:00:00Z"
            }
        }
    }
}
```

In this policy, the **`aws:CurrentTime`** condition key is used to allow requests only between 09:00:00 UTC and 17:00:00 UTC.

**Example 4: Allow Access Only With MFA**

This IAM policy allows deleting an Amazon S3 bucket (**`s3:DeleteBucket`**) but only if the requester is using multi-factor authentication (MFA):

```json
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "s3:DeleteBucket",
        "Resource": "*",
        "Condition": {
            "Bool": {
                "aws:MultiFactorAuthPresent": "true"
            }
        }
    }
}
```

In this policy, the **`aws:MultiFactorAuthPresent`** condition key is used to check whether the request was made using MFA.

Remember, conditions provide an additional layer of security to control when and who can use the actions granted in your IAM policies. By understanding and leveraging conditions, you can greatly enhance the security of your AWS resources.

## **A Note on IAM Principles**

In an AWS IAM policy, the **`Principal`** element identifies the user, account, service, or other entity allowed or denied access to a resource. Here are different types of principals:

1. **AWS:** Specifies an AWS account, IAM user, IAM role, federated user, or assumed-role user.
2. **Service:** Allows AWS services to act on a resource.
3. **Federated Users:** Used for identities federated into AWS.
4. **Anonymous:** The wildcard "*" allows unauthenticated access.
5. **AWS Organizations:** Specifies the entire organization or an organizational unit (OU).

Remember to grant only the minimum necessary permissions to maintain security.

## Examples

**Example 1: AWS Principle**

This is a resource-based policy that grants an IAM user in another AWS account the permission to read objects from an S3 bucket:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "GrantReadAccess",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:user/Alice"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my_example_bucket/*"
        }
    ]
}
```

**Example 2: Service Principle**

This is a resource-based policy that allows the EC2 service to assume a role:

```json
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Principal": {
            "Service": "ec2.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
    }
}
```

## **Conclusion**

IAM policies form the backbone of AWS's access control capabilities. They can be complex, so taking the time to understand the different elements and principles is essential for managing AWS resources securely and effectively. Always remember the guiding rule of granting the least amount of access necessary to perform a function. It's a crucial step in maintaining the security of your AWS infrastructure.