shadow

Use the shadow InSpec audit resource to test the contents of /etc/shadow, which contains password details that are only readable by the root user. The format for /etc/shadow includes:

  • A username
  • The password for that user (on newer systems passwords should be stored in /etc/shadow )
  • The last time a password was changed
  • The minimum number of days a password must exist, before it may be changed
  • The maximum number of days after which a password must be changed
  • The number of days a user is warned about an expiring password
  • The number of days a user must be inactive before the user account is disabled
  • The number of days a user account has been disabled

These entries are defined as a colon-delimited row in the file, one row per user:

dannos:Gb7crrO5CDF.:10063:0:99999:7:::


Syntax

A shadow resource block declares one (or more) users and associated user information to be tested:

describe shadow do
  its('users') { should_not include 'forbidden_user' }
end

or with a single query:

describe shadow.users('root') do
  its('count') { should eq 1 }
end

or with a filter:

describe shadow.filter(min_days: '0', max_days: '99999') do
  its('count') { should eq 1 }
end

The following properties are available:

  • users
  • passwords
  • last_changes
  • min_days
  • max_days
  • warn_days
  • inactive_days
  • expiry_date
  • reserved

Properties can be used as a single query or can be joined together with the .filter method.


Examples

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

Test for a forbidden user

describe shadow do
  its('users') { should_not include 'forbidden_user' }
end

Test that a user appears one time

describe shadow.users('bin') do
  its('passwords') { should cmp 'x' }
  its('count') { should eq 1 }
end


Matchers

For a full list of available matchers, please visit our matchers page.

count

The count matcher tests the number of times the named user appears in /etc/shadow:

its('count') { should eq 1 }

This matcher is best used in conjunction with filters. For example:

describe shadow.users('dannos') do
   its('count') { should eq 1 }
end

expiry_dates

The expiry_dates matcher tests the number of days a user account has been disabled:

its('expiry_dates') { should eq '' }

inactive_days

The inactive_days matcher tests the number of days a user must be inactive before the user account is disabled:

its('inactive_days') { should eq '' }

last_changes

The last_changes matcher tests the last time a password was changed:

its('last_changes') { should eq '' }

max_days

The max_days matcher tests the maximum number of days after which a password must be changed:

its('max_days') { should eq 90 }

min_days

The min_days matcher tests the minimum number of days a password must exist, before it may be changed:

its('min_days') { should eq 0 }

passwords

The passwords matcher returns the encrypted password string from the shadow file. The returned string may not be an encrypted password, but rather a * or similar which indicates that direct logins are not allowed.

For example:

its('passwords') { should cmp '*' }

users

The users matcher tests if the user name exists /etc/shadow:

its('users') { should eq 'root' }

warn_days

The warn_days matcher tests the number of days a user is warned about an expiring password:

its('warn_days') { should eq 7 }