2015-07-15 13:16:10 +00:00
|
|
|
# encoding: utf-8
|
|
|
|
# copyright: 2015, Vulcano Security GmbH
|
2015-10-06 16:55:44 +00:00
|
|
|
# author: Christoph Hartmann
|
|
|
|
# author: Dominik Richter
|
2015-07-15 13:16:10 +00:00
|
|
|
# license: All rights reserved
|
|
|
|
|
|
|
|
# The file format consists of
|
|
|
|
# - group name
|
2015-10-06 11:56:29 +00:00
|
|
|
# - password - group's encrypted password
|
|
|
|
# - gid - group's decimal ID
|
|
|
|
# - member list - group members, comma seperated list
|
2015-09-05 20:26:21 +00:00
|
|
|
#
|
|
|
|
# Usage:
|
|
|
|
# describe etc_group do
|
|
|
|
# its('gids') { should_not contain_duplicates }
|
|
|
|
# its('groups') { should include 'my_user' }
|
|
|
|
# its('users') { should include 'my_user' }
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# describe etc_group.where(name: 'my_group') do
|
|
|
|
# its('users') { should include 'my_user' }
|
|
|
|
# end
|
2015-07-15 13:16:10 +00:00
|
|
|
|
2015-10-06 12:00:19 +00:00
|
|
|
require 'utils/convert'
|
2015-10-06 11:56:29 +00:00
|
|
|
require 'utils/parser'
|
|
|
|
|
2015-08-28 19:52:59 +00:00
|
|
|
class EtcGroup < Vulcano.resource(1)
|
2015-10-06 12:00:19 +00:00
|
|
|
include Converter
|
2015-10-06 11:56:29 +00:00
|
|
|
include ContentParser
|
|
|
|
|
2015-08-28 19:52:59 +00:00
|
|
|
name 'etc_group'
|
2015-07-15 13:16:10 +00:00
|
|
|
|
2015-08-28 19:52:59 +00:00
|
|
|
attr_accessor :gid, :entries
|
|
|
|
def initialize(path = nil)
|
|
|
|
@path = path || '/etc/group'
|
2015-10-06 11:56:29 +00:00
|
|
|
@entries = parse_group(@path)
|
2015-10-06 11:57:22 +00:00
|
|
|
|
|
|
|
# skip resource if it is not supported on current OS
|
|
|
|
return skip_resource 'The `etc_group` resource is not supported on your OS.' \
|
|
|
|
unless %w{ubuntu debian redhat fedora arch darwin freebsd}.include?(vulcano.os[:family])
|
2015-07-26 10:30:12 +00:00
|
|
|
end
|
2015-07-15 13:16:10 +00:00
|
|
|
|
2015-09-05 20:26:21 +00:00
|
|
|
def groups(filter = nil)
|
|
|
|
entries = filter || @entries
|
2015-10-07 10:33:33 +00:00
|
|
|
entries.map { |x| x['name'] } if !entries.nil?
|
2015-07-26 10:30:12 +00:00
|
|
|
end
|
2015-07-15 13:16:10 +00:00
|
|
|
|
2015-09-05 20:26:21 +00:00
|
|
|
def gids(filter = nil)
|
|
|
|
entries = filter || @entries
|
2015-10-07 10:33:33 +00:00
|
|
|
entries.map { |x| x['gid'] } if !entries.nil?
|
2015-07-26 10:30:12 +00:00
|
|
|
end
|
2015-07-15 13:16:10 +00:00
|
|
|
|
2015-09-05 20:26:21 +00:00
|
|
|
def users(filter = nil)
|
|
|
|
entries = filter || @entries
|
|
|
|
return nil if entries.nil?
|
|
|
|
# filter the user entry
|
|
|
|
res = entries.map { |x|
|
2015-10-07 10:33:33 +00:00
|
|
|
x['members'].split(',') if !x.nil? && !x['members'].nil?
|
2015-09-05 20:26:21 +00:00
|
|
|
}.flatten
|
|
|
|
# filter nil elements
|
|
|
|
res.reject { |x| x.nil? || x.empty? }
|
2015-07-26 10:30:12 +00:00
|
|
|
end
|
2015-07-15 13:16:10 +00:00
|
|
|
|
2015-09-03 18:43:58 +00:00
|
|
|
def where(conditions = {})
|
2015-08-03 01:42:05 +00:00
|
|
|
return if conditions.empty?
|
|
|
|
fields = {
|
2015-10-07 10:33:33 +00:00
|
|
|
name: 'name',
|
|
|
|
group_name: 'name',
|
|
|
|
password: 'password',
|
|
|
|
gid: 'gid',
|
|
|
|
group_id: 'gid',
|
|
|
|
users: 'members',
|
|
|
|
members: 'members',
|
2015-08-03 01:42:05 +00:00
|
|
|
}
|
|
|
|
res = entries
|
2015-10-07 10:33:33 +00:00
|
|
|
|
2015-09-04 07:59:30 +00:00
|
|
|
conditions.each do |k, v|
|
2015-08-03 01:49:05 +00:00
|
|
|
idx = fields[k.to_sym]
|
2015-08-03 01:42:05 +00:00
|
|
|
next if idx.nil?
|
2015-09-05 20:26:21 +00:00
|
|
|
res = res.select { |x| x[idx] == v.to_s }
|
2015-08-03 01:42:05 +00:00
|
|
|
end
|
2015-10-07 10:33:33 +00:00
|
|
|
|
2015-09-05 20:26:21 +00:00
|
|
|
EtcGroupView.new(self, res)
|
2015-07-15 13:16:10 +00:00
|
|
|
end
|
2015-08-03 01:42:05 +00:00
|
|
|
|
2015-10-12 11:01:58 +00:00
|
|
|
def to_s
|
|
|
|
'/etc/group'
|
|
|
|
end
|
|
|
|
|
2015-08-28 19:52:59 +00:00
|
|
|
private
|
2015-08-03 00:40:08 +00:00
|
|
|
|
2015-10-06 11:56:29 +00:00
|
|
|
def parse_group(path)
|
2015-08-30 02:33:15 +00:00
|
|
|
@content = vulcano.file(path).content
|
2015-10-06 11:56:29 +00:00
|
|
|
# iterate over each line and filter comments
|
|
|
|
@content.split("\n").each_with_object([]) do |line, lines|
|
|
|
|
grp_info = parse_group_line(line)
|
|
|
|
lines.push(grp_info) if !grp_info.nil? && grp_info.size > 0
|
2015-08-28 19:52:59 +00:00
|
|
|
end
|
2015-08-03 00:40:08 +00:00
|
|
|
end
|
2015-10-06 11:56:29 +00:00
|
|
|
|
|
|
|
def parse_group_line(line)
|
|
|
|
opts = {
|
|
|
|
comment_char: '#',
|
|
|
|
standalone_comments: false,
|
|
|
|
}
|
|
|
|
line, _idx_nl = parse_comment_line(line, opts)
|
2015-10-07 10:33:33 +00:00
|
|
|
x = line.split(':')
|
|
|
|
# abort if we have an empty or comment line
|
|
|
|
return nil if x.size == 0
|
|
|
|
# map data
|
|
|
|
{
|
|
|
|
'name' => x.at(0), # Name of the group.
|
|
|
|
'password' => x.at(1), # Group's encrypted password.
|
|
|
|
'gid' => convert_to_i(x.at(2)), # The group's decimal ID.
|
|
|
|
'members' => x.at(3), # Group members.
|
|
|
|
}
|
2015-10-06 11:56:29 +00:00
|
|
|
end
|
2015-08-28 19:52:59 +00:00
|
|
|
end
|
2015-09-05 20:26:21 +00:00
|
|
|
|
|
|
|
# object that hold a specifc view on etc group
|
|
|
|
class EtcGroupView
|
|
|
|
def initialize(parent, filter)
|
|
|
|
@parent = parent
|
|
|
|
@filter = filter
|
|
|
|
end
|
|
|
|
|
2015-10-07 09:28:00 +00:00
|
|
|
# returns the group object
|
2015-10-07 10:33:33 +00:00
|
|
|
def entries
|
2015-10-07 09:28:00 +00:00
|
|
|
@filter
|
|
|
|
end
|
|
|
|
|
|
|
|
# only returns group name
|
2015-10-07 10:33:33 +00:00
|
|
|
def groups
|
2015-09-09 16:37:16 +00:00
|
|
|
@parent.groups(@filter)
|
|
|
|
end
|
2015-09-05 20:26:21 +00:00
|
|
|
|
2015-10-07 09:28:00 +00:00
|
|
|
# only return gids
|
2015-09-09 16:37:16 +00:00
|
|
|
def gids
|
|
|
|
@parent.gids(@filter)
|
|
|
|
end
|
2015-09-05 20:26:21 +00:00
|
|
|
|
2015-10-07 09:28:00 +00:00
|
|
|
# only returns users
|
2015-09-09 16:37:16 +00:00
|
|
|
def users
|
|
|
|
@parent.users(@filter)
|
|
|
|
end
|
2015-09-05 20:26:21 +00:00
|
|
|
end
|