Modified DarwinGroup to collect all users properly. (#4343)

group resource: Modified DarwinGroup to collect all users properly on macos
This commit is contained in:
Clinton Wolfe 2019-08-08 11:55:48 -04:00 committed by GitHub
commit 95e6bcb317
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 10 deletions

View file

@ -1,6 +1,8 @@
# copyright: 2015, Vulcano Security GmbH
require "inspec/resource"
require "inspec/resources/platform"
require "inspec/resources/os"
module Inspec::Resources
class Cmd < Inspec.resource(1)

View file

@ -164,22 +164,40 @@ module Inspec::Resources
# OSX uses opendirectory for groups, so `/etc/group` may not be fully accurate
# This uses `dscacheutil` to get the group info instead of `etc_group`
class DarwinGroup < GroupInfo
def groups
group_info = inspec.command("dscacheutil -q group").stdout.split("\n\n")
def runmap(cmd, &blk)
hashmap(inspec.command(cmd).stdout.lines, &blk)
end
def hashmap(enum, &blk)
enum.map(&blk).to_h
end
def groups
group_by_id = runmap("dscl . -list /Groups PrimaryGroupID") { |l| name, id = l.split; [id.to_i, name] }
userss = runmap("dscl . -list /Users PrimaryGroupID") { |l| name, id = l.split; [name, id.to_i] }
membership = runmap("dscl . -list /Groups GroupMembership") { |l| key, *vs = l.split; [key, vs] }
membership.default_proc = ->(h, k) { h[k] = [] }
users_by_group = hashmap(userss.keys.group_by { |k| userss[k] }) { |k, vs| [group_by_id[k], vs] }
users_by_group.each do |name, users|
membership[name].concat users
end
group_info = inspec.command("dscacheutil -q group").stdout.split("\n\n").uniq
groups = []
regex = /^([^:]*?)\s*:\s(.*?)\s*$/
group_info.each do |data|
groups << inspec.parse_config(data, assignment_regex: regex).params
groups = group_info.map do |data|
inspec.parse_config(data, assignment_regex: regex).params
end
# Convert the `dscacheutil` groups to match `inspec.etc_group.entries`
groups.each { |g| g["gid"] = g["gid"].to_i }
groups.each do |g|
next if g["users"].nil?
g["members"] = g.delete("users")
g["members"].tr!(" ", ",")
users = g.delete("users") || ""
users = users.split
users += Array(users_by_group[g["name"]])
g["members"] = users
g["members"].sort.join ","
end
end
end

View file

@ -33,6 +33,7 @@ module Inspec
extend Forwardable
attr_reader :backend, :rules
attr_accessor :target_profiles
def attributes
Inspec.deprecate(:rename_attributes_to_inputs, "Don't call runner.attributes, call runner.inputs")

View file

@ -23,6 +23,13 @@ if ENV["CI_ENABLE_COVERAGE"]
end
end
module Minitest::Guard
# TODO: push up to minitest
def osx?(platform = RUBY_PLATFORM)
/darwin/ =~ platform
end
end
##
#
# Do not add any other code from here until the end of this code

View file

@ -1,5 +1,4 @@
require "helper"
require "inspec/resource"
require "inspec/resources/groups"
describe "Inspec::Resources::Group" do
@ -37,6 +36,28 @@ describe "Inspec::Resources::Group" do
_(resource.gid).must_equal 0
end
def unmock(&blk)
require "fetchers/mock"
require "inspec/runner"
# TODO: there is WAY too much magic going on in here
runner = Inspec::Runner.new
runner.add_target("inspec.yml" => "name: inspec-shell")
profile = runner.target_profiles.first
ctx = profile.runner_context
ctx.load blk
end
if osx?
it "actually verifies group on mac" do
resource = unmock { group "staff" }
_(resource.exists?).must_equal true
_(resource.members).must_include "root"
_(resource.members).must_include ENV["LOGNAME"]
end
end
# freebsd
it "verify group on freebsd" do
resource = MockLoader.new(:freebsd10).load_resource("group", "root")