This is the third article in a three-part series on Amazon S3 Security In-Depth. In Part I of this series, we discussed the different mechanisms you can use to allow access to your Amazon S3 buckets and objects. In Part II, we looked at writing identity-based policies to manage access to your S3 resources. In this Part III, we will cover authentication and identity within the context of AWS Identity and Access Management (IAM).
In the previous post in this series, we noted that IAM has two broad categories: identities and permissions. Permissions, which we covered in the previous post, describe which actions a particular identity may or may not perform. These permissions are managed in IAM policies, and AWS allows you to write fine-grained policies to lock down access to your resources.
The second half of IAM is identities, which are the tools used to authenticate requests within the AWS ecosystem. This topic includes user and group management, authentication credentials, and delegation. IAM identities are the focus of this post.
In this post, we’ll cover:
- How AWS handles authentication on API requests;
- IAM users, groups, and roles, and the differences between them;
- Best practices with IAM identities.
Table of Contents
Authenticating with Access Keys
When making a request to Amazon S3, your request is either anonymous or authenticated. If your request is anonymous, this means you have not included any credentials used to identify yourself as a user. For your request to succeed, you will need the relevant permissions to be granted via an S3 bucket policy or an ACL. Read Part I of this series for more information on these permission schemes.
More commonly, you will make authenticated requests to your S3 resources. Authenticated requests use access keys to identify the requesting user. Access keys are similar to a username and password -- there is an access key ID, which is comparable to your username, and a secret access key, which is similar to your password. AWS uses a request-signing method using the AWS Signature Version 4 algorithm, or “Sigv4” for short. The details of Sigv4 is outside the scope of this article, but you can check out AWS’s materials on authenticating with Sigv4.
In the previous section, we learned that AWS uses access keys to authenticate the identity of the entity making a request. In this section, we’ll learn about one way to provision access keys by creating an IAM user.
An IAM user is an entity in IAM that should map to an actual human user. When creating an IAM user, you can provision a password that allows the user to sign in to the AWS console. You can also create up to two access key pairs for the IAM user. These access key pairs are most commonly used with something like the AWS CLI for interacting with AWS resources in your terminal or with GUI tools like CloudBerry Explorer that help you manage your AWS resources.
By default, an IAM user has no permissions. You can grant an IAM user the ability to access and manipulate resources by attaching policies to the user. We covered writing IAM policies in the previous post in this series. Be sure to check the “Use Managed Policies over Inline Policies” portion of the Best Practices section below for additional advice on IAM policies.
Often you will have multiple IAM users that need the same IAM permissions. To make this easier, you can create an IAM group. An IAM group is a collection of IAM users. You can attach policies to an IAM group just as you would to an individual IAM user, and the policies will apply to all users in the group.
AWS IAM Roles
An IAM role is similar to an IAM user, with a few key differences.
- First, it is not tied to a particular identity, such as a human user. Rather, an IAM role is intended to be assumed by someone or something (such as an EC2 instance) that has permission to use the role. The person or service that assumes the role will temporarily have all of the IAM permissions of the assumed role.
- Secondly, an IAM role is temporarily assumed, thus has no permanent credentials associated with it. There’s no password to sign into the AWS console as an IAM role, and there are no permanent access key pairs for the IAM role. AWS will automatically generate temporary access keys for any person or entity that assumes a role. These temporary credentials will be valid for a specified period of time and will have all permissions assigned to the role.
IAM roles can be unintuitive at first, so let’s walk through two examples of where IAM roles prove invaluable.
#1 IAM Permissions for an EC2 Instance
First, imagine that you have a user-facing web application that is running on EC2 instances. Your application will save and display images from Amazon S3 and thus will need the proper IAM permissions to interact with your S3 resources. Without IAM roles, you would need to create an IAM user and generate an access key pair. Then you would need to make sure the access key pair is available to your web application on the EC2 instance. If you’re automatically creating and destroying EC2 instances as your application scales up and down, you’ll need to determine a secure way to store your credentials that your new instance can access on boot. Finally, you’ll need to manage the rotation of those access keys without causing downtime to your users.
With IAM roles, this process is much easier. You can associate your EC2 instance with an IAM role upon creation, as shown in the screenshot below.
Your EC2 instance will have access to temporary access credentials for making requests to AWS services. These credentials will have the permissions given to the IAM role you delegated to the EC2 instance. You no longer need to worry about access key management or key rotation on your instances -- it’s all automatic.
To retrieve these credentials, your EC2 instance will query the instance metadata service. The instance metadata service is an HTTP-accessible service provided by AWS that provides important metadata that is specific to your EC2 instance. The instance metadata service is accessible from each EC2 instance at http://169.254.169.254, and it includes information such as the AMI used to launch your EC2 instance, the public and private hostname of your instance, and, if associated with an IAM role, a pair of temporary access keys for your instance to use for all AWS API requests.
#2 IAM Roles in the AWS Console
IAM roles also can be helpful in the AWS console. This can be helpful in two situations: first, to provide different levels of access to a particular IAM user in the AWS console, and second, to allow an IAM user to access multiple AWS accounts in the AWS console.
In the first situation, this can be helpful if you want to force an IAM user to go through an additional level of security before performing important actions. For example, deleting an S3 bucket may require a user in the AWS console to assume a higher role that requires multi-factor authentication. This can ensure that S3 deletion by a bad actor on a browser that was left open.
The second time it might be helpful - if your organization handles multiple AWS accounts, such as different accounts for development, staging, and production. You allow an IAM user in one account to assume an IAM role in another account. This allows your developers to manage one set of authentication credentials while still maintaining separation between AWS accounts.
Amazon S3 IAM Identity Best Practices
#1 Prefer Roles over Users
IAM roles simplify many aspects of credential management. By always using temporary credentials, you don’t need to worry as much about key rotation and having your credentials fall into the wrong hands. Further, having AWS manage access credentials for you means you don’t need to build systems to encrypt and decrypt credentials when they need to be shared across multiple machines.
#2 Don’t Share Access Keys
When it is necessary to use IAM users rather than roles, do not share your user’s access keys with multiple people. Each person that needs AWS console or programmatic access via the AWS CLI or language-specific SDKs should have their own IAM user with their own credentials.
There are two reasons for this.
- First, sharing access keys increases the attack vector for someone to steal the keys. The keys are now stored in more locations that could be left vulnerable.
- Second, it makes it more difficult to monitor usage in your AWS account. If a single pair of access keys is shared across an entire department, it’s impossible to find out who used the keys for nefarious purposes in the event of an internal breach.
#3 Rotate IAM User Credentials Regularly
For IAM users with AWS console passwords and/or access keys, you should rotate these credentials regularly. Rotating passwords and access keys will limit the amount of time an exposed credential is available for attack. It also helps you create a nice rhythm of rotating your credentials in the event you need to disable your credentials in an emergency situation, such as during an attack.
Note that if you’re using IAM roles, you don’t need to worry about rotating access keys. AWS will automatically provide you with temporary access keys when you’re using a role and will manage the rotation of these keys.
#4 Use Managed Policies over Inline Policies
When writing IAM policies to grant permissions to an IAM user, you can create managed or inline policies. Inline policies are policies that are attached directly to an IAM user, group, or role. Managed policies are created separately and may be attached to one or more IAM users, groups, or roles.
When possible, you should prefer using managed policies rather than inline policies. Managed policies provide a few benefits.
- First, AWS provides versioning of managed policies. Whenever you update an existing managed policy, AWS is actually creating a new version of the policy. AWS will retain up to five versions of a managed policy. This makes it easier to rollback to a previous version if you make a mistake as well as to audit any changes by checking the differences between the two versions.
- A second reason to use managed policies is that they’re more reusable. You will often have multiple users or roles that need similar permissions across services. If you add these to a user or role via an inline policy, you would need to update each user or role whenever you need a new permission. This can lead to configuration drift across users and roles and make it more difficult to audit what each user has. By using managed policies, you can update these policies in one place and have it apply to all relevant users and roles.
#5 Monitor IAM User and Role Usage
AWS provides a few different services that allow you to monitor the actual API requests made by particular users in your systems. There are two that are relevant for Amazon S3.
First, AWS CloudTrail is a service that tracks certain high-level API calls across many different AWS services. Generally, CloudTrail works to log API actions that occur at the control layer -- deleting an S3 bucket, creating a new DynamoDB table, etc. It usually does not log actions that occur at the data layer -- reading an S3 object, inserting an item into a DynamoDB table.
The CloudTrail integration for Amazon S3 is more expansive. By default, CloudTrail will log all bucket-related actions in Amazon S3. However, you can also choose to enable object-level actions, including all object reads and writes. You will be charged for the additional volume, but it can be a great way to get granular data on your S3 access patterns.
The second way to monitor is to use Amazon S3 Server Access Logging. With Server Access Logging, AWS will monitor all requests to your S3 bucket. It will periodically make dump files of the requests. Each request log will include information such as the time, the object requested, the requesting user (if authenticated), the object size, and more. Server Access Logging can be cheaper than using CloudTrail for data layer events, particularly if your Amazon S3 resources are accessed quite frequently.
In this post, we discussed the identity aspect of IAM. We learned how AWS authenticates requests, then covered IAM users, groups, and roles. Finally, we learned some best practices around managing your IAM identities.
This concludes our three-part series on Amazon S3 Security. You should have a basic understanding of the various tools at your disposal and how to avoid some serious mistakes. Security is a complex issue that is never finished, so don’t stop learning. Set up the proper processes to allow your team to move quickly while staying secure.