inspec 0.14.8 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -2
- data/bin/inspec +3 -4
- data/examples/inheritance/README.md +19 -0
- data/examples/inheritance/controls/example.rb +11 -0
- data/examples/inheritance/inspec.yml +10 -0
- data/lib/bundles/inspec-compliance/cli.rb +1 -4
- data/lib/bundles/inspec-supermarket/cli.rb +1 -4
- data/lib/inspec/dsl.rb +48 -55
- data/lib/inspec/profile.rb +6 -2
- data/lib/inspec/profile_context.rb +21 -8
- data/lib/inspec/runner.rb +17 -12
- data/lib/inspec/runner_rspec.rb +1 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/apache.rb +20 -18
- data/lib/resources/apache_conf.rb +92 -90
- data/lib/resources/apt.rb +92 -90
- data/lib/resources/audit_policy.rb +35 -33
- data/lib/resources/auditd_conf.rb +41 -39
- data/lib/resources/auditd_rules.rb +155 -153
- data/lib/resources/bond.rb +1 -1
- data/lib/resources/bridge.rb +97 -95
- data/lib/resources/command.rb +47 -45
- data/lib/resources/csv.rb +23 -21
- data/lib/resources/directory.rb +1 -1
- data/lib/resources/etc_group.rb +116 -114
- data/lib/resources/file.rb +1 -1
- data/lib/resources/gem.rb +39 -37
- data/lib/resources/group.rb +100 -98
- data/lib/resources/host.rb +103 -101
- data/lib/resources/inetd_conf.rb +42 -40
- data/lib/resources/ini.rb +15 -13
- data/lib/resources/interface.rb +106 -104
- data/lib/resources/iptables.rb +36 -34
- data/lib/resources/json.rb +64 -62
- data/lib/resources/kernel_module.rb +30 -28
- data/lib/resources/kernel_parameter.rb +44 -42
- data/lib/resources/limits_conf.rb +41 -39
- data/lib/resources/login_def.rb +38 -36
- data/lib/resources/mount.rb +43 -41
- data/lib/resources/mysql.rb +67 -65
- data/lib/resources/mysql_conf.rb +89 -87
- data/lib/resources/mysql_session.rb +46 -44
- data/lib/resources/npm.rb +35 -33
- data/lib/resources/ntp_conf.rb +44 -42
- data/lib/resources/oneget.rb +46 -44
- data/lib/resources/os.rb +22 -20
- data/lib/resources/os_env.rb +47 -45
- data/lib/resources/package.rb +213 -211
- data/lib/resources/parse_config.rb +59 -57
- data/lib/resources/passwd.rb +89 -87
- data/lib/resources/pip.rb +60 -58
- data/lib/resources/port.rb +352 -350
- data/lib/resources/postgres.rb +26 -24
- data/lib/resources/postgres_conf.rb +66 -64
- data/lib/resources/postgres_session.rb +47 -45
- data/lib/resources/processes.rb +56 -54
- data/lib/resources/registry_key.rb +150 -148
- data/lib/resources/script.rb +30 -28
- data/lib/resources/security_policy.rb +56 -54
- data/lib/resources/service.rb +638 -636
- data/lib/resources/shadow.rb +98 -96
- data/lib/resources/ssh_conf.rb +58 -56
- data/lib/resources/user.rb +363 -361
- data/lib/resources/windows_feature.rb +46 -44
- data/lib/resources/xinetd.rb +111 -109
- data/lib/resources/yaml.rb +16 -14
- data/lib/resources/yum.rb +107 -105
- data/lib/utils/base_cli.rb +18 -0
- data/test/helper.rb +2 -2
- data/test/unit/profile_context_test.rb +1 -1
- data/test/unit/resources/file_test.rb +1 -1
- data/test/unit/resources/mount_test.rb +1 -1
- metadata +5 -2
data/lib/resources/npm.rb
CHANGED
@@ -2,45 +2,47 @@
|
|
2
2
|
# author: Christoph Hartmann
|
3
3
|
# author: Dominik Richter
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
module Inspec::Resources
|
6
|
+
class NpmPackage < Inspec.resource(1)
|
7
|
+
name 'npm'
|
8
|
+
desc 'Use the npm InSpec audit resource to test if a global npm package is installed. npm is the the package manager for Nodejs packages, such as bower and StatsD.'
|
9
|
+
example "
|
10
|
+
describe npm('bower') do
|
11
|
+
it { should be_installed }
|
12
|
+
end
|
13
|
+
"
|
14
|
+
|
15
|
+
def initialize(package_name)
|
16
|
+
@package_name = package_name
|
17
|
+
@cache = nil
|
11
18
|
end
|
12
|
-
"
|
13
19
|
|
14
|
-
|
15
|
-
|
16
|
-
@cache = nil
|
17
|
-
end
|
18
|
-
|
19
|
-
def info
|
20
|
-
return @info if defined?(@info)
|
20
|
+
def info
|
21
|
+
return @info if defined?(@info)
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
cmd = inspec.command("npm ls -g --json #{@package_name}")
|
24
|
+
@info = {
|
25
|
+
name: @package_name,
|
26
|
+
type: 'npm',
|
27
|
+
installed: cmd.exit_status == 0,
|
28
|
+
}
|
29
|
+
return @info unless @info[:installed]
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
pkgs = JSON.parse(cmd.stdout)
|
32
|
+
@info[:version] = pkgs['dependencies'][@package_name]['version']
|
33
|
+
@info
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
def installed?
|
37
|
+
info[:installed] == true
|
38
|
+
end
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
def version
|
41
|
+
info[:version]
|
42
|
+
end
|
42
43
|
|
43
|
-
|
44
|
-
|
44
|
+
def to_s
|
45
|
+
"Npm Package #{@package_name}"
|
46
|
+
end
|
45
47
|
end
|
46
48
|
end
|
data/lib/resources/ntp_conf.rb
CHANGED
@@ -6,53 +6,55 @@
|
|
6
6
|
|
7
7
|
require 'utils/simpleconfig'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
module Inspec::Resources
|
10
|
+
class NtpConf < Inspec.resource(1)
|
11
|
+
name 'ntp_conf'
|
12
|
+
desc 'Use the ntp_conf InSpec audit resource to test the synchronization settings defined in the ntp.conf file. This file is typically located at /etc/ntp.conf.'
|
13
|
+
example "
|
14
|
+
describe ntp_conf do
|
15
|
+
its('server') { should_not eq nil }
|
16
|
+
its('restrict') { should include '-4 default kod notrap nomodify nopeer noquery'}
|
17
|
+
end
|
18
|
+
"
|
19
|
+
|
20
|
+
def initialize(path = nil)
|
21
|
+
@conf_path = path || '/etc/ntp.conf'
|
16
22
|
end
|
17
|
-
"
|
18
23
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
param = read_params[name.to_s]
|
25
|
-
# extract first value if we have only one value in array
|
26
|
-
return param[0] if param.is_a?(Array) and param.length == 1
|
27
|
-
param
|
28
|
-
end
|
29
|
-
|
30
|
-
def to_s
|
31
|
-
'ntp.conf'
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def read_params
|
37
|
-
return @params if defined?(@params)
|
38
|
-
|
39
|
-
if !inspec.file(@conf_path).file?
|
40
|
-
skip_resource "Can't find file \"#{@conf_path}\""
|
41
|
-
return @params = {}
|
24
|
+
def method_missing(name)
|
25
|
+
param = read_params[name.to_s]
|
26
|
+
# extract first value if we have only one value in array
|
27
|
+
return param[0] if param.is_a?(Array) and param.length == 1
|
28
|
+
param
|
42
29
|
end
|
43
30
|
|
44
|
-
|
45
|
-
|
46
|
-
skip_resource "Can't read file \"#{@conf_path}\""
|
47
|
-
return @params = {}
|
31
|
+
def to_s
|
32
|
+
'ntp.conf'
|
48
33
|
end
|
49
34
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
35
|
+
private
|
36
|
+
|
37
|
+
def read_params
|
38
|
+
return @params if defined?(@params)
|
39
|
+
|
40
|
+
if !inspec.file(@conf_path).file?
|
41
|
+
skip_resource "Can't find file \"#{@conf_path}\""
|
42
|
+
return @params = {}
|
43
|
+
end
|
44
|
+
|
45
|
+
content = inspec.file(@conf_path).content
|
46
|
+
if content.empty? && inspec.file(@conf_path).size > 0
|
47
|
+
skip_resource "Can't read file \"#{@conf_path}\""
|
48
|
+
return @params = {}
|
49
|
+
end
|
50
|
+
|
51
|
+
# parse the file
|
52
|
+
conf = SimpleConfig.new(
|
53
|
+
content,
|
54
|
+
assignment_re: /^\s*(\S+)\s+(.*)\s*$/,
|
55
|
+
multiple_values: true,
|
56
|
+
)
|
57
|
+
@params = conf.params
|
58
|
+
end
|
57
59
|
end
|
58
60
|
end
|
data/lib/resources/oneget.rb
CHANGED
@@ -9,61 +9,63 @@
|
|
9
9
|
# describe oneget('zoomit') do
|
10
10
|
# it { should be_installed }
|
11
11
|
# end
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
module Inspec::Resources
|
13
|
+
class OneGetPackage < Inspec.resource(1)
|
14
|
+
name 'oneget'
|
15
|
+
desc 'Use the oneget InSpec audit resource to test if the named package and/or package version is installed on the system. This resource uses OneGet, which is part of the Windows Management Framework 5.0 and Windows 10. This resource uses the Get-Package cmdlet to return all of the package names in the OneGet repository.'
|
16
|
+
example "
|
17
|
+
describe oneget('zoomit') do
|
18
|
+
it { should be_installed }
|
19
|
+
end
|
20
|
+
"
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
def initialize(package_name)
|
23
|
+
@package_name = package_name
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
# verify that this resource is only supported on Windows
|
26
|
+
return skip_resource 'The `oneget` resource is not supported on your OS.' if inspec.os[:family] != 'windows'
|
27
|
+
end
|
27
28
|
|
28
|
-
|
29
|
-
|
29
|
+
def info
|
30
|
+
return @info if defined?(@info)
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
@info = {}
|
33
|
+
@info[:type] = 'oneget'
|
34
|
+
@info[:installed] = false
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
cmd = inspec.command("Get-Package -Name '#{@package_name}' | ConvertTo-Json")
|
37
|
+
# cannot rely on exit code for now, successful command returns exit code 1
|
38
|
+
# return nil if cmd.exit_status != 0
|
39
|
+
# try to parse json
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
begin
|
42
|
+
pkgs = JSON.parse(cmd.stdout)
|
43
|
+
@info[:installed] = true
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
# sometimes we get multiple values
|
46
|
+
if pkgs.is_a?(Array)
|
47
|
+
# select the first entry
|
48
|
+
pkgs = pkgs.first
|
49
|
+
end
|
50
|
+
rescue JSON::ParserError => _e
|
51
|
+
return @info
|
48
52
|
end
|
49
|
-
rescue JSON::ParserError => _e
|
50
|
-
return @info
|
51
|
-
end
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
@info[:name] = pkgs['Name'] if pkgs.key?('Name')
|
55
|
+
@info[:version] = pkgs['Version'] if pkgs.key?('Version')
|
56
|
+
@info
|
57
|
+
end
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
|
59
|
+
def installed?
|
60
|
+
info[:installed] == true
|
61
|
+
end
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
63
|
+
def version
|
64
|
+
info[:version]
|
65
|
+
end
|
65
66
|
|
66
|
-
|
67
|
-
|
67
|
+
def to_s
|
68
|
+
"OneGet Package #{@package_name}"
|
69
|
+
end
|
68
70
|
end
|
69
71
|
end
|
data/lib/resources/os.rb
CHANGED
@@ -2,29 +2,31 @@
|
|
2
2
|
# author: Dominik Richter
|
3
3
|
# author: Christoph Hartmann
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
5
|
+
module Inspec::Resources
|
6
|
+
class OSResource < Inspec.resource(1)
|
7
|
+
name 'os'
|
8
|
+
desc 'Use the os InSpec audit resource to test the platform on which the system is running.'
|
9
|
+
example "
|
10
|
+
describe os[:family] do
|
11
|
+
it { should eq 'redhat' }
|
12
|
+
end
|
13
|
+
"
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
# reuse helper methods from backend
|
16
|
+
%w{aix? redhat? debian? suse? bsd? solaris? linux? unix? windows?}.each do |os_family|
|
17
|
+
define_method(os_family.to_sym) do
|
18
|
+
inspec.backend.os.send(os_family)
|
19
|
+
end
|
18
20
|
end
|
19
|
-
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
def [](name)
|
23
|
+
# convert string to symbol
|
24
|
+
name = name.to_sym if name.is_a? String
|
25
|
+
inspec.backend.os[name]
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
28
|
+
def to_s
|
29
|
+
'Operating System Detection'
|
30
|
+
end
|
29
31
|
end
|
30
32
|
end
|
data/lib/resources/os_env.rb
CHANGED
@@ -13,60 +13,62 @@
|
|
13
13
|
|
14
14
|
require 'utils/simpleconfig'
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
module Inspec::Resources
|
17
|
+
class OsEnv < Inspec.resource(1)
|
18
|
+
name 'os_env'
|
19
|
+
desc 'Use the os_env InSpec audit resource to test the environment variables for the platform on which the system is running.'
|
20
|
+
example "
|
21
|
+
describe os_env('VARIABLE') do
|
22
|
+
its('matcher') { should eq 1 }
|
23
|
+
end
|
24
|
+
"
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
attr_reader :content
|
27
|
+
def initialize(env = nil)
|
28
|
+
@osenv = env
|
29
|
+
@content = nil
|
30
|
+
@content = value_for(env) unless env.nil?
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
33
|
+
def split
|
34
|
+
# we can't take advantage of `File::PATH_SEPARATOR` as code is
|
35
|
+
# evaluated on the host machine
|
36
|
+
path_separator = inspec.os.windows? ? ';' : ':'
|
37
|
+
# -1 is required to catch cases like dir1::dir2:
|
38
|
+
# where we have a trailing :
|
39
|
+
@content.nil? ? [] : @content.split(path_separator, -1)
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
def to_s
|
43
|
+
if @osenv.nil?
|
44
|
+
'Environment variables'
|
45
|
+
else
|
46
|
+
"Environment variable #{@osenv}"
|
47
|
+
end
|
46
48
|
end
|
47
|
-
end
|
48
49
|
|
49
|
-
|
50
|
+
private
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
def value_for(env)
|
53
|
+
command = if inspec.os.windows?
|
54
|
+
"$Env:#{env}"
|
55
|
+
else
|
56
|
+
'env'
|
57
|
+
end
|
57
58
|
|
58
|
-
|
59
|
+
out = inspec.command(command)
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
unless out.exit_status == 0
|
62
|
+
skip_resource "Can't read environment variables on #{os[:family]}. "\
|
63
|
+
"Tried `#{command}` which returned #{out.exit_status}"
|
64
|
+
end
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
if inspec.os.windows?
|
67
|
+
out.stdout.strip
|
68
|
+
else
|
69
|
+
params = SimpleConfig.new(out.stdout).params
|
70
|
+
params[env]
|
71
|
+
end
|
70
72
|
end
|
71
73
|
end
|
72
74
|
end
|
data/lib/resources/package.rb
CHANGED
@@ -8,253 +8,255 @@
|
|
8
8
|
# describe package('nginx') do
|
9
9
|
# it { should be_installed }
|
10
10
|
# end
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
module Inspec::Resources
|
12
|
+
class Package < Inspec.resource(1)
|
13
|
+
name 'package'
|
14
|
+
desc 'Use the package InSpec audit resource to test if the named package and/or package version is installed on the system.'
|
15
|
+
example "
|
16
|
+
describe package('nginx') do
|
17
|
+
it { should be_installed }
|
18
|
+
its('version') { should eq 1.9.5 }
|
19
|
+
end
|
20
|
+
"
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
def initialize(package_name = nil) # rubocop:disable Metrics/AbcSize
|
23
|
+
@package_name = package_name
|
24
|
+
@name = @package_name
|
25
|
+
@cache = nil
|
26
|
+
# select package manager
|
27
|
+
@pkgman = nil
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
29
|
+
os = inspec.os
|
30
|
+
if os.debian?
|
31
|
+
@pkgman = Deb.new(inspec)
|
32
|
+
elsif os.redhat? || os.suse?
|
33
|
+
@pkgman = Rpm.new(inspec)
|
34
|
+
elsif ['arch'].include?(os[:family])
|
35
|
+
@pkgman = Pacman.new(inspec)
|
36
|
+
elsif ['darwin'].include?(os[:family])
|
37
|
+
@pkgman = Brew.new(inspec)
|
38
|
+
elsif inspec.os.windows?
|
39
|
+
@pkgman = WindowsPkg.new(inspec)
|
40
|
+
elsif ['aix'].include?(os[:family])
|
41
|
+
@pkgman = BffPkg.new(inspec)
|
42
|
+
elsif os.solaris?
|
43
|
+
@pkgman = SolarisPkg.new(inspec)
|
44
|
+
else
|
45
|
+
return skip_resource 'The `package` resource is not supported on your OS yet.'
|
46
|
+
end
|
45
47
|
end
|
46
|
-
end
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
# returns true if the package is installed
|
50
|
+
def installed?(_provider = nil, _version = nil)
|
51
|
+
return false if info.nil?
|
52
|
+
info[:installed] == true
|
53
|
+
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
55
|
+
# returns the package description
|
56
|
+
def info
|
57
|
+
return @cache if !@cache.nil?
|
58
|
+
return nil if @pkgman.nil?
|
59
|
+
@pkgman.info(@package_name)
|
60
|
+
end
|
60
61
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
62
|
+
# return the package version
|
63
|
+
def version
|
64
|
+
info = @pkgman.info(@package_name)
|
65
|
+
return nil if info.nil?
|
66
|
+
info[:version]
|
67
|
+
end
|
67
68
|
|
68
|
-
|
69
|
-
|
69
|
+
def to_s
|
70
|
+
"System Package #{@package_name}"
|
71
|
+
end
|
70
72
|
end
|
71
|
-
end
|
72
73
|
|
73
|
-
class PkgManagement
|
74
|
-
|
75
|
-
|
76
|
-
|
74
|
+
class PkgManagement
|
75
|
+
attr_reader :inspec
|
76
|
+
def initialize(inspec)
|
77
|
+
@inspec = inspec
|
78
|
+
end
|
77
79
|
end
|
78
|
-
end
|
79
80
|
|
80
|
-
# Debian / Ubuntu
|
81
|
-
class Deb < PkgManagement
|
82
|
-
|
83
|
-
|
84
|
-
|
81
|
+
# Debian / Ubuntu
|
82
|
+
class Deb < PkgManagement
|
83
|
+
def info(package_name)
|
84
|
+
cmd = inspec.command("dpkg -s #{package_name}")
|
85
|
+
return nil if cmd.exit_status.to_i != 0
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
87
|
+
params = SimpleConfig.new(
|
88
|
+
cmd.stdout.chomp,
|
89
|
+
assignment_re: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
|
90
|
+
multiple_values: false,
|
91
|
+
).params
|
92
|
+
{
|
93
|
+
name: params['Package'],
|
94
|
+
installed: true,
|
95
|
+
version: params['Version'],
|
96
|
+
type: 'deb',
|
97
|
+
}
|
98
|
+
end
|
97
99
|
end
|
98
|
-
end
|
99
100
|
|
100
|
-
# RHEL family
|
101
|
-
class Rpm < PkgManagement
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
101
|
+
# RHEL family
|
102
|
+
class Rpm < PkgManagement
|
103
|
+
def info(package_name)
|
104
|
+
cmd = inspec.command("rpm -qia #{package_name}")
|
105
|
+
# CentOS does not return an error code if the package is not installed,
|
106
|
+
# therefore we need to check for emptyness
|
107
|
+
return nil if cmd.exit_status.to_i != 0 || cmd.stdout.chomp.empty?
|
108
|
+
params = SimpleConfig.new(
|
109
|
+
cmd.stdout.chomp,
|
110
|
+
assignment_re: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
|
111
|
+
multiple_values: false,
|
112
|
+
).params
|
113
|
+
# On some (all?) systems, the linebreak before the vendor line is missing
|
114
|
+
if params['Version'] =~ /\s*Vendor:/
|
115
|
+
v = params['Version'].split(' ')[0]
|
116
|
+
else
|
117
|
+
v = params['Version']
|
118
|
+
end
|
119
|
+
# On some (all?) systems, the linebreak before the build line is missing
|
120
|
+
if params['Release'] =~ /\s*Build Date:/
|
121
|
+
r = params['Release'].split(' ')[0]
|
122
|
+
else
|
123
|
+
r = params['Release']
|
124
|
+
end
|
125
|
+
{
|
126
|
+
name: params['Name'],
|
127
|
+
installed: true,
|
128
|
+
version: "#{v}-#{r}",
|
129
|
+
type: 'rpm',
|
130
|
+
}
|
123
131
|
end
|
124
|
-
{
|
125
|
-
name: params['Name'],
|
126
|
-
installed: true,
|
127
|
-
version: "#{v}-#{r}",
|
128
|
-
type: 'rpm',
|
129
|
-
}
|
130
132
|
end
|
131
|
-
end
|
132
133
|
|
133
|
-
# MacOS / Darwin implementation
|
134
|
-
class Brew < PkgManagement
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
134
|
+
# MacOS / Darwin implementation
|
135
|
+
class Brew < PkgManagement
|
136
|
+
def info(package_name)
|
137
|
+
cmd = inspec.command("brew info --json=v1 #{package_name}")
|
138
|
+
return nil if cmd.exit_status.to_i != 0
|
139
|
+
# parse data
|
140
|
+
pkg = JSON.parse(cmd.stdout)[0]
|
141
|
+
{
|
142
|
+
name: pkg.name.to_s,
|
143
|
+
installed: true,
|
144
|
+
version: pkg.installed.version.to_s,
|
145
|
+
type: 'brew',
|
146
|
+
}
|
147
|
+
end
|
146
148
|
end
|
147
|
-
end
|
148
149
|
|
149
|
-
# Arch Linux
|
150
|
-
class Pacman < PkgManagement
|
151
|
-
|
152
|
-
|
153
|
-
|
150
|
+
# Arch Linux
|
151
|
+
class Pacman < PkgManagement
|
152
|
+
def info(package_name)
|
153
|
+
cmd = inspec.command("pacman -Qi #{package_name}")
|
154
|
+
return nil if cmd.exit_status.to_i != 0
|
154
155
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
156
|
+
params = SimpleConfig.new(
|
157
|
+
cmd.stdout.chomp,
|
158
|
+
assignment_re: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
|
159
|
+
multiple_values: false,
|
160
|
+
).params
|
160
161
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
162
|
+
{
|
163
|
+
name: params['Name'],
|
164
|
+
installed: true,
|
165
|
+
version: params['Version'],
|
166
|
+
type: 'pacman',
|
167
|
+
}
|
168
|
+
end
|
167
169
|
end
|
168
|
-
end
|
169
170
|
|
170
|
-
# Determines the installed packages on Windows
|
171
|
-
# Currently we use 'Get-WmiObject -Class Win32_Product' as a detection method
|
172
|
-
# TODO: evaluate if alternative methods as proposed by Microsoft are still valid:
|
173
|
-
# @see: http://blogs.technet.com/b/heyscriptingguy/archive/2013/11/15/use-powershell-to-find-installed-software.aspx
|
174
|
-
class WindowsPkg < PkgManagement
|
175
|
-
|
176
|
-
|
177
|
-
|
171
|
+
# Determines the installed packages on Windows
|
172
|
+
# Currently we use 'Get-WmiObject -Class Win32_Product' as a detection method
|
173
|
+
# TODO: evaluate if alternative methods as proposed by Microsoft are still valid:
|
174
|
+
# @see: http://blogs.technet.com/b/heyscriptingguy/archive/2013/11/15/use-powershell-to-find-installed-software.aspx
|
175
|
+
class WindowsPkg < PkgManagement
|
176
|
+
def info(package_name)
|
177
|
+
# Find the package
|
178
|
+
cmd = inspec.command("Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -eq '#{package_name}'} | Select-Object -Property Name,Version,Vendor,PackageCode,Caption,Description | ConvertTo-Json")
|
178
179
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
180
|
+
begin
|
181
|
+
package = JSON.parse(cmd.stdout)
|
182
|
+
rescue JSON::ParserError => _e
|
183
|
+
return nil
|
184
|
+
end
|
184
185
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
186
|
+
{
|
187
|
+
name: package['Name'],
|
188
|
+
installed: true,
|
189
|
+
version: package['Version'],
|
190
|
+
type: 'windows',
|
191
|
+
}
|
192
|
+
end
|
191
193
|
end
|
192
|
-
end
|
193
194
|
|
194
|
-
# AIX
|
195
|
-
class BffPkg < PkgManagement
|
196
|
-
|
197
|
-
|
198
|
-
|
195
|
+
# AIX
|
196
|
+
class BffPkg < PkgManagement
|
197
|
+
def info(package_name)
|
198
|
+
cmd = inspec.command("lslpp -cL #{package_name}")
|
199
|
+
return nil if cmd.exit_status.to_i != 0
|
199
200
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
201
|
+
bff_pkg = cmd.stdout.split("\n").last.split(':')
|
202
|
+
{
|
203
|
+
name: bff_pkg[1],
|
204
|
+
installed: true,
|
205
|
+
version: bff_pkg[2],
|
206
|
+
type: 'bff',
|
207
|
+
}
|
208
|
+
end
|
207
209
|
end
|
208
|
-
end
|
209
210
|
|
210
|
-
# Solaris
|
211
|
-
class SolarisPkg < PkgManagement
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
211
|
+
# Solaris
|
212
|
+
class SolarisPkg < PkgManagement
|
213
|
+
def info(package_name)
|
214
|
+
if inspec.os[:release].to_i <= 10
|
215
|
+
solaris10_info(package_name)
|
216
|
+
else
|
217
|
+
solaris11_info(package_name)
|
218
|
+
end
|
217
219
|
end
|
218
|
-
end
|
219
220
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
221
|
+
# solaris 10
|
222
|
+
def solaris10_info(package_name)
|
223
|
+
cmd = inspec.command("pkginfo -l #{package_name}")
|
224
|
+
return nil if cmd.exit_status.to_i != 0
|
224
225
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
226
|
+
params = SimpleConfig.new(
|
227
|
+
cmd.stdout.chomp,
|
228
|
+
assignment_re: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
|
229
|
+
multiple_values: false,
|
230
|
+
).params
|
230
231
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
232
|
+
# parse 11.10.0,REV=2006.05.18.01.46
|
233
|
+
v = params['VERSION'].split(',')
|
234
|
+
{
|
235
|
+
name: params['PKGINST'],
|
236
|
+
installed: true,
|
237
|
+
version: v[0] + '-' + v[1].split('=')[1],
|
238
|
+
type: 'pkg',
|
239
|
+
}
|
240
|
+
end
|
240
241
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
242
|
+
# solaris 11
|
243
|
+
def solaris11_info(package_name)
|
244
|
+
cmd = inspec.command("pkg info #{package_name}")
|
245
|
+
return nil if cmd.exit_status.to_i != 0
|
245
246
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
247
|
+
params = SimpleConfig.new(
|
248
|
+
cmd.stdout.chomp,
|
249
|
+
assignment_re: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
|
250
|
+
multiple_values: false,
|
251
|
+
).params
|
251
252
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
253
|
+
{
|
254
|
+
name: params['Name'],
|
255
|
+
installed: true,
|
256
|
+
# 0.5.11-0.175.3.1.0.5.0
|
257
|
+
version: "#{params['Version']}-#{params['Branch']}",
|
258
|
+
type: 'pkg',
|
259
|
+
}
|
260
|
+
end
|
259
261
|
end
|
260
262
|
end
|