inspec-core 4.21.3 → 4.22.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cefaf29ca67cbd5cdc90ac2bc3a41e990f38f966761d324489d46f8c9a32fdc5
4
- data.tar.gz: 933e72e1021a81bffac47c3de56378ea0945682c6ed8f51b0e9751bd42859398
3
+ metadata.gz: 5517c996bd812fed2bb1190f2db0ae0f38ae3eddeab32494fb82dd843c9d9ef3
4
+ data.tar.gz: e293cd323bec3ac3da7300e52d49637a322f6a7a3ac156be4c45bfdc9b4a7440
5
5
  SHA512:
6
- metadata.gz: 0b4919f052f1f9f7bccdbf4116c2d33fded92f508f6c3057bed3a56a8214c7fa20754e281e3f50f04a5807be4c8693740e2952a0441f96447c44d2bc43059c67
7
- data.tar.gz: 1c6b5778d3fe67831b7bd680dd1475f1ca7ddbb1becc24fbbeb1d245e8f6698f2c36d94d5f565564572039a87a94a6f82e9d7ddd50b70475a45c280f43766eca
6
+ metadata.gz: dbb3737b7b031b251d78fadc50e50d32612b5a8a8a183ef204e3abe3b005c5f937850206347ba350f1584145b124bf4ddbdeaf2e6f5c5bbe93a20e979c9883dc
7
+ data.tar.gz: d128dbec0edc3ef77481bf8cb2dd5d70f48189d7c53e1abe19e52480361edcfbbc865f84b2a085cf2b8ab0a27de5ee26c96921f4fba1dca9b688ea9147ac7c65
@@ -4,6 +4,7 @@ module Inspec
4
4
  module Exceptions
5
5
  class InputsFileDoesNotExist < ArgumentError; end
6
6
  class InputsFileNotReadable < ArgumentError; end
7
+ class ProfileLoadFailed < StandardError; end
7
8
  class ResourceFailed < StandardError; end
8
9
  class ResourceSkipped < StandardError; end
9
10
  class SecretsBackendNotFound < ArgumentError; end
@@ -165,7 +165,8 @@ module Inspec
165
165
  raise ArgumentError, "ERROR: An '=' is required when using --input. Usage: --input input_name1=input_value1 input2=value2"
166
166
  end
167
167
  end
168
- input_name, input_value = pair.split("=")
168
+ pair = pair.match(/(.*?)=(.*)/)
169
+ input_name, input_value = pair[1], pair[2]
169
170
  input_value = parse_cli_input_value(input_name, input_value)
170
171
  evt = Inspec::Input::Event.new(
171
172
  value: input_value,
@@ -9,7 +9,12 @@ require "inspec/version"
9
9
  require "inspec/utils/spdx"
10
10
 
11
11
  module Inspec
12
- # Extract metadata.rb information
12
+ # The Metadata class represents a profile's metadata.
13
+ # This includes the metadata stored in the profile's metadata.rb file, as well as inferred
14
+ # metadata like if this profile supports the current runtime and the intended target.
15
+ # This class does NOT represent the runtime state of a profile during execution.
16
+ # See lib/inspec/profile.rb for the runtime representation of a profile.
17
+ #
13
18
  # A Metadata object may be created and finalized with invalid data.
14
19
  # This allows the check CLI command to analyse the issues.
15
20
  # Use valid? to determine if the metadata is coherent.
@@ -94,6 +94,7 @@ module Inspec
94
94
  @input_values = options[:inputs]
95
95
  @tests_collected = false
96
96
  @libraries_loaded = false
97
+ @state = :loaded
97
98
  @check_mode = options[:check_mode] || false
98
99
  @parent_profile = options[:parent_profile]
99
100
  @legacy_profile_path = options[:profiles_path] || false
@@ -146,7 +147,12 @@ module Inspec
146
147
  options[:profile_context] ||
147
148
  Inspec::ProfileContext.for_profile(self, @backend)
148
149
 
149
- @supports_platform = metadata.supports_platform?(@backend)
150
+ if metadata.supports_platform?(@backend)
151
+ @supports_platform = true
152
+ else
153
+ @supports_platform = false
154
+ @state = :skipped
155
+ end
150
156
  @supports_runtime = metadata.supports_runtime?
151
157
  end
152
158
 
@@ -162,6 +168,10 @@ module Inspec
162
168
  @writable
163
169
  end
164
170
 
171
+ def failed?
172
+ @state == :failed
173
+ end
174
+
165
175
  #
166
176
  # Is this profile is supported on the current platform of the
167
177
  # backend machine and the current inspec version.
@@ -197,7 +207,7 @@ module Inspec
197
207
  end
198
208
 
199
209
  def collect_tests(include_list = @controls)
200
- unless @tests_collected
210
+ unless @tests_collected || failed?
201
211
  return unless supports_platform?
202
212
 
203
213
  locked_dependencies.each(&:collect_tests)
@@ -206,7 +216,12 @@ module Inspec
206
216
  next if content.nil? || content.empty?
207
217
 
208
218
  abs_path = source_reader.target.abs_path(path)
209
- @runner_context.load_control_file(content, abs_path, nil)
219
+ begin
220
+ @runner_context.load_control_file(content, abs_path, nil)
221
+ rescue => e
222
+ @state = :failed
223
+ raise Inspec::Exceptions::ProfileLoadFailed, "Failed to load source for #{path}: #{e}"
224
+ end
210
225
  end
211
226
  @tests_collected = true
212
227
  end
@@ -249,12 +264,13 @@ module Inspec
249
264
  d = dep.profile
250
265
  # this will force a dependent profile load so we are only going to add
251
266
  # this metadata if the parent profile is supported.
252
- if supports_platform? && !d.supports_platform?
267
+ if @supports_platform && !d.supports_platform?
253
268
  # since ruby 1.9 hashes are ordered so we can just use index values here
254
269
  # TODO: NO! this is a violation of encapsulation to an extreme
255
270
  metadata.dependencies[i][:status] = "skipped"
256
271
  msg = "Skipping profile: '#{d.name}' on unsupported platform: '#{d.backend.platform.name}/#{d.backend.platform.release}'."
257
- metadata.dependencies[i][:skip_message] = msg
272
+ metadata.dependencies[i][:status_message] = msg
273
+ metadata.dependencies[i][:skip_message] = msg # Repeat as skip_message for backward compatibility
258
274
  next
259
275
  elsif metadata.dependencies[i]
260
276
  # Currently wrapper profiles will load all dependencies, and then we
@@ -324,12 +340,13 @@ module Inspec
324
340
  res[:sha256] = sha256
325
341
  res[:parent_profile] = parent_profile unless parent_profile.nil?
326
342
 
327
- if !supports_platform?
343
+ if @supports_platform
344
+ res[:status_message] = @status_message || ""
345
+ res[:status] = failed? ? "failed" : "loaded"
346
+ else
328
347
  res[:status] = "skipped"
329
348
  msg = "Skipping profile: '#{name}' on unsupported platform: '#{backend.platform.name}/#{backend.platform.release}'."
330
- res[:skip_message] = msg
331
- else
332
- res[:status] = "loaded"
349
+ res[:status_message] = msg
333
350
  end
334
351
 
335
352
  # convert legacy os-* supports to their platform counterpart
@@ -455,6 +472,10 @@ module Inspec
455
472
  params[:controls].values.length
456
473
  end
457
474
 
475
+ def set_status_message(msg)
476
+ @status_message = msg.to_s
477
+ end
478
+
458
479
  # generates a archive of a folder profile
459
480
  # assumes that the profile was checked before
460
481
  def archive(opts)
@@ -72,6 +72,7 @@ module Inspec::Reporters
72
72
  "Profile" => format_profile_name(profile),
73
73
  "Version" => profile[:version] || "(not specified)",
74
74
  }
75
+ header["Failure Message"] = profile[:status_message] if profile[:status] == "failed"
75
76
  header["Target"] = run_data[:platform][:target] unless run_data[:platform][:target].nil?
76
77
  header["Target ID"] = @config["target_id"] unless @config["target_id"].nil?
77
78
 
@@ -45,8 +45,8 @@ module Inspec::Reporters
45
45
  end
46
46
 
47
47
  def profiles
48
- run_data[:profiles].map { |p|
49
- {
48
+ run_data[:profiles].map do |p|
49
+ res = {
50
50
  name: p[:name],
51
51
  version: p[:version],
52
52
  sha256: p[:sha256],
@@ -64,10 +64,15 @@ module Inspec::Reporters
64
64
  groups: profile_groups(p),
65
65
  controls: profile_controls(p),
66
66
  status: p[:status],
67
- skip_message: p[:skip_message],
67
+ status_message: p[:status_message],
68
68
  waiver_data: p[:waiver_data],
69
69
  }.reject { |_k, v| v.nil? }
70
- }
70
+
71
+ # For backwards compatibility
72
+ res[:skip_message] = res[:status_message] if res[:status] == "skipped"
73
+
74
+ res
75
+ end
71
76
  end
72
77
 
73
78
  def profile_groups(profile)
@@ -90,12 +90,14 @@ module Inspec::Resources
90
90
  # deb "http://archive.ubuntu.com/ubuntu/" wily main restricted ...
91
91
  # deb http://archive.ubuntu.com/ubuntu/ wily main restricted ...
92
92
  # deb [trusted=yes] http://archive.ubuntu.com/ubuntu/ wily main restricted ...
93
+ # deb cdrom:[Ubuntu 15.10 _Wily Werewolf_ - Release amd64 (20151021)]/ wily main restricted ...
93
94
 
94
95
  words = line.split
95
96
  words.delete_at 1 if words[1] && words[1].start_with?("[")
96
97
  type, url, distro, *components = words
97
98
  url = url.delete('"') if url
98
99
 
100
+ next if words[1] && words[1].start_with?("cdrom:") # skip unsupported apt-cdrom repos
99
101
  next if components.empty?
100
102
  next unless URI::HTTP === URI.parse(url)
101
103
  next unless %w{deb deb-src}.include? type
@@ -154,7 +154,7 @@ module Inspec::Resources
154
154
  end
155
155
  when "wrlinux"
156
156
  SysV.new(inspec, service_ctl)
157
- when "mac_os_x"
157
+ when "mac_os_x", "darwin"
158
158
  LaunchCtl.new(inspec, service_ctl)
159
159
  when "freebsd"
160
160
  BSDInit.new(inspec, service_ctl)
@@ -47,7 +47,7 @@ module Inspec
47
47
  # core reporters have been migrated to plugins. It is probable that new data elements
48
48
  # and new Hash compatibility behavior will be added during the core reporter plugin
49
49
  # conversion process.
50
- SCHEMA_VERSION = "0.1.0".freeze
50
+ SCHEMA_VERSION = "0.2.0".freeze
51
51
 
52
52
  def self.compatible_schema?(constraints)
53
53
  reqs = Gem::Requirement.create(constraints)
@@ -15,7 +15,7 @@ module Inspec
15
15
  :summary,
16
16
  :supports, # complex local
17
17
  :parent_profile,
18
- :skip_message,
18
+ :status_message,
19
19
  :waiver_data, # Undocumented but used in JSON reporter - should not be?
20
20
  :title,
21
21
  :version
@@ -40,7 +40,7 @@ module Inspec
40
40
  title
41
41
  version
42
42
  parent_profile
43
- skip_message
43
+ status_message
44
44
  waiver_data
45
45
  }.each do |field|
46
46
  self[field] = raw_prof_data[field]
@@ -51,11 +51,11 @@ module Inspec
51
51
  class Profile
52
52
  # Good candidate for keyword_init, but that is not in 2.4
53
53
  Dependency = Struct.new(
54
- :name, :path, :status, :skip_message, :git, :url, :compliance, :supermarket, :branch, :tag, :commit, :version, :relative_path
54
+ :name, :path, :status, :status_message, :git, :url, :compliance, :supermarket, :branch, :tag, :commit, :version, :relative_path
55
55
  ) do
56
56
  include HashLikeStruct
57
57
  def initialize(raw_dep_data)
58
- %i{name path status skip_message git url supermarket compliance branch tag commit version relative_path}.each { |f| self[f] = raw_dep_data[f] }
58
+ %i{name path status status_message git url supermarket compliance branch tag commit version relative_path}.each { |f| self[f] = raw_dep_data[f] }
59
59
  end
60
60
  end
61
61
 
@@ -115,8 +115,14 @@ module Inspec
115
115
  @test_collector.add_profile(requirement.profile)
116
116
  end
117
117
 
118
- tests = profile.collect_tests
119
- all_controls += tests unless tests.nil?
118
+ begin
119
+ tests = profile.collect_tests
120
+ all_controls += tests unless tests.nil?
121
+ rescue Inspec::Exceptions::ProfileLoadFailed => e
122
+ Inspec::Log.error "Failed to load profile #{profile.name}: #{e}"
123
+ profile.set_status_message e.to_s
124
+ next
125
+ end
120
126
  end
121
127
 
122
128
  all_controls.each do |rule|
@@ -90,9 +90,12 @@ module Inspec
90
90
  return @rspec_exit_code if @formatter.results.empty?
91
91
 
92
92
  stats = @formatter.results[:statistics][:controls]
93
+ load_failures = @formatter.results[:profiles]&.select { |p| p[:status] == "failed" }&.any?
93
94
  skipped = @formatter.results.dig(:profiles, 0, :status) == "skipped"
94
- if stats[:failed][:total] == 0 && stats[:skipped][:total] == 0 && !skipped
95
+ if stats[:failed][:total] == 0 && stats[:skipped][:total] == 0 && !skipped && !load_failures
95
96
  0
97
+ elsif load_failures
98
+ @conf["distinct_exit"] ? 102 : 1
96
99
  elsif stats[:failed][:total] > 0
97
100
  @conf["distinct_exit"] ? 100 : 1
98
101
  elsif stats[:skipped][:total] > 0 || skipped
@@ -147,6 +147,8 @@ module Inspec
147
147
  "license" => { "type" => "string", "optional" => true },
148
148
  "summary" => { "type" => "string", "optional" => true },
149
149
  "status" => { "type" => "string", "optional" => false },
150
+ "status_message" => { "type" => "string", "optional" => true },
151
+ # skip_message is deprecated, status_message should be used to store the reason for skipping
150
152
  "skip_message" => { "type" => "string", "optional" => true },
151
153
 
152
154
  "supports" => {
@@ -83,7 +83,7 @@ module Inspec
83
83
  "required" => %w{name sha256 supports attributes groups controls},
84
84
  # Name is mandatory in inspec.yml.
85
85
  # supports, controls, groups, and attributes are always present, even if empty
86
- # sha256, status, skip_message
86
+ # sha256, status, status_message
87
87
  "properties" => {
88
88
  # These are provided in inspec.yml
89
89
  "name" => Primitives::STRING,
@@ -100,10 +100,11 @@ module Inspec
100
100
  "description" => Primitives::STRING,
101
101
  "inspec_version" => Primitives::STRING,
102
102
 
103
- # These are generated at runtime, and all except skip_message are guaranteed
103
+ # These are generated at runtime, and all except status_message and skip_message are guaranteed
104
104
  "sha256" => Primitives::STRING,
105
105
  "status" => Primitives::STRING,
106
- "skip_message" => Primitives::STRING, # If skipped, why
106
+ "status_message" => Primitives::STRING, # If skipped or failed to load, why
107
+ "skip_message" => Primitives::STRING, # Deprecated field storing reason for skipping. status_message should be used instead.
107
108
  "controls" => Primitives.array(CONTROL.ref),
108
109
  "groups" => Primitives.array(Primitives::CONTROL_GROUP.ref),
109
110
  "attributes" => Primitives.array(Primitives::INPUT),
@@ -160,7 +160,7 @@ module Inspec
160
160
  "url" => URL,
161
161
  "branch" => STRING,
162
162
  "path" => STRING,
163
- "skip_message" => STRING,
163
+ "status_message" => STRING,
164
164
  "status" => STRING,
165
165
  "git" => URL,
166
166
  "supermarket" => STRING,
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "4.21.3".freeze
2
+ VERSION = "4.22.0".freeze
3
3
  end
@@ -7,8 +7,11 @@
7
7
  <% if profile.summary %>
8
8
  <tr class="profile-summary"><th>Summary:</th><td><%= profile.summary %></td></tr>
9
9
  <% end %>
10
- <% if profile.skip_message %>
11
- <tr class="profile-skip-message"><th>Skip Message:</th><td><%= profile.skip_message %></td></tr>
10
+ <% if profile.status != "loaded" %>
11
+ <tr class="profile-status"><th>Status:</th><td><%= profile.status %></td></tr>
12
+ <% end %>
13
+ <% if profile.status_message && !profile.status_message.empty? %>
14
+ <tr class="profile-status-message"><th>Status Message:</th><td><%= profile.status_message %></td></tr>
12
15
  <% end %>
13
16
  </table>
14
17
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.21.3
4
+ version: 4.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef InSpec Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-30 00:00:00.000000000 Z
11
+ date: 2020-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry