inspec-core 4.41.2 → 4.41.20

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: 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