mirror of
https://github.com/inspec/inspec
synced 2024-11-10 23:24:18 +00:00
This adds the more_permissive_than?(mode)
matcher to the file
resource.
Fixes #3893 Signed-off-by: Aaron Lippold <lippold@gmail.com>
This commit is contained in:
parent
7887d25251
commit
a2a86860d6
3 changed files with 67 additions and 0 deletions
|
@ -119,6 +119,8 @@ not
|
|||
|
||||
Without the zero prefix for the octal value, InSpec will interpret it as the _decimal_ value 644, which is octal 1024 or `-----w-r-T`, and any test for a file that is `-rw-r--r--` will fail.
|
||||
|
||||
#### Note: If you want to validate that a file has an upper or lower bound in `mode` see the [`more_permissive_than?`(mode)](#more_permissive_than?(mode)) matcher below.
|
||||
|
||||
### mtime
|
||||
|
||||
The `mtime` property tests if the file modification time for the file matches the specified value. The mtime, where supported, is returned as the number of seconds since the epoch.
|
||||
|
@ -541,3 +543,21 @@ The `exist` matcher tests if the named file exists:
|
|||
The `have_mode` matcher tests if a file has a mode assigned to it:
|
||||
|
||||
it { should have_mode }
|
||||
|
||||
### `more_permissive_than?(mode)`
|
||||
|
||||
`more_permissive_than?(mode)` takes the maximum desired mode - in `octal format`
|
||||
('0644' or '0777') - of your file as a `String` and returns a `Boolean`. It will
|
||||
return `true` if your file has a mode with greater permissions than specified.
|
||||
|
||||
describe file('/etc/passwd') do
|
||||
it { should_not be_more_permissive_than?('0644') }
|
||||
it { should be_more_permissive_than?('0000') }
|
||||
end
|
||||
|
||||
my_file = file('/etc/passwd')
|
||||
describe "The file #{my_file.path} with permissions: `#{my_file.mode.to_s(8)}`" do
|
||||
subject { my_file }
|
||||
it { should_not be_more_permissive_than?('0644') }
|
||||
it { should be_more_permissive_than?('0000') }
|
||||
end
|
||||
|
|
|
@ -133,6 +133,35 @@ module Inspec::Resources
|
|||
|
||||
alias sticky? sticky
|
||||
|
||||
def more_permissive_than?(max_mode = nil)
|
||||
raise Inspec::Exceptions::ResourceFailed, 'The file' + file.path + 'doesn\'t seem to exist' unless exist?
|
||||
raise ArgumentError, 'You must provide a value for the `maximum permission target` for the file.' if max_mode.nil?
|
||||
raise ArgumentError, 'You must proivde the `maximum permission target` as a `String`, you provided: ' + max_mode.class.to_s unless max_mode.is_a?(String)
|
||||
raise ArgumentError, 'The value of the `maximum permission target` should be a valid file mode in 4-ditgit octal format: for example, `0644` or `0777`' unless /(0)?([0-7])([0-7])([0-7])/.match?(max_mode)
|
||||
|
||||
# Using the files mode and a few bit-wise calculations we can ensure a
|
||||
# file is no more permisive than desired.
|
||||
#
|
||||
# 1. Calculate the inverse of the desired mode (e.g., 0644) by XOR it with
|
||||
# 0777 (all 1s). We are interested in the bits that are currently 0 since
|
||||
# it indicates that the actual mode is more permissive than the desired mode.
|
||||
# Conversely, we dont care about the bits that are currently 1 because they
|
||||
# cannot be any more permissive and we can safely ignore them.
|
||||
#
|
||||
# 2. Calculate the above result of ANDing the actual mode and the inverse
|
||||
# mode. This will determine if any of the bits that would indicate a more
|
||||
# permissive mode are set in the actual mode.
|
||||
#
|
||||
# 3. If the result is 0000. If the result is 0000, the files mode is equal
|
||||
# to or less permissive than the desired mode (PASS). Otherwise, the files
|
||||
# mode is more permissive than the desired mode (FAIL).
|
||||
|
||||
max_mode = max_mode.rjust(4, '0')
|
||||
binary_desired_mode = format('%04b', max_mode).to_i(2)
|
||||
desired_mode_inverse = (binary_desired_mode ^ 0b111111111)
|
||||
(desired_mode_inverse & file.mode).zero? ? false : true
|
||||
end
|
||||
|
||||
def to_s
|
||||
"File #{source_path}"
|
||||
end
|
||||
|
@ -212,6 +241,10 @@ module Inspec::Resources
|
|||
raise '`check_file_permission_by_mask` is not supported on Windows'
|
||||
end
|
||||
|
||||
def more_permissive_than?(*)
|
||||
raise Inspec::Exceptions::ResourceSkipped, 'The `more_permissive_than?` matcher is not supported on your OS yet.'
|
||||
end
|
||||
|
||||
def check_file_permission_by_user(access_type, user, path)
|
||||
access_rule = translate_perm_names(access_type)
|
||||
access_rule = convert_to_powershell_array(access_rule)
|
||||
|
|
|
@ -22,6 +22,7 @@ describe Inspec::Resources::FileResource do
|
|||
resource.stubs(:file_permission_granted?).with('write', 'by_usergroup', 'by_specific_user').returns('test_result')
|
||||
resource.stubs(:file_permission_granted?).with('execute', 'by_usergroup', 'by_specific_user').returns('test_result')
|
||||
_(resource.content).must_equal 'content'
|
||||
_(resource.more_permissive_than?('000').must_equal false)
|
||||
_(resource.exist?).must_equal true
|
||||
_(resource.mounted?).must_equal true
|
||||
_(resource.to_s).must_equal 'File /fakepath/fakefile'
|
||||
|
@ -34,6 +35,8 @@ describe Inspec::Resources::FileResource do
|
|||
_(resource.suid).must_equal true
|
||||
_(resource.sgid).must_equal true
|
||||
_(resource.sticky).must_equal true
|
||||
proc { resource.send(:more_permissive_than?, nil) }.must_raise(ArgumentError)
|
||||
proc { resource.send(:more_permissive_than?, 0700) }.must_raise(ArgumentError)
|
||||
end
|
||||
it 'responds on Windows' do
|
||||
resource = MockLoader.new(:windows).load_resource('file', 'C:/fakepath/fakefile')
|
||||
|
@ -79,3 +82,14 @@ describe Inspec::Resources::FileResource do
|
|||
proc { resource.send(:contain, nil) }.must_raise(RuntimeError)
|
||||
end
|
||||
end
|
||||
|
||||
describe Inspec::Resources::FileResource do
|
||||
let(:file) { stub(unix_mode_mask: 000, mode: 644) }
|
||||
it 'responds on Ubuntu' do
|
||||
resource = MockLoader.new(:ubuntu1404).load_resource('file', '/fakepath/fakefile')
|
||||
_(resource.more_permissive_than?('755').must_equal false)
|
||||
_(resource.more_permissive_than?('644').must_equal false)
|
||||
_(resource.more_permissive_than?('640').must_equal true)
|
||||
proc { resource.send(:more_permissive_than?, '0888') }.must_raise(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue