inspec 1.45.9 → 1.45.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +54 -32
  3. data/CHANGELOG.md +29 -21
  4. data/Gemfile +1 -1
  5. data/docs/resources/ini.md.erb +14 -1
  6. data/docs/shell.md +1 -1
  7. data/inspec.gemspec +2 -2
  8. data/lib/bundles/inspec-artifact/cli.rb +3 -8
  9. data/lib/bundles/inspec-compliance/configuration.rb +5 -5
  10. data/lib/bundles/inspec-compliance/http.rb +2 -5
  11. data/lib/bundles/inspec-compliance/target.rb +6 -6
  12. data/lib/bundles/inspec-compliance/test/integration/default/cli.rb +1 -1
  13. data/lib/bundles/inspec-habitat/profile.rb +68 -74
  14. data/lib/bundles/inspec-supermarket/api.rb +7 -7
  15. data/lib/bundles/inspec-supermarket/cli.rb +1 -1
  16. data/lib/fetchers/git.rb +3 -8
  17. data/lib/fetchers/local.rb +7 -13
  18. data/lib/fetchers/url.rb +1 -1
  19. data/lib/inspec/backend.rb +0 -1
  20. data/lib/inspec/base_cli.rb +1 -1
  21. data/lib/inspec/cached_fetcher.rb +11 -12
  22. data/lib/inspec/cli.rb +0 -1
  23. data/lib/inspec/control_eval_context.rb +2 -2
  24. data/lib/inspec/dependencies/lockfile.rb +13 -15
  25. data/lib/inspec/dependencies/requirement.rb +1 -1
  26. data/lib/inspec/dependencies/resolver.rb +3 -5
  27. data/lib/inspec/dsl.rb +5 -5
  28. data/lib/inspec/dsl_shared.rb +1 -1
  29. data/lib/inspec/env_printer.rb +26 -26
  30. data/lib/inspec/metadata.rb +11 -10
  31. data/lib/inspec/objects/or_test.rb +4 -2
  32. data/lib/inspec/objects/test.rb +1 -1
  33. data/lib/inspec/profile.rb +2 -2
  34. data/lib/inspec/resource.rb +1 -3
  35. data/lib/inspec/rspec_json_formatter.rb +6 -8
  36. data/lib/inspec/shell.rb +51 -52
  37. data/lib/inspec/version.rb +1 -1
  38. data/lib/matchers/matchers.rb +1 -2
  39. data/lib/resources/audit_policy.rb +2 -2
  40. data/lib/resources/auditd.rb +6 -3
  41. data/lib/resources/dh_params.rb +1 -2
  42. data/lib/resources/docker.rb +2 -2
  43. data/lib/resources/docker_container.rb +4 -4
  44. data/lib/resources/elasticsearch.rb +2 -6
  45. data/lib/resources/etc_group.rb +2 -4
  46. data/lib/resources/groups.rb +14 -14
  47. data/lib/resources/host.rb +2 -3
  48. data/lib/resources/packages.rb +1 -1
  49. data/lib/resources/port.rb +1 -1
  50. data/lib/resources/postgres.rb +6 -6
  51. data/lib/resources/powershell.rb +1 -1
  52. data/lib/resources/service.rb +4 -5
  53. data/lib/resources/users.rb +58 -58
  54. data/lib/resources/vbscript.rb +10 -10
  55. data/lib/resources/virtualization.rb +3 -4
  56. data/lib/resources/x509_certificate.rb +1 -1
  57. data/lib/resources/yum.rb +1 -1
  58. data/lib/source_readers/inspec.rb +2 -1
  59. data/lib/utils/command_wrapper.rb +3 -8
  60. data/lib/utils/filter.rb +1 -1
  61. data/lib/utils/json_log.rb +2 -1
  62. data/lib/utils/latest_version.rb +5 -4
  63. data/lib/utils/object_traversal.rb +1 -1
  64. data/lib/utils/parser.rb +2 -2
  65. metadata +4 -4
@@ -42,7 +42,7 @@ module Inspec
42
42
  def describe_chain
43
43
  return nil if @qualifier.empty?
44
44
 
45
- resource = (@qualifier.length > 1) ? @qualifier[0..-2] : [@qualifier[0]]
45
+ resource = @qualifier.length > 1 ? @qualifier[0..-2] : [@qualifier[0]]
46
46
  res = resource.map { |q| ruby_qualifier(q) }.join('.')
47
47
  xres = nil
48
48
 
@@ -106,7 +106,7 @@ module Inspec
106
106
  # we share the backend between profiles.
107
107
  #
108
108
  # This will cause issues if a profile attempts to load a file via `inspec.profile.file`
109
- train_options = options.select { |k, _| k != 'target' } # See https://github.com/chef/inspec/pull/1646
109
+ train_options = options.reject { |k, _| k == 'target' } # See https://github.com/chef/inspec/pull/1646
110
110
  @backend = options[:backend].nil? ? Inspec::Backend.create(train_options) : options[:backend].dup
111
111
  @runtime_profile = RuntimeProfile.new(self)
112
112
  @backend.profile = @runtime_profile
@@ -421,7 +421,7 @@ module Inspec
421
421
  [['inspec.yml', source_reader.metadata.content]] +
422
422
  [['inspec.lock.deps', YAML.dump(deps)]]
423
423
 
424
- files.sort { |a, b| a[0] <=> b[0] }
424
+ files.sort_by { |a| a[0] }
425
425
  .map { |f| res << f[0] << "\0" << f[1] << "\0" }
426
426
 
427
427
  res.digest.unpack('H*')[0]
@@ -66,9 +66,7 @@ module Inspec
66
66
  end
67
67
 
68
68
  def self.validate_resource_dsl_version!(version)
69
- if version != 1
70
- raise 'Only resource version 1 is supported!'
71
- end
69
+ raise 'Only resource version 1 is supported!' if version != 1
72
70
  end
73
71
  end
74
72
 
@@ -455,10 +455,10 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
455
455
  end
456
456
 
457
457
  def print_last_control_with_examples
458
- if @last_control
459
- print_control(@last_control)
460
- @last_control.examples.each { |example| print_result(example) }
461
- end
458
+ return unless @last_control
459
+
460
+ print_control(@last_control)
461
+ @last_control.examples.each { |example| print_result(example) }
462
462
  end
463
463
 
464
464
  def last_control_is_anonymous?
@@ -634,8 +634,7 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
634
634
  s = format('Profile Summary: %s, %s, %s',
635
635
  format_with_color(success_color, success_str),
636
636
  format_with_color(failed_color, failed_str),
637
- format_with_color(skipped_color, skipped_str),
638
- )
637
+ format_with_color(skipped_color, skipped_str))
639
638
  output.puts(s) if summary['total'] > 0
640
639
  end
641
640
 
@@ -651,8 +650,7 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
651
650
  s = format('Test Summary: %s, %s, %s',
652
651
  format_with_color(success_color, "#{summary['passed']} successful"),
653
652
  format_with_color(failed_color, failed_str),
654
- format_with_color(skipped_color, "#{summary['skipped']} skipped"),
655
- )
653
+ format_with_color(skipped_color, "#{summary['skipped']} skipped"))
656
654
 
657
655
  output.puts(s)
658
656
  end
data/lib/inspec/shell.rb CHANGED
@@ -103,35 +103,34 @@ module Inspec
103
103
 
104
104
  def print_target_info
105
105
  ctx = @runner.backend
106
- puts <<EOF
107
- You are currently running on:
106
+ puts <<~EOF
107
+ You are currently running on:
108
108
 
109
- OS platform: #{mark ctx.os[:name] || 'unknown'}
110
- OS family: #{mark ctx.os[:family] || 'unknown'}
111
- OS release: #{mark ctx.os[:release] || 'unknown'}
112
- EOF
109
+ OS platform: #{mark ctx.os[:name] || 'unknown'}
110
+ OS family: #{mark ctx.os[:family] || 'unknown'}
111
+ OS release: #{mark ctx.os[:release] || 'unknown'}
112
+ EOF
113
113
  end
114
114
 
115
115
  def help(topic = nil)
116
116
  if topic.nil?
117
117
 
118
- puts <<EOF
118
+ puts <<~EOF
119
+ Available commands:
119
120
 
120
- Available commands:
121
+ `[resource]` - run resource on target machine
122
+ `help resources` - show all available resources that can be used as commands
123
+ `help [resource]` - information about a specific resource
124
+ `help matchers` - show information about common matchers
125
+ `exit` - exit the InSpec shell
121
126
 
122
- `[resource]` - run resource on target machine
123
- `help resources` - show all available resources that can be used as commands
124
- `help [resource]` - information about a specific resource
125
- `help matchers` - show information about common matchers
126
- `exit` - exit the InSpec shell
127
+ You can use resources in this environment to test the target machine. For example:
127
128
 
128
- You can use resources in this environment to test the target machine. For example:
129
+ command('uname -a').stdout
130
+ file('/proc/cpuinfo').content => "value"
129
131
 
130
- command('uname -a').stdout
131
- file('/proc/cpuinfo').content => "value"
132
-
133
- #{print_target_info}
134
- EOF
132
+ #{print_target_info}
133
+ EOF
135
134
  elsif topic == 'resources'
136
135
  resources.sort.each do |resource|
137
136
  puts " - #{resource}"
@@ -164,60 +163,60 @@ EOF
164
163
  end
165
164
 
166
165
  def print_matchers_help
167
- puts <<-EOL
168
- Matchers are used to compare resource values to expectations. While some
169
- resources implement their own custom matchers, the following matchers are
170
- common amongst all resources:
166
+ puts <<~EOL
167
+ Matchers are used to compare resource values to expectations. While some
168
+ resources implement their own custom matchers, the following matchers are
169
+ common amongst all resources:
171
170
 
172
- #{mark 'be'}
171
+ #{mark 'be'}
173
172
 
174
- The #{mark 'be'} matcher can be used to compare numeric values.
173
+ The #{mark 'be'} matcher can be used to compare numeric values.
175
174
 
176
- its('size') { should be >= 10 }
175
+ its('size') { should be >= 10 }
177
176
 
178
- #{mark 'cmp'}
177
+ #{mark 'cmp'}
179
178
 
180
- The #{mark 'cmp'} matcher is like #{mark 'eq'} but less restrictive. It will try
181
- to fit the resource value to the expectation.
179
+ The #{mark 'cmp'} matcher is like #{mark 'eq'} but less restrictive. It will try
180
+ to fit the resource value to the expectation.
182
181
 
183
- "Protocol" likely returns a string, but cmp will ensure it's a number before
184
- comparing:
182
+ "Protocol" likely returns a string, but cmp will ensure it's a number before
183
+ comparing:
185
184
 
186
- its('Protocol') { should cmp 2 }
187
- its('Protocol') { should cmp '2' }
185
+ its('Protocol') { should cmp 2 }
186
+ its('Protocol') { should cmp '2' }
188
187
 
189
- "users" may return an array, but if it contains only one item, cmp will compare
190
- it as a string or number as needed:
188
+ "users" may return an array, but if it contains only one item, cmp will compare
189
+ it as a string or number as needed:
191
190
 
192
- its('users') { should cmp 'root' }
191
+ its('users') { should cmp 'root' }
193
192
 
194
- cmp is not case-sensitive:
193
+ cmp is not case-sensitive:
195
194
 
196
- its('log_format') { should cmp 'raw' }
197
- its('log_format') { should cmp 'RAW' }
195
+ its('log_format') { should cmp 'raw' }
196
+ its('log_format') { should cmp 'RAW' }
198
197
 
199
- #{mark 'eq'}
198
+ #{mark 'eq'}
200
199
 
201
- The #{mark 'eq'} matcher tests for exact equality of two values. Value type
202
- (string, number, etc.) is important and must be the same. For a less-restrictive
203
- comparison matcher, use the #{mark 'cmp'} matcher.
200
+ The #{mark 'eq'} matcher tests for exact equality of two values. Value type
201
+ (string, number, etc.) is important and must be the same. For a less-restrictive
202
+ comparison matcher, use the #{mark 'cmp'} matcher.
204
203
 
205
- its('RSAAuthentication') { should_not eq 'no' }
204
+ its('RSAAuthentication') { should_not eq 'no' }
206
205
 
207
- #{mark 'include'}
206
+ #{mark 'include'}
208
207
 
209
- The #{mark 'include'} matcher tests to see if a value is included in a list.
208
+ The #{mark 'include'} matcher tests to see if a value is included in a list.
210
209
 
211
- its('users') { should include 'my_user' }
210
+ its('users') { should include 'my_user' }
212
211
 
213
- #{mark 'match'}
212
+ #{mark 'match'}
214
213
 
215
- The #{mark 'match'} matcher can be used to test a string for a match using a
216
- regular expression.
214
+ The #{mark 'match'} matcher can be used to test a string for a match using a
215
+ regular expression.
217
216
 
218
- its('content') { should_not match /^MyKey:\\s+some value/ }
217
+ its('content') { should_not match /^MyKey:\\s+some value/ }
219
218
 
220
- For more examples, see: https://www.inspec.io/docs/reference/matchers/
219
+ For more examples, see: https://www.inspec.io/docs/reference/matchers/
221
220
 
222
221
  EOL
223
222
  end
@@ -4,5 +4,5 @@
4
4
  # author: Christoph Hartmann
5
5
 
6
6
  module Inspec
7
- VERSION = '1.45.9'
7
+ VERSION = '1.45.13'
8
8
  end
@@ -266,7 +266,7 @@ end
266
266
  # - compare strings case-insensitive
267
267
  # - you expect a number (strings will be converted if possible)
268
268
  #
269
- RSpec::Matchers.define :cmp do |first_expected|
269
+ RSpec::Matchers.define :cmp do |first_expected| # rubocop:disable Metrics/BlockLength
270
270
 
271
271
  def integer?(value)
272
272
  !(value =~ /\A0+\Z|\A[1-9]\d*\Z/).nil?
@@ -324,7 +324,6 @@ RSpec::Matchers.define :cmp do |first_expected|
324
324
 
325
325
  # fallback to simple operation
326
326
  actual.method(op).call(expected)
327
-
328
327
  rescue NameError => _
329
328
  false
330
329
  rescue ArgumentError
@@ -43,9 +43,9 @@ module Inspec::Resources
43
43
 
44
44
  # find line
45
45
  target = nil
46
- result.each_line {|s|
46
+ result.each_line do |s|
47
47
  target = s.strip if s =~ /\b.*#{key}.*\b/
48
- }
48
+ end
49
49
 
50
50
  # extract value
51
51
  values = nil
@@ -101,7 +101,8 @@ module Inspec::Resources
101
101
  'permissions' => perms,
102
102
  'key' => key,
103
103
  'fields_nokey' => fields_nokey,
104
- },)
104
+ },
105
+ )
105
106
  end
106
107
 
107
108
  def syscall_rules_for(line)
@@ -128,7 +129,8 @@ module Inspec::Resources
128
129
  'permissions' => perms,
129
130
  'exit' => exit_field,
130
131
  'fields_nokey' => fields_nokey,
131
- },)
132
+ },
133
+ )
132
134
  end
133
135
  end
134
136
 
@@ -142,7 +144,8 @@ module Inspec::Resources
142
144
  'file' => file,
143
145
  'key' => key,
144
146
  'permissions' => perms,
145
- },)
147
+ },
148
+ )
146
149
  end
147
150
 
148
151
  def to_s
@@ -26,8 +26,7 @@ class DhParams < Inspec.resource(1)
26
26
  def initialize(filename)
27
27
  @dh_params_path = filename
28
28
  file = inspec.file(@dh_params_path)
29
- return skip_resource 'Unable to find DH parameters file ' \
30
- "#{@dh_params_path}" unless file.exist?
29
+ return skip_resource "Unable to find DH parameters file #{@dh_params_path}" unless file.exist?
31
30
 
32
31
  begin
33
32
  @dh_params = OpenSSL::PKey::DH.new file.content
@@ -146,7 +146,7 @@ module Inspec::Resources
146
146
  # @see https://github.com/moby/moby/issues/20625, works for docker 1.13+
147
147
  # raw_containers = inspec.command('docker ps -a --no-trunc --format \'{{ json . }}\'').stdout
148
148
  # therefore we stick with older approach
149
- labels = %w{Command CreatedAt ID Image Labels Mounts Names Ports RunningFor Size Status}
149
+ labels = %w{Command CreatedAt ID Image Labels Mounts Names Ports RunningFor Size Status}
150
150
 
151
151
  # Networks LocalVolumes work with 1.13+ only
152
152
  if !version.empty? && Gem::Version.new(version['Client']['Version']) >= Gem::Version.new('1.13')
@@ -183,7 +183,7 @@ module Inspec::Resources
183
183
  end
184
184
 
185
185
  def ensure_container_keys(entry)
186
- %w{Command CreatedAt ID Image Labels Mounts Names Ports RunningFor Size Status Networks LocalVolumes}.each { |key|
186
+ %w{Command CreatedAt ID Image Labels Mounts Names Ports RunningFor Size Status Networks LocalVolumes}.each { |key|
187
187
  entry[key.downcase] = nil if !entry.key?(key.downcase)
188
188
  }
189
189
  entry
@@ -63,10 +63,10 @@ module Inspec::Resources
63
63
  end
64
64
 
65
65
  def command
66
- if container_info.entries.length == 1
67
- cmd = container_info.commands[0]
68
- cmd.slice(1, cmd.length - 2)
69
- end
66
+ return unless container_info.entries.length == 1
67
+
68
+ cmd = container_info.commands[0]
69
+ cmd.slice(1, cmd.length - 2)
70
70
  end
71
71
 
72
72
  def image
@@ -154,9 +154,7 @@ module Inspec::Resources
154
154
  raise 'Connection refused - peer certificate issuer is not recognized'
155
155
  end
156
156
 
157
- if !cmd.exit_status.zero?
158
- raise "Error fetching Elastcsearch data from curl #{url}: #{cmd.stderr}"
159
- end
157
+ raise "Error fetching Elastcsearch data from curl #{url}: #{cmd.stderr}" unless cmd.exit_status.zero?
160
158
  end
161
159
 
162
160
  def verify_json_payload!(content)
@@ -164,9 +162,7 @@ module Inspec::Resources
164
162
  raise "#{content['error']['type']}: #{content['error']['reason']}"
165
163
  end
166
164
 
167
- if content['_nodes']['successful'].zero?
168
- raise 'No successful nodes available in cluster'
169
- end
165
+ raise 'No successful nodes available in cluster' if content['_nodes']['successful'].zero?
170
166
  end
171
167
  end
172
168
  end
@@ -49,13 +49,11 @@ module Inspec::Resources
49
49
  end
50
50
 
51
51
  def groups(filter = nil)
52
- entries = filter || @entries
53
- entries.map { |x| x['name'] } if !entries.nil?
52
+ (filter || @entries)&.map { |x| x['name'] }
54
53
  end
55
54
 
56
55
  def gids(filter = nil)
57
- entries = filter || @entries
58
- entries.map { |x| x['gid'] } if !entries.nil?
56
+ (filter || @entries)&.map { |x| x['gid'] }
59
57
  end
60
58
 
61
59
  def users(filter = nil)
@@ -157,20 +157,20 @@ module Inspec::Resources
157
157
  class WindowsGroup < GroupInfo
158
158
  # returns all local groups
159
159
  def groups
160
- script = <<-EOH
161
- Function ConvertTo-SID { Param([byte[]]$BinarySID)
162
- (New-Object System.Security.Principal.SecurityIdentifier($BinarySID,0)).Value
163
- }
164
-
165
- $Computername = $Env:Computername
166
- $adsi = [ADSI]"WinNT://$Computername"
167
- $groups = $adsi.Children | where {$_.SchemaClassName -eq 'group'} | ForEach {
168
- $name = $_.Name[0]
169
- $sid = ConvertTo-SID -BinarySID $_.ObjectSID[0]
170
- $group =[ADSI]$_.Path
171
- new-object psobject -property @{name = $group.Name[0]; gid = $sid; domain=$Computername}
172
- }
173
- $groups | ConvertTo-Json -Depth 3
160
+ script = <<~EOH
161
+ Function ConvertTo-SID { Param([byte[]]$BinarySID)
162
+ (New-Object System.Security.Principal.SecurityIdentifier($BinarySID,0)).Value
163
+ }
164
+
165
+ $Computername = $Env:Computername
166
+ $adsi = [ADSI]"WinNT://$Computername"
167
+ $groups = $adsi.Children | where {$_.SchemaClassName -eq 'group'} | ForEach {
168
+ $name = $_.Name[0]
169
+ $sid = ConvertTo-SID -BinarySID $_.ObjectSID[0]
170
+ $group =[ADSI]$_.Path
171
+ new-object psobject -property @{name = $group.Name[0]; gid = $sid; domain=$Computername}
172
+ }
173
+ $groups | ConvertTo-Json -Depth 3
174
174
  EOH
175
175
  cmd = inspec.powershell(script)
176
176
  # cannot rely on exit code for now, successful command returns exit code 1
@@ -70,9 +70,8 @@ module Inspec::Resources
70
70
  end
71
71
 
72
72
  missing_requirements = @host_provider.missing_requirements(protocol)
73
- unless missing_requirements.empty?
74
- return skip_resource "The following requirements are not met for this resource: #{missing_requirements.join(', ')}"
75
- end
73
+ return skip_resource 'The following requirements are not met for this resource: ' \
74
+ "#{missing_requirements.join(', ')}" unless missing_requirements.empty?
76
75
  end
77
76
 
78
77
  def proto
@@ -97,7 +97,7 @@ module Inspec::Resources
97
97
  class Rpms < PkgsManagement
98
98
  def build_package_list
99
99
  # use two spaces as delimiter in case any of the fields has a space in it
100
- command = "rpm -qa --queryformat '%{NAME} %{VERSION}-%{RELEASE}\\n'"
100
+ command = "rpm -qa --queryformat '%{NAME} %{VERSION}-%{RELEASE}\\n'" # rubocop:disable Style/FormatStringToken
101
101
  cmd = inspec.command(command)
102
102
  all = cmd.stdout.split("\n")
103
103
  return [] if all.nil?
@@ -242,7 +242,7 @@ module Inspec::Resources
242
242
  procs[proc_id] = [] unless procs.key?(proc_id)
243
243
 
244
244
  # change address '*' to zero
245
- host = (port_id =~ /^ipv6:/) ? '[::]' : '0.0.0.0' if host == '*'
245
+ host = port_id =~ /^ipv6:/ ? '[::]' : '0.0.0.0' if host == '*'
246
246
  # entrust URI to scrub the host and port
247
247
  begin
248
248
  uri = URI("addr://#{host}:#{port}")