inspec-core 5.22.3 → 5.22.36

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: 257ccbe0a55a1779ee75f8d6e9e8e0ff612990c123e5cdb10d8cf1e19dbade54
4
- data.tar.gz: 820f9a0ec86451f48f65f229befe175cf937648ddb5669df1c8a7c27ebfb234b
3
+ metadata.gz: bbe23835cae58303aa3ac665ecd59e269752bbe4f6448e33db3219df0f04dbc8
4
+ data.tar.gz: 9a6d1e0e7758054f4d2746355a0c5538ede8af58a4220b3160d999f5e3093f34
5
5
  SHA512:
6
- metadata.gz: 8150cdd9aca6ac14ae762dd4b6d09867dab6651f0a0705a28f7256a94683a1fd59b7841bfc69e1a362c253d6c2a847d2e9a03b901dd20118ecc1566b4496a8a9
7
- data.tar.gz: a3469cb7fa6786e1d9416e9493fed402ccfb6c8e6ac0a2d40a0029ab63c09b09671cf6729736899ed1a039ca75e36a6a57428deba9a8c5d6dbf0975711a06d13
6
+ metadata.gz: c074f69651db5a586e4fee3b1a621ef9cc43d05634136dae9e0008a22c2d74d0515fe2938f83df42aace4ad089bbab3e95cf3d70bf3825b88aaca5e8e0696518
7
+ data.tar.gz: f01196343c6f7109cb44ced5f3a23a2b3f7b543f88a48d34d0b49c2b2a47dae31c599af4f51febca1afecbc1355f471c543c2ac8484c5c1a669ea4fec41cfe45
data/Gemfile CHANGED
@@ -11,6 +11,10 @@ gem "inspec-bin", path: "./inspec-bin"
11
11
 
12
12
  gem "ffi", ">= 1.9.14", "!= 1.13.0", "!= 1.14.2"
13
13
 
14
+ # We have a build issue 2023-11-13 with unf_ext 0.0.9 so we are pinning to 0.0.8.2
15
+ # See https://github.com/knu/ruby-unf_ext/issues/74 https://buildkite.com/chef/inspec-inspec-inspec-5-omnibus-release/builds/22
16
+ gem "unf_ext", "= 0.0.8.2"
17
+
14
18
  # inspec tests depend text output that changed in the 3.10 release
15
19
  # but our runtime dep is still 3.9+
16
20
  gem "rspec", ">= 3.10"
@@ -25,11 +29,11 @@ end
25
29
  group :test do
26
30
  gem "chefstyle", "~> 2.2.2"
27
31
  gem "concurrent-ruby", "~> 1.0"
28
- gem "json_schemer", ">= 0.2.1", "< 0.2.19"
32
+ gem "json_schemer", ">= 0.2.1", "< 2.0.1"
29
33
  gem "m"
30
34
  gem "minitest-sprint", "~> 1.0"
31
35
  gem "minitest", "5.15.0"
32
- gem "mocha", "~> 1.1"
36
+ gem "mocha", "~> 2.1"
33
37
  gem "nokogiri", "~> 1.9"
34
38
  gem "pry-byebug"
35
39
  gem "pry", "~> 0.10"
@@ -47,20 +51,3 @@ end
47
51
  group :deploy do
48
52
  gem "inquirer"
49
53
  end
50
-
51
- group :kitchen do
52
- gem "berkshelf"
53
-
54
- # Chef 18 requires ruby 3
55
- if Gem.ruby_version >= Gem::Version.new("3.0.0")
56
- gem "chef", ">= 17.0"
57
- else
58
- # Ruby 2.7 presumably - TODO remove this when 2.7 is sunsetted
59
- gem "chef", "~> 16.0"
60
- end
61
-
62
- gem "test-kitchen", ">= 2.8"
63
- gem "kitchen-inspec", ">= 2.0"
64
- gem "kitchen-dokken", ">= 2.11"
65
- gem "git"
66
- end
data/inspec-core.gemspec CHANGED
@@ -25,13 +25,15 @@ Gem::Specification.new do |spec|
25
25
  # Implementation dependencies
26
26
  spec.add_dependency "chef-telemetry", "~> 1.0", ">= 1.0.8" # 1.0.8+ removes the http dep
27
27
  spec.add_dependency "license-acceptance", ">= 0.2.13", "< 3.0"
28
- spec.add_dependency "thor", ">= 0.20", "< 2.0"
28
+ # TODO: We should remove the thor pinning in next upcoming releases currently it's breaking our unit test in cli_args_test for aliases due to
29
+ # recent changes made in thor library REF: https://github.com/rails/thor/releases/tag/v1.3.0 & https://github.com/rails/thor/pull/800
30
+ spec.add_dependency "thor", ">= 0.20", "< 1.3.0"
29
31
  spec.add_dependency "method_source", ">= 0.8", "< 2.0"
30
32
  spec.add_dependency "rubyzip", ">= 1.2.2", "< 3.0"
31
- spec.add_dependency "rspec", ">= 3.9", "<= 3.11"
33
+ spec.add_dependency "rspec", ">= 3.9", "<= 3.12"
32
34
  spec.add_dependency "rspec-its", "~> 1.2"
33
35
  spec.add_dependency "pry", "~> 0.13"
34
- spec.add_dependency "hashie", ">= 3.4", "< 5.0"
36
+ spec.add_dependency "hashie", ">= 3.4", "< 6.0"
35
37
  spec.add_dependency "mixlib-log", "~> 3.0"
36
38
  spec.add_dependency "sslshake", "~> 1.2"
37
39
  spec.add_dependency "parallel", "~> 1.9"
@@ -41,7 +43,7 @@ Gem::Specification.new do |spec|
41
43
  spec.add_dependency "tty-prompt", "~> 0.17"
42
44
  spec.add_dependency "tomlrb", ">= 1.2", "< 2.1"
43
45
  spec.add_dependency "addressable", "~> 2.4"
44
- spec.add_dependency "parslet", ">= 1.5", "< 2.0" # Pinned < 2.0, see #5389
46
+ spec.add_dependency "parslet", ">= 1.5", "< 3.0" # Pinned < 2.0, see #5389
45
47
  spec.add_dependency "semverse", "~> 3.0"
46
48
  spec.add_dependency "multipart-post", "~> 2.0"
47
49
 
data/lib/inspec/cli.rb CHANGED
@@ -68,8 +68,14 @@ class Inspec::InspecCLI < Inspec::BaseCLI
68
68
  desc: "A list of controls to include. Ignore all other tests."
69
69
  option :tags, type: :array,
70
70
  desc: "A list of tags to filter controls and include only those. Ignore all other tests."
71
+ option :legacy_export, type: :boolean, default: false,
72
+ desc: "Run with legacy export."
71
73
  profile_options
72
74
  def json(target)
75
+ # Config initialisation is needed before deprecation warning can be issued
76
+ # Deprecator calls config get method to fetch the config value
77
+ # Without config initialisation, the config value is not set and hence calling config get through deprecator will set the value of config as blank, making options of json command inaccessible.
78
+ config
73
79
  # This deprecation warning is ignored currently.
74
80
  Inspec.deprecate(:renamed_to_inspec_export)
75
81
  export(target, true)
@@ -86,6 +92,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI
86
92
  desc: "For --what=profile, a list of controls to include. Ignore all other tests."
87
93
  option :tags, type: :array,
88
94
  desc: "For --what=profile, a list of tags to filter controls and include only those. Ignore all other tests."
95
+ option :legacy_export, type: :boolean, default: false,
96
+ desc: "Run with legacy export."
89
97
  profile_options
90
98
  def export(target, as_json = false)
91
99
  o = config
@@ -121,16 +129,17 @@ class Inspec::InspecCLI < Inspec::BaseCLI
121
129
 
122
130
  case what
123
131
  when "profile"
132
+ profile_info = o[:legacy_export] ? profile.info : profile.info_from_parse
124
133
  if format == "json"
125
134
  require "json" unless defined?(JSON)
126
135
  # Write JSON
127
136
  Inspec::Utils::JsonProfileSummary.produce_json(
128
- info: profile.info,
137
+ info: profile_info,
129
138
  write_path: dst
130
139
  )
131
140
  elsif format == "yaml"
132
141
  Inspec::Utils::YamlProfileSummary.produce_yaml(
133
- info: profile.info,
142
+ info: profile_info,
134
143
  write_path: dst
135
144
  )
136
145
  end
@@ -152,6 +161,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI
152
161
  desc: "The output format to use. Valid values: `json` and `doc`. Default value: `doc`."
153
162
  option :with_cookstyle, type: :boolean,
154
163
  desc: "Enable or disable cookstyle checks.", default: false
164
+ option :legacy_check, type: :boolean, default: false,
165
+ desc: "Run with legacy check."
155
166
  profile_options
156
167
  def check(path) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
157
168
  o = config
@@ -166,7 +177,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
166
177
 
167
178
  # run check
168
179
  profile = Inspec::Profile.for_target(path, o)
169
- result = profile.check
180
+ result = o[:legacy_check] ? profile.legacy_check : profile.check
170
181
 
171
182
  if o["format"] == "json"
172
183
  puts JSON.generate(result)
@@ -244,6 +255,12 @@ class Inspec::InspecCLI < Inspec::BaseCLI
244
255
  desc: "Fallback to using local archives if fetching fails."
245
256
  option :ignore_errors, type: :boolean, default: false,
246
257
  desc: "Ignore profile warnings."
258
+ option :check, type: :boolean, default: false,
259
+ desc: "Run profile check before archiving."
260
+ option :export, type: :boolean, default: false,
261
+ desc: "Export the profile to inspec.json and include in archive"
262
+ option :legacy_export, type: :boolean, default: false,
263
+ desc: "Export the profile in legacy mode to inspec.json and include in archive"
247
264
  def archive(path, log_level = nil)
248
265
  o = config
249
266
  diagnose(o)
@@ -264,7 +281,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
264
281
  o[:logger].warn "Archiving a profile that contains gem dependencies, but InSpec cannot package gems with the profile! Please archive your ~/.inspec/gems directory separately."
265
282
  end
266
283
 
267
- result = profile.check
284
+ result = profile.check if o[:check]
268
285
 
269
286
  if result && !o[:ignore_errors] == false
270
287
  o[:logger].info "Profile check failed. Please fix the profile before generating an archive."
@@ -514,7 +531,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
514
531
  end
515
532
 
516
533
  def run_command(opts)
517
- runner = Inspec::Runner.new(Inspec::Config.new(opts))
534
+ runner = Inspec::Runner.new(opts)
518
535
  res = runner.eval_with_virtual_profile(opts[:command])
519
536
  runner.load
520
537
 
data/lib/inspec/config.rb CHANGED
@@ -448,6 +448,22 @@ module Inspec
448
448
  # Reporter options may be defined top-level.
449
449
  options.merge!(config_file_reporter_options)
450
450
 
451
+ # when sent reporter from compliance-mode (via chef-client), the reporter is a symbol
452
+ if @cli_opts.key?(:reporter) && @cli_opts["reporter"].nil?
453
+ @cli_opts["reporter"] = @cli_opts[:reporter]
454
+ @cli_opts.delete(:reporter)
455
+ elsif @cli_opts.key?(:reporter) && @cli_opts.key?("reporter") && @cli_opts["reporter"].is_a?(Array)
456
+ # combine reporter and "reporter" options into "reporter" option
457
+ @cli_opts["reporter"] = @cli_opts[:reporter] + @cli_opts["reporter"]
458
+ end
459
+
460
+ if @cli_opts["reporter"]
461
+ # Add reporter_cli_opts in options to capture reporter cli opts separately
462
+ options.merge!({ "reporter_cli_opts" => @cli_opts["reporter"] })
463
+ # Delete reporter from cli_opts to avoid direct merging of reporter info of cli and config
464
+ @cli_opts.delete("reporter")
465
+ end
466
+
451
467
  # Highest precedence: merge in any options defined via the CLI
452
468
  options.merge!(@cli_opts)
453
469
 
@@ -476,13 +492,13 @@ module Inspec
476
492
  end
477
493
 
478
494
  def finalize_parse_reporters(options) # rubocop:disable Metrics/AbcSize
479
- # default to cli report for ad-hoc runners
480
- options["reporter"] = ["cli"] if options["reporter"].nil?
495
+ # Default to cli report for ad-hoc runners
496
+ options["reporter_cli_opts"] = ["cli"] if (options["reporter"].nil? || options["reporter"].empty?) && options["reporter_cli_opts"].nil?
481
497
 
482
- # parse out cli to proper report format
483
- if options["reporter"].is_a?(Array)
498
+ # Parse out reporter_cli_opts to proper report format
499
+ if options["reporter_cli_opts"].is_a?(Array)
484
500
  reports = {}
485
- options["reporter"].each do |report|
501
+ options["reporter_cli_opts"].each do |report|
486
502
  reporter_name, destination = report.split(":", 2)
487
503
  if destination.nil? || destination.strip == "-"
488
504
  reports[reporter_name] = { "stdout" => true }
@@ -494,7 +510,12 @@ module Inspec
494
510
  reports[reporter_name]["target_id"] = options["target_id"] if options["target_id"]
495
511
  end
496
512
  end
497
- options["reporter"] = reports
513
+
514
+ if options["reporter"].nil? || options["reporter"].empty?
515
+ options["reporter"] = reports
516
+ else
517
+ options["reporter"].merge!(reports)
518
+ end
498
519
  end
499
520
 
500
521
  # add in stdout if not specified
@@ -507,6 +528,10 @@ module Inspec
507
528
  end
508
529
 
509
530
  validate_reporters!(options["reporter"])
531
+
532
+ # Delete reporter_cli_opts after graceful merging of cli and config reporters
533
+ options.delete("reporter_cli_opts")
534
+
510
535
  options
511
536
  end
512
537
 
@@ -548,15 +573,12 @@ module Inspec
548
573
  class Defaults
549
574
  DEFAULTS = {
550
575
  exec: {
551
- "reporter" => ["cli"],
552
576
  "show_progress" => false,
553
577
  "color" => true,
554
578
  "create_lockfile" => true,
555
579
  "backend_cache" => true,
556
580
  },
557
- shell: {
558
- "reporter" => ["cli"],
559
- },
581
+ shell: {},
560
582
  }.freeze
561
583
 
562
584
  def self.for_command(command_name)
@@ -41,6 +41,7 @@ module Inspec::Fetcher
41
41
  @ref = opts[:ref]
42
42
  @remote_url = expand_local_path(remote_url)
43
43
  @repo_directory = nil
44
+ @resolved_ref = nil
44
45
  @relative_path = opts[:relative_path] if opts[:relative_path] && !opts[:relative_path].empty?
45
46
  end
46
47
 
@@ -70,7 +71,7 @@ module Inspec::Fetcher
70
71
  if @relative_path
71
72
  perform_relative_path_fetch(destination_path, working_dir)
72
73
  else
73
- Inspec::Log.debug("Checkout of #{resolved_ref} successful. " \
74
+ Inspec::Log.debug("Checkout of #{resolved_ref.nil? ? @remote_url : resolved_ref} successful. " \
74
75
  "Moving checkout to #{destination_path}")
75
76
  FileUtils.cp_r(working_dir + "/.", destination_path)
76
77
  end
@@ -80,14 +81,14 @@ module Inspec::Fetcher
80
81
  end
81
82
 
82
83
  def perform_relative_path_fetch(destination_path, working_dir)
83
- Inspec::Log.debug("Checkout of #{resolved_ref} successful. " \
84
+ Inspec::Log.debug("Checkout of #{resolved_ref.nil? ? @remote_url : resolved_ref} successful. " \
84
85
  "Moving #{@relative_path} to #{destination_path}")
85
86
  unless File.exist?("#{working_dir}/#{@relative_path}")
86
87
  # Cleanup the destination path - otherwise we'll have an empty dir
87
88
  # in the cache, which is enough to confuse the cache reader
88
89
  # This is a courtesy, assuming we're writing to the cache; if we're
89
90
  # vendoring to something more complex, don't bother.
90
- FileUtils.rmdir(destination_path) if Dir.empty?(destination_path)
91
+ FileUtils.rm_r(destination_path) if Dir.exist?(destination_path)
91
92
 
92
93
  raise Inspec::FetcherFailure, "Cannot find relative path '#{@relative_path}' " \
93
94
  "within profile in git repo specified by '#{@remote_url}'"
@@ -96,9 +97,16 @@ module Inspec::Fetcher
96
97
  end
97
98
 
98
99
  def cache_key
99
- return resolved_ref unless @relative_path
100
-
101
- OpenSSL::Digest.hexdigest("SHA256", resolved_ref + @relative_path)
100
+ cache_key = if @relative_path && !resolved_ref.nil?
101
+ OpenSSL::Digest.hexdigest("SHA256", resolved_ref + @relative_path)
102
+ elsif @relative_path && resolved_ref.nil?
103
+ OpenSSL::Digest.hexdigest("SHA256", @remote_url + @relative_path)
104
+ elsif resolved_ref.nil?
105
+ OpenSSL::Digest.hexdigest("SHA256", @remote_url)
106
+ else
107
+ resolved_ref
108
+ end
109
+ cache_key
102
110
  end
103
111
 
104
112
  def archive_path
@@ -106,7 +114,11 @@ module Inspec::Fetcher
106
114
  end
107
115
 
108
116
  def resolved_source
109
- source = { git: @remote_url, ref: resolved_ref }
117
+ if resolved_ref.nil?
118
+ source = { git: @remote_url }
119
+ else
120
+ source = { git: @remote_url, ref: resolved_ref }
121
+ end
110
122
  source[:relative_path] = @relative_path if @relative_path
111
123
  source
112
124
  end
@@ -125,33 +137,27 @@ module Inspec::Fetcher
125
137
  elsif @tag
126
138
  resolve_ref(@tag)
127
139
  else
128
- resolve_ref(default_ref)
140
+ resolve_ref
129
141
  end
130
142
  end
131
143
 
132
- def default_ref
133
- command_string = "git remote show #{@remote_url}"
144
+ def resolve_ref(ref_name = nil)
145
+ command_string = if ref_name.nil?
146
+ # Running git ls-remote command helps to raise error if git URL is invalid and avoids cache_key creation
147
+ "git ls-remote \"#{@remote_url}\""
148
+ else
149
+ "git ls-remote \"#{@remote_url}\" \"#{ref_name}*\""
150
+ end
134
151
  cmd = shellout(command_string)
135
- unless cmd.exitstatus == 0
136
- raise(Inspec::FetcherFailure, "Profile git dependency failed with default reference - #{@remote_url} - error running '#{command_string}': #{cmd.stderr}")
152
+ raise(Inspec::FetcherFailure, "Profile git dependency failed for #{@remote_url} - error running '#{command_string}': #{cmd.stderr}") unless cmd.exitstatus == 0
153
+
154
+ if ref_name.nil?
155
+ ref = nil
137
156
  else
138
- ref = cmd.stdout.lines.detect { |l| l.include? "HEAD branch:" }&.split(":")&.last&.strip
157
+ ref = parse_ls_remote(cmd.stdout, ref_name)
139
158
  unless ref
140
- raise(Inspec::FetcherFailure, "Profile git dependency failed with default reference - #{@remote_url} - error running '#{command_string}': NULL reference")
159
+ raise Inspec::FetcherFailure, "Profile git dependency failed - unable to resolve #{ref_name} to a specific git commit for #{@remote_url}"
141
160
  end
142
-
143
- ref
144
- end
145
- end
146
-
147
- def resolve_ref(ref_name)
148
- command_string = "git ls-remote \"#{@remote_url}\" \"#{ref_name}*\""
149
- cmd = shellout(command_string)
150
- raise(Inspec::FetcherFailure, "Profile git dependency failed for #{@remote_url} - error running '#{command_string}': #{cmd.stderr}") unless cmd.exitstatus == 0
151
-
152
- ref = parse_ls_remote(cmd.stdout, ref_name)
153
- unless ref
154
- raise Inspec::FetcherFailure, "Profile git dependency failed - unable to resolve #{ref_name} to a specific git commit for #{@remote_url}"
155
161
  end
156
162
 
157
163
  ref
@@ -200,7 +206,14 @@ module Inspec::Fetcher
200
206
 
201
207
  def checkout(dir = @repo_directory)
202
208
  clone(dir)
203
- git_cmd("checkout #{resolved_ref}", dir)
209
+ # In case of branch, tag or git reference is not provided by User the resolved_ref will always be nil
210
+ # and will always checkout the default HEAD branch, else it will checkout specific branch, tag or git reference.
211
+ if resolved_ref.nil?
212
+ git_cmd("checkout", dir)
213
+ else
214
+ git_cmd("checkout #{resolved_ref}", dir)
215
+ end
216
+
204
217
  @repo_directory
205
218
  end
206
219
 
@@ -208,6 +221,8 @@ module Inspec::Fetcher
208
221
  cmd = shellout("git #{cmd}", cwd: dir)
209
222
  cmd.error!
210
223
  cmd.status
224
+ rescue Mixlib::ShellOut::ShellCommandFailed => e
225
+ raise Inspec::FetcherFailure, "Error while running git command. #{e.message} "
211
226
  rescue Errno::ENOENT
212
227
  raise Inspec::FetcherFailure, "Profile git dependency failed for #{@remote_url} - to use git sources, you must have git installed."
213
228
  end
@@ -160,7 +160,7 @@ module Inspec::Formatters
160
160
  end
161
161
 
162
162
  # added this additionally because stats summary is also used for determining exit code in runner rspec
163
- skipped += 1 if control[:results].any? { |r| r[:status] == "skipped" }
163
+ skipped += 1 if control[:results] && (control[:results].any? { |r| r[:status] == "skipped" })
164
164
 
165
165
  end
166
166
  total = error + not_applicable + not_reviewed + failed + passed