inspec-core 6.8.24 → 7.0.95
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 +4 -4
- data/Gemfile +8 -8
- data/etc/deprecations.json +42 -4
- data/inspec-core.gemspec +14 -7
- data/lib/inspec/archive/tar.rb +1 -0
- data/lib/inspec/backend.rb +2 -0
- data/lib/inspec/base_cli.rb +15 -2
- data/lib/inspec/cached_fetcher.rb +17 -1
- data/lib/inspec/cli.rb +2 -0
- data/lib/inspec/dependencies/cache.rb +47 -7
- data/lib/inspec/dsl.rb +44 -10
- data/lib/inspec/exceptions.rb +1 -0
- data/lib/inspec/fetcher/gem.rb +117 -0
- data/lib/inspec/fetcher/git.rb +21 -1
- data/lib/inspec/fetcher/local.rb +1 -1
- data/lib/inspec/fetcher.rb +1 -0
- data/lib/inspec/file_provider.rb +47 -1
- data/lib/inspec/metadata.rb +2 -0
- data/lib/inspec/plugin/v2/concerns/gem_spec_helper.rb +30 -0
- data/lib/inspec/plugin/v2/gem_source_manager.rb +50 -0
- data/lib/inspec/plugin/v2/installer.rb +65 -18
- data/lib/inspec/plugin/v2/loader.rb +37 -6
- data/lib/inspec/plugin/v2/plugin_types/resource_pack.rb +8 -0
- data/lib/inspec/plugin/v2.rb +1 -0
- data/lib/inspec/profile.rb +22 -3
- data/lib/inspec/profile_context.rb +10 -0
- data/lib/inspec/resources/audit_policy.rb +8 -2
- data/lib/inspec/resources/groups.rb +52 -0
- data/lib/inspec/resources.rb +0 -14
- data/lib/inspec/rule.rb +2 -0
- data/lib/inspec/runner.rb +7 -1
- data/lib/inspec/source_reader.rb +2 -0
- data/lib/inspec/ui.rb +1 -0
- data/lib/inspec/utils/deprecated_core_resources_list.rb +2 -2
- data/lib/inspec/utils/deprecation/config_file.rb +39 -3
- data/lib/inspec/utils/deprecation/deprecator.rb +10 -3
- data/lib/inspec/utils/simpleconfig.rb +2 -0
- data/lib/inspec/utils/telemetry/run_context_probe.rb +5 -2
- data/lib/inspec/version.rb +1 -1
- data/lib/inspec/waiver_file_reader.rb +35 -18
- data/lib/inspec.rb +2 -0
- data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +1 -1
- data/lib/plugins/shared/core_plugin_test_helper.rb +1 -1
- data/lib/source_readers/gem.rb +67 -0
- metadata +82 -43
- data/lib/inspec/resources/docker.rb +0 -274
- data/lib/inspec/resources/docker_container.rb +0 -116
- data/lib/inspec/resources/docker_image.rb +0 -141
- data/lib/inspec/resources/docker_object.rb +0 -52
- data/lib/inspec/resources/docker_plugin.rb +0 -68
- data/lib/inspec/resources/docker_service.rb +0 -95
- data/lib/inspec/resources/elasticsearch.rb +0 -165
- data/lib/inspec/resources/ibmdb2_conf.rb +0 -65
- data/lib/inspec/resources/ibmdb2_session.rb +0 -78
- data/lib/inspec/resources/mongodb.rb +0 -69
- data/lib/inspec/resources/mongodb_conf.rb +0 -44
- data/lib/inspec/resources/mongodb_session.rb +0 -98
- data/lib/inspec/resources/opa.rb +0 -26
- data/lib/inspec/resources/opa_api.rb +0 -49
- data/lib/inspec/resources/opa_cli.rb +0 -57
- data/lib/inspec/resources/podman.rb +0 -353
- data/lib/inspec/resources/podman_container.rb +0 -84
- data/lib/inspec/resources/podman_image.rb +0 -108
- data/lib/inspec/resources/podman_network.rb +0 -81
- data/lib/inspec/resources/podman_pod.rb +0 -101
- data/lib/inspec/resources/podman_volume.rb +0 -87
- data/lib/inspec/resources/rabbitmq_conf.rb +0 -2
- data/lib/inspec/resources/rabbitmq_config.rb +0 -56
- data/lib/inspec/resources/sybase_conf.rb +0 -41
- data/lib/inspec/resources/sybase_session.rb +0 -124
- data/lib/inspec/utils/podman.rb +0 -24
data/lib/inspec/file_provider.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require "rubygems/package" unless defined?(Gem::Package)
|
|
2
|
+
require "rubygems/package/tar_header" unless defined?(Gem::Package::TarHeader)
|
|
2
3
|
require "pathname" unless defined?(Pathname)
|
|
3
4
|
require "zlib" unless defined?(Zlib)
|
|
4
5
|
require "zip" unless defined?(Zip)
|
|
@@ -7,8 +8,12 @@ require "inspec/iaf_file"
|
|
|
7
8
|
module Inspec
|
|
8
9
|
class FileProvider
|
|
9
10
|
def self.for_path(path)
|
|
10
|
-
if path.
|
|
11
|
+
raise "Profile or dependency path not resolved." if path.nil?
|
|
12
|
+
|
|
13
|
+
if path.is_a?(Hash) && !path.key?(:gem)
|
|
11
14
|
MockProvider.new(path)
|
|
15
|
+
elsif path.is_a?(Hash) && path.key?(:gem)
|
|
16
|
+
GemProvider.new(path)
|
|
12
17
|
elsif File.directory?(path)
|
|
13
18
|
DirProvider.new(path)
|
|
14
19
|
elsif File.exist?(path) && path.end_with?(".tar.gz", "tgz")
|
|
@@ -99,6 +104,47 @@ module Inspec
|
|
|
99
104
|
end
|
|
100
105
|
end # class DirProvider
|
|
101
106
|
|
|
107
|
+
class GemProvider < FileProvider
|
|
108
|
+
attr_reader :files
|
|
109
|
+
def initialize(gem_info)
|
|
110
|
+
# Determine a path to the gem installation directory
|
|
111
|
+
gem_name = gem_info[:gem]
|
|
112
|
+
bootstrap_file = gem_info[:path]
|
|
113
|
+
gem_version = gem_info[:version]
|
|
114
|
+
if bootstrap_file
|
|
115
|
+
# We were given an explicit path - go two directories up
|
|
116
|
+
parts = Pathname(gem_info[:path]).each_filename.to_a
|
|
117
|
+
@gem_lib_root = File.join(parts.slice(0, parts.length - 2))
|
|
118
|
+
@files = Dir[File.join(Shellwords.shellescape(@gem_lib_root), "**", "*")]
|
|
119
|
+
else
|
|
120
|
+
# Look up where the gem is installed, respecting version
|
|
121
|
+
loader = Inspec::Plugin::V2::Loader.new
|
|
122
|
+
gem_path = loader.find_gem_directory(gem_name, gem_version)
|
|
123
|
+
if gem_path && File.exist?(gem_path)
|
|
124
|
+
gem = DirProvider.new(gem_path)
|
|
125
|
+
@files = gem.files
|
|
126
|
+
gem
|
|
127
|
+
else
|
|
128
|
+
raise Inspec::Exceptions::GemDependencyNotFound, "Dependency does not exist #{gem_name}"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def read(file)
|
|
134
|
+
return nil unless files.include?(file)
|
|
135
|
+
return nil unless File.file?(file)
|
|
136
|
+
|
|
137
|
+
File.read(file)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def binread(file)
|
|
141
|
+
return nil unless files.include?(file)
|
|
142
|
+
return nil unless File.file?(file)
|
|
143
|
+
|
|
144
|
+
File.binread(file)
|
|
145
|
+
end
|
|
146
|
+
end # class GemProvider
|
|
147
|
+
|
|
102
148
|
class ZipProvider < FileProvider
|
|
103
149
|
attr_reader :files
|
|
104
150
|
|
data/lib/inspec/metadata.rb
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Inspec
|
|
4
|
+
module Plugin
|
|
5
|
+
module V2
|
|
6
|
+
# holds all GemSpec related helper functions
|
|
7
|
+
module GemSpecHelper
|
|
8
|
+
|
|
9
|
+
def loaded_recent_most_version_of?(gemspec)
|
|
10
|
+
# Check if the gem is already loaded via bundler
|
|
11
|
+
# In most cases this is true since all Plugins/Resource Packs inherit from inspec-core
|
|
12
|
+
gem_name = gemspec.name
|
|
13
|
+
loaded_gem = Gem.loaded_specs[gem_name]
|
|
14
|
+
return false unless loaded_gem
|
|
15
|
+
|
|
16
|
+
# follow bundler's original philosophy i.e load gems that are recent most
|
|
17
|
+
# This logic works unless there is a pinned version which we don't expect to have since these are managed by us
|
|
18
|
+
if gemspec.version > loaded_gem.version
|
|
19
|
+
# deactivate the lower version specs that are loaded via bundler
|
|
20
|
+
Gem.loaded_specs.delete(gem_name)
|
|
21
|
+
false # so it can re-activate the requested spec
|
|
22
|
+
else
|
|
23
|
+
# don't activate requested gemspec when the already loaded gem is the most recent version
|
|
24
|
+
true
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "singleton" unless defined?(Singleton)
|
|
3
|
+
require "forwardable" unless defined?(Forwardable)
|
|
4
|
+
require "chef-licensing"
|
|
5
|
+
|
|
6
|
+
module Inspec::Plugin::V2
|
|
7
|
+
class GemSourceManager
|
|
8
|
+
include Singleton
|
|
9
|
+
extend Forwardable
|
|
10
|
+
|
|
11
|
+
DEFAULT_CHEF_RUBY_GEMS_SERVER = "rubygems.chef.io"
|
|
12
|
+
DEFAULT_USERNAME = "v1"
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@sources = Gem.sources
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def_delegator :@sources, :sources
|
|
19
|
+
|
|
20
|
+
def add_chef_rubygems_server
|
|
21
|
+
register_source(chef_rubygems_server)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def add(sources)
|
|
25
|
+
Array(sources).each { |source| register_source(source) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def chef_rubygems_server
|
|
31
|
+
# If there are no license keys, return nil to avoid adding an invalid source
|
|
32
|
+
"https://#{DEFAULT_USERNAME}:#{licenses_string}@#{DEFAULT_CHEF_RUBY_GEMS_SERVER}" unless licenses_string.empty?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def register_source(source)
|
|
36
|
+
return if source.nil? # If the source is nil, we don't want to add it
|
|
37
|
+
|
|
38
|
+
gem_source = Gem::Source.new(source)
|
|
39
|
+
sources << gem_source unless sources.include?(gem_source)
|
|
40
|
+
rescue StandardError => e
|
|
41
|
+
raise StandardError, "Unable to add gem source #{source}: #{e.message}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def licenses_string
|
|
45
|
+
ChefLicensing.license_keys.join(",")
|
|
46
|
+
rescue StandardError
|
|
47
|
+
""
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -12,6 +12,9 @@ require "rubygems/uninstaller"
|
|
|
12
12
|
require "rubygems/remote_fetcher"
|
|
13
13
|
|
|
14
14
|
require "inspec/plugin/v2/filter"
|
|
15
|
+
require "inspec/plugin/v2/concerns/gem_spec_helper"
|
|
16
|
+
|
|
17
|
+
require "inspec/plugin/v2/gem_source_manager"
|
|
15
18
|
|
|
16
19
|
module Inspec::Plugin::V2
|
|
17
20
|
# Handles all actions modifying the user's plugin set:
|
|
@@ -23,6 +26,7 @@ module Inspec::Plugin::V2
|
|
|
23
26
|
class Installer
|
|
24
27
|
include Singleton
|
|
25
28
|
extend Forwardable
|
|
29
|
+
include Inspec::Plugin::V2::GemSpecHelper
|
|
26
30
|
|
|
27
31
|
Gem.configuration["verbose"] = false
|
|
28
32
|
|
|
@@ -45,6 +49,10 @@ module Inspec::Plugin::V2
|
|
|
45
49
|
list_installed_plugin_gems.detect { |spec| spec.name == name && spec.version == Gem::Version.new(version) }
|
|
46
50
|
end
|
|
47
51
|
|
|
52
|
+
def ensure_installed(name)
|
|
53
|
+
plugin_installed?(name) || install(name)
|
|
54
|
+
end
|
|
55
|
+
|
|
48
56
|
# Installs a plugin. Defaults to assuming the plugin provided is a gem, and will try to install
|
|
49
57
|
# from whatever gemsources `rubygems` thinks it should use.
|
|
50
58
|
# If it's a gem, installs it and its dependencies to the `gem_path`. The gem is not activated.
|
|
@@ -213,7 +221,10 @@ module Inspec::Plugin::V2
|
|
|
213
221
|
if opts.key?(:version) && plugin_version_installed?(plugin_name, opts[:version])
|
|
214
222
|
raise InstallError, "#{plugin_name} version #{opts[:version]} is already installed."
|
|
215
223
|
else
|
|
216
|
-
|
|
224
|
+
# Do not redirect to plugin update when using gem based plugin
|
|
225
|
+
unless gem_based_plugin?(opts)
|
|
226
|
+
raise InstallError, "#{plugin_name} is already installed. Use 'inspec plugin update' to change version."
|
|
227
|
+
end
|
|
217
228
|
end
|
|
218
229
|
end
|
|
219
230
|
|
|
@@ -274,7 +285,16 @@ module Inspec::Plugin::V2
|
|
|
274
285
|
#===================================================================#
|
|
275
286
|
|
|
276
287
|
def install_from_path(requested_plugin_name, opts)
|
|
277
|
-
|
|
288
|
+
return unless gem_based_plugin?(opts)
|
|
289
|
+
|
|
290
|
+
local_gem_path = opts[:path]
|
|
291
|
+
Inspec::Log.debug("Installing #{requested_plugin_name} from path #{local_gem_path}")
|
|
292
|
+
raise InstallError, "Gem File not found: #{local_gem_path}" unless File.exist?(local_gem_path)
|
|
293
|
+
|
|
294
|
+
gem_installer = Gem::Installer.at(local_gem_path, install_dir: gem_path, ignore_dependencies: true, document: [])
|
|
295
|
+
gem_installer.install
|
|
296
|
+
|
|
297
|
+
Inspec::Log.debug("Installed gem from path: #{local_gem_path} to #{gem_path}")
|
|
278
298
|
end
|
|
279
299
|
|
|
280
300
|
def install_from_gem_file(requested_plugin_name, opts)
|
|
@@ -296,18 +316,21 @@ module Inspec::Plugin::V2
|
|
|
296
316
|
install_gem_to_plugins_dir(plugin_dependency, [requested_local_gem_set])
|
|
297
317
|
end
|
|
298
318
|
|
|
299
|
-
def install_from_remote_gems(requested_plugin_name, opts)
|
|
319
|
+
def install_from_remote_gems(requested_plugin_name, opts, source_manager: GemSourceManager.instance)
|
|
300
320
|
plugin_dependency = Gem::Dependency.new(requested_plugin_name, opts[:version] || "> 0")
|
|
321
|
+
source_manager.add_chef_rubygems_server # ensure CHEF RUBYGEMS server is added to the source
|
|
322
|
+
|
|
323
|
+
# This adds custom gem sources to the memoized `Gem.Sources` for this specific run
|
|
324
|
+
# Note: This will not make any change to the environment Gem source list and
|
|
325
|
+
# in fact will consider all of the environment Gem sources and custom gem sources to resolve deps
|
|
326
|
+
source_manager.add(opts[:source])
|
|
301
327
|
|
|
302
|
-
# BestSet is rubygems.org API + indexing
|
|
303
|
-
sources
|
|
304
|
-
|
|
305
|
-
else
|
|
306
|
-
Gem::Resolver::BestSet.new
|
|
307
|
-
end
|
|
328
|
+
# BestSet is rubygems.org API + indexing by default
|
|
329
|
+
# `Gem.sources` is injected as a dependency implicitly while BestSet is initialized
|
|
330
|
+
sources = Gem::Resolver::BestSet.new
|
|
308
331
|
|
|
309
332
|
begin
|
|
310
|
-
install_gem_to_plugins_dir(plugin_dependency, [sources], opts[:update_mode])
|
|
333
|
+
install_gem_to_plugins_dir(plugin_dependency, [sources], opts[:update_mode], opts: opts)
|
|
311
334
|
rescue Gem::RemoteFetcher::FetchError => gem_ex
|
|
312
335
|
# TODO: Give a hint if the host was not resolvable or a 404 occured
|
|
313
336
|
ex = Inspec::Plugin::V2::InstallError.new(gem_ex.message)
|
|
@@ -318,13 +341,16 @@ module Inspec::Plugin::V2
|
|
|
318
341
|
|
|
319
342
|
def install_gem_to_plugins_dir(new_plugin_dependency, # rubocop: disable Metrics/AbcSize
|
|
320
343
|
extra_request_sets = [],
|
|
321
|
-
update_mode = false)
|
|
344
|
+
update_mode = false, opts: {})
|
|
322
345
|
|
|
323
346
|
# Get a list of all the gems available to us.
|
|
324
347
|
gem_to_force_update = update_mode ? new_plugin_dependency.name : nil
|
|
325
348
|
set_available_for_resolution = build_gem_request_universe(extra_request_sets, gem_to_force_update)
|
|
326
349
|
|
|
327
350
|
# Solve the dependency (that is, find a way to install the new plugin and anything it needs)
|
|
351
|
+
# [WARN]: Gem::RequestSet cannot resolve from multiple directories
|
|
352
|
+
# So all dependent gems will be resolved to the GEM_HOME/Gem.default_dir directory
|
|
353
|
+
# assuming everything will be installed in the same dir
|
|
328
354
|
request_set = Gem::RequestSet.new(new_plugin_dependency)
|
|
329
355
|
|
|
330
356
|
begin
|
|
@@ -338,21 +364,37 @@ module Inspec::Plugin::V2
|
|
|
338
364
|
|
|
339
365
|
# Activate all current plugins before trying to activate the new one
|
|
340
366
|
loader.list_managed_gems.each do |spec|
|
|
341
|
-
|
|
367
|
+
# Skip in case of update mode
|
|
368
|
+
# Skip in case using a gem based plugin
|
|
369
|
+
next if spec.name == new_plugin_dependency.name && (update_mode || gem_based_plugin?(opts))
|
|
342
370
|
|
|
343
|
-
|
|
371
|
+
# activate the requested gemspec from the Gem::RequestSet
|
|
372
|
+
spec.activate unless loaded_recent_most_version_of?(spec)
|
|
344
373
|
end
|
|
345
374
|
|
|
346
375
|
# Make sure we remove any previously loaded gem on update
|
|
347
|
-
|
|
376
|
+
# Make sure we remove any previously loaded gem when trying to use resource pack gem
|
|
377
|
+
# Gem based plugin when updated need to deactivate older version of gem
|
|
378
|
+
Gem.loaded_specs.delete(new_plugin_dependency.name) if update_mode || gem_based_plugin?(opts)
|
|
348
379
|
|
|
349
380
|
# Test activating the solution. This makes sure we do not try to load two different versions
|
|
350
381
|
# of the same gem on the stack or a malformed dependency.
|
|
351
382
|
begin
|
|
352
383
|
solution.each do |activation_request|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
384
|
+
requested_gemspec = activation_request.full_spec
|
|
385
|
+
next if requested_gemspec.activated?
|
|
386
|
+
|
|
387
|
+
# The specs at this point are pointed to GEM_HOME/Gem.default_dir directory
|
|
388
|
+
# because of the resolved set's assumption that we will install Gems in the same directory
|
|
389
|
+
# In many cases, RubyGems has already loaded gems from default dir
|
|
390
|
+
# Hence at this point it is really only a sanity check
|
|
391
|
+
# And if the requested_gemspec_file has not been downloaded in this default dir do not activate it
|
|
392
|
+
# Activation will be taken care after the downloads
|
|
393
|
+
requested_gemspec_file = File.join(requested_gemspec.gem_dir, "#{requested_gemspec.name}.gemspec")
|
|
394
|
+
next unless File.exist?(requested_gemspec_file) || File.exist?(requested_gemspec.spec_file)
|
|
395
|
+
|
|
396
|
+
# activate the requested gemspec from the Gem::RequestSet
|
|
397
|
+
requested_gemspec.activate unless loaded_recent_most_version_of?(requested_gemspec)
|
|
356
398
|
end
|
|
357
399
|
rescue Gem::LoadError => gem_ex
|
|
358
400
|
ex = Inspec::Plugin::V2::InstallError.new(gem_ex.message)
|
|
@@ -375,7 +417,7 @@ module Inspec::Plugin::V2
|
|
|
375
417
|
File.write(path_inside_source, spec.to_ruby)
|
|
376
418
|
end
|
|
377
419
|
end
|
|
378
|
-
|
|
420
|
+
loader.activate_managed_gems_for_plugin(new_plugin_dependency.name)
|
|
379
421
|
# Locate the GemVersion for the new dependency and return it
|
|
380
422
|
solution.detect { |g| g.name == new_plugin_dependency.name }.version
|
|
381
423
|
end
|
|
@@ -536,5 +578,10 @@ module Inspec::Plugin::V2
|
|
|
536
578
|
|
|
537
579
|
conf_file
|
|
538
580
|
end
|
|
581
|
+
|
|
582
|
+
def gem_based_plugin?(opts)
|
|
583
|
+
# Param passed by gem fetcher while installing a new gem plugin dependency.
|
|
584
|
+
!!opts[:gem]
|
|
585
|
+
end
|
|
539
586
|
end
|
|
540
587
|
end
|
|
@@ -2,6 +2,7 @@ require "inspec/log"
|
|
|
2
2
|
require "inspec/version"
|
|
3
3
|
require "inspec/plugin/v2/config_file"
|
|
4
4
|
require "inspec/plugin/v2/filter"
|
|
5
|
+
require "inspec/plugin/v2/concerns/gem_spec_helper"
|
|
5
6
|
|
|
6
7
|
module Inspec::Plugin::V2
|
|
7
8
|
class Loader
|
|
@@ -10,6 +11,7 @@ module Inspec::Plugin::V2
|
|
|
10
11
|
# For {inspec|train}_plugin_name?
|
|
11
12
|
include Inspec::Plugin::V2::FilterPredicates
|
|
12
13
|
extend Inspec::Plugin::V2::FilterPredicates
|
|
14
|
+
include Inspec::Plugin::V2::GemSpecHelper
|
|
13
15
|
|
|
14
16
|
def initialize(options = {})
|
|
15
17
|
@options = options
|
|
@@ -68,7 +70,9 @@ module Inspec::Plugin::V2
|
|
|
68
70
|
require plugin_details.entry_point
|
|
69
71
|
else
|
|
70
72
|
load_path = plugin_details.entry_point
|
|
71
|
-
|
|
73
|
+
next if load_path.end_with?(".gem") # local resource pack's path will have gem path
|
|
74
|
+
|
|
75
|
+
load_path += ".rb" unless load_path.end_with?(".rb")
|
|
72
76
|
load load_path
|
|
73
77
|
end
|
|
74
78
|
plugin_details.loaded = true
|
|
@@ -157,6 +161,33 @@ module Inspec::Plugin::V2
|
|
|
157
161
|
self.class.list_managed_gems
|
|
158
162
|
end
|
|
159
163
|
|
|
164
|
+
def self.find_gem_directory(gem_name, version = nil)
|
|
165
|
+
selected_gemspec = find_gemspec_of(gem_name, version)
|
|
166
|
+
selected_gemspec&.full_gem_path
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def self.find_gemspec_directory(gem_name, version = nil)
|
|
170
|
+
selected_gemspec = find_gemspec_of(gem_name, version)
|
|
171
|
+
selected_gemspec&.loaded_from
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def self.find_gemspec_of(gem_name, version = nil)
|
|
175
|
+
version = Gem::Version.new(version) if version && !version.is_a?(Gem::Version)
|
|
176
|
+
|
|
177
|
+
list_managed_gems
|
|
178
|
+
.select { |g| g.name == gem_name }
|
|
179
|
+
.sort_by(&:version)
|
|
180
|
+
.yield_self { |gems| version ? gems.find { |g| g.version == version } : gems.last }
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def find_gemspec_directory(gem_name, version = nil)
|
|
184
|
+
self.class.find_gemspec_directory(gem_name, version)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def find_gem_directory(gem_name, version = nil)
|
|
188
|
+
self.class.find_gem_directory(gem_name, version)
|
|
189
|
+
end
|
|
190
|
+
|
|
160
191
|
# Lists all plugin gems found in the plugin_gem_path.
|
|
161
192
|
# This is simply all gems that begin with train- or inspec-
|
|
162
193
|
# and are not on the exclusion list.
|
|
@@ -169,8 +200,6 @@ module Inspec::Plugin::V2
|
|
|
169
200
|
self.class.list_managed_gems
|
|
170
201
|
end
|
|
171
202
|
|
|
172
|
-
private
|
|
173
|
-
|
|
174
203
|
# 'Activating' a gem adds it to the load path, so 'require "gemname"' will work.
|
|
175
204
|
# Given a gem name, this activates the gem and all of its dependencies, respecting
|
|
176
205
|
# version pinning needs.
|
|
@@ -208,13 +237,15 @@ module Inspec::Plugin::V2
|
|
|
208
237
|
raise ex
|
|
209
238
|
end
|
|
210
239
|
solution.each do |activation_request|
|
|
211
|
-
|
|
240
|
+
requested_gemspec = activation_request.full_spec
|
|
241
|
+
next if requested_gemspec.activated?
|
|
212
242
|
|
|
213
|
-
|
|
214
|
-
# TODO: If we are under Bundler, inform it that we loaded a gem
|
|
243
|
+
requested_gemspec.activate unless loaded_recent_most_version_of?(requested_gemspec)
|
|
215
244
|
end
|
|
216
245
|
end
|
|
217
246
|
|
|
247
|
+
private
|
|
248
|
+
|
|
218
249
|
def annotate_status_after_loading(plugin_name)
|
|
219
250
|
status = registry[plugin_name]
|
|
220
251
|
return if status.api_generation == 2 # Gen2 have self-annotating superclasses
|
data/lib/inspec/plugin/v2.rb
CHANGED
data/lib/inspec/profile.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
# Copyright 2015 Dominik Richter
|
|
2
|
+
# Copyright © 2015-2025 Progress Software Corporation and/or its subsidiaries or affiliates.
|
|
3
|
+
# All Rights Reserved.
|
|
2
4
|
|
|
3
5
|
require "forwardable" unless defined?(Forwardable)
|
|
4
6
|
require "openssl" unless defined?(OpenSSL)
|
|
@@ -299,7 +301,14 @@ module Inspec
|
|
|
299
301
|
# # Pull together waiver
|
|
300
302
|
waived_control_ids = []
|
|
301
303
|
waiver_paths.each do |waiver_path|
|
|
302
|
-
|
|
304
|
+
# Ruby 3.1 treats YAML load as a dangerous operation by default, requiring us to declare date and time classes as permitted
|
|
305
|
+
# It's not a valid option in 3.0.x
|
|
306
|
+
if Gem.ruby_version >= Gem::Version.new("3.1.0")
|
|
307
|
+
waiver_content = ::YAML.load_file(waiver_path, permitted_classes: [Date, Time])
|
|
308
|
+
else
|
|
309
|
+
waiver_content = YAML.load_file(waiver_path)
|
|
310
|
+
end
|
|
311
|
+
|
|
303
312
|
unless waiver_content
|
|
304
313
|
# Note that we will have already issued a detailed warning
|
|
305
314
|
Inspec::Log.error "YAML parsing error in #{waiver_path}"
|
|
@@ -391,6 +400,16 @@ module Inspec
|
|
|
391
400
|
included_tags
|
|
392
401
|
end
|
|
393
402
|
|
|
403
|
+
# InSpec 7 introduced gem-based resource packs, so some "profiles" are now gem-based
|
|
404
|
+
# In this case, they are backed by a gem that contains an inspec.yml and a lib/PATH/plugin.rb
|
|
405
|
+
# which contains activator code which needs to be fired.
|
|
406
|
+
def activate_plugin_if_gem_based
|
|
407
|
+
return unless source_reader.is_a?(SourceReaders::GemReader)
|
|
408
|
+
|
|
409
|
+
reg = Inspec::Plugin::V2::Registry.instance
|
|
410
|
+
reg.find_activator(plugin_name: name.to_sym).activate!
|
|
411
|
+
end
|
|
412
|
+
|
|
394
413
|
def load_libraries
|
|
395
414
|
return @runner_context if @libraries_loaded
|
|
396
415
|
|
|
@@ -618,7 +637,7 @@ module Inspec
|
|
|
618
637
|
include_tests: include_tests)
|
|
619
638
|
|
|
620
639
|
# Collect all metadata defined in the control block and inputs defined inside the control block
|
|
621
|
-
src.ast
|
|
640
|
+
src.ast&.each_node { |n|
|
|
622
641
|
ctl_id_collector.process(n)
|
|
623
642
|
input_collector.process(n)
|
|
624
643
|
}
|
|
@@ -680,7 +699,7 @@ module Inspec
|
|
|
680
699
|
}
|
|
681
700
|
source_location_ref = @source_reader.target.abs_path(control_filename)
|
|
682
701
|
Inspec::Profile::AstHelper::TitleCollector.new(group_data)
|
|
683
|
-
.process(src.ast
|
|
702
|
+
.process(src.ast&.child_nodes&.first) # Picking the title defined for the whole controls file
|
|
684
703
|
group_controls = @info_from_parse[:controls].select { |control| control[:source_location][:ref] == source_location_ref }
|
|
685
704
|
group_data[:controls] = group_controls.map { |control| control[:id] }
|
|
686
705
|
|
|
@@ -121,6 +121,7 @@ module Inspec
|
|
|
121
121
|
@control_subcontexts << context
|
|
122
122
|
end
|
|
123
123
|
|
|
124
|
+
# Expects arrays of arrays of [[content, path, line]]
|
|
124
125
|
def load_libraries(libs)
|
|
125
126
|
lib_prefix = "libraries" + File::SEPARATOR
|
|
126
127
|
autoloads = []
|
|
@@ -130,11 +131,20 @@ module Inspec
|
|
|
130
131
|
next unless source.end_with?(".rb")
|
|
131
132
|
|
|
132
133
|
path = source
|
|
134
|
+
# Create a list of files (presumably resources) to autoload by stripping the prefixes
|
|
135
|
+
# InSpec < 6: libraries/*.rb
|
|
136
|
+
# In InSpec 7, libraries can be installed under (for example)
|
|
137
|
+
# lib/inspec-test-resources/resources/demo_resource.rb
|
|
138
|
+
|
|
133
139
|
if source.start_with?(lib_prefix)
|
|
134
140
|
path = source.sub(lib_prefix, "")
|
|
135
141
|
no_subdir = File.dirname(path) == "."
|
|
136
142
|
|
|
137
143
|
autoloads.push(path) if no_subdir
|
|
144
|
+
elsif source.match(%r{^lib/.+/resources/.*\.rb})
|
|
145
|
+
# Gem Resource Pack
|
|
146
|
+
path = source.sub(%r{^lib/}, "")
|
|
147
|
+
autoloads.push(path)
|
|
138
148
|
end
|
|
139
149
|
|
|
140
150
|
@require_loader.add(path, content, source, line)
|
|
@@ -39,11 +39,17 @@ module Inspec::Resources
|
|
|
39
39
|
# expected result:
|
|
40
40
|
# Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting
|
|
41
41
|
# WIN-MB8NINQ388J,System,Kerberos Authentication Service,{0CCE9242-69AE-11D9-BED3-505054503030},No Auditing,
|
|
42
|
-
|
|
42
|
+
auditpol_cmd = "Auditpol /get /subcategory:'#{key}' /r"
|
|
43
|
+
result ||= inspec.command(auditpol_cmd)
|
|
44
|
+
|
|
45
|
+
unless result.exit_status == 0
|
|
46
|
+
error = result.stdout + "\n" + result.stderr
|
|
47
|
+
raise Inspec::Exceptions::ResourceFailed, "Error while executing #{auditpol_cmd} command: #{error}"
|
|
48
|
+
end
|
|
43
49
|
|
|
44
50
|
# find line
|
|
45
51
|
target = nil
|
|
46
|
-
result.each_line do |s|
|
|
52
|
+
result.stdout.each_line do |s|
|
|
47
53
|
target = s.strip if s =~ /\b.*#{key}.*\b/
|
|
48
54
|
end
|
|
49
55
|
|
|
@@ -200,8 +200,60 @@ module Inspec::Resources
|
|
|
200
200
|
# implements generic unix groups via /etc/group
|
|
201
201
|
class UnixGroup < GroupInfo
|
|
202
202
|
def groups
|
|
203
|
+
get_group_info
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
private
|
|
207
|
+
|
|
208
|
+
def get_group_info
|
|
209
|
+
# First, try to fetch group info using getent
|
|
210
|
+
group_info = fetch_group_info_using_getent
|
|
211
|
+
|
|
212
|
+
return group_info unless group_info.empty?
|
|
213
|
+
|
|
214
|
+
# If getent fails, fallback to reading group info from /etc/group using inspec.etc_group.entries
|
|
215
|
+
Inspec::Log.debug("Falling back to reading group info from /etc/group as getent is unavailable or failed.")
|
|
203
216
|
inspec.etc_group.entries
|
|
204
217
|
end
|
|
218
|
+
|
|
219
|
+
# Fetches group information using the getent utility
|
|
220
|
+
def fetch_group_info_using_getent
|
|
221
|
+
# Find getent utility on the system
|
|
222
|
+
bin = find_getent_utility
|
|
223
|
+
|
|
224
|
+
# If getent is available, fetch group info
|
|
225
|
+
return [] unless bin
|
|
226
|
+
|
|
227
|
+
cmd = inspec.command("#{bin} group")
|
|
228
|
+
return parse_group_info(cmd) if cmd.exit_status.to_i == 0
|
|
229
|
+
|
|
230
|
+
# If getent fails, log the error and return an empty array
|
|
231
|
+
Inspec::Log.debug("Failed to execute #{bin} group: #{cmd.stderr}.")
|
|
232
|
+
[]
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Parses group info from the command output
|
|
236
|
+
def parse_group_info(cmd)
|
|
237
|
+
cmd.stdout.strip.split("\n").map do |line|
|
|
238
|
+
name, password, gid, members = line.split(":")
|
|
239
|
+
{
|
|
240
|
+
"name" => name,
|
|
241
|
+
"password" => password,
|
|
242
|
+
"gid" => gid.to_i,
|
|
243
|
+
"members" => members,
|
|
244
|
+
}
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Checks if getent exists on the system
|
|
249
|
+
def find_getent_utility
|
|
250
|
+
%w{/usr/bin/getent /bin/getent getent}.each do |cmd|
|
|
251
|
+
return cmd if inspec.command(cmd).exist?
|
|
252
|
+
end
|
|
253
|
+
# Log debug information if getent is not found
|
|
254
|
+
Inspec::Log.debug("Could not find `getent` on your system.")
|
|
255
|
+
nil # Return nil if getent is not found
|
|
256
|
+
end
|
|
205
257
|
end
|
|
206
258
|
|
|
207
259
|
# OSX uses opendirectory for groups, so `/etc/group` may not be fully accurate
|
data/lib/inspec/resources.rb
CHANGED
|
@@ -30,12 +30,6 @@ require "inspec/resources/cron"
|
|
|
30
30
|
require "inspec/resources/timezone"
|
|
31
31
|
require "inspec/resources/dh_params"
|
|
32
32
|
require "inspec/resources/directory"
|
|
33
|
-
require "inspec/resources/docker"
|
|
34
|
-
require "inspec/resources/docker_container"
|
|
35
|
-
require "inspec/resources/docker_image"
|
|
36
|
-
require "inspec/resources/docker_plugin"
|
|
37
|
-
require "inspec/resources/docker_service"
|
|
38
|
-
require "inspec/resources/elasticsearch"
|
|
39
33
|
require "inspec/resources/etc_fstab"
|
|
40
34
|
require "inspec/resources/etc_group"
|
|
41
35
|
require "inspec/resources/etc_hosts_allow_deny"
|
|
@@ -48,8 +42,6 @@ require "inspec/resources/groups"
|
|
|
48
42
|
require "inspec/resources/grub_conf"
|
|
49
43
|
require "inspec/resources/host"
|
|
50
44
|
require "inspec/resources/http"
|
|
51
|
-
require "inspec/resources/ibmdb2_conf"
|
|
52
|
-
require "inspec/resources/ibmdb2_session"
|
|
53
45
|
require "inspec/resources/iis_app"
|
|
54
46
|
require "inspec/resources/iis_app_pool"
|
|
55
47
|
require "inspec/resources/iis_site"
|
|
@@ -64,9 +56,6 @@ require "inspec/resources/key_rsa"
|
|
|
64
56
|
require "inspec/resources/ksh"
|
|
65
57
|
require "inspec/resources/limits_conf"
|
|
66
58
|
require "inspec/resources/login_defs"
|
|
67
|
-
require "inspec/resources/mongodb"
|
|
68
|
-
require "inspec/resources/mongodb_conf"
|
|
69
|
-
require "inspec/resources/mongodb_session"
|
|
70
59
|
require "inspec/resources/mount"
|
|
71
60
|
require "inspec/resources/mssql_session"
|
|
72
61
|
require "inspec/resources/mssql_sys_conf"
|
|
@@ -82,8 +71,6 @@ require "inspec/resources/oneget"
|
|
|
82
71
|
require "inspec/resources/oracle"
|
|
83
72
|
require "inspec/resources/oracledb_conf"
|
|
84
73
|
require "inspec/resources/oracledb_listener_conf"
|
|
85
|
-
require "inspec/resources/opa_cli"
|
|
86
|
-
require "inspec/resources/opa_api"
|
|
87
74
|
require "inspec/resources/oracledb_session"
|
|
88
75
|
require "inspec/resources/os"
|
|
89
76
|
require "inspec/resources/os_env"
|
|
@@ -102,7 +89,6 @@ require "inspec/resources/postgres_ident_conf"
|
|
|
102
89
|
require "inspec/resources/postgres_session"
|
|
103
90
|
require "inspec/resources/powershell"
|
|
104
91
|
require "inspec/resources/processes"
|
|
105
|
-
require "inspec/resources/rabbitmq_config"
|
|
106
92
|
require "inspec/resources/registry_key"
|
|
107
93
|
require "inspec/resources/security_identifier"
|
|
108
94
|
require "inspec/resources/security_policy"
|