mirror of
https://github.com/inspec/inspec
synced 2024-11-10 15:14:23 +00:00
Merge pull request #3895 from mitre/al-mitre/more-permissive-than
Signed-off-by: Aaron Lippold <lippold@gmail.com>
This commit is contained in:
commit
0c884b1415
3 changed files with 60 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.
|
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: see the [`be_more_permissive_than(mode)`](#be_more_permissive_than?(mode)) matcher for upper and lower bounds on file mode.
|
||||||
|
|
||||||
### mtime
|
### 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.
|
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,14 @@ The `exist` matcher tests if the named file exists:
|
||||||
The `have_mode` matcher tests if a file has a mode assigned to it:
|
The `have_mode` matcher tests if a file has a mode assigned to it:
|
||||||
|
|
||||||
it { should have_mode }
|
it { should have_mode }
|
||||||
|
|
||||||
|
### `be_more_permissive_than(mode)`
|
||||||
|
|
||||||
|
`be_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
|
||||||
|
|
|
@ -133,6 +133,35 @@ module Inspec::Resources
|
||||||
|
|
||||||
alias sticky? sticky
|
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 proivde a value for the `maximum allowable permission` 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, 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
|
def to_s
|
||||||
"File #{source_path}"
|
"File #{source_path}"
|
||||||
end
|
end
|
||||||
|
@ -212,6 +241,10 @@ module Inspec::Resources
|
||||||
raise '`check_file_permission_by_mask` is not supported on Windows'
|
raise '`check_file_permission_by_mask` is not supported on Windows'
|
||||||
end
|
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)
|
def check_file_permission_by_user(access_type, user, path)
|
||||||
access_rule = translate_perm_names(access_type)
|
access_rule = translate_perm_names(access_type)
|
||||||
access_rule = convert_to_powershell_array(access_rule)
|
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('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.stubs(:file_permission_granted?).with('execute', 'by_usergroup', 'by_specific_user').returns('test_result')
|
||||||
_(resource.content).must_equal 'content'
|
_(resource.content).must_equal 'content'
|
||||||
|
_(resource.more_permissive_than?('000').must_equal false)
|
||||||
_(resource.exist?).must_equal true
|
_(resource.exist?).must_equal true
|
||||||
_(resource.mounted?).must_equal true
|
_(resource.mounted?).must_equal true
|
||||||
_(resource.to_s).must_equal 'File /fakepath/fakefile'
|
_(resource.to_s).must_equal 'File /fakepath/fakefile'
|
||||||
|
@ -34,6 +35,8 @@ describe Inspec::Resources::FileResource do
|
||||||
_(resource.suid).must_equal true
|
_(resource.suid).must_equal true
|
||||||
_(resource.sgid).must_equal true
|
_(resource.sgid).must_equal true
|
||||||
_(resource.sticky).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
|
end
|
||||||
it 'responds on Windows' do
|
it 'responds on Windows' do
|
||||||
resource = MockLoader.new(:windows).load_resource('file', 'C:/fakepath/fakefile')
|
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)
|
proc { resource.send(:contain, nil) }.must_raise(RuntimeError)
|
||||||
end
|
end
|
||||||
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