Tobias Davis

Designing better software systems.

Resources | Writings | Email List | RSS

Site logo image

Introduction to AWS IAM

Controlling access to resources in AWS is done using IAM policies. You attach pre-made or custom policies to users, either directly or using groups, giving the user access to those resources.

Note: I wrote a much longer article here, this article is just a brief introduction. The full AWS documentation is also available here.

Policies #

All policies have this basic structure:

{
"Statement": [
{
"Action": [ "s3:ListBucket" ],
"Resource": [ "arn:aws:s3:::test" ],
"Effect": "Allow"
}
]
}

"Action" is the action you are allowing or denying, such as s3:GetItem or kinesis:PutRecord. (You can exclude actions with "NotAction".)

"Resource" is the specific resource. For example, you can restrict the s3:GetItem to anything in a bucket, or a wildcard-matched set of files in a bucket. (You can exclude resources with "NotResource".)

"Effect" is whether to "Allow" or "Deny" access, based on whether the Action and Resource match.

The different statements are evaluated first to last, so for example you could have a statement allowing write access to everything in a bucket, but then follow it with a statement denying access to a specific file. This would give write access to everything except that one file.

Different AWS resources have more or less granularity of control, so you will need to read the documentation for each resource to determine what the least privilege is.

Example #

Suppose that you use a service like Travis CI to automatically push up built JavaScript/CSS assets for your webapp to a public S3 bucket. You’ll need to configure credentials inside Travis CI to give that process permission to write to S3.

The wrong way to give that access would be with an “allow all” policy:

{
"Statement": [
{
"Action": [ "s3:*" ],
"Resource": [ "arn:aws:s3:::*" ],
"Effect": "Allow"
}
]
}

This policy would give Travis CI permission to take any action to any S3 bucket in the AWS account, including creating new buckets. That’s clearly a horrible idea.

Note: If you are attaching the default AWS policies, this is probably what you are doing! To administrate access to your resources correctly, you will almost always need to create your own policies.

A much better policy would be something like:

{
"Statement": [
{
"Action": [ "s3:PutItem" ],
"Resource": [ "arn:aws:s3:::my-app/asset-folder/*" ],
"Effect": "Allow"
}
]
}

This will give permission only to the my-app bucket, and only allow it to write files with the keypath prefix asset-folder/, for example asset-folder/branch-name/file.js.

Documentation #

Finding out what the available policy rules are for each resource can be difficult.

Here are the steps I usually take:

  1. Start at the main AWS Documentation page,
  2. Click in to the resource type you are investigating,
  3. Go into the “Developer Guide” (sometimes named slightly different) HTML version,
  4. Look on the left navigation area for something called “Security”, “Access Control”, or similar,
  5. Look for something labeled IAM or “Identity Access Management”
  6. Look around in there for some sort of “Reference” page

Here are some links to ones I work with commonly:

Want to learn more? I wrote a longer article here!


Your thoughts and feedback are always welcome! 🙇‍♂️