IAM roles vs users

Many developers and system administrators create dedicated users for applications and bake user credentials in the code. This is considered as a bad practice and should be avoided at all times. Instead, the use of roles is recommended by AWS.

There is some confusion about IAM roles and users when one writes an application that has to connect to other AWS services.

1. Users

A user is an IAM entity that has a name and credentials with permissions to some (or all) AWS services.

For example, james.bond can be a user in an AWS account, and he can have both Console and programmatic access.

Console access consists of a username and password which the user can log in to the Console with. Changing passwords is the user’s responsibility, but this can be forced by the account administrators.

When users have programmatic access to AWS, they will have an access key and a secret access key. If you have an AWS account and have programmatic access (or your company provided you with credentials), you’ll find these credentials in the ~/.aws/credentials file:

cat ~/.aws/credentials

Users of an account can be listed with the following CLI command (given that you have permissions to do so):

aws iam list-users

The response should be similar to this:

{
  "Users": [
    {
      "Path": "/",
      "UserName": "james.bond",
      "UserId": "AIDAxxxxxxxxxxxxxxxxT",
      "Arn": "arn:aws:iam::123456789123:user/james.bond",
      "CreateDate": "2019-11-14T06:06:57Z",
      "PasswordLastUsed": "2019-11-16T07:22:57Z"
    }
  ]
}

2. Roles

An IAM role is an entity, just like users or groups, but it doesn’t have username and password set. It’s not a real person like a user (should be).

Instead, roles have temporary credentials to services, and AWS manages the rotation of these credentials.

Roles can be assumed by both users and applications/services.

When a user assumes a role, they will temporarily lose their original permissions they were assigned. For example, if a user has permissions to create a CloudFormation stack and the role doesn’t have that permission, by assuming the role the user won’t be able to create a new stack. After the user has quit the role, they will get their original permissions back.

An example for an application having a role is when a Lambda function is created. The example shows a basic role that gives Lambda permission to write to CloudWatch. When new policies are attached to the role, Lambda will be able to access more services.

The least privilege principle should apply to both role and user permissions.

If you have ever played with AWS services, chances are that AWS already created some roles:

aws iam list-roles

If this is the case, the response will list all available roles:

{
  "Roles": [
    {
      "Path": "/aws-service-role/inspector.amazonaws.com/",
      "RoleName": "AWSServiceRoleForAmazonInspector",
      "RoleId": "AROAxxxxxxxxxxxxxxxxL",
      "Arn": "arn:aws:iam::123456789123:role/aws-service-role/inspector.amazonaws.com/AWSServiceRoleForAmazonInspector",
      "CreateDate": "2019-11-13T12:37:13Z",
      "AssumeRolePolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
          {
            "Effect": "Allow",
            "Principal": {
                "Service": "inspector.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
          }
        ]
      },
      "MaxSessionDuration": 3600
    },
    ...
  ]
}

As it can be seen, the RoleId is very similar to the access key. The AssumeRolePolicyDocument property contains the permissions the role has. More on the policy elements can be found here.

3. Use roles in applications

One of the biggest disservices to security is to create a user for an application and hardcode its credentials (access key and secret access key) in the app.

This is a big no as it can lead to serious security issues even if the user has been specifically created for the application. (The We have been operating for years and no one has ever attacked us BS is not an excuse. These guys will be attacked; it’s just a matter of time.)

The role is attached to the service which hosts the application. For example, this service can be Lambda, EC2 or ECS.

So with roles one won’t need to embed (and possibly source code) security credentials to the application.

Another distinct advantage of using roles over users is that permissions are only temporary with AWS managing the rotation of the keys. For example, it can happen that two invocations of the same function will use two different set of credentials when fetching a password from Secrets Manager.

To cut it short, use roles and avoid users for applications.

4. Summary

IAM users and roles are sometimes used incorrectly in applications.

The best practice is to use roles, which provide the application with temporary credentials, and avoid hardcoding user access keys.

Thanks for reading and see you next time.