How to perform an IAM Security Audit in AWS

Riyaz Walikar
Feature image

What is AWS IAM?

AWS Identity and Access Management (IAM) is a service within AWS’ cloud infrastructure that provides access control across all other services within AWS and including IAM itself. IAM allows you to create users, roles and policies that can be assigned to folks within your organisation or other services within AWS to perform specific functions.

Given that IAM essentially acts as the gatekeeper to access control for all AWS resources, it is imperative that the security of IAM itself must be considered when verifying the security of your cloud infrastructure.

Why should we audit AWS IAM?

An audit is the process of verifying information for a resource based on evidence that is gathered and to draw conclusions based on the evidence.

A security audit is an extension of this definition. In this sense, a security audit evaluates if the gaps between evidence and what is recorded results in security weaknesses or could potentially provide an attacker a window of opportunity.

AWS IAM is used to provision users, roles and their permissions so that different AWS resources can perform their functions and you (or other resources) can interact with each other. Given that this is such a critical component of AWS, a security audit allows us to answer security pertinent questions like:

  1. How many users have access to your AWS account?
  2. How many of them have never logged in?
  3. How many users use ACCESS and SECRET keys instead of passwords to access the AWS infrastructure?
  4. When did they last rotate these keys? Are any of them still unused?
  5. Are there any roles that are over-privileged and could be used to gain access to other resources within AWS?

Let’s take a look at at performing a step by step audit of IAM and its various components

Step by Step Auditing AWS IAM

Creating the user that will be used to perform the Audit

To begin the audit, an AWS IAM user with IAM ReadOnly permissions is required. This can easily be achieved by logging into the AWS console and creating a user. Of course, if you already have a user with administrative privileges you can use that user to continue, however, it would be a security best practice to create a user for this activity and use it periodically to perform the audit.

Step 1: Navigate to https://console.aws.amazon.com/iamv2/home?#/users and click on the “Add users” button. Give it a name. We are using the name “iamauditor”

AWS IAM user

Step 2: Click “Next: Permissions” to go to the permissions page where we will create an IAM user group and attach the “IAMReadOnlyAccess” permission to the group instead of to the user. The name of the group we are creating is “iamauditors”

AWS IAM user Permissions”

Click on “Create Group” to create the new group and have it selected in the Add user page.

AWS IAM Create Group

AWS IAM Add user to Group

Step 3: Click on “Next: Tags” to add tags to the user being created. Tags allow us to add attributes that can be used to filter and manage properties based on their functions. In this case, we are adding 3 tags “createdBy”, “createdFor” and “createdDate”.


Step 4: The last page offers you a review of the user being created. Click on the “Create user” button to create the user that we will be using for the audit.

review page of user

Step 5: Download and save the CSV file containing the user credentials. We will be configuring these credentials on our system next.

Download and save CSV file

Configuring a profile for the audit

In this section we will configure the credentials that we obtained of the new user locally on our system and use AWS CLI commands to perform the audit.

Step 1: Skip this step, if you already have the AWS CLI installed. Else download and install the AWS CLI for your operating system from https://aws.amazon.com/cli/.

Step 2: You can configure a new profile using the following command. Enter the information from the CSV when prompted. We can provide any region (us-east-1 for example) since IAM is a global service.

aws configure --profile iamauditor

aws configure profile

Step 3: Export the profile you just created to the “AWS_PROFILE” environment variable so that we don’t have to specify it every time on the command line. Confirm your account is set up using the following command:

export AWS_PROFILE=iamauditor

aws sts get-caller-identity

aws configure profile through cli

We are now ready to begin the audit.

Enumerating AWS IAM resource information for the Audit

We need to enumerate information about the following resources:

  1. IAM Account Password Policy
  2. Users
  3. User Groups
  4. Roles
  5. Policies

For each of these resources we will perform additional steps to identify and answer security related questions.

Enumerate IAM Account Password Policy

A password policy enforces users to set up and operate their accounts in adherence to rules that the organization requires. For example, a password policy prevents users from reusing their last 3 passwords.

In the case of AWS IAM, you can use the following command to obtain the current password policy that is enforced

aws iam get-account-password-policy

aws iam get-account-password-policy

Based on how secure you want the user passwords to be, you can verify if the password policy meets your requirement or not.

If you receive an error (NoSuchEntity), it means that the password policy was never created and this audit check can be considered a failure. However, a default AWS password policy does exist which enforces the following conditions on the password:

Refer to this AWS documentation to setup your own password policy - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html

Enumerating IAM user information using a credential report

AWS IAM provides a pretty neat feature that allows us to create an attribute snapshot of the users within IAM that can be used to answer a multitude of security questions.

Step 1: Generate an IAM security credential report using the following commands

aws iam generate-credential-report

aws iam generate-credential-report

Step 2: Download the credential report after a minute or so of running the previous command. If “State”: “COMPLETE” is printed as shown in the previous screenshot, you can go ahead and run the next command to download the report instead of waiting.

aws iam get-credential-report --query "Content" | cut -d '"' -f 2 | base64 -d > iam-credential-report.csv

This sequence of commands will take the response from the AWS IAM get-credential-report command and extract only the Base64 part and decode it with the help of the base64 command.

The report is saved in the i_am-credential-report.csv_ file.

Step 3: Open the file in a text editor like VSCode or since it’s a comma separated value file, you can open it in MS Excel or LibreOffice (or equivalent). The screenshot below shows the file in CSV preview mode in Visual Studio Code.

aws iam report

Step 4: Using the credential report, answer the following set of questions for your AWS account:

  1. Do you know all the users that are listed in the report? Are there any unfamiliar users?
  2. Are there any users whose password is enabled AND the password last used value is over 90 days? Why does a user exist who has not logged into AWS in the last 90 days? Is this user required?
  3. Are there any users whose password is enabled AND the password last changed value is over 90 days? Why hasn’t this user rotated their password as a security best practice?
  4. Are there any users whose password is enabled AND who do not have 2 factor authentication enabled? The value for the “Mfa_active” column will be False for these users.
  5. Are there any users who have Access keys? The columns “Access_key_1_active” or “Access_key_2_active” will be True. In case both the columns are True, then the user has 2 active Access Keys. Are there any such users with both keys active? Why?
  6. Which users have not used their Access Key in the last 90 days? This can be obtained from the values of the “Access_key_1_last_user_date” and “Access_key_2_last_user_date” columns.
  7. Which users have not rotated their Active key in the last 90 days? This can be obtained from the values of the “Access_key_1_last_rotated” and “Access_key_1_last_rotated” columns.

The answers to these questions will enable you to remove unnecessary users and unused keys from your AWS IAM thereby reducing your attack footprint.

Enumerating groups and policies attached to them

As we saw while creating a new user, it is recommended to add a user to a group and assign the group the permissions you want the user to have. In this section, we will enumerate the various user groups within IAM, identify what users are present in each group and check what effective permissions the users have because of policies attached to the group.

Step 1: Run the following command to get a list of groups:

aws iam list-groups

aws iam list-groups

Do you recognise all of the groups listed in the output of the above command? Are all of them required and relevant to your business?

Step 2: For each of the groups, enumerate the policies that are attached to the group. Three kinds of policies can be attached to a group (and to a user directly) - AWS Managed Policies, Customer Managed Policies and an Inline Policy. The following commands will list Inline policies and Managed (AWS and Customer) policies that are attached to the group:

aws iam list-group-policies --group-name <groupname>

aws iam list-attached-group-policies --group-name <groupname>

aws iam list-policies

Step 3: For each user, obtain a list of the groups that the user belongs to. Run the following commands to fetch a list of all users and the next command to get all the groups to which the provided user belongs:

aws iam list-users --query "Users[].UserName"

 aws iam list-groups-for-user --user-name <username-here>

aws iam list-groups-for-user

Now that we have users, the groups that they belong to and the policies attached to those groups, we can expand the policies and examine them if any of them give extra privileges to the groups and indirectly to the user within those groups.

**Step 4:**Run the following command to fetch the actual policy definition by providing the policy name in the command. The policy names were obtained from Step 2.

**Step 4.1:**For AWS and Customer Managed Policies that have been created, obtain the attached policy ARN and the policy version number.

aws iam list-attached-group-policies --group-name <groupname>

aws iam get-policy --policy-arn <policy-arn>

obtain attached policy ARN & policy version number

Next, obtain the policy document using the version number and the get-policy-version IAM command.

aws iam get-policy-version --policy-arn <policy-arn> --version-id <version>

aws iam get-policy-version

Review the Action and Resource section of the policy to determine privileges and identify if any of the policies are overprivileged.

Step 4.2: For inline policies, you can use the following command

aws iam get-group-policy --group-name <groupname> --policy-name <custom-policy-name>

aws iam get-group-policy

Verify the Action and Resource section of the policy and identify any untoward extraneous permissions.

Based on the group that these policies are attached to, verify if these sets of permissions are required or not by the business and the teams that use this AWS account.

Enumerating directly attached policies to users

Although it’s a recommended practice to attach policies to groups and assign users to specific groups based on the attached policies, it is still possible to directly attach a policy to a user.

Use the following steps to identify which users have directly attached policies and what these policies contain.

Step 1: Enumerate the list of users and check if any of them have a policy directly attached to them

Step 1.1: Run the following command to list all managed (AWS and Customer) policies that have been directly attached to the user

aws iam list-attached-user-policies --user-name <username>

aws iam list-attached-user-policies

Next, obtain the policy document using the version number and the get-policy-version IAM command.

aws iam get-policy-version --policy-arn <policy-arn> --version-id <version>

Review the Action and Resource section of the policy to determine privileges and identify if any of the policies are overprivileged.

Step 1.2: Run the following command to list inline policies attached directly to the user

aws iam list-user-policies --user-name <username>

aws iam list-user-policies

You can then use the following command to list the policy document of the attached inline policy to the user.

aws iam get-user-policy --user-name <username> --policy-name <policy-name>

aws iam get-user-policy

Verify the Action and Resource section of the policy and identify any untoward extraneous permissions.

Based on the user that these policies are attached to, verify if these sets of permissions are required or not by the business and the teams that use this AWS account.

Enumerating roles and the policies attached to them

Just like AWS IAM users are used to administer and manage cloud resources, AWS IAM Roles are used to provide different resources, say EC2 instances, the ability to interact with other services, say S3. These roles can be assigned permissions via policies based on their functions, but more often than not, roles end up with higher privileges.

In this section we will enumerate the roles and their policies as part of the audit

Step 1: Enumerate all the roles within your AWS account using the following commands. This can be a fairly large list.

aws iam list-roles

aws iam list-roles

You can use the query parameter, you can only extract the RoleName so that it is easier to fetch the policy in the next step. You can do this using the following command:

aws iam list-roles --query "Roles[].RoleName"

aws iam list-roles query rolename

From the list of existing roles, their names should give you an idea of what these roles are being used for. However, it is important to look at their attached policies as well to identify any role that has been maliciously created perhaps.

Step 2: For each of these roles, their attached policies need to be enumerated. Both Managed (AWS and Customer) and inline policy statements.

This can be done using the following commands:

aws iam list-role-policies --role-name <role-name>

aws iam list-attached-role-policies --role-name <role-name>

aws iam list-attached-role-policies

Step 3: The last step is to fetch the policy document itself. You can use the following commands to list the policy document of the policy attached to the role by first fetching the active version of the policy in use.

aws iam get-policy --policy-arn <policy-arn>

aws iam get-policy-version --version-id <policy-version> --policy-arn <policy-arn>

aws iam get-policy-version

Based on the policy statement you can determine if the policy is over privileged for the role that is attached to.

Next steps

Now that we have collected the following information (and on the way already answered a bunch of security questions) we can inspect the evidence and data collected to check and validate the security implications of their properties.

Thus far, we have,

  1. Collected all user information within AWS IAM, their password usage, key usage and MFA status;
  2. Enumerated privileges of individual users by inspecting any directly attached policies to them and by inspecting the policies attached to the groups to which they belong (if they do)
  3. Enumerated the password policy of the organization;
  4. Enumerated the roles, and policies attached to those roles so that we have an understanding of whether a role has privileges it is not supposed to have

From the data collected and the security questions answered along the way we can identify security deviations based on what works for your organization. You can also refer to the CIS Amazon Web Services Foundations Benchmark guidance to identify security compliance failures for IAM using the data collected.


In this post we learnt how to collect data about users, groups, roles and policies to answer security questions about AWS IAM. The Audit steps highlighted in this document can be used on a weekly or a monthly cadence to ensure security best practices and the principles of least privileges are being followed by users as well as resources within AWS.

In future articles, we will see how we can identify security vulnerabilities arising out of these audit failures leading to misconfiguration that can be exploited by attackers.


This article is brought to you by Kloudle Academy, a free e-resource compilation, created and curated by Kloudle. Kloudle is a cloud security management platform that uses the power of automation and simplifies human requirements in cloud security. If you wish to give your feedback on this article, you can write to us here.

← Back to Academy