inspec 0.14.8 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
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