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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -2
  3. data/bin/inspec +3 -4
  4. data/examples/inheritance/README.md +19 -0
  5. data/examples/inheritance/controls/example.rb +11 -0
  6. data/examples/inheritance/inspec.yml +10 -0
  7. data/lib/bundles/inspec-compliance/cli.rb +1 -4
  8. data/lib/bundles/inspec-supermarket/cli.rb +1 -4
  9. data/lib/inspec/dsl.rb +48 -55
  10. data/lib/inspec/profile.rb +6 -2
  11. data/lib/inspec/profile_context.rb +21 -8
  12. data/lib/inspec/runner.rb +17 -12
  13. data/lib/inspec/runner_rspec.rb +1 -0
  14. data/lib/inspec/version.rb +1 -1
  15. data/lib/resources/apache.rb +20 -18
  16. data/lib/resources/apache_conf.rb +92 -90
  17. data/lib/resources/apt.rb +92 -90
  18. data/lib/resources/audit_policy.rb +35 -33
  19. data/lib/resources/auditd_conf.rb +41 -39
  20. data/lib/resources/auditd_rules.rb +155 -153
  21. data/lib/resources/bond.rb +1 -1
  22. data/lib/resources/bridge.rb +97 -95
  23. data/lib/resources/command.rb +47 -45
  24. data/lib/resources/csv.rb +23 -21
  25. data/lib/resources/directory.rb +1 -1
  26. data/lib/resources/etc_group.rb +116 -114
  27. data/lib/resources/file.rb +1 -1
  28. data/lib/resources/gem.rb +39 -37
  29. data/lib/resources/group.rb +100 -98
  30. data/lib/resources/host.rb +103 -101
  31. data/lib/resources/inetd_conf.rb +42 -40
  32. data/lib/resources/ini.rb +15 -13
  33. data/lib/resources/interface.rb +106 -104
  34. data/lib/resources/iptables.rb +36 -34
  35. data/lib/resources/json.rb +64 -62
  36. data/lib/resources/kernel_module.rb +30 -28
  37. data/lib/resources/kernel_parameter.rb +44 -42
  38. data/lib/resources/limits_conf.rb +41 -39
  39. data/lib/resources/login_def.rb +38 -36
  40. data/lib/resources/mount.rb +43 -41
  41. data/lib/resources/mysql.rb +67 -65
  42. data/lib/resources/mysql_conf.rb +89 -87
  43. data/lib/resources/mysql_session.rb +46 -44
  44. data/lib/resources/npm.rb +35 -33
  45. data/lib/resources/ntp_conf.rb +44 -42
  46. data/lib/resources/oneget.rb +46 -44
  47. data/lib/resources/os.rb +22 -20
  48. data/lib/resources/os_env.rb +47 -45
  49. data/lib/resources/package.rb +213 -211
  50. data/lib/resources/parse_config.rb +59 -57
  51. data/lib/resources/passwd.rb +89 -87
  52. data/lib/resources/pip.rb +60 -58
  53. data/lib/resources/port.rb +352 -350
  54. data/lib/resources/postgres.rb +26 -24
  55. data/lib/resources/postgres_conf.rb +66 -64
  56. data/lib/resources/postgres_session.rb +47 -45
  57. data/lib/resources/processes.rb +56 -54
  58. data/lib/resources/registry_key.rb +150 -148
  59. data/lib/resources/script.rb +30 -28
  60. data/lib/resources/security_policy.rb +56 -54
  61. data/lib/resources/service.rb +638 -636
  62. data/lib/resources/shadow.rb +98 -96
  63. data/lib/resources/ssh_conf.rb +58 -56
  64. data/lib/resources/user.rb +363 -361
  65. data/lib/resources/windows_feature.rb +46 -44
  66. data/lib/resources/xinetd.rb +111 -109
  67. data/lib/resources/yaml.rb +16 -14
  68. data/lib/resources/yum.rb +107 -105
  69. data/lib/utils/base_cli.rb +18 -0
  70. data/test/helper.rb +2 -2
  71. data/test/unit/profile_context_test.rb +1 -1
  72. data/test/unit/resources/file_test.rb +1 -1
  73. data/test/unit/resources/mount_test.rb +1 -1
  74. metadata +5 -2
@@ -13,77 +13,79 @@
13
13
  # }
14
14
  # describe parse_config(audit, options ) do
15
15
 
16
- class PConfig < Inspec.resource(1)
17
- name 'parse_config'
18
- desc 'Use the parse_config InSpec audit resource to test arbitrary configuration files.'
19
- example "
20
- output = command('some-command').stdout
16
+ module Inspec::Resources
17
+ class PConfig < Inspec.resource(1)
18
+ name 'parse_config'
19
+ desc 'Use the parse_config InSpec audit resource to test arbitrary configuration files.'
20
+ example "
21
+ output = command('some-command').stdout
21
22
 
22
- describe parse_config(output, { data_config_option: value } ) do
23
- its('setting') { should eq 1 }
24
- end
25
- "
23
+ describe parse_config(output, { data_config_option: value } ) do
24
+ its('setting') { should eq 1 }
25
+ end
26
+ "
26
27
 
27
- def initialize(content = nil, useropts = nil)
28
- @opts = {}
29
- @opts = useropts.dup unless useropts.nil?
30
- @files_contents = {}
31
- @params = nil
28
+ def initialize(content = nil, useropts = nil)
29
+ @opts = {}
30
+ @opts = useropts.dup unless useropts.nil?
31
+ @files_contents = {}
32
+ @params = nil
32
33
 
33
- @content = content
34
- read_content if @content.nil?
35
- end
34
+ @content = content
35
+ read_content if @content.nil?
36
+ end
36
37
 
37
- def method_missing(name)
38
- @params || read_content
39
- @params[name.to_s]
40
- end
38
+ def method_missing(name)
39
+ @params || read_content
40
+ @params[name.to_s]
41
+ end
41
42
 
42
- def parse_file(conf_path)
43
- @conf_path = conf_path
43
+ def parse_file(conf_path)
44
+ @conf_path = conf_path
44
45
 
45
- # read the file
46
- if !inspec.file(conf_path).file?
47
- return skip_resource "Can't find file \"#{conf_path}\""
48
- end
49
- @content = read_file(conf_path)
50
- if @content.empty? && inspec.file(conf_path).size > 0
51
- return skip_resource "Can't read file \"#{conf_path}\""
46
+ # read the file
47
+ if !inspec.file(conf_path).file?
48
+ return skip_resource "Can't find file \"#{conf_path}\""
49
+ end
50
+ @content = read_file(conf_path)
51
+ if @content.empty? && inspec.file(conf_path).size > 0
52
+ return skip_resource "Can't read file \"#{conf_path}\""
53
+ end
54
+
55
+ read_content
52
56
  end
53
57
 
54
- read_content
55
- end
58
+ def read_file(path)
59
+ @files_contents[path] ||= inspec.file(path).content
60
+ end
56
61
 
57
- def read_file(path)
58
- @files_contents[path] ||= inspec.file(path).content
59
- end
62
+ def read_content
63
+ # parse the file
64
+ @params = SimpleConfig.new(@content, @opts).params
65
+ @content
66
+ end
60
67
 
61
- def read_content
62
- # parse the file
63
- @params = SimpleConfig.new(@content, @opts).params
64
- @content
68
+ def to_s
69
+ "Parse Config #{@conf_path}"
70
+ end
65
71
  end
66
72
 
67
- def to_s
68
- "Parse Config #{@conf_path}"
69
- end
70
- end
73
+ class PConfigFile < PConfig
74
+ name 'parse_config_file'
75
+ desc 'Use the parse_config_file InSpec audit resource to test arbitrary configuration files. It works identiacal to parse_config. Instead of using a command output, this resource works with files.'
76
+ example "
77
+ describe parse_config_file('/path/to/file') do
78
+ its('setting') { should eq 1 }
79
+ end
80
+ "
71
81
 
72
- class PConfigFile < PConfig
73
- name 'parse_config_file'
74
- desc 'Use the parse_config_file InSpec audit resource to test arbitrary configuration files. It works identiacal to parse_config. Instead of using a command output, this resource works with files.'
75
- example "
76
- describe parse_config_file('/path/to/file') do
77
- its('setting') { should eq 1 }
82
+ def initialize(path, opts = nil)
83
+ super(nil, opts)
84
+ parse_file(path)
78
85
  end
79
- "
80
-
81
- def initialize(path, opts = nil)
82
- super(nil, opts)
83
- parse_file(path)
84
- end
85
86
 
86
- def to_s
87
- "Parse Config File #{@conf_path}"
87
+ def to_s
88
+ "Parse Config File #{@conf_path}"
89
+ end
88
90
  end
89
91
  end
@@ -15,112 +15,114 @@
15
15
 
16
16
  require 'utils/parser'
17
17
 
18
- class Passwd < Inspec.resource(1)
19
- name 'passwd'
20
- 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.'
21
- example "
22
- describe passwd do
23
- its('users') { should_not include 'forbidden_user' }
24
- end
18
+ module Inspec::Resources
19
+ class Passwd < Inspec.resource(1)
20
+ name 'passwd'
21
+ 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.'
22
+ example "
23
+ describe passwd do
24
+ its('users') { should_not include 'forbidden_user' }
25
+ end
25
26
 
26
- describe passwd.uids(0) do
27
- its('users') { should cmp 'root' }
28
- its('count') { should eq 1 }
29
- end
27
+ describe passwd.uids(0) do
28
+ its('users') { should cmp 'root' }
29
+ its('count') { should eq 1 }
30
+ end
30
31
 
31
- describe passwd.shells(/nologin/) do
32
- # find all users with a nologin shell
33
- its('users') { should_not include 'my_login_user' }
32
+ describe passwd.shells(/nologin/) do
33
+ # find all users with a nologin shell
34
+ its('users') { should_not include 'my_login_user' }
35
+ end
36
+ "
37
+
38
+ include PasswdParser
39
+
40
+ attr_reader :uid
41
+ attr_reader :params
42
+ attr_reader :content
43
+ attr_reader :lines
44
+
45
+ def initialize(path = nil, opts = nil)
46
+ opts ||= {}
47
+ @path = path || '/etc/passwd'
48
+ @content = opts[:content] || inspec.file(@path).content
49
+ @lines = @content.to_s.split("\n")
50
+ @filters = opts[:filters] || ''
51
+ @params = parse_passwd(@content)
34
52
  end
35
- "
36
-
37
- include PasswdParser
38
-
39
- attr_reader :uid
40
- attr_reader :params
41
- attr_reader :content
42
- attr_reader :lines
43
-
44
- def initialize(path = nil, opts = nil)
45
- opts ||= {}
46
- @path = path || '/etc/passwd'
47
- @content = opts[:content] || inspec.file(@path).content
48
- @lines = @content.to_s.split("\n")
49
- @filters = opts[:filters] || ''
50
- @params = parse_passwd(@content)
51
- end
52
53
 
53
- def filter(hm = {})
54
- return self if hm.nil? || hm.empty?
55
- res = @params
56
- filters = ''
57
- hm.each do |attr, condition|
58
- condition = condition.to_s if condition.is_a? Integer
59
- filters += " #{attr} = #{condition.inspect}"
60
- res = res.find_all do |line|
61
- case line[attr.to_s]
62
- when condition
63
- true
64
- else
65
- false
54
+ def filter(hm = {})
55
+ return self if hm.nil? || hm.empty?
56
+ res = @params
57
+ filters = ''
58
+ hm.each do |attr, condition|
59
+ condition = condition.to_s if condition.is_a? Integer
60
+ filters += " #{attr} = #{condition.inspect}"
61
+ res = res.find_all do |line|
62
+ case line[attr.to_s]
63
+ when condition
64
+ true
65
+ else
66
+ false
67
+ end
66
68
  end
67
69
  end
70
+ content = res.map { |x| x.values.join(':') }.join("\n")
71
+ Passwd.new(@path, content: content, filters: @filters + filters)
68
72
  end
69
- content = res.map { |x| x.values.join(':') }.join("\n")
70
- Passwd.new(@path, content: content, filters: @filters + filters)
71
- end
72
73
 
73
- def usernames
74
- warn '[DEPRECATION] `passwd.usernames` is deprecated. Please use `passwd.users` instead. It will be removed in version 1.0.0.'
75
- users
76
- end
74
+ def usernames
75
+ warn '[DEPRECATION] `passwd.usernames` is deprecated. Please use `passwd.users` instead. It will be removed in version 1.0.0.'
76
+ users
77
+ end
77
78
 
78
- def username
79
- warn '[DEPRECATION] `passwd.user` is deprecated. Please use `passwd.users` instead. It will be removed in version 1.0.0.'
80
- users[0]
81
- end
79
+ def username
80
+ warn '[DEPRECATION] `passwd.user` is deprecated. Please use `passwd.users` instead. It will be removed in version 1.0.0.'
81
+ users[0]
82
+ end
82
83
 
83
- def uid(x)
84
- warn '[DEPRECATION] `passwd.uid(arg)` is deprecated. Please use `passwd.uids(arg)` instead. It will be removed in version 1.0.0.'
85
- uids(x)
86
- end
84
+ def uid(x)
85
+ warn '[DEPRECATION] `passwd.uid(arg)` is deprecated. Please use `passwd.uids(arg)` instead. It will be removed in version 1.0.0.'
86
+ uids(x)
87
+ end
87
88
 
88
- def users(name = nil)
89
- name.nil? ? map_data('user') : filter(user: name)
90
- end
89
+ def users(name = nil)
90
+ name.nil? ? map_data('user') : filter(user: name)
91
+ end
91
92
 
92
- def passwords(password = nil)
93
- password.nil? ? map_data('password') : filter(password: password)
94
- end
93
+ def passwords(password = nil)
94
+ password.nil? ? map_data('password') : filter(password: password)
95
+ end
95
96
 
96
- def uids(uid = nil)
97
- uid.nil? ? map_data('uid') : filter(uid: uid)
98
- end
97
+ def uids(uid = nil)
98
+ uid.nil? ? map_data('uid') : filter(uid: uid)
99
+ end
99
100
 
100
- def gids(gid = nil)
101
- gid.nil? ? map_data('gid') : filter(gid: gid)
102
- end
101
+ def gids(gid = nil)
102
+ gid.nil? ? map_data('gid') : filter(gid: gid)
103
+ end
103
104
 
104
- def homes(home = nil)
105
- home.nil? ? map_data('home') : filter(home: home)
106
- end
105
+ def homes(home = nil)
106
+ home.nil? ? map_data('home') : filter(home: home)
107
+ end
107
108
 
108
- def shells(shell = nil)
109
- shell.nil? ? map_data('shell') : filter(shell: shell)
110
- end
109
+ def shells(shell = nil)
110
+ shell.nil? ? map_data('shell') : filter(shell: shell)
111
+ end
111
112
 
112
- def to_s
113
- f = @filters.empty? ? '' : ' with'+@filters
114
- "/etc/passwd#{f}"
115
- end
113
+ def to_s
114
+ f = @filters.empty? ? '' : ' with'+@filters
115
+ "/etc/passwd#{f}"
116
+ end
116
117
 
117
- def count
118
- @params.length
119
- end
118
+ def count
119
+ @params.length
120
+ end
120
121
 
121
- private
122
+ private
122
123
 
123
- def map_data(id)
124
- @params.map { |x| x[id] }
124
+ def map_data(id)
125
+ @params.map { |x| x[id] }
126
+ end
125
127
  end
126
128
  end
data/lib/resources/pip.rb CHANGED
@@ -7,75 +7,77 @@
7
7
  # it { should be_installed }
8
8
  # end
9
9
  #
10
- class PipPackage < Inspec.resource(1)
11
- name 'pip'
12
- desc 'Use the pip InSpec audit resource to test packages that are installed using the pip installer.'
13
- example "
14
- describe pip('Jinja2') do
15
- it { should be_installed }
16
- end
17
- "
10
+ module Inspec::Resources
11
+ class PipPackage < Inspec.resource(1)
12
+ name 'pip'
13
+ desc 'Use the pip InSpec audit resource to test packages that are installed using the pip installer.'
14
+ example "
15
+ describe pip('Jinja2') do
16
+ it { should be_installed }
17
+ end
18
+ "
18
19
 
19
- def initialize(package_name)
20
- @package_name = package_name
21
- end
20
+ def initialize(package_name)
21
+ @package_name = package_name
22
+ end
22
23
 
23
- def info
24
- return @info if defined?(@info)
24
+ def info
25
+ return @info if defined?(@info)
25
26
 
26
- @info = {}
27
- @info[:type] = 'pip'
28
- cmd = inspec.command("#{pip_cmd} show #{@package_name}")
29
- return @info if cmd.exit_status != 0
27
+ @info = {}
28
+ @info[:type] = 'pip'
29
+ cmd = inspec.command("#{pip_cmd} show #{@package_name}")
30
+ return @info if cmd.exit_status != 0
30
31
 
31
- params = SimpleConfig.new(
32
- cmd.stdout,
33
- assignment_re: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
34
- multiple_values: false,
35
- ).params
36
- @info[:name] = params['Name']
37
- @info[:version] = params['Version']
38
- @info[:installed] = true
39
- @info
40
- end
32
+ params = SimpleConfig.new(
33
+ cmd.stdout,
34
+ assignment_re: /^\s*([^:]*?)\s*:\s*(.*?)\s*$/,
35
+ multiple_values: false,
36
+ ).params
37
+ @info[:name] = params['Name']
38
+ @info[:version] = params['Version']
39
+ @info[:installed] = true
40
+ @info
41
+ end
41
42
 
42
- def installed?
43
- info[:installed] == true
44
- end
43
+ def installed?
44
+ info[:installed] == true
45
+ end
45
46
 
46
- def version
47
- info[:version]
48
- end
47
+ def version
48
+ info[:version]
49
+ end
49
50
 
50
- def to_s
51
- "Pip Package #{@package_name}"
52
- end
51
+ def to_s
52
+ "Pip Package #{@package_name}"
53
+ end
53
54
 
54
- private
55
+ private
55
56
 
56
- def pip_cmd
57
- # Pip is not on the default path for Windows, therefore we do some logic
58
- # to find the binary on Windows
59
- family = inspec.os[:family]
60
- case family
61
- when 'windows'
62
- # we need to detect the pip command on Windows
63
- cmd = inspec.command('New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Pip -Value (Invoke-Command -ScriptBlock {where.exe pip}) -PassThru | Add-Member -MemberType NoteProperty -Name Python -Value (Invoke-Command -ScriptBlock {where.exe python}) -PassThru | ConvertTo-Json')
64
- begin
65
- paths = JSON.parse(cmd.stdout)
66
- # use pip if it on system path
67
- pipcmd = paths['Pip']
68
- # calculate path on windows
69
- if defined?(paths['Python']) && pipcmd.nil?
70
- pipdir = paths['Python'].split('\\')
71
- # remove python.exe
72
- pipdir.pop
73
- pipcmd = pipdir.push('Scripts').push('pip.exe').join('/')
57
+ def pip_cmd
58
+ # Pip is not on the default path for Windows, therefore we do some logic
59
+ # to find the binary on Windows
60
+ family = inspec.os[:family]
61
+ case family
62
+ when 'windows'
63
+ # we need to detect the pip command on Windows
64
+ cmd = inspec.command('New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Pip -Value (Invoke-Command -ScriptBlock {where.exe pip}) -PassThru | Add-Member -MemberType NoteProperty -Name Python -Value (Invoke-Command -ScriptBlock {where.exe python}) -PassThru | ConvertTo-Json')
65
+ begin
66
+ paths = JSON.parse(cmd.stdout)
67
+ # use pip if it on system path
68
+ pipcmd = paths['Pip']
69
+ # calculate path on windows
70
+ if defined?(paths['Python']) && pipcmd.nil?
71
+ pipdir = paths['Python'].split('\\')
72
+ # remove python.exe
73
+ pipdir.pop
74
+ pipcmd = pipdir.push('Scripts').push('pip.exe').join('/')
75
+ end
76
+ rescue JSON::ParserError => _e
77
+ return nil
74
78
  end
75
- rescue JSON::ParserError => _e
76
- return nil
77
79
  end
80
+ pipcmd || 'pip'
78
81
  end
79
- pipcmd || 'pip'
80
82
  end
81
83
  end