Understanding AWS IAM policies best practices from zero

Julián Calle
Globant
Published in
5 min readJun 4, 2022

Introduction

I have been using AWS for a long time now and one of the most critical, and sometimes difficult aspects to understand is the correct management of IAM policies.

I know many companies have many restrictions that enforce the creation of proper IAM policies, but that is not always the case.

Furthermore, I will not lie, I have taken lightly many times the IAM policies creation for many reasons, the environment is not critical, this is only a PoC, I will delete the resources immediately, the AWS is fully secured, and many more reasons, you can name them. However, when you get into the habit of writing lightly IAM policies, you get used to it (a huge mistake).

Now, why does this happen? I’m talking about myself, but I have seen many people doing the same before, so I was not probably the only one making use of this bad practice.

Commonly, one of the reasons to write lightly IAM policies is because you do not have enough time (who has enough time?) and you do not fully understand how they work. I will try to put a simple yet in-depth explanation of how the IAM policies work, so the next time that you write one, you can avoid the wildcard.

The following sections will be reviewed in this article:

Basics of IAM Policies

Policy Evaluation

The least privilege principle

Conclusions

Basics of IAM Policies

So let’s start with the basics, an IAM policy allows to define of granular level access on what permissions need to be given to access a particular AWS resource. Policies are attached to IAM identities (users, groups of users, or roles) or AWS resources. AWS evaluates these policies when an IAM principal (user or role) makes a request.

IAM policies are defined as JSON documents and are composed of some elements, where we will discuss in detail only 4 of them: Statement, Effect, Action, and Resource, where the former 3 are part of the Statement element. This is a typical example of what an IAM policy looks like:

{    “Statement”: {        “Effect”: “Allow”,        “Action”: “ec2:DescribeInstances”,        “Resource”: “*”    }}

Statement: This is the main element of the IAM policy and is required. The Statement element can contain multiple individual statements, where the individual statements are enclosed in blocks of {}.

Effect: Specifies whether the statement is allowed or explicitly denied. There are only 2 possible values: Allow or Deny.

Action: Defines the list of actions that will be allowed or denied. Each AWS Service has its own set of actions, for example:

ec2:DescribeInstances

rds:CreateDBInstance

s3:ListObjects

sqs:SendMessage

Resource: Defines the object that the statement covers. It is defined as an Amazon Resource Name (ARN) that can uniquely identify an AWS resource.

Policy Evaluation

Now that the basic structure of an IAM policy is defined, we can go a little bit further and talk about how the IAM policies are evaluated.

  1. The Evaluation always starts with an implicit Deny, this is because everything in AWS is denied by default.
  2. The Effect element is evaluated.
  3. If the value of Effect is Deny, the evaluation will be to deny the request.
  4. If the value of Effect is Allow the evaluation will be to allow the request.
  5. If no Allow is found, the evaluation will be to deny the request.

As you can notice, the evaluation process is very straightforward, not rocket science at all. Things get complicated when you need to create policies for operations that involve multiple actions (and you do not specify which actions are those).

The least privilege principle

Defining policies on AWS is based on the principle of the least privileges, meaning that you give identities the least amount of access and responsibility necessary to complete their duty.
One good practice is always to start with a minimal set of permissions and grant additional permissions as necessary.

One common example is creating backups and managing snapshots for RDS databases. This operation actually involves many actions that you need to grant to perform the whole operation.
If you are in a rush you will probably feel tempted by creating a policy with a wildcard allowing all the operations in RDS, something like this:

{    “Statement”: {        “Effect”: “Allow”,        “Action”: “rds:*”,        “Resource”: “*”    }}

This policy will grant access to all the operations on RDS for a principal, but all operations include dangerous actions like removing all of your databases, so indeed, this is not a good practice.

An ideal policy for this use case will list each action needed and then narrow the scope of the Resource section to only those required ARNs.

{    “Statement”: [    {        “Effect”: “Allow”,        “Action”: [            “rds:AddTagsToResource”,            “rds:DeleteDBSnapshot”        ],        “Resource”: “arn:aws:rds:us-east-1::snapshot:db-snapshot”    },    {        “Effect”: “Allow”,        “Action”: [            “rds:ListTagsForResource”,            “rds:CreateDBSnapshot”        ],        “Resource”: “arn:aws:rds:us-east-1:*”    },    {        “Effect”: “Allow”,        “Action”: [            “rds:DescribeDBSnapshots”        ],        “Resource”: “*”    }    ]}

This demonstrates how to narrow both the actions and the resources sections of the policy; however, you may notice a wildcard at the end of the policy, and we have been talking about using wildcards as a general good practice?

Well, using wildcards is generally not recommended but sometimes needed, so do not panic at all every time that you see a wildcard if one of your policies, for example, in the policy above is needed because you might have multiple snapshots, and it could become impossible to reference them one by one on a list.

Conclusions

In the end, creating IAM policies is critical but not difficult or impossible. This is a list that summarizes the best practices when creating IAM policies:

  • Grant least privilege. Grant only the permissions needed to perform a task.
  • Validate the policies. It is possible to use a tool such as IAM Access Analyzer which generates security warnings when a statement is considered over permissive.
  • Generate policies based on access activity. IAM Access Analyzer can review the AWS CloudTrail Logs and generate a policy template with the permissions that have been used by the entity.
  • Review events with AWS CloudTrail. You can use AWS CloudTrail to track the permissions used by identity and remove the unnecessary ones if needed.

--

--

Julián Calle
Globant
Writer for

AWS, DevOps, and IoT enthusiast. Writing some stuff in Python and teaching AWS. Currently working at @Globant