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:
Miah Johnson 2018-03-07 06:31:30 -08:00 committed by Christoph Hartmann
parent acd20e8aea
commit f6db0e345a
3 changed files with 105 additions and 66 deletions

View file

@ -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

View file

@ -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)

View file

@ -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