Reducing privileges and tightening IAM policies are best practices for all identity principals, be it an application’s IAM role or an IAM user with an access key. In some cases, it may be easier to reduce the risks of the access keys by first tightening the IAM policies, before transitioning them to alternative authentication solutions.
This post is the second article in the series "How to get rid of AWS access keys". Read the first article at Part 1: The easy wins.
Identify high-impact keys To identify the keys posing the highest risks to your environments, it can be helpful to identify which keys have high privileges (e.g. an IAM user with the AdministrativeAccess policy attached to it). High-risk keys can also be identified by finding those keys that are in sensitive accounts or have access to sensitive data.
Tighten IAM policies In order to mitigate the risks associated with a principal being compromised there are two techniques that can be used to tighten the IAM policies:
Remove unnecessary privileges Removing unnecessary privileges can be done at varying levels of granularity. For instance, at the service level, an access key with the AdministratorAccess policy may be restricted to just s3:*
permissions instead. You can use AWS’s IAM Access Advisor information to identify the service level adjustments.
The next level of granularity would be to identify the specific action level privileges required, which can be done with Access Analyzer policy generator. However, it is worth noting that the Access Analyzer’s accuracy is based on the information AWS records in CloudTrail logs which has some special cases that can cause suggestions to miss things at times.
The important privileges to watch out for are ones that offer privilege escalation or the ability to list resources. For example, privileges in the iam
or sts
services may provide some form of privilege escalation, and privileges such as s3:ListAllMyBuckets
will allow an attacker to see all the S3 buckets in an account. If an attacker compromises a principal with some form of S3 read or write access, but does not know which S3 buckets they have access to, it may prevent the attacker from abusing the access they have. Although removing the read or write privileges altogether would be more secure, that may prevent the legitimate needs of the principal, while the privileges to list the resources are less often required.
The next level of granularity beyond this is to specify the individual resources that the principal needs access to, which requires manually reviewing the CloudTrail logs or the source code of the application.
Apply additional restrictions In some cases, you may be able to apply additional restrictions on the IAM policy such as denying access based on the source IP using the aws:SourceIp
condition. However, you need to be careful that the IP address will not change. Depending on your network setup, you may be able to use VPC endpoints instead, which is preferred.
Proxy sensitive access Given the risks of access keys, it is worth considering whether the data they need access to can be made less sensitive or the access to it can be better controlled. This might be done through a proxy service which may add additional controls. For example, if an application needs full access to a sensitive S3 bucket via an access key, it may be better if a Lambda performed the operations on behalf of the application, and through that you could perform rate-limiting, geo-IP restrictions, and data redaction or tokenization where possible. Although there are a number of ways to implement this type of risk mitigation, with AWS’s S3 Object Lambdas, it may be possible to implement with minimal changes to the external application.
Isolate functionality requiring access keys There are sometimes cases where AWS services require access keys for certain use cases. One example is when you want S3 pre-signed URLs that remain valid for multiple days. There is an argument to be made that you should seek to remove that requirement for pre-signed URLs that live that long, but we’ll assume that can’t be changed for your use case. You could isolate the functionality that generates these URLs and put it into its own microservice that has limited privileges to accomplish this goal. The main application could then call this microservice to obtain the pre-signed URLs, and the access key would therefore be isolated from certain risks that come from being part of a larger application.
Conclusion This blog post explained how to reduce the risks associated with AWS access keys by applying a least-privilege strategy. This same concept can be applied to other AWS principals as well. In the final blog post in this series, we’ll discuss alternative authentication solutions for principals that use AWS access keys.