IAM Users and Roles both enable you to manage access to your AWS resources with specific sets of permissions, but the two types of IAM access are used differently in practice. In this article, we explain the differences and how to use them.
Users Are External (Used For People)
The fundamental difference between IAM Users and Roles is from where access is allowed.
IAM Users permits external access to your AWS resources. You use these resources to give employees access to the AWS Management Console, and to authenticate the CLI running on their machines. IAM Users gives direct access to services using the given security tokens. IAM Roles are only meant for internal use, and are something you can assign to things like EC2 instances and Lambda functions to enable them to do their job effectively. Roles don’t give any access on their own, but they enable services to act as though they have certain permissions.
With that out of the way, let’s talk about IAM Users, the more straightforward of the two. They present a fantastic way to manage access for everything from service accounts to real employees. With Users, you’re given an access key ID and secret access key, which are used to authenticate the AWS CLI. You can have the CLI assume a role once you’re authenticated, but you still need an IAM User account with permission to do so (with the exception of EC2 instances, more on that later).
You can also give access to the AWS Management Console (the web GUI), which makes IAM Users perfect for employees. You still need to give out the right permissions, or the console will throw a lot of errors, but the ability to use the console is crucial.
You can add IAM users to groups rather than specifying permissions directly, which enables you to more easily manage the different roles in your organization.
However, Users present a few issues in practice. The first is that in order to authenticate an application running on EC2, you must leave access keys on that instance. It’s not as bad as leaving your root access keys, but it’s still a security issue that doesn’t need to exist. The problem is especially bad when you consider that this may enable employees to escalate their privileges; if an application runs with higher privilege and stores its keys on-disk, the employee can steal and use those keys, which is not ideal.
The second issue is that IAM Users enables access to your AWS resources from anywhere, even outside of AWS. This is necessary for employee accounts, but isn’t necessary for applications that are already running inside AWS.
Roles Are Meant to Be Assumed By Authorized Entities
The solution to the problems with Users is solved by Roles. Roles are essentially the same as Users, but without the access keys or management console access. In essence, they’re just a set of permissions that can be given to different services.
For example, a common problem is authenticating services must be able to upload objects to S3. Instead of creating a user account, which would leave secret keys on your EC2 server (and any custom AMIs you have set up) and enable external access, you instead create a role that permits S3 access, such as “S3Uploader”.
You can give this role to a Lambda function enabling it to put objects in your bucket, or you can assign it to an EC2 instance directly. The service given a role is then permited to access the resources its been given, but it won’t pose a security risk. Many AWS services create roles by default to operate, so your IAM console may already have a bunch of them.
Roles can also be used by users to enable managed privilege escalation. An employee can assume a role (which is logged in CloudTrail), giving them the permissions of that role for a short time. This enables the user to request short-term credentials from AWS STS, which is more secure than attaching the permissions directly to the user’s access keys.
Adding roles to EC2 instances is very useful. You can add a role to an instance from the EC2 Management Console by right clicking on an instance and selecting “Instance Settings” > “Attach/Replace IAM Role”:
You can also specify the role within a launch template or launch configuration. Each instance (and most services) can only have one role, but you can attach any number of policies to the role itself.
The AWS CLI automatically uses the role for the given instance, so much setup isn’t required. If you’d like to manually switch to a role, you can do so with the assume-role command:
Note, this does require an IAM User account to run this command, making this only useful for enabling privilege escalation for employees.