Best Practices for More Secure AWS IAM


With companies maintaining tens to hundreds of individual AWS accounts at a time, each with 1,000+ available predefined or custom roles connecting to numerous services, and with multiple ways for users to authenticate to those accounts, secure AWS access management can quickly go from complex to nearly impossible. Compounding this complexity is how critical AWS is to both a company’s productivity and its security. Some of the major issues you can face managing AWS IAM include:

  • Access bottlenecks that prevent engineering from getting the resources they need to do their job or troubleshoot outages
  • Access bottlenecks that prevent security teams from investigating incidents in a timely manner
  • Workload burden on DevOps to manually review, approve, and provision AWS access
  • Standing access and over permissioning that leaves sensitive or confidential data open to vulnerabilities and threats

In general, there’s a constant tradeoff battle between productivity—give almost everyone access so they can get their work done, and security—give almost no one access so there are less threats to data security. Ideally, you don’t have to choose between these tradeoffs. Read on for step by step best practices for making AWS IAM more secure with the principle of least privilege.

1. Use a multi-account strategy & make authentication easy

The first step to securing your AWS access is to use a multi-account strategy that segregates each account by purpose. For example, you should have a dedicated account for your sandbox, staging, production, security logging, and so on, depending on your needs. You can then use organizational units (OUs) to organize all of the accounts into a logical structure, create specific permission sets within each account, i.e. prod-admin and prod-read-only, and use AWS SSO to make it easy for users to log into the accounts they need. For a more complete guide and thorough recommendations on setting this up, follow the AWS Security Reference Architecture.

If you have an IdP or SSO provider like Okta, AzureAD, Google Workspace or any other, you should map every AWS permission set in each account to a group in your IdP. This is a tedious exercise, so it’s possible to use Terraform to bulk create and map IdP groups to AWS permission sets to speed up the process. Groups will make it much easier to manage cohorts of users who need access to specific resources.

Now you should have a solid AWS multi-account structure, with the right permission sets, mapped to the right IdP groups to make authentication and getting access easy for any user. Here’s where the principle of least privilege comes into play—85% or more of your engineering team doesn’t need admin access on any given day. Authentication is taken care of, so authorization is the next priority.

2. Move to just-in-time & time-based access

While theoretically difficult to implement, just-in-time and time-based access controls are some of the best tools to achieve least privilege. Your engineering team may all have read-only access to the staging or production account, but there are only a select few who should have admin or read-write access. Set up a rotation, for example weekly, where a single engineer or team of engineers is on-call and actively pushing production changes. This person or group of people should get just-in-time access for the week. Make sure that users are deprovisioned from the IdP group or AWS permission set at the end of the time period.

Just-in-time access is also especially important for outages or security incidents that need to be investigated by someone who doesn’t (and shouldn’t) have standing privileges. In order to cut down on resolution time, access needs to be granted and provisioned within minutes or seconds after the request is sent and approved.

Overall, using just-in-time and time-based access eliminates standing privileges. Standing privileges unnecessarily increase the number of AWS users and their access levels at any given time. Those with access privileges hold the keys not only to proprietary data but to sensitive customer data as well. It only takes one user, whether maliciously or by mistake, to expose, compromise, or steal that data.

3. Automate as much as possible

Being able to grant just-in-time access and time-based access hinges on your ability to use some automation for provisioning and deprovisioning. If not, you’ll be inundated with tickets and manual tasks in a variety of applications. When a user requests access to an AWS permission set, it should automatically be provisioned directly in the AWS account or more ideally, in the IdP group you’re using that’s mapped to that permission set. The requester doesn’t need to know the behind the scenes details, but to maintain good authentication practices the access should be granted through the IdP group.

Deprovisioning is key to time-based access. Any access that’s granted for a set period of time needs to be tracked and revoked at the end. On top of that, all access changes should be logged and easily available to report on.

Maintaining visibility, tracking access changes, and continuously reviewing AWS access details not only helps achieve compliance goals, but strengthens your security posture in the process.

ConductorOne: Least Privilege Access Control for AWS

At ConductorOne, we believe modern workforces require modern solutions for access control—and this couldn’t be more true when considering the complexity of AWS IAM. ConductorOne orchestrates and automates the most time-consuming aspects of the best practices above, including just-in-time and time-based access with zero touch provisioning and deprovisioning. No more bottlenecks, no more standing privileges, no more overprivileged access slipping through the cracks, leaving sensitive data vulnerable. We help companies meet their security and compliance objectives with a quick time-to-value and an experience that users love.

Want to learn more about least privilege access controls for modern workforces? Chat with us.