--- title: About the shadow Resource platform: linux --- # 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 hashed password for that user * 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 user properties to be tested: describe shadow do its('user') { should_not include 'forbidden_user' } end Properties can be used as a single query: describe shadow.user('root') do its('count') { should eq 1 } end Use the `.where` method to find properties that match a value: describe shadow.where { min_days == '0' } do its ('user') { should include 'nfs' } end describe shadow.where { password =~ /[x|!|*]/ } do its('count') { should eq 0 } end The following properties are available: * `user` * `password` * `last_change` * `min_days` * `max_days` * `warn_days` * `inactive_days` * `expiry_date` * `reserved`
## Examples The following examples show how to use this InSpec audit resource. ### Test for a forbidden user describe shadow do its('user') { should_not include 'forbidden_user' } end ### Test that a user appears one time describe shadow.user('bin') do its('password') { should cmp 'x' } its('count') { should eq 1 } end
## Properties ### user The `user` property tests if the username exists `/etc/shadow`: its('user') { should eq 'root' } ### password The `password` property 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('password') { should cmp '*' } ### last_change The `last_change` property tests the last time a password was changed: its('last_change') { should be_empty } ### min_days The `min_days` property tests the minimum number of days a password must exist, before it may be changed: its('min_days') { should eq 0 } ### max_days The `max_days` property tests the maximum number of days after which a password must be changed: its('max_days') { should eq 90 } ### warn_days The `warn_days` property tests the number of days a user is warned about an expiring password: its('warn_days') { should eq 7 } ### inactive_days The `inactive_days` property tests the number of days a user must be inactive before the user account is disabled: its('inactive_days') { should be_empty } ### expiry_date The `expiry_date` property tests the number of days a user account has been disabled: its('expiry_date') { should be_empty } ### count The `count` property tests the number of times the named property appears: describe shadow.user('root') do its('count') { should eq 1 } end This property is best used in conjunction with filters. For example: describe shadow.where { password =~ /[x|!|*]/ } do its('count') { should eq 0 } end
## Matchers For a full list of available matchers, please visit our [matchers page](https://www.inspec.io/docs/reference/matchers/).