2015-07-15 13:16:10 +00:00
# encoding: utf-8
# copyright: 2015, Vulcano Security GmbH
# 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'
2018-03-22 12:25:45 +00:00
require 'utils/file_reader'
2015-10-06 11:56:29 +00:00
2016-03-08 18:06:55 +00:00
module Inspec::Resources
class EtcGroup < Inspec . resource ( 1 )
include Converter
include CommentParser
name 'etc_group'
2018-02-19 14:26:49 +00:00
supports platform : 'unix'
2016-03-08 18:06:55 +00:00
desc 'Use the etc_group InSpec audit resource to test groups that are defined on Linux and UNIX platforms. The /etc/group file stores details about each group---group name, password, group identifier, along with a comma-separate list of users that belong to the group.'
2019-03-19 14:17:32 +00:00
example << ~ EXAMPLE
2016-03-08 18:06:55 +00:00
describe etc_group do
its ( 'gids' ) { should_not contain_duplicates }
its ( 'groups' ) { should include 'my_user' }
its ( 'users' ) { should include 'my_user' }
end
2019-03-19 14:17:32 +00:00
EXAMPLE
2016-03-08 18:06:55 +00:00
2018-03-22 12:25:45 +00:00
include FileReader
2016-03-08 18:06:55 +00:00
attr_accessor :gid , :entries
def initialize ( path = nil )
@path = path || '/etc/group'
@entries = parse_group ( @path )
2015-11-27 13:02:38 +00:00
end
2015-07-15 13:16:10 +00:00
2016-03-08 18:06:55 +00:00
def groups ( filter = nil )
2017-11-21 07:49:41 +00:00
( filter || @entries ) & . map { | x | x [ 'name' ] }
2015-08-03 01:42:05 +00:00
end
2015-10-07 10:33:33 +00:00
2016-03-08 18:06:55 +00:00
def gids ( filter = nil )
2017-11-21 07:49:41 +00:00
( filter || @entries ) & . map { | x | x [ 'gid' ] }
2016-03-08 18:06:55 +00:00
end
2015-08-03 01:42:05 +00:00
2016-03-08 18:06:55 +00:00
def users ( filter = nil )
entries = filter || @entries
return nil if entries . nil?
# filter the user entry
res = entries . map { | x |
x [ 'members' ] . split ( ',' ) if ! x . nil? && ! x [ 'members' ] . nil?
} . flatten
# filter nil elements
res . reject { | x | x . nil? || x . empty? }
end
2015-10-12 11:01:58 +00:00
2016-03-08 18:06:55 +00:00
def where ( conditions = { } )
return if conditions . empty?
fields = {
name : 'name' ,
group_name : 'name' ,
password : 'password' ,
gid : 'gid' ,
group_id : 'gid' ,
users : 'members' ,
members : 'members' ,
}
res = entries
2018-04-26 16:29:12 +00:00
unless res . nil?
conditions . each do | k , v |
idx = fields [ k . to_sym ]
next if idx . nil?
res = res . select { | x | x [ idx ] . to_s == v . to_s }
end
2016-03-08 18:06:55 +00:00
end
EtcGroupView . new ( self , res )
end
2015-08-03 00:40:08 +00:00
2016-03-08 18:06:55 +00:00
def to_s
'/etc/group'
2015-10-26 15:11:28 +00:00
end
2016-03-08 18:06:55 +00:00
private
def parse_group ( path )
2018-03-22 12:25:45 +00:00
@content = read_file_content ( path , allow_empty : true )
2016-03-08 18:06:55 +00:00
# iterate over each line and filter comments
@content . split ( " \n " ) . each_with_object ( [ ] ) do | line , lines |
grp_info = parse_group_line ( line )
2017-02-08 22:49:16 +00:00
lines . push ( grp_info ) if ! grp_info . nil? && ! grp_info . empty?
2016-03-08 18:06:55 +00:00
end
2015-08-28 19:52:59 +00:00
end
2015-10-06 11:56:29 +00:00
2016-03-08 18:06:55 +00:00
def parse_group_line ( line )
opts = {
comment_char : '#' ,
standalone_comments : false ,
}
line , _idx_nl = parse_comment_line ( line , opts )
x = line . split ( ':' )
# abort if we have an empty or comment line
2017-02-08 22:49:16 +00:00
return nil if x . empty?
2016-03-08 18:06:55 +00:00
# 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.
}
end
2015-10-06 11:56:29 +00:00
end
2015-09-05 20:26:21 +00:00
2016-03-08 18:06:55 +00:00
# object that hold a specifc view on etc group
class EtcGroupView
def initialize ( parent , filter )
@parent = parent
@filter = filter
end
2015-09-05 20:26:21 +00:00
2016-03-08 18:06:55 +00:00
# returns the group object
def entries
@filter
end
2015-10-07 09:28:00 +00:00
2016-03-08 18:06:55 +00:00
# only returns group name
def groups
@parent . groups ( @filter )
end
2015-09-05 20:26:21 +00:00
2016-03-08 18:06:55 +00:00
# only return gids
def gids
@parent . gids ( @filter )
end
2015-09-05 20:26:21 +00:00
2016-03-08 18:06:55 +00:00
# only returns users
def users
@parent . users ( @filter )
end
2015-09-09 16:37:16 +00:00
end
2015-09-05 20:26:21 +00:00
end