inspec/lib/resources/group.rb
Adam Leff 577688a3a0 Placing all resources in the Inspec::Resources namespace
Many of the resources are named as a top-level class with a fairly generic class name, such as "OS". This causes an issue specifically with kitchen-google which depends on a gem which depends on the "os" gem which itself defines an OS class with a different superclass. This prevents users from using TK, Google Compute, and Inspec without this fix.

Some mocked commands had their digest changed as well due to the new indentation, specifically in the User and RegistryKey classes.

I strongly recommend viewing this diff with `git diff --ignore-space-change`
to see the *real* changes. :)
2016-03-08 13:40:16 -05:00

137 lines
3.5 KiB
Ruby

# encoding: utf-8
# author: Christoph Hartmann
# author: Dominik Richter
# Usage:
# describe group('root') do
# it { should exist }
# its('gid') { should eq 0 }
# end
#
# deprecated has matcher
# describe group('root') do
# it { should have_gid 0 }
# end
module Inspec::Resources
class Group < Inspec.resource(1)
name 'group'
desc 'Use the group InSpec audit resource to test groups on the system.'
example "
describe group('root') do
it { should exist }
its('gid') { should eq 0 }
end
"
def initialize(groupname, domain = nil)
@group = groupname.downcase
@domain = domain
@domain = @domain.downcase unless @domain.nil?
@cache = nil
# select group manager
@group_provider = nil
if inspec.os.unix?
@group_provider = UnixGroup.new(inspec)
elsif inspec.os.windows?
@group_provider = WindowsGroup.new(inspec)
else
return skip_resource 'The `group` resource is not supported on your OS yet.'
end
end
# verifies if a group exists
def exists?
# ensure that we found one group
!group_info.nil? && group_info.size > 0
end
def gid
return nil if group_info.nil? || group_info.size == 0
# the default case should be one group
return group_info[0][:gid] if group_info.size == 1
# return array if we got multiple gids
group_info.map { |grp| grp[:gid] }
end
# implements rspec has matcher, to be compatible with serverspec
def has_gid?(compare_gid)
gid == compare_gid
end
def local
return nil if group_info.nil? || group_info.size == 0
# the default case should be one group
return group_info[0][:local] if group_info.size == 1
# return array if we got multiple gids
group_info.map { |grp| grp[:local] }
end
def to_s
"Group #{@group}"
end
private
def group_info
return @cache if !@cache.nil?
@cache = @group_provider.group_info(@group, @domain) if !@group_provider.nil?
end
end
class GroupInfo
attr_reader :inspec
def initialize(inspec)
@inspec = inspec
end
end
# implements generic unix groups via /etc/group
class UnixGroup < GroupInfo
def group_info(group, _domain = nil)
inspec.etc_group.where(name: group).entries.map { |grp|
{
name: grp['name'],
gid: grp['gid'],
}
}
end
end
class WindowsGroup < GroupInfo
def group_info(compare_group, compare_domain = nil)
cmd = inspec.command('Get-WmiObject Win32_Group | Select-Object -Property Caption, Domain, Name, SID, LocalAccount | ConvertTo-Json')
# cannot rely on exit code for now, successful command returns exit code 1
# return nil if cmd.exit_status != 0, try to parse json
begin
groups = JSON.parse(cmd.stdout)
rescue JSON::ParserError => _e
return nil
end
# ensure we have an array of groups
groups = [groups] if !groups.is_a?(Array)
# reduce list
groups.each_with_object([]) do |grp, grp_collection|
# map object
grp_info = {
name: grp['Name'],
domain: grp['Domain'],
caption: grp['Caption'],
gid: nil,
sid: grp['SID'],
local: grp['LocalAccount'],
}
return grp_collection.push(grp_info) if grp_info[:name].casecmp(compare_group) == 0 && (compare_domain.nil? || grp_info[:domain].casecmp(compare_domain) == 0)
end
end
end
end