DEV Community

Arpad Toth for AWS Community Builders

Posted on • Originally published at arpadt.com

Improving policy readability with NotAction

You can save time and improve the readability of your policies by using NotAction. In some cases, when you want to deny only a few actions and want to allow many of them, choosing this policy element can be a good option.

1. The problem

Alice and Bob work for the same company. Alice is a DevSecOps engineer, and Bob is in a non-technical department.

Alice is an administrator of the AWS accounts of the company. She is reliable and knows her stuff. Bob is new, and while he is probably reliable and knows his stuff in his field, he is not a technical person.

Alice just got the task to give Bob access to some department buckets in S3. He should be able to download and upload files to the buckets and modify them, too, and it is a requirement that Bob could not delete the objects, the buckets, and the object tags.

2. Possible solutions

Alice has a couple of options to mitigate the risk of data loss, which includes versioning and MFA delete, but she decided to disallow Bob the entire deletion operation.

She wants to solve this problem with IAM policies, and wants AWS to display big red error messages when Bob attempts to delete anything from the bucket or the bucket itself.

2.1. Allow what is needed

Alice can write a policy for Bob where she displays all actions that she wants to allow him except the forbidden ones.

It means the Bob can have all permissions except s3:DeleteBucket, s3:DeleteObject,s3:DeleteObjectTagging and s3:DeleteBucketPolicy (just to be on the safe side).

Part of the identity-based policy assigned to Bob can look like this:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:GetObjectTagging",
        "s3:ListBucket",
        "s3:PutObject",
        // ... and many more actions
      ],
      "Resource": [
        "arn:aws:s3:::MY-BUCKET-NAME",
        "arn:aws:s3:::MY-BUCKET-NAME/*"
      ]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

I counted 128 IAM permissions for S3 today (S3 Object Lambda and S3 Outposts excluded), which means that Alice needs to list a lot of actions if she wants to allow Bob full S3 experience except deleting objects, tags, and buckets.

This policy is hard to read and is very long. If Alice creates a couple more statements like this, she might exceed the policy size limit, too.

2.2. Use managed policies

Alice could use managed policies, which provide permissions for common use cases.

AWS provides the AmazonS3FullAccess and AmazonS3ReadOnlyAccess managed policies for S3.

AmazonS3FullAccess looks like this:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:*",
        "s3-object-lambda:*"
      ],
      "Resource": "*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

The * includes the delete actions, so she decides not to go with this policy.

The AmazonS3ReadOnlyAccess managed policy, on the other hand, does not allow Bob to upload objects to the bucket, for example, so it is too narrow for him.

2.3. Deny deletion

Alice can decide to add an explicit deny to the delete actions. She can write something like this:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": [
        "s3:DeleteObject",
        "s3:DeleteBucket",
        "s3:DeleteObjectTagging",
        "s3:DeleteBucketPolicy",
      ],
      "Resource": [
        "arn:aws:s3:::MY-BUCKET-NAME",
        "arn:aws:s3:::MY-BUCKET-NAME/*"
      ]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

It looks good because explicit deny always wins no matter what, so Bob will not be able to delete anything from the bucket.

The problem is that the necessary actions (read and write) are still not allowed. Alice only denied deletion but she did not allow anything. Bob cannot get any objects from the bucket, and he cannot upload anything there either. His permission will need to contain an explicit allow for all other actions, and we are again back to point 2.1.

3. Use NotAction

IAM has a policy element called NotAction that acts like an inverse Action.

The meaning of NotAction is every action but. Given the scenario above, Alice can write a policy like this and attach it to Bob's identity:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "NotAction": "s3:Delete*",
      "Resource": [
        "arn:aws:s3:::MY-BUCKET-NAME",
        "arn:aws:s3:::MY-BUCKET-NAME/*"
      ]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

The policy above means that Bob is ALLOWed to do everything except the Delete actions on the bucket called MY-BUCKET-NAME. Initially, Alice wanted to prevent Bob from deleting objects, buckets, tags, and bucket policy. She can achieve it with just one line of code by replacing the Action element with NotAction. (In fact, this policy disallows more than the required four actions because S3 has more Delete APIs. If Alice wants to be less strict, she can list these four actions in an array as the value of the NotAction key.)

This policy will result in an implicit deny for example, for the s3:DeleteObject actions because Alice explicitly allows (Effect: Allow) everything but s3:Delete*. It means that Bob cannot delete any objects from the bucket because he does not have explicit permission to do so.

4. Summary

We can create shorter, more concise policies using NotAction. In some cases, we can avoid listing many actions, which will make the policy statements more readable.

NotAction works well when we want to make a few exceptions from a large group of actions, like in the example above.

5. References and further reading

IAM JSON policy elements reference - collection of all policy elements, including NotAction

Policy evaluation logic - describes how IAM decides when to allow or deny an action

Discussion (0)