mirror of
https://github.com/inspec/inspec
synced 2024-11-23 13:13:22 +00:00
Update shadow resource to use FilterTable (#2642)
* Change shadow resource to use FilterTable rather than custom filter implementation. Add tests for singluar aliased methods and other minor changes to work with FilterTable output. Coverage is at 100% Signed-off-by: Miah Johnson <miah@chia-pet.org> * merge master Signed-off-by: Miah Johnson <miah@chia-pet.org>
This commit is contained in:
parent
acd20e8aea
commit
f6db0e345a
3 changed files with 105 additions and 66 deletions
|
@ -93,11 +93,11 @@ This matcher is best used in conjunction with filters. For example:
|
|||
its('count') { should eq 1 }
|
||||
end
|
||||
|
||||
### expiry_dates
|
||||
### expiry_date
|
||||
|
||||
The `expiry_dates` matcher tests the number of days a user account has been disabled:
|
||||
The `expiry_date` matcher tests the number of days a user account has been disabled:
|
||||
|
||||
its('expiry_dates') { should eq '' }
|
||||
its('expiry_date') { should eq '' }
|
||||
|
||||
### inactive_days
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# encoding: utf-8
|
||||
# copyright: 2016, Chef Software Inc.
|
||||
|
||||
require 'forwardable'
|
||||
require 'utils/filter'
|
||||
|
||||
# The file format consists of
|
||||
# - user
|
||||
|
@ -31,78 +31,65 @@ module Inspec::Resources
|
|||
end
|
||||
"
|
||||
|
||||
extend Forwardable
|
||||
attr_reader :params
|
||||
attr_reader :content
|
||||
attr_reader :lines
|
||||
|
||||
def initialize(path = '/etc/shadow', opts = nil)
|
||||
opts ||= {}
|
||||
@path = path || '/etc/shadow'
|
||||
@content = opts[:content] || inspec.file(@path).content
|
||||
@lines = @content.to_s.split("\n")
|
||||
@raw_content = opts[:content] || inspec.file(@path).content
|
||||
@lines = @raw_content.to_s.split("\n")
|
||||
@filters = opts[:filters] || ''
|
||||
raise Inspec::Exceptions::ResourceSkipped, 'The `shadow` resource is not supported on your OS.' unless inspec.os.unix?
|
||||
@params = @lines.map { |l| parse_shadow_line(l) }
|
||||
end
|
||||
|
||||
def filter(hm = {})
|
||||
return self if hm.nil? || hm.empty?
|
||||
res = @params
|
||||
filters = ''
|
||||
hm.each do |attr, condition|
|
||||
condition = condition.to_s if condition.is_a? Integer
|
||||
filters += " #{attr} = #{condition.inspect}"
|
||||
res = res.find_all do |line|
|
||||
case line[attr.to_s]
|
||||
when condition
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
content = res.map { |x| x.values.join(':') }.join("\n")
|
||||
Shadow.new(@path, content: content, filters: @filters + filters)
|
||||
filter = FilterTable.create
|
||||
filter.add_accessor(:where)
|
||||
.add_accessor(:entries)
|
||||
.add(:users, field: 'user')
|
||||
.add(:passwords, field: 'password')
|
||||
.add(:last_changes, field: 'last_change')
|
||||
.add(:min_days, field: 'min_days')
|
||||
.add(:max_days, field: 'max_days')
|
||||
.add(:warn_days, field: 'warn_days')
|
||||
.add(:inactive_days, field: 'inactive_days')
|
||||
.add(:expiry_date, field: 'expiry_date')
|
||||
|
||||
filter.add(:content) { |t, _|
|
||||
t.entries.map do |e|
|
||||
[e.user, e.password, e.last_change, e.min_days, e.max_days, e.warn_days, e.inactive_days, e.expiry_date].compact.join(':')
|
||||
end.join("\n")
|
||||
}
|
||||
|
||||
filter.add(:count) { |i, _|
|
||||
i.entries.length
|
||||
}
|
||||
|
||||
filter.connect(self, :params)
|
||||
|
||||
def user(filter = nil)
|
||||
warn '[DEPRECATION] The shadow `user` property is deprecated and will be removed' \
|
||||
' in InSpec 3.0. Please use `users` instead.'
|
||||
filter.nil? ? users : users(filter)
|
||||
end
|
||||
|
||||
def entries
|
||||
@lines.map do |line|
|
||||
params = parse_shadow_line(line)
|
||||
Shadow.new(@path, content: line,
|
||||
filters: "#{@filters} on entry user=#{params['user']}")
|
||||
end
|
||||
def password(filter = nil)
|
||||
warn '[DEPRECATION] The shadow `password` property is deprecated and will be removed' \
|
||||
' in InSpec 3.0. Please use `passwords` instead.'
|
||||
filter.nil? ? passwords : passwords(filter)
|
||||
end
|
||||
|
||||
def users(name = nil)
|
||||
name.nil? ? map_data('user') : filter(user: name)
|
||||
def last_change(filter = nil)
|
||||
warn '[DEPRECATION] The shadow `last_change` property is deprecated and will be removed' \
|
||||
' in InSpec 3.0. Please use `last_changes` instead.'
|
||||
filter.nil? ? last_changes : last_changes(filter)
|
||||
end
|
||||
|
||||
def passwords(password = nil)
|
||||
password.nil? ? map_data('password') : filter(password: password)
|
||||
end
|
||||
|
||||
def last_changes(filter_by = nil)
|
||||
filter_by.nil? ? map_data('last_change') : filter(last_change: filter_by)
|
||||
end
|
||||
|
||||
def min_days(filter_by = nil)
|
||||
filter_by.nil? ? map_data('min_days') : filter(min_days: filter_by)
|
||||
end
|
||||
|
||||
def max_days(filter_by = nil)
|
||||
filter_by.nil? ? map_data('max_days') : filter(max_days: filter_by)
|
||||
end
|
||||
|
||||
def warn_days(filter_by = nil)
|
||||
filter_by.nil? ? map_data('warn_days') : filter(warn_days: filter_by)
|
||||
end
|
||||
|
||||
def inactive_days(filter_by = nil)
|
||||
filter_by.nil? ? map_data('inactive_days') : filter(inactive_days: filter_by)
|
||||
end
|
||||
|
||||
def expiry_dates(filter_by = nil)
|
||||
filter_by.nil? ? map_data('expiry_date') : filter(expiry_date: filter_by)
|
||||
def expiry_dates(filter = nil)
|
||||
warn '[DEPRECATION] The shadow `expiry_dates` property is deprecated and will be removed' \
|
||||
' in InSpec 3.0. Please use `expiry_date` instead.'
|
||||
filter.nil? ? expiry_date : expiry_date(filter)
|
||||
end
|
||||
|
||||
def to_s
|
||||
|
@ -110,8 +97,6 @@ module Inspec::Resources
|
|||
"/etc/shadow#{f}"
|
||||
end
|
||||
|
||||
def_delegator :@params, :length, :count
|
||||
|
||||
private
|
||||
|
||||
def map_data(id)
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# encoding: utf-8
|
||||
# author: Dominik Richter
|
||||
# author: Christoph Hartmann
|
||||
|
||||
require 'helper'
|
||||
require 'inspec/resource'
|
||||
|
@ -8,8 +6,13 @@ require 'inspec/resource'
|
|||
describe 'Inspec::Resources::Shadow' do
|
||||
let(:shadow) { load_resource('shadow') }
|
||||
|
||||
it 'content should be mapped correctly' do
|
||||
_(shadow.content).must_equal "root:x:1:2:3\nwww-data:!!:10:20:30:40:50:60"
|
||||
end
|
||||
|
||||
it 'retrieve users via field' do
|
||||
_(shadow.users).must_equal %w{root www-data}
|
||||
_(shadow.count).must_equal 2
|
||||
end
|
||||
|
||||
it 'retrieve passwords via field' do
|
||||
|
@ -37,7 +40,7 @@ describe 'Inspec::Resources::Shadow' do
|
|||
end
|
||||
|
||||
it 'retrieve dates when account will expire via field' do
|
||||
_(shadow.expiry_dates).must_equal [nil, "60"]
|
||||
_(shadow.expiry_date).must_equal [nil, "60"]
|
||||
end
|
||||
|
||||
it 'access all lines of the file' do
|
||||
|
@ -52,6 +55,30 @@ describe 'Inspec::Resources::Shadow' do
|
|||
})
|
||||
end
|
||||
|
||||
it 'returns deprecation notice on user property' do
|
||||
proc { _(shadow.user).must_equal %w{root www-data} }.must_output nil,
|
||||
'[DEPRECATION] The shadow `user` property is deprecated and will' \
|
||||
" be removed in InSpec 3.0. Please use `users` instead.\n"
|
||||
end
|
||||
|
||||
it 'returns deprecatation notice on password property' do
|
||||
proc { _(shadow.password).must_equal %w{x !!} }.must_output nil,
|
||||
'[DEPRECATION] The shadow `password` property is deprecated and will' \
|
||||
" be removed in InSpec 3.0. Please use `passwords` instead.\n"
|
||||
end
|
||||
|
||||
it 'returns deprecation notice on last_change property' do
|
||||
proc { _(shadow.last_change).must_equal %w{1 10} }.must_output nil,
|
||||
'[DEPRECATION] The shadow `last_change` property is deprecated and will' \
|
||||
" be removed in InSpec 3.0. Please use `last_changes` instead.\n"
|
||||
end
|
||||
|
||||
it 'returns deprecation notice on expiry_dates property' do
|
||||
proc { _(shadow.expiry_dates).must_equal [nil, "60"] }.must_output nil,
|
||||
'[DEPRECATION] The shadow `expiry_dates` property is deprecated and will' \
|
||||
" be removed in InSpec 3.0. Please use `expiry_date` instead.\n"
|
||||
end
|
||||
|
||||
describe 'filter via name =~ /^www/' do
|
||||
let(:child) { shadow.users(/^www/) }
|
||||
|
||||
|
@ -61,7 +88,34 @@ describe 'Inspec::Resources::Shadow' do
|
|||
end
|
||||
|
||||
it 'prints a nice to_s string' do
|
||||
_(child.to_s).must_equal '/etc/shadow with user = /^www/'
|
||||
_(child.to_s).must_equal '/etc/shadow with user == /^www/'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'filter via name = root' do
|
||||
let(:child) { shadow.users('root') }
|
||||
|
||||
it 'filters by user name' do
|
||||
_(child.users).must_equal %w{root}
|
||||
_(child.count).must_equal 1
|
||||
end
|
||||
end
|
||||
|
||||
describe 'filter via min_days' do
|
||||
let(:child) { shadow.min_days('20') }
|
||||
|
||||
it 'filters by property' do
|
||||
_(child.users).must_equal %w{www-data}
|
||||
_(child.count).must_equal 1
|
||||
end
|
||||
end
|
||||
|
||||
describe 'it raises errors' do
|
||||
it 'raises error on unsupported os' do
|
||||
resource = MockLoader.new(:windows).load_resource('shadow')
|
||||
_(resource.resource_skipped?).must_equal true
|
||||
_(resource.resource_exception_message).must_equal 'The `shadow` resource is not supported on your OS.'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue