---
title: About the aws_iam_users Resource
platform: aws
---

# aws\_iam\_users

Use the `aws_iam_users` Chef InSpec audit resource to test properties of a all or multiple users.

To test properties of a single user, use the `aws_iam_user` resource.

To test properties of the special AWS root user (which owns the account), use the `aws_iam_root_user` resource.

<br>

## Availability

### Installation

This resource is distributed along with Chef InSpec itself. You can use it automatically.

### Version

This resource first became available in v2.0.16 of InSpec.

## Syntax

An `aws_iam_users` resource block uses a filter to select a group of users and then tests that group. With no filter, it returns all AWS IAM users.

    # No filter
    # We expect 42 users
    describe aws_iam_users do
      its('usernames.count') { should eq 42 }
    end

    # Using a filter
    # All users should have MFA (no user without MFA should exist)
    describe aws_iam_users.where(has_mfa_enabled?: false) do
      it { should_not exist }
    end

## Examples

The following examples show how to use this Chef InSpec audit resource.

### Test that all users have Multi-Factor Authentication enabled

    describe aws_iam_users.where(has_mfa_enabled?: false) do
      it { should_not exist }
    end

### Test that at least one user has a console password to log into the AWS web console

    describe aws_iam_users.where(has_console_password?: true) do
      it { should exist }
    end

### Test that all users who have a console password have Multi-Factor Authentication enabled

    console_users_without_mfa = aws_iam_users
                                .where(has_console_password?: true)
                                .where(has_mfa_enabled?: false)

    describe console_users_without_mfa do
      it { should_not exist }
    end

### Test that all users who have a console password have used it at least once

    console_users_with_unused_password = aws_iam_users
                                         .where(has_console_password?: true)
                                         .where(password_never_used?: true)

    describe console_users_with_unused_password do
      it { should_not exist }
    end

### Test that at least one user exists who has a console password and has used it at least once

    console_users_with_used_password = aws_iam_users
                                       .where(has_console_password?: true)
                                       .where(password_ever_used?: true)

    describe console_users_with_used_password do
      it { should exist }
    end


### Test that users with passwords that have not been used for 90 days do not

    describe aws_iam_users.where { password_last_used_days_ago > 90 } do
      it { should_not exist }
    end

<br>

## Filter Criteria

You may pass filter criteria to `where` to narrow down the result set.

### has\_attached\_policies

True or false. Filters the users to include only those that have at least one IAM managed policy attached to the user.

    # Don't attach policies to users
    describe aws_iam_users.where(has_attached_policies: true) do
      it { should_not exist }
    end

### has\_console\_password

True or false. Filters the users to include only those that have a console password (that is, they are able to login to the AWS web UI using a password).

    # No console passwords for anyone
    describe aws_iam_users.where(has_console_password: true) do
      it { should_not exist }
    end

### has\_inline\_policies

True or false. Filters the users to include only those that have at least one IAM policy directly embedded in the user record.

    # Embedding policies is usually hard to manage
    describe aws_iam_users.where(has_inline_policies: true) do
      it { should_not exist }
    end

### has\_mfa\_enabled

True or false. Filters the users to include only those that have some kind of Mult-Factor Authentication enabled (virtual or hardware).

    # Require MFA for everyone
    describe aws_iam_users.where(has_mfa_enabled: false) do
      it { should_not exist }
    end

### password\_ever\_used

True or false. Filters the users to include only those that have used their password at least once.

    # Someone should have used their password
    describe aws_iam_users.where(password_ever_used: true) do
      it { should exist }
    end

### password\_last\_used_days\_ago

Integer. Filters the users to include only those who used their password a certain number of days ago. '0' means today.

    # Bob should login every day
    describe aws_iam_users.where(password_ever_used: true, password_last_used_days_ago:0) do
      its('usernames') { should include 'bob' }
    end

    # This filter is often more useful in block mode, using a greater-than
    # Here, audit users who have not logged in in the last 30 days
    describe aws_iam_users.where do
      password_ever_used && password_last_used_days_ago > 30
    end do
      it { should_not exist' }
    end

### password\_never\_used

True or false. Filters the users to include only those that have used _never_ their password.

    # No zombie accounts!
    describe aws_iam_users.where(password_never_used: true) do
      it { should_not exist }
    end

### username

String. Filters the users to include only those whose username matches the value you provide.

    # Block mode example (recommended)
    # Service users should not have a password
    describe aws_iam_users.where { username.start_with?('service') } do
      it { should_not have_console_password }
    end

    # Method call example. This is a poor use of aws_iam_users (plural);
    # if you want to audit an individual user whose username you know, use
    # aws_iam_user (singular)
    # Verify Bob exists
    describe aws_iam_users.where(username: 'bob') do
      it { should exist }
    end

## Properties

Properties are used with the `its` test to obtain information about the matched users. Properties always return arrays, though they may be empty.

### attached\_policy\_arns

Array of strings. Each entry is the ARN of an IAM managed policy that is attached to at least one matched user. The list is de-duplicated, so if you have five users that are all attached to the same policy, `attached_policy_arns` will return only one ARN, not five.

    # Service users should be attached to a custom service policy
    describe aws_iam_users.where { username.start_with?('service') } do
      its('attached_policy_arns') { should include  'arn:aws:iam::123456789012:policy/MyServicePolicy' }
    end

### attached\_policy\_names

Array of strings. Each entry is the friendly name of an IAM managed policy that is attached to at least one matched user. The list is de-duplicated, so if you have five users that are all attached to the same policy, `attached_policy_names` will return only one name, not five.

    # Service users should be attached to a custom service policy
    # and not include Admin policy!
    describe aws_iam_users.where { username.start_with?('service') } do
      its('attached_policy_names') { should include  'MyServicePolicy' }
      its('attached_policy_names') { should_not include  'AdministratorAccess' }
    end

### inline\_policy\_names

Array of strings. Each entry is the name of an embedded policy that is embedded in at least one matched user. Keep in mind that each user has a copy of a policy (which can then be modified). This means that two users can have an embedded policy with the same name, but very different contents. The list is de-duplicated, so if you have five users that have an inline policy with the same name, `inline_policy_names` will return only one name, not five.

    # Service users should have a bespoke policy
    describe aws_iam_users.where { username.start_with?('service') } do
      its('inline_policy_names') { should include  'some-bespoke-policy' }
    end

### usernames

Array of strings. Each entry is the name of a user that matched. There will be exactly as many usernames here as there were users that matched, though it is possible to have non-unique usernames.

    # 42 Users, including Bob, should have a password.
    describe aws_iam_users.where(has_console_password: true) do
      its('usernames') { should include  'bob' }
      its('usernames.count') { should eq 42 }
    end

## Matchers

This Chef InSpec audit resource has the following resource-specific matchers.
For a full list of available matchers, please visit our [universal matchers page](https://www.inspec.io/docs/reference/matchers/).

As a plural resource, all matchers beginning with `have_` will return true if _any_ of the selected users match.

### exist

The test passes if the filtered user set is not empty. This basic matcher is frequently used with `should_not` to detect undesired conditions.

    # Require MFA for everyone
    describe aws_iam_users.where(has_mfa_enabled: false) do
      it { should_not exist }
    end

### have\_attached\_policies

The test passes if at least one user in the filtered set has at least one attached IAM managed policy.

    # Bachelors don't have attachments
    describe aws_iam_users.where { username =~ /bachelor/ } do
      it { should_not have_attached_policies }
    end

### have\_console\_password

The test passes if at least one user in the filtered set has a console password.

    describe aws_iam_users do
      it { should_not have_console_password }
    end

### have\_inline\_policies

The test passes if at least one user in the filtered set has at least one embedded policy.

    # No one should have an inline policy
    describe aws_iam_users do
      it { should_not have_inline_policies }
    end

### have\_mfa\_enabled

The test passes if at least one user in the filtered set has MFA enabled (virtual or hardware).

    # At least one person should use MFA.
    # This does not mean ALL users have MFA.
    describe aws_iam_users do
      it { should have_mfa_enabled }
    end

## AWS Permissions

Your [Principal](https://docs.aws.amazon.com/IAM/latest/UserGuide/intro-structure.html#intro-structure-principal) will need the `iam:ListUsers`, `iam:GetLoginProfile`, `iam:ListMFADevices`, `iam:ListAccessKeys`, `iam:ListUserPolicies`, and `iam:ListAttachedUserPolicies` action with Effect set to Allow.

You can find detailed documentation at [Actions, Resources, and Condition Keys for Identity And Access Management](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_identityandaccessmanagement.html).