inspec/lib/resources/passwd.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

128 lines
3.2 KiB
Ruby

# encoding: utf-8
# copyright: 2015, Vulcano Security GmbH
# author: Christoph Hartmann
# author: Dominik Richter
# license: All rights reserved
# The file format consists of
# - username
# - password
# - userid
# - groupid
# - user id info
# - home directory
# - command
require 'utils/parser'
module Inspec::Resources
class Passwd < Inspec.resource(1)
name 'passwd'
desc 'Use the passwd InSpec audit resource to test the contents of /etc/passwd, which contains the following information for users that may log into the system and/or as users that own running processes.'
example "
describe passwd do
its('users') { should_not include 'forbidden_user' }
end
describe passwd.uids(0) do
its('users') { should cmp 'root' }
its('count') { should eq 1 }
end
describe passwd.shells(/nologin/) do
# find all users with a nologin shell
its('users') { should_not include 'my_login_user' }
end
"
include PasswdParser
attr_reader :uid
attr_reader :params
attr_reader :content
attr_reader :lines
def initialize(path = nil, opts = nil)
opts ||= {}
@path = path || '/etc/passwd'
@content = opts[:content] || inspec.file(@path).content
@lines = @content.to_s.split("\n")
@filters = opts[:filters] || ''
@params = parse_passwd(@content)
end
def filter(hm = {})
return self if hm.nil? || hm.empty?
res = @params
filters = ''
hm.each do |attr, condition|
condition = condition.to_s if condition.is_a? Integer
filters += " #{attr} = #{condition.inspect}"
res = res.find_all do |line|
case line[attr.to_s]
when condition
true
else
false
end
end
end
content = res.map { |x| x.values.join(':') }.join("\n")
Passwd.new(@path, content: content, filters: @filters + filters)
end
def usernames
warn '[DEPRECATION] `passwd.usernames` is deprecated. Please use `passwd.users` instead. It will be removed in version 1.0.0.'
users
end
def username
warn '[DEPRECATION] `passwd.user` is deprecated. Please use `passwd.users` instead. It will be removed in version 1.0.0.'
users[0]
end
def uid(x)
warn '[DEPRECATION] `passwd.uid(arg)` is deprecated. Please use `passwd.uids(arg)` instead. It will be removed in version 1.0.0.'
uids(x)
end
def users(name = nil)
name.nil? ? map_data('user') : filter(user: name)
end
def passwords(password = nil)
password.nil? ? map_data('password') : filter(password: password)
end
def uids(uid = nil)
uid.nil? ? map_data('uid') : filter(uid: uid)
end
def gids(gid = nil)
gid.nil? ? map_data('gid') : filter(gid: gid)
end
def homes(home = nil)
home.nil? ? map_data('home') : filter(home: home)
end
def shells(shell = nil)
shell.nil? ? map_data('shell') : filter(shell: shell)
end
def to_s
f = @filters.empty? ? '' : ' with'+@filters
"/etc/passwd#{f}"
end
def count
@params.length
end
private
def map_data(id)
@params.map { |x| x[id] }
end
end
end