inspec/lib/resources/file.rb
2016-01-03 00:03:24 +01:00

146 lines
4.1 KiB
Ruby

# encoding: utf-8
# copyright: 2015, Vulcano Security GmbH
# author: Dominik Richter
# author: Christoph Hartmann
# license: All rights reserved
module Inspec::Resources
class File < Inspec.resource(1)
name 'file'
desc 'Use the file InSpec audit resource to test all system file types, including files, directories, symbolic links, named pipes, sockets, character devices, block devices, and doors.'
example "
describe file('path') do
it { should exist }
it { should be_file }
it { should be_readable }
it { should be_writable }
it { should be_owned_by 'root' }
its('mode') { should eq 0644 }
end
"
include MountParser
attr_reader :file, :path, :mount_options
def initialize(path)
@path = path
@file = inspec.backend.file(@path)
end
%w{
type exist? file? block_device? character_device? socket? directory?
symlink? pipe? mode mode? owner owned_by? group grouped_into? link_target
link_path linked_to? content mtime size selinux_label immutable?
product_version file_version version? md5sum sha256sum
}.each do |m|
define_method m.to_sym do |*args|
file.method(m.to_sym).call(*args)
end
end
def contain(*_)
fail 'Contain is not supported. Please use standard RSpec matchers.'
end
def readable?(by_usergroup, by_specific_user)
return false unless exist?
file_permission_granted?('r', by_usergroup, by_specific_user)
end
def writable?(by_usergroup, by_specific_user)
return false unless exist?
file_permission_granted?('w', by_usergroup, by_specific_user)
end
def executable?(by_usergroup, by_specific_user)
return false unless exist?
file_permission_granted?('x', by_usergroup, by_specific_user)
end
def mounted?(expected_options = nil, identical = false)
mounted = file.mounted
# return if no additional parameters have been provided
return file.mounted? if expected_options.nil?
# deprecation warning, this functionality will be removed in future version
warn "[DEPRECATION] `be_mounted.with and be_mounted.only_with` are deprecated. Please use `mount('#{path}')` instead."
# we cannot read mount data on non-Linux systems
return nil if !inspec.os.linux?
# parse content if we are on linux
@mount_options ||= parse_mount_options(mounted.stdout, true)
if identical
# check if the options should be identical
@mount_options == expected_options
else
# otherwise compare the selected values
@mount_options.contains(expected_options)
end
end
def to_s
"File #{path}"
end
private
def file_permission_granted?(flag, by_usergroup, by_specific_user)
fail 'Checking file permissions is not supported on your os' unless unix?
usergroup = usergroup_for(by_usergroup, by_specific_user)
if by_specific_user.nil?
check_file_permission_by_mask(usergroup, flag)
else
check_file_permission_by_user(by_specific_user, flag)
end
end
def check_file_permission_by_mask(usergroup, flag)
mask = file.unix_mode_mask(usergroup, flag)
fail 'Invalid usergroup/owner provided' if mask.nil?
(file.mode & mask) != 0
end
def check_file_permission_by_user(user, flag)
if linux?
perm_cmd = "su -s /bin/sh -c \"test -#{flag} #{path}\" #{user}"
elsif family == 'freebsd'
perm_cmd = "sudo -u #{user} test -#{flag} #{path}"
else
return skip_resource 'The `file` resource does not support `by_user` on your OS.'
end
cmd = inspec.command(perm_cmd)
cmd.exit_status == 0 ? true : false
end
def usergroup_for(usergroup, specific_user)
if usergroup == 'others'
'other'
elsif (usergroup.nil? || usergroup.empty?) && specific_user.nil?
'all'
else
usergroup
end
end
def unix?
inspec.os.unix?
end
def linux?
inspec.os.linux?
end
def family
inspec.os[:family]
end
end
end