mirror of
https://github.com/inspec/inspec
synced 2024-11-25 22:20:27 +00:00
Merge pull request #4452 from mhackethal/user-windows-fix
User windows fix
This commit is contained in:
commit
e48d08343b
5 changed files with 151 additions and 9 deletions
|
@ -34,13 +34,16 @@ A `user` resource block declares a user name, and then one (or more) matchers:
|
|||
its('mindays') { should eq 0 }
|
||||
its('maxdays') { should eq 90 }
|
||||
its('warndays') { should eq 8 }
|
||||
its('passwordage') { should eq 355 }
|
||||
its('maxbadpasswords') { should eq nil } // Only valid on Windows OS
|
||||
its('badpasswordattempts') { should eq 0 }
|
||||
end
|
||||
|
||||
where
|
||||
|
||||
* `('root')` is the user to be tested
|
||||
* `it { should exist }` tests if the user exists
|
||||
* `gid`, `group`, `groups`, `home`, `maxdays`, `mindays`, `shell`, `uid`, and `warndays` are valid matchers for this resource
|
||||
* `gid`, `group`, `groups`, `home`, `maxdays`, `mindays`, `shell`, `uid`, `warndays`´, `passwordage`, `maxbadpasswords` and `badpasswordattempts` are valid matchers for this resource
|
||||
|
||||
<br>
|
||||
|
||||
|
@ -90,6 +93,7 @@ The `gid` matcher tests the group identifier:
|
|||
its('gid') { should eq 1234 }
|
||||
|
||||
where `1234` represents the user identifier.
|
||||
The `gid` option is only available on Linux and will return `nil` for Windows os.
|
||||
|
||||
### group
|
||||
|
||||
|
@ -98,6 +102,7 @@ The `group` matcher tests the group to which the user belongs:
|
|||
its('group') { should eq 'root' }
|
||||
|
||||
where `root` represents the group.
|
||||
The `group` option is only available on Linux and will return `nil` for Windows os.
|
||||
|
||||
### groups
|
||||
|
||||
|
@ -148,3 +153,29 @@ The `warndays` matcher tests the number of days a user is warned before a passwo
|
|||
its('warndays') { should eq 5 }
|
||||
|
||||
where `5` represents the number of days a user is warned.
|
||||
|
||||
### passwordage
|
||||
|
||||
The `passwordage` matcher tests the number of days a user changed its password:
|
||||
|
||||
its('passwordage') { should_be <= 365 }
|
||||
|
||||
where `365` represents the number of days since the last password change.
|
||||
|
||||
### maxbadpasswords
|
||||
|
||||
The `maxbadpasswords` matcher tests the count of max badpassword settings for a specific user.
|
||||
|
||||
its('maxbadpasswords') { should eq 7 }
|
||||
|
||||
where `7` is the count of maximum bad password attempts.
|
||||
|
||||
### badpasswordattempts
|
||||
|
||||
The `badpasswordattempts` matcher tests the count of bad password attempts for a user.
|
||||
|
||||
its('badpasswordattempts') { should eq 0 }
|
||||
|
||||
where `0` is the count of bad passwords for a user.
|
||||
On Linux based operating systems it relies on `lastb` and for Windows it uses information stored for the user object.
|
||||
These settings will be resetted to `0` depending on your operating system configuration.
|
|
@ -31,7 +31,7 @@ A `users` resource block declares a user name, and then one (or more) matchers:
|
|||
|
||||
where
|
||||
|
||||
* `gid`, `group`, `groups`, `home`, `maxdays`, `mindays`, `shell`, `uid`, and `warndays` are valid matchers for this resource
|
||||
* `gid`, `group`, `groups`, `home`, `maxdays`, `mindays`, `shell`, `uid`, `warndays`, `passwordage`, `maxbadpasswords` and `badpasswordattempts` are valid matchers for this resource
|
||||
* `where(uid: 0).entries` represents a filter that runs the test only against matching users
|
||||
|
||||
For example:
|
||||
|
@ -149,3 +149,29 @@ The `warndays` matcher tests the number of days a user is warned before a passwo
|
|||
its('warndays') { should eq 5 }
|
||||
|
||||
where `5` represents the number of days a user is warned.
|
||||
|
||||
### passwordage
|
||||
|
||||
The `passwordage` matcher tests the number of days a user changed its password:
|
||||
|
||||
its('passwordage') { should_be <= 365 }
|
||||
|
||||
where `365` represents the number of days since the last password change.
|
||||
|
||||
### maxbadpasswords
|
||||
|
||||
The `maxbadpasswords` matcher tests the count of max badpassword settings for a specific user.
|
||||
|
||||
its('maxbadpasswords') { should eq 7 }
|
||||
|
||||
where `7` is the count of maximum bad password attempts.
|
||||
|
||||
### badpasswordattempts
|
||||
|
||||
The `badpasswordattempts` matcher tests the count of bad password attempts for a user.
|
||||
|
||||
its('badpasswordattempts') { should eq 0 }
|
||||
|
||||
where `0` is the count of bad passwords for a user.
|
||||
On Linux based operating systems it relies on `lastb` and for Windows it uses information stored for the user object.
|
||||
These settings will be resetted to `0` depending on your operating system configuration.
|
|
@ -3,6 +3,7 @@ require "inspec/utils/convert"
|
|||
require "inspec/utils/filter"
|
||||
require "inspec/utils/simpleconfig"
|
||||
require "inspec/resources/powershell"
|
||||
require "date"
|
||||
|
||||
module Inspec::Resources
|
||||
# This file contains two resources, the `user` and `users` resource.
|
||||
|
@ -116,6 +117,24 @@ module Inspec::Resources
|
|||
# its('mindays') { should eq 0 }
|
||||
# its('maxdays') { should eq 99 }
|
||||
# its('warndays') { should eq 5 }
|
||||
# its('passwordage') { should be >= 0 }
|
||||
# its('maxbadpasswords') { should eq nil } // not yet supported on linux
|
||||
# its('badpasswordattempts') { should eq 0 }
|
||||
# end
|
||||
# describe user('Administrator') do
|
||||
# it { should exist }
|
||||
# its('uid') { should eq "S-1-5-21-1759981009-4135989804-1844563890-500" }
|
||||
# its('gid') { should eq nil } // not supported on Windows
|
||||
# its('group') { should eq nil } // not supported on Windows
|
||||
# its('groups') { should eq ['Administrators', 'Users']}
|
||||
# its('home') { should eq '' }
|
||||
# its('shell') { should eq nil } // not supported on Windows
|
||||
# its('mindays') { should eq 0 }
|
||||
# its('maxdays') { should eq 42 }
|
||||
# its('warndays') { should eq nil }
|
||||
# its('passwordage') { should eq 355 }
|
||||
# its('maxbadpasswords') { should eq 0 }
|
||||
# its('badpasswordattempts') { should eq 0 }
|
||||
# end
|
||||
#
|
||||
# The following Serverspec matchers are deprecated in favor for direct value access
|
||||
|
@ -196,6 +215,14 @@ module Inspec::Resources
|
|||
meta_info[:shell] unless meta_info.nil?
|
||||
end
|
||||
|
||||
def domain
|
||||
meta_info[:domain] unless meta_info.nil?
|
||||
end
|
||||
|
||||
def userflags
|
||||
meta_info[:userflags] unless meta_info.nil?
|
||||
end
|
||||
|
||||
# returns the minimum days between password changes
|
||||
def mindays
|
||||
credentials[:mindays] unless credentials.nil?
|
||||
|
@ -211,6 +238,18 @@ module Inspec::Resources
|
|||
credentials[:warndays] unless credentials.nil?
|
||||
end
|
||||
|
||||
def badpasswordattempts
|
||||
credentials[:badpasswordattempts] unless credentials.nil?
|
||||
end
|
||||
|
||||
def maxbadpasswords
|
||||
credentials[:maxbadpasswords] unless credentials.nil?
|
||||
end
|
||||
|
||||
def passwordage
|
||||
credentials[:passwordage] unless credentials.nil?
|
||||
end
|
||||
|
||||
# implement 'mindays' method to be compatible with serverspec
|
||||
def minimum_days_between_password_change
|
||||
Inspec.deprecate(:resource_user_serverspec_compat, "The user resource `minimum_days_between_password_change` property is deprecated. Please use `mindays`.")
|
||||
|
@ -425,10 +464,17 @@ module Inspec::Resources
|
|||
multiple_values: false
|
||||
).params
|
||||
|
||||
dparse = Date.parse "#{params['Last password change']}"
|
||||
dayslastset = (Date.today - dparse).to_i
|
||||
cmd = inspec.command("lastb -w -a | grep #{username} | wc -l")
|
||||
badpasswordattempts = convert_to_i(cmd.stdout.chomp) if cmd.exit_status == 0
|
||||
|
||||
{
|
||||
mindays: convert_to_i(params["Minimum number of days between password change"]),
|
||||
maxdays: convert_to_i(params["Maximum number of days between password change"]),
|
||||
warndays: convert_to_i(params["Number of days of warning before password expires"]),
|
||||
passwordage: dayslastset,
|
||||
badpasswordattempts: badpasswordattempts,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
@ -481,6 +527,8 @@ module Inspec::Resources
|
|||
mindays: user_sec[1].to_i * 7,
|
||||
maxdays: user_sec[2].to_i * 7,
|
||||
warndays: user_sec[3].to_i,
|
||||
passwordage: nil,
|
||||
badpasswordattempts: nil,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
@ -573,6 +621,31 @@ module Inspec::Resources
|
|||
res[0] unless res.empty?
|
||||
end
|
||||
|
||||
def meta_info(username)
|
||||
res = identity(username)
|
||||
return if res.nil?
|
||||
{
|
||||
home: res[:home],
|
||||
shell: res[:shell],
|
||||
domain: res[:domain],
|
||||
userflags: res[:userflags],
|
||||
}
|
||||
end
|
||||
|
||||
def credentials(username)
|
||||
res = identity(username)
|
||||
return if res.nil?
|
||||
{
|
||||
mindays: res[:mindays],
|
||||
maxdays: res[:maxdays],
|
||||
warndays: res[:warndays],
|
||||
badpasswordattempts: res[:badpasswordattempts],
|
||||
maxbadpasswords: res[:maxbadpasswords],
|
||||
minpasswordlength: res[:minpasswordlength],
|
||||
passwordage: res[:passwordage],
|
||||
}
|
||||
end
|
||||
|
||||
def list_users
|
||||
collect_user_details.map { |user| user[:username] }
|
||||
end
|
||||
|
|
|
@ -91,6 +91,12 @@ if os.windows?
|
|||
# should return the SID of the user
|
||||
its('uid') { should_not eq nil}
|
||||
its('groups') { should include userinfo[:groups] }
|
||||
its('mindays') { should eq 0 }
|
||||
its('maxdays') { should eq 42 }
|
||||
its('warndays') { should eq nil }
|
||||
its('passwordage') { should_be > 5 }
|
||||
its('maxbadpasswords') { should eq 0 }
|
||||
its('badpasswordattempts') { should eq 0 }
|
||||
end
|
||||
|
||||
# also support simple username for local users without domain
|
||||
|
@ -99,7 +105,13 @@ if os.windows?
|
|||
# should return the SID of the user
|
||||
its('uid') { should_not eq nil}
|
||||
its('groups') { should include userinfo[:groups] }
|
||||
end
|
||||
its('mindays') { should eq 0 }
|
||||
its('maxdays') { should eq 42 }
|
||||
its('warndays') { should eq nil }
|
||||
its('passwordage') { should_be > 5 }
|
||||
its('maxbadpasswords') { should eq 0 }
|
||||
its('badpasswordattempts') { should eq 0 }
|
||||
end
|
||||
else
|
||||
# test single `user` resource
|
||||
describe user(userinfo[:username]) do
|
||||
|
|
|
@ -120,10 +120,10 @@ describe "Inspec::Resources::User" do
|
|||
_(resource.exists?).must_equal true
|
||||
_(resource.group).must_be_nil
|
||||
_(resource.groups).must_equal %w{Administrators Users}
|
||||
_(resource.home).must_be_nil
|
||||
_(resource.home).wont_be_nil
|
||||
_(resource.shell).must_be_nil
|
||||
_(resource.mindays).must_be_nil
|
||||
_(resource.maxdays).must_be_nil
|
||||
_(resource.mindays).wont_be_nil
|
||||
_(resource.maxdays).wont_be_nil
|
||||
_(resource.warndays).must_be_nil
|
||||
_(resource.disabled?).must_equal false
|
||||
end
|
||||
|
@ -134,10 +134,10 @@ describe "Inspec::Resources::User" do
|
|||
_(resource.exists?).must_equal true
|
||||
_(resource.group).must_be_nil
|
||||
_(resource.groups).must_equal ["Users"]
|
||||
_(resource.home).must_be_nil
|
||||
_(resource.home).wont_be_nil
|
||||
_(resource.shell).must_be_nil
|
||||
_(resource.mindays).must_be_nil
|
||||
_(resource.maxdays).must_be_nil
|
||||
_(resource.mindays).wont_be_nil
|
||||
_(resource.maxdays).wont_be_nil
|
||||
_(resource.warndays).must_be_nil
|
||||
_(resource.disabled?).must_equal true
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue