AWS Partner Network (APN) Blog

IAM 10th Anniversary: Top Recommendations for Working with IAM from Our AWS Heroes – Part 1

By Rowan Udell, Principal Solutions Architect – Stax

IAM 10th Anniversary

If you have used Amazon Web Services (AWS), then you have used AWS Identity and Access Management (IAM).

Not only does IAM grant secure access to what you and your applications do in AWS, it also grants access to the many AWS service-to-service calls that occur behind the scenes.

IAM handles more than 400 million API calls per second worldwide. Even as you navigate through the AWS Management Console, when you view settings and resources, this causes authorization requests to be validated against IAM.

IAM is essential in securing your applications and your AWS environment as a whole.

This year marks the 10th anniversary of IAM, and to help you get the most out of this critical AWS service I am excited to participate in a blog series featuring top recommendations for using IAM from AWS Heroes and AWS Partner Network (APN) Ambassadors.

AWS Heroes and APN Ambassadors love sharing their knowledge to benefit the AWS community. You can find us blogging, posting on social media, speaking at events and conferences, and overall making a big impact by helping everyone have a better experience when using AWS.

I am a Principal Solutions Architect at Stax, an AWS ISV Partner and a managed platform that accelerates secure AWS outcomes through prefabricated patterns, proactive guardrails, and data insights.

While focusing on serverless computing and security, I work with builders across most of the AWS services. I am a co-author of the AWS Administration Cookbook and am currently working on my next book, the Practical AWS IAM Guide.

In this blog series, I invite you to read on as my fellow AWS Heroes and APN Ambassadors share their recommendations, which are driven from personal experiences using a service that’s foundational for the security of AWS customers.

Less is More When it Comes to Privileges

The term “least privilege” is used a lot in the cloud business today. It’s something that is attainable with IAM, and something you should aim for. As you do, remember that least privilege is a journey, not a destination.

The principle of least privilege is all about giving the principals who interact with your systems the least amount of access possible, while still allowing them to do their jobs.

Almost every team I have worked with over the years wants to achieve least privilege, but most of them have had challenges doing it without impacting their rate of change and innovation. Based on that experience, I want to put forward an approach that balances using least privilege where it counts, and having flexibility where it’s needed.

This approach works best with a role-based access control (RBAC) implementation, which is the more common approach to access control. RBAC in IAM means giving access to one or more roles that have a specific purpose or job, and allowing the right users access to them at the right time.

If you’re using attribute-based access control (ABAC), the implementation changes slightly, but the goal and motivation remain the same.

Make it Easy for Builders to Do the Right Thing

The only time your privileges will be static is when you stop changing. While that might be possible for some specific parts of your AWS usage, chances are you came to AWS for the services and features it releases on a regular basis, and that implies change.

The idea behind this approach is to gradually “turn the dial up” on your level of control as you progress through your environments, starting in development where you experience the most change and provide the least restrictive permissions. Next, you’ll reduce the permissions in your test (sometimes also called staging) environment, and finally enforce specific privileges in production.

This approach works best if you’re following a multi-account approach. Implementing these practices will be much easier and safer if each of your environments are distinct from each other. If you’re stuck in a situation where all of your environments are in the same AWS account, then you will likely have to go with an ABAC-based approach.

Fewer Privileges

Starting in your development environment, you’ll need broader-scoped policies to let developers do their job effectively and quickly. Over-limiting their privileges here, even with the best of intentions, will only slow your developers down, frustrate them, and probably encourage them to find ways around the restrictions.

At this stage, your goal should be simply to use fewer privileges, not least privileges. This means no administrator access.

A good starting point is limiting developers to only the AWS services they need. You can achieve this by using AWS managed policies, which have the benefit of being focused on common roles you’ll need when working with services, or by creating a policy that uses wildcards with the service names your developers need to use, such as cloudformation:*, lambda:*.

You get bonus points if you take the extra step to allow these services only in your development accounts, by using AWS Organizations service control policies (SCPs), and deny all other services.

Specific Privileges

After your builders have had a chance to play, learn, and use the services in their development environment, it’s time to get more specific about their privileges. In your test environment, you should mandate that service-level permissions are not allowed, and all actions must be specified.

You might decide to make a small compromise and allow wildcards in part of the action, which means that developers can think of their privileges in terms of Create, Read, Update, and Delete (CRUD) actions.

In practice, this looks like cloudformation:Create* for create actions in AWS CloudFormation, or lambda:Get*, lambda:List* for read operations in AWS Lambda. Allowing these extra privileges goes a long way to improving developer velocity.

Note: You should read the IAM documentation carefully, because some actions, such as Put*, might also allow you to modify access permissions for the resource. For example, s3:PutBucketAcl allows you to modify your bucket’s accessibility from outside your account. You can choose to deny actions such as these for additional safety.

Some teams are happy to stop at this level, because it gives them the ability to reason broadly (in CRUD terms) about what roles can and cannot do in their environment, without knowing about every action in the IAM policy specification.

This is where your developers should be able to uncover the last few “Permission Denied” errors before going to production. Remember, everyone has a test environment—some are just fortunate enough that it’s not also their production environment!

Least Privileges

As your roles progress into your production environment, you should require that all IAM actions are explicitly specified in your policies. It’s quick and easy to check for wildcards in your policies and flag these in your deployment pipelines.

In practice, this might be a gradual process, depending on your risk appetite and timeframes.

Don’t Force it, Review it

Remember that “perfect is the enemy of good” and that it’s better to limit your policies as much as possible, even if literal least privilege is hard to achieve.

There are a variety of tools out there that can help you craft your least privilege policies, such as iamlive by the prolific Ian Mckay; Policy Sentry by Salesforce (which is a domain-specific language that makes it easier to craft your policies with a CRUD-like focus on defining actions); and IAM Access Analyzer’s recently released functionality that recommends what your policy should include.

IAM Unique IDs

Behind the scenes, IAM has its own unique, immutable IDs for resources. Although you don’t generally need to worry about implementation details like these, occasionally you may come across them.

I’ve seen more than a few teams surprised by something in their policies that they didn’t put there, and quite rightly! Being aware of changes to your policies is critical when managing IAM in your AWS environment.

What Resource IDs Look Like

Each IAM resource has an alphanumeric identification string as its ID, and you can discern the specific resource by its prefix. The most common ones you will see start with “AIDA…” for users, and “AROA…” for roles.

A full list of prefixes is available in the IAM User Guide.

When You See Resource IDs

Normally, when you specify a principal, you’ll use the friendly Amazon Resource Name (ARN) for clarity and consistency with other parts of the policy specification.

As long as the ARN is valid, you will see the ARN. If the ARN becomes invalid, usually because the principal has been deleted, then the underlying ID is shown.

Trust Policy: Before Deleting a Referenced Principal

Here’s an example of a user principal that has permissions granted through a trust policy.

Figure 1 - What you see after creating the trust policy.

Figure 1 – What you see after creating the trust policy.

In the policy JSON, the principal uses the ARN as you’d expect:

"Statement": [
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::123456789012:user/rowan"
        "Action": "sts:AssumeRole"

Trust Policy: After Deleting a Referenced Principal

After the user principal has been deleted, the friendly ARN is no longer valid, so the ID is shown (note the “AIDA” prefix).

Figure 2 - What you see after deleting a principal referenced from the trust policy.

Figure 2 – What you see after deleting a principal references from the trust policy.

This ID string also shows up in the JSON version of the policy:

"Statement": [
        "Effect": "Allow",
        "Principal": {
            "AWS": "AIDA22MSEQDJQKCO66JOR"
        "Action": "sts:AssumeRole"

This behavior has the side effect of preventing “escalation of privilege” attacks. If IAM policies relied upon the friendly ARN to designate principals, a malicious user could delete and recreate a principal with the same friendly name, and inherit all the permissions of the previous entity.

Because you aren’t relying on a fungible ARN, any changes must be verified and explicitly accepted. This means you can reuse friendly names if you need to in the future, without compromising your security.

You can also find out the IDs of your resources by using a few specific API calls.

How to Fix IDs

If you do see IDs in your policies, first make sure that they match your expectations. If they’re not what you’re expecting, then update the policy to point to the new ARN to remove the old reference and display the friendly name again.


In this post, I showed you a practical approach to achieving least privilege by balancing developer innovation with security. With lower environments having less restrictive permissions to enable developers to do their job more efficiently, you can enforce more specific permissions in upper environments where least privilege counts the most.

Additionally, I explained IAM resource IDs, where you find them, and how they provide additional security by associating your trust policy with the unique user principal it represents. These recommendations will help you better secure your AWS environment.

Be sure to check out the other posts in our IAM 10th anniversary series on the APN Blog:

The content and opinions in this blog are those of the third-party author and AWS is not responsible for the content or accuracy of this post.


Stax – AWS Partner Spotlight

Stax is an AWS Competency Partner and managed platform that accelerates secure AWS outcomes through prefabricated patterns, proactive guardrails, and data insights.

Contact Stax | Partner Overview | AWS Marketplace

*Already worked with Stax? Rate the Partner

*To review an AWS Partner, you must be a customer that has worked with them directly on a project.