inspec-core 4.41.2 → 4.41.20

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ccadabfe4c0ecceecb305842e1874255ce4797a8df92e9d1d940bfe52f4b2dbb
4
- data.tar.gz: 8bed2e86c15c05fcd6ee5974e1167aab1f2ab6c2d321a6f802af738594fafe5b
3
+ metadata.gz: 26a893a79810f4d3e7aeb90032bd625636c045c8edc11274dddef456d504d278
4
+ data.tar.gz: 05c34cf8764889bc585a0175cfd7d7c63ef54a4c45c30d182f599de1b3ef8a56
5
5
  SHA512:
6
- metadata.gz: ac9a9e7a80179eaa6f1a77ff4fd4aa4505a39ce389a655bdf853caeece477c58ea7ef46db749cf54a11c2e5dff5e62b09fdd950caac396ffbab4640183549924
7
- data.tar.gz: 613c20973b4b10202fe0d0aac0e53b65cb0cb201150b93665304f0a5f7d4341981768cc799865bb3d7b9ad6b9afa93f782a9651d88001001b899d85b4521e1b6
6
+ metadata.gz: 6d04b25d7423b4fec6be048b8f131bfc28e90266a631829270930b8aa96a520b220c19a0d8fe463689441f67cb8d567d6163df7f56fcc27786ef72f25508dbfc
7
+ data.tar.gz: f798eee0dafda728d169d34ac8a73fef9803f3a70b1b1342d395d3954420644cef3fedcc202c1dc30204bdf1b2098741831af0200b1b3758c03511f38874e9ca
data/Gemfile CHANGED
@@ -30,7 +30,11 @@ end
30
30
  group :test do
31
31
  gem "chefstyle", "~> 2.0.3"
32
32
  gem "concurrent-ruby", "~> 1.0"
33
- gem "html-proofer", platforms: :ruby # do not attempt to run proofer on windows
33
+ if Gem.ruby_version.to_s.start_with?("2.5")
34
+ gem "html-proofer", "= 3.19.1" , platforms: :ruby # do not attempt to run proofer on windows
35
+ else
36
+ gem "html-proofer", platforms: :ruby # do not attempt to run proofer on windows
37
+ end
34
38
  gem "json_schemer", ">= 0.2.1", "< 0.2.19"
35
39
  gem "m"
36
40
  gem "minitest-sprint", "~> 1.0"
@@ -43,11 +43,15 @@ module Inspec
43
43
  begin
44
44
  if (allowed_commands & ARGV.map(&:downcase)).empty? && # Did they use a non-exempt command?
45
45
  !ARGV.empty? # Did they supply at least one command?
46
- LicenseAcceptance::Acceptor.check_and_persist(
46
+ license_acceptor_output = LicenseAcceptance::Acceptor.check_and_persist(
47
47
  Inspec::Dist::EXEC_NAME,
48
48
  Inspec::VERSION,
49
49
  logger: Inspec::Log
50
50
  )
51
+ if license_acceptor_output && ARGV.count == 1 && (ARGV.first.include? "--chef-license")
52
+ Inspec::UI.new.exit
53
+ end
54
+ license_acceptor_output
51
55
  end
52
56
  rescue LicenseAcceptance::LicenseNotAcceptedError
53
57
  Inspec::Log.error "#{Inspec::Dist::PRODUCT_NAME} cannot execute without accepting the license"
@@ -6,9 +6,9 @@ module Inspec
6
6
  extend Forwardable
7
7
 
8
8
  attr_reader :cache, :target, :fetcher
9
- def initialize(target, cache)
9
+ def initialize(target, cache, opts = {})
10
10
  @target = target
11
- @fetcher = Inspec::Fetcher::Registry.resolve(target)
11
+ @fetcher = Inspec::Fetcher::Registry.resolve(target, opts)
12
12
 
13
13
  if @fetcher.nil?
14
14
  raise("Could not fetch inspec profile in #{target.inspect}.")
@@ -53,19 +53,26 @@ module Inspec
53
53
 
54
54
  def control(id, opts = {}, &block)
55
55
  opts[:skip_only_if_eval] = @skip_only_if_eval
56
- tag_ids = control_tags(&block)
57
- if (controls_list_empty? && tags_list_empty?) || control_exist_in_controls_list?(id) || tag_exist_in_control_tags?(tag_ids)
56
+ if (controls_list_empty? && tags_list_empty?) || control_exist_in_controls_list?(id)
58
57
  register_control(Inspec::Rule.new(id, profile_id, resources_dsl, opts, &block))
58
+ elsif !tags_list_empty?
59
+ # Inside elsif rule is initialised before registering it because it enables fetching of control tags
60
+ # This condition is only true when --tags option is used
61
+ inspec_rule = Inspec::Rule.new(id, profile_id, resources_dsl, opts, &block)
62
+ tag_ids = control_tags(inspec_rule)
63
+ register_control(inspec_rule) if tag_exist_in_control_tags?(tag_ids)
59
64
  end
60
65
  end
61
66
 
62
67
  alias rule control
63
68
 
64
- def control_tags(&block)
65
- tag_source = block.source.split("\n").select { |src| src.split.first.eql?("tag") }
66
- tag_source = tag_source.map { |src| src.sub("tag", "").strip }.map { |src| src.split(",").map { |final_src| final_src.sub(/([^:]*):/, "") } }.flatten
67
- output = tag_source.map { |src| src.sub(/\[|\]/, "") }.map { |src| instance_eval(src) }
68
- output.compact.uniq
69
+ def control_tags(inspec_rule)
70
+ all_tags = []
71
+ inspec_rule.tag.each do |key, value|
72
+ all_tags.push(key)
73
+ all_tags.push(value) unless value.nil?
74
+ end
75
+ all_tags.flatten.compact.uniq.map(&:to_s)
69
76
  rescue
70
77
  []
71
78
  end
@@ -44,11 +44,17 @@ module Inspec::Fetcher
44
44
  # - Branch URL
45
45
  # - Commit URL
46
46
  #
47
- # master url:
47
+ # master url(default branch master):
48
48
  # https://github.com/nathenharvey/tmp_compliance_profile/ is transformed to
49
49
  # https://github.com/nathenharvey/tmp_compliance_profile/archive/master.tar.gz
50
50
  # https://bitbucket.org/username/repo is transformed to
51
51
  # https://bitbucket.org/username/repo/get/master.tar.gz
52
+
53
+ # main url(default branch main):
54
+ # https://github.com/nathenharvey/tmp_compliance_profile/ is transformed to
55
+ # https://github.com/nathenharvey/tmp_compliance_profile/archive/main.tar.gz
56
+ # https://bitbucket.org/username/repo is transformed to
57
+ # https://bitbucket.org/username/repo/get/main.tar.gz
52
58
  #
53
59
  # branch:
54
60
  # https://github.com/hardening-io/tests-os-hardening/tree/2.0 is transformed to
@@ -68,14 +74,18 @@ module Inspec::Fetcher
68
74
  BITBUCKET_URL_REGEX = %r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)(\.git)?(/)?$}.freeze
69
75
  BITBUCKET_URL_BRANCH_REGEX = %r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)/branch/(?<branch>[\w\.]+)(/)?$}.freeze
70
76
  BITBUCKET_URL_COMMIT_REGEX = %r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)/commits/(?<commit>[\w\.]+)(/)?$}.freeze
77
+ GITHUB_URL = "https://github.com".freeze
78
+ BITBUCKET_URL = "https://bitbucket.org".freeze
71
79
 
72
80
  def self.transform(target)
73
81
  transformed_target = if m = GITHUB_URL_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
74
- "https://github.com/#{m[:user]}/#{m[:repo]}/archive/master.tar.gz"
82
+ default_branch = default_ref(m, GITHUB_URL)
83
+ "https://github.com/#{m[:user]}/#{m[:repo]}/archive/#{default_branch}.tar.gz"
75
84
  elsif m = GITHUB_URL_WITH_TREE_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
76
85
  "https://github.com/#{m[:user]}/#{m[:repo]}/archive/#{m[:commit]}.tar.gz"
77
86
  elsif m = BITBUCKET_URL_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
78
- "https://bitbucket.org/#{m[:user]}/#{m[:repo]}/get/master.tar.gz"
87
+ default_branch = default_ref(m, BITBUCKET_URL)
88
+ "https://bitbucket.org/#{m[:user]}/#{m[:repo]}/get/#{default_branch}.tar.gz"
79
89
  elsif m = BITBUCKET_URL_BRANCH_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
80
90
  "https://bitbucket.org/#{m[:user]}/#{m[:repo]}/get/#{m[:branch]}.tar.gz"
81
91
  elsif m = BITBUCKET_URL_COMMIT_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
@@ -120,6 +130,38 @@ module Inspec::Fetcher
120
130
 
121
131
  private
122
132
 
133
+ class << self
134
+ def default_ref(match_data, repo_url)
135
+ remote_url = "#{repo_url}/#{match_data[:user]}/#{match_data[:repo]}.git"
136
+ command_string = "git remote show #{remote_url}"
137
+ cmd = shellout(command_string)
138
+ unless cmd.exitstatus == 0
139
+ raise(Inspec::FetcherFailure, "Profile git dependency failed with default reference - #{remote_url} - error running '#{command_string}': #{cmd.stderr}")
140
+ else
141
+ ref = cmd.stdout.lines.detect { |l| l.include? "HEAD branch:" }&.split(":")&.last&.strip
142
+ unless ref
143
+ raise(Inspec::FetcherFailure, "Profile git dependency failed with default reference - #{remote_url} - error running '#{command_string}': NULL reference")
144
+ end
145
+
146
+ ref
147
+ end
148
+ end
149
+
150
+ def shellout(cmd, opts = {})
151
+ Inspec::Log.debug("Running external command: #{cmd} (#{opts})")
152
+ cmd = Mixlib::ShellOut.new(cmd, opts)
153
+ cmd.run_command
154
+ Inspec::Log.debug("External command: completed with exit status: #{cmd.exitstatus}")
155
+ Inspec::Log.debug("External command: STDOUT BEGIN")
156
+ Inspec::Log.debug(cmd.stdout)
157
+ Inspec::Log.debug("External command: STDOUT END")
158
+ Inspec::Log.debug("External command: STDERR BEGIN")
159
+ Inspec::Log.debug(cmd.stderr)
160
+ Inspec::Log.debug("External command: STDERR END")
161
+ cmd
162
+ end
163
+ end
164
+
123
165
  def parse_uri(target)
124
166
  return URI.parse(target) if target.is_a?(String)
125
167
 
@@ -2,12 +2,12 @@ require "inspec/plugin/v1"
2
2
 
3
3
  module Inspec
4
4
  class FetcherRegistry < PluginRegistry
5
- def resolve(target)
5
+ def resolve(target, opts = {})
6
6
  if fetcher_specified?(target)
7
- super(target)
7
+ super(target, opts)
8
8
  else
9
9
  Inspec::Log.debug("Assuming default supermarket source for #{target}")
10
- super(with_default_fetcher(target))
10
+ super(with_default_fetcher(target), opts)
11
11
  end
12
12
  end
13
13
 
@@ -9,9 +9,13 @@ class PluginRegistry
9
9
  #
10
10
  # @param [String] target to resolve
11
11
  # @return [Plugin] plugin instance if it can be resolved, nil otherwise
12
- def resolve(target)
12
+ def resolve(target, opts = {})
13
13
  modules.each do |m|
14
- res = m.resolve(target)
14
+ res = if Inspec::Fetcher::Url == m
15
+ m.resolve(target, opts)
16
+ else
17
+ m.resolve(target)
18
+ end
15
19
  return res unless res.nil?
16
20
  end
17
21
  nil
@@ -18,9 +18,9 @@ module Inspec
18
18
  class Profile
19
19
  extend Forwardable
20
20
 
21
- def self.resolve_target(target, cache)
21
+ def self.resolve_target(target, cache, opts = {})
22
22
  Inspec::Log.debug "Resolve #{target} into cache #{cache.path}"
23
- Inspec::CachedFetcher.new(target, cache)
23
+ Inspec::CachedFetcher.new(target, cache, opts)
24
24
  end
25
25
 
26
26
  # Check if the profile contains a vendored cache, move content into global cache
@@ -70,7 +70,11 @@ module Inspec
70
70
 
71
71
  def self.for_target(target, opts = {})
72
72
  opts[:vendor_cache] ||= Cache.new
73
- fetcher = resolve_target(target, opts[:vendor_cache])
73
+ config = {}
74
+ unless opts[:runner_conf].nil?
75
+ config = opts[:runner_conf].respond_to?(:final_options) ? opts[:runner_conf].final_options : opts[:runner_conf]
76
+ end
77
+ fetcher = resolve_target(target, opts[:vendor_cache], config)
74
78
  for_fetcher(fetcher, opts)
75
79
  end
76
80
 
@@ -82,7 +82,7 @@ module Inspec::Resources
82
82
  end
83
83
  end
84
84
 
85
- @params.merge!(params)
85
+ @params.merge!(params) { |key, current_val, new_val| [*current_val].to_a + [*new_val].to_a }
86
86
 
87
87
  to_read = to_read.drop(1)
88
88
  to_read += include_files(params).find_all do |fp|
@@ -101,12 +101,14 @@ module Inspec::Resources
101
101
  include_files_optional = params["IncludeOptional"] || []
102
102
 
103
103
  includes = []
104
- (include_files + include_files_optional).each do |f|
105
- id = Pathname.new(f).absolute? ? f : File.join(conf_dir, f)
106
- files = find_files(id, depth: 1, type: "file")
107
- files += find_files(id, depth: 1, type: "link")
104
+ unless conf_dir.nil?
105
+ (include_files + include_files_optional).each do |f|
106
+ id = Pathname.new(f).absolute? ? f : File.join(conf_dir, f)
107
+ files = find_files(id, depth: 1, type: "file")
108
+ files += find_files(id, depth: 1, type: "link")
108
109
 
109
- includes.push(files) if files
110
+ includes.push(files) if files
111
+ end
110
112
  end
111
113
 
112
114
  # [].flatten! == nil
@@ -46,8 +46,6 @@ module Inspec::Resources
46
46
  @host = host || "localhost"
47
47
  @port = port || 5432
48
48
  raise Inspec::Exceptions::ResourceFailed, "Can't run PostgreSQL SQL checks without authentication." if @user.nil? || @pass.nil?
49
-
50
- test_connection
51
49
  end
52
50
 
53
51
  def query(query, db = [])
@@ -65,10 +63,6 @@ module Inspec::Resources
65
63
 
66
64
  private
67
65
 
68
- def test_connection
69
- query("select now()\;")
70
- end
71
-
72
66
  def escaped_query(query)
73
67
  Shellwords.escape(query)
74
68
  end
@@ -105,7 +105,7 @@ module Inspec::Resources
105
105
  children_keys(@options[:path], filter)
106
106
  end
107
107
 
108
- # returns nil, if not existant or value
108
+ # returns nil, if not existent or value
109
109
  def method_missing(*keys)
110
110
  # allow the use of array syntax in an `its` block so that users
111
111
  # can use it to query for keys with . characters in them
@@ -57,14 +57,14 @@ module Inspec::Resources
57
57
  @sids = {}
58
58
  case @type
59
59
  when :group
60
- sid_data = wmi_results(:group)
60
+ sid_data = cim_results(:group)
61
61
  when :user
62
- sid_data = wmi_results(:user)
62
+ sid_data = cim_results(:user)
63
63
  when :unspecified
64
64
  # try group first, then user
65
- sid_data = wmi_results(:group)
65
+ sid_data = cim_results(:group)
66
66
  if sid_data.empty?
67
- sid_data = wmi_results(:user)
67
+ sid_data = cim_results(:user)
68
68
  end
69
69
  else
70
70
  raise "Unhandled entity type '#{@type}'"
@@ -72,20 +72,14 @@ module Inspec::Resources
72
72
  sid_data.each { |sid| @sids[sid[1]] = sid[2] }
73
73
  end
74
74
 
75
- def wmi_results(type)
76
- query = "wmic "
75
+ def cim_results(type)
77
76
  case type
78
77
  when :group
79
- query += "group"
78
+ cmd = "Get-CimInstance -ClassName Win32_Account | Select-Object -Property Domain, Name, SID | Where-Object { $_.Name -eq '#{@name}' -and { $_.SIDType -eq 4 -or $_.SIDType -eq 5 } } | ConvertTo-Csv -NoTypeInformation"
80
79
  when :user
81
- query += "useraccount"
80
+ cmd = "Get-CimInstance -ClassName Win32_Account | Select-Object -Property Domain, Name, SID, SIDType | Where-Object { $_.Name -eq '#{@name}' -and $_.SIDType -eq 1 } | ConvertTo-Csv -NoTypeInformation"
82
81
  end
83
- query += " where 'Name=\"#{@name}\"' get Name\",\"SID /format:csv"
84
- # Example output:
85
- # inspec> command("wmic useraccount where 'Name=\"Administrator\"' get Name\",\"SID /format:csv").stdout
86
- # => "\r\n\r\nNode,Name,SID\r\n\r\nComputer1,Administrator,S-1-5-21-650485088-1194226989-968533923-500\r\n\r\n"
87
- # Remove the \r characters, split on \n\n, ignore the CSV header row
88
- inspec.command(query).stdout.strip.tr("\r", "").split("\n\n")[1..-1].map { |entry| entry.split(",") }
82
+ inspec.command(cmd).stdout.strip.gsub("\"", "").tr("\r", "").split("\n")[1..-1].map { |entry| entry.split(",") }
89
83
  end
90
84
  end
91
85
  end
@@ -147,7 +147,7 @@ module Inspec::Resources
147
147
 
148
148
  # extracts the values, this methods detects:
149
149
  # numbers and SIDs and optimizes them for further usage
150
- def extract_value(val)
150
+ def extract_value(key, val)
151
151
  if val =~ /^\d+$/
152
152
  val.to_i
153
153
  # special handling for SID array
@@ -166,14 +166,15 @@ module Inspec::Resources
166
166
  elsif !(m = /^\"(.*)\"$/.match(val)).nil?
167
167
  m[1]
168
168
  else
169
- val
169
+ # When there is Registry Values we are not spliting the value for backward compatibility
170
+ key.include?("\\") ? val : val.split(",")
170
171
  end
171
172
  end
172
173
 
173
174
  def convert_hash(hash)
174
175
  new_hash = {}
175
176
  hash.each do |k, v|
176
- v.is_a?(Hash) ? value = convert_hash(v) : value = extract_value(v)
177
+ v.is_a?(Hash) ? value = convert_hash(v) : value = extract_value(k, v)
177
178
  new_hash[k.strip] = value
178
179
  end
179
180
  new_hash
@@ -152,6 +152,12 @@ module Inspec::Resources
152
152
  else
153
153
  SysV.new(inspec, service_ctl || "/sbin/service")
154
154
  end
155
+ when "alibaba"
156
+ if os[:release].to_i >= 3
157
+ Systemd.new(inspec, service_ctl)
158
+ else
159
+ SysV.new(inspec, service_ctl || "/sbin/service")
160
+ end
155
161
  when "wrlinux"
156
162
  SysV.new(inspec, service_ctl)
157
163
  when "mac_os_x", "darwin"
@@ -36,7 +36,7 @@ module Inspec::Resources
36
36
  end
37
37
  end
38
38
 
39
- # returns nil, if not existant or value
39
+ # returns nil, if not existent or value
40
40
  def method_missing(*keys)
41
41
  # catch behavior of rspec its implementation
42
42
  # @see https://github.com/rspec/rspec-its/blob/v1.2.0/lib/rspec/its.rb#L110
@@ -256,7 +256,7 @@ module FilterTable
256
256
  end
257
257
 
258
258
  def matches(x, y)
259
- x === y # rubocop:disable Style/CaseEquality
259
+ y === x # rubocop:disable Style/CaseEquality
260
260
  end
261
261
 
262
262
  def filter_raw_data(current_raw_data, field, desired_value)
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "4.41.2".freeze
2
+ VERSION = "4.41.20".freeze
3
3
  end
@@ -16,6 +16,6 @@ inputs:
16
16
  description: 'Optional Custom AWS VPC Id'
17
17
  depends:
18
18
  - name: inspec-aws
19
- url: https://github.com/inspec/inspec-aws/archive/master.tar.gz
19
+ url: https://github.com/inspec/inspec-aws/archive/main.tar.gz
20
20
  supports:
21
21
  - platform: aws
@@ -9,6 +9,6 @@ version: 0.1.0
9
9
  inspec_version: '>= 2.2.7'
10
10
  depends:
11
11
  - name: inspec-azure
12
- url: https://github.com/inspec/inspec-azure/archive/master.tar.gz
12
+ url: https://github.com/inspec/inspec-azure/archive/main.tar.gz
13
13
  supports:
14
14
  - platform: azure
@@ -13,6 +13,6 @@ inputs:
13
13
  description: 'The GCP project identifier.'
14
14
  depends:
15
15
  - name: inspec-gcp
16
- url: https://github.com/inspec/inspec-gcp/archive/master.tar.gz
16
+ url: https://github.com/inspec/inspec-gcp/archive/main.tar.gz
17
17
  supports:
18
18
  - platform: gcp
@@ -232,10 +232,10 @@ module InspecPlugins
232
232
 
233
233
  # Already installed?
234
234
  if registry.known_plugin?(plugin_name.to_sym)
235
- ui.red("Plugin already installed - #{plugin_name} - Use '#{EXEC_NAME} " \
236
- "plugin list' to see previously installed plugin - " \
237
- "installation failed.\n")
238
- ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
235
+ ui.bold("Plugin already installed - #{plugin_name} - Use '#{EXEC_NAME} " \
236
+ "plugin list' to see previously installed plugin - " \
237
+ "installation failed.\n")
238
+ ui.exit Inspec::UI::EXIT_NORMAL
239
239
  end
240
240
 
241
241
  # Can we figure out how to load it?
@@ -391,19 +391,20 @@ module InspecPlugins
391
391
  they_explicitly_asked_for_a_version = !options[:version].nil?
392
392
  what_we_would_install_is_already_installed = pre_installed_versions.include?(requested_version)
393
393
  if what_we_would_install_is_already_installed && they_explicitly_asked_for_a_version
394
- ui.red("Plugin already installed at requested version - plugin " \
394
+ ui.bold("Plugin already installed at requested version - plugin " \
395
395
  "#{plugin_name} #{requested_version} - refusing to install.\n")
396
+ ui.exit Inspec::UI::EXIT_NORMAL
396
397
  elsif what_we_would_install_is_already_installed && !they_explicitly_asked_for_a_version
397
398
  ui.red("Plugin already installed at latest version - plugin " \
398
399
  "#{plugin_name} #{requested_version} - refusing to install.\n")
399
- else
400
- # There are existing versions installed, but none of them are what was requested
401
- ui.red("Update required - plugin #{plugin_name}, requested " \
402
- "#{requested_version}, have " \
403
- "#{pre_installed_versions.join(", ")}; use `inspec " \
404
- "plugin update` - refusing to install.\n")
400
+ ui.exit Inspec::UI::EXIT_NORMAL
405
401
  end
406
402
 
403
+ # There are existing versions installed, but none of them are what was requested
404
+ ui.red("Update required - plugin #{plugin_name}, requested " \
405
+ "#{requested_version}, have " \
406
+ "#{pre_installed_versions.join(", ")}; use `inspec " \
407
+ "plugin update` - refusing to install.\n")
407
408
  ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
408
409
  end
409
410
 
@@ -433,7 +434,7 @@ module InspecPlugins
433
434
  "version #{options[:version]} found on #{source_host} - " \
434
435
  "installation failed.\n")
435
436
  else
436
- ui.red("Unknown error occured - installation failed.\n")
437
+ ui.red("Unknown error occurred - installation failed.\n")
437
438
  end
438
439
  ui.exit Inspec::UI::EXIT_USAGE_ERROR
439
440
  end
@@ -457,15 +458,15 @@ module InspecPlugins
457
458
  end
458
459
  end
459
460
 
460
- # Check for latest version (and implicitly, existance)
461
+ # Check for latest version (and implicitly, existence)
461
462
  latest_version = installer.search(plugin_name, exact: true, scope: :latest)
462
463
  latest_version = latest_version[plugin_name]&.last
463
464
 
464
465
  if pre_update_versions.include?(latest_version)
465
- ui.plain_line("#{ui.red("Already installed at latest version:", print: false)} " \
466
+ ui.plain_line("#{ui.bold("Already installed at latest version:", print: false)} " \
466
467
  "#{plugin_name} is at #{latest_version}, which the " \
467
468
  "latest - refusing to update")
468
- ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
469
+ ui.exit Inspec::UI::EXIT_NORMAL
469
470
  end
470
471
  end
471
472
 
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.41.2
4
+ version: 4.41.20
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: 2021-08-13 00:00:00.000000000 Z
11
+ date: 2021-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry