inspec-core 6.6.0 → 6.8.1
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 +22 -22
- data/etc/features.sig +6 -6
- data/etc/features.yaml +3 -0
- data/inspec-core.gemspec +10 -3
- data/lib/inspec/base_cli.rb +1 -1
- data/lib/inspec/cli.rb +1 -1
- data/lib/inspec/config.rb +9 -0
- data/lib/inspec/dependencies/dependency_set.rb +2 -2
- data/lib/inspec/dsl.rb +1 -1
- data/lib/inspec/feature/runner.rb +4 -1
- data/lib/inspec/feature.rb +8 -0
- data/lib/inspec/fetcher/url.rb +29 -7
- data/lib/inspec/iaf_file.rb +3 -2
- data/lib/inspec/input_registry.rb +5 -1
- data/lib/inspec/profile.rb +2 -2
- data/lib/inspec/reporters/cli.rb +1 -1
- data/lib/inspec/resources/nftables.rb +14 -1
- data/lib/inspec/resources/oracledb_session.rb +12 -3
- data/lib/inspec/resources/ssh_config.rb +100 -9
- data/lib/inspec/resources/ssh_key.rb +124 -0
- data/lib/inspec/resources/sshd_active_config.rb +2 -0
- data/lib/inspec/resources/sybase_session.rb +11 -2
- data/lib/inspec/resources/virtualization.rb +1 -1
- data/lib/inspec/resources.rb +1 -0
- data/lib/inspec/rule.rb +15 -10
- data/lib/inspec/runner.rb +10 -2
- data/lib/inspec/utils/profile_ast_helpers.rb +1 -2
- data/lib/inspec/utils/telemetry/base.rb +149 -0
- data/lib/inspec/utils/telemetry/http.rb +40 -0
- data/lib/inspec/utils/telemetry/null.rb +11 -0
- data/lib/inspec/utils/telemetry/run_context_probe.rb +13 -1
- data/lib/inspec/utils/telemetry.rb +74 -3
- data/lib/inspec/utils/waivers/csv_file_reader.rb +1 -1
- data/lib/inspec/utils/waivers/excel_file_reader.rb +1 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/inspec.rb +0 -1
- data/lib/matchers/matchers.rb +3 -3
- data/lib/plugins/inspec-parallel/lib/inspec-parallel/runner.rb +5 -0
- data/lib/plugins/inspec-parallel/lib/inspec-parallel/super_reporter/status.rb +1 -0
- data/lib/plugins/inspec-sign/lib/inspec-sign/base.rb +14 -6
- metadata +27 -11
- data/lib/inspec/utils/telemetry/collector.rb +0 -81
- data/lib/inspec/utils/telemetry/data_series.rb +0 -44
- data/lib/inspec/utils/telemetry/global_methods.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 935114b2bfd94c210bbaa34c7dcb77185f41d3fe40f2460f0cc202fc81bcf229
|
4
|
+
data.tar.gz: 1b32490bab8349155734d036c8690460436c13531318427a1a7cbbe4d1556479
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebc7bfa5348adaf7ef7f6fa066ced78691167acb491fa1d30dc70fba35125f7b44d9598be47b4868c280796e902e86ca8efcac1d4a71f294b5725b6f3c80a813
|
7
|
+
data.tar.gz: 426261a3570f1db8a1a99f0a07cd6f92eea754943c4d6e904b8a73f7e7dea49bc1758989d94047ca1689efa1c78d2149ca532c345e380c595e103e799f29c1d4
|
data/Gemfile
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
+
# TODO: Commentine artifactory source block temporarily
|
2
|
+
# to addres JIRA #9390 (Chef InSpec Verify pipeline is failing due to checksum mismatch of mixlib-shellout gem)
|
1
3
|
# For Chef internal builds, allows preview versions of gems if available.
|
2
|
-
if ENV["ARTIFACTORY_BASE_URL"]
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
4
|
+
# if ENV["ARTIFACTORY_BASE_URL"]
|
5
|
+
# source ENV["ARTIFACTORY_BASE_URL"] + "/artifactory/api/gems/omnibus-gems-local/" do
|
6
|
+
# # TODO: either fully populate this list, or revert back to non-block format
|
7
|
+
# # to sweep all Chef gems from Artifactory.
|
8
|
+
# gem "chef-licensing"
|
9
|
+
# end
|
10
|
+
# end
|
9
11
|
|
10
12
|
source "https://rubygems.org"
|
11
13
|
|
@@ -18,7 +20,10 @@ gem "inspec", path: "."
|
|
18
20
|
# in it in order to package the executable. Hence the odd backwards dependency.
|
19
21
|
gem "inspec-bin", path: "./inspec-bin"
|
20
22
|
|
21
|
-
|
23
|
+
# ffi version v1.17.0 is breaking verify pipeline as it requires
|
24
|
+
# rubygems version to be upgraded to >= 3.3.22 Ref:https://buildkite.com/chef/inspec-inspec-main-verify-private/builds/812#018fe177-2ccb-45ed-a25e-213c8a6453df/698-707
|
25
|
+
|
26
|
+
gem "ffi", ">= 1.15.5", "< 1.17.0"
|
22
27
|
|
23
28
|
# inspec tests depend text output that changed in the 3.10 release
|
24
29
|
# but our runtime dep is still 3.9+
|
@@ -32,25 +37,20 @@ group :omnibus do
|
|
32
37
|
end
|
33
38
|
|
34
39
|
group :test do
|
35
|
-
gem "chefstyle"
|
36
|
-
gem "concurrent-ruby"
|
37
|
-
gem "json_schemer"
|
40
|
+
gem "chefstyle"
|
41
|
+
gem "concurrent-ruby"
|
42
|
+
gem "json_schemer"
|
38
43
|
gem "m"
|
39
44
|
gem "minitest-sprint", "~> 1.0"
|
40
45
|
gem "minitest", "5.15.0"
|
41
|
-
gem "mocha"
|
42
|
-
gem "nokogiri"
|
46
|
+
gem "mocha"
|
47
|
+
gem "nokogiri"
|
43
48
|
gem "pry-byebug"
|
44
|
-
gem "pry"
|
45
|
-
gem "rake"
|
46
|
-
gem "simplecov"
|
49
|
+
gem "pry"
|
50
|
+
gem "rake"
|
51
|
+
gem "simplecov"
|
47
52
|
gem "simplecov_json_formatter"
|
48
|
-
gem "webmock"
|
49
|
-
|
50
|
-
if Gem.ruby_version >= Gem::Version.new("3.0.0")
|
51
|
-
# html-proofer has a dep on io-event, which is ruby-3 only
|
52
|
-
gem "html-proofer", "~> 3.19.4", platforms: :ruby # do not attempt to run proofer on windows. Pinned to 3.19.4 as test is breaking in updated versions.
|
53
|
-
end
|
53
|
+
gem "webmock"
|
54
54
|
end
|
55
55
|
|
56
56
|
group :deploy do
|
data/etc/features.sig
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
nr7EKXZMiAwYI0Kon1ctCMkDulEkovRbT/FRezvP04yx8wVhJaSi7dMhL/mP
|
2
|
+
NvTzMOuT9G4R/QsP6VV7QKs4eBmAOPGrvgZgyfXDvfe1TPYcvpsVncSXm5rx
|
3
|
+
TO+g7i0XGz9s/FtvdzOpl2urhgOsQ35wk7IsNu9Ktij2HqZw7UmxMvtT954s
|
4
|
+
aQuW6eVvvM9n+bobEBVSErkhgvOvJ7jZyz5r0cv/uuhrayIC6V1qegod9QHa
|
5
|
+
uCdasmmEqglyNQYXIM7V7iNrnfuYB80or44Ewi640edHarSw8YU/Tul2Y2l/
|
6
|
+
DWeXRHsXxmuEL1wXA9ZIV6wqK0RsxaufwY6M7bqWSQ==
|
data/etc/features.yaml
CHANGED
data/inspec-core.gemspec
CHANGED
@@ -21,7 +21,7 @@ Source code obtained from the Chef GitHub repository is made available under Apa
|
|
21
21
|
spec.license = "LicenseRef-Chef-EULA"
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
|
-
spec.required_ruby_version = ">=
|
24
|
+
spec.required_ruby_version = ">= 3.1.0"
|
25
25
|
|
26
26
|
# the gemfile and gemspec are necessary for appbundler so don't remove it
|
27
27
|
spec.files =
|
@@ -38,7 +38,7 @@ Source code obtained from the Chef GitHub repository is made available under Apa
|
|
38
38
|
spec.add_dependency "thor", ">= 0.20", "< 1.3.0"
|
39
39
|
spec.add_dependency "method_source", ">= 0.8", "< 2.0"
|
40
40
|
spec.add_dependency "rubyzip", ">= 1.2.2", "< 3.0"
|
41
|
-
spec.add_dependency "rspec", ">= 3.9", "<= 3.
|
41
|
+
spec.add_dependency "rspec", ">= 3.9", "<= 3.14"
|
42
42
|
spec.add_dependency "rspec-its", "~> 1.2"
|
43
43
|
spec.add_dependency "pry", "~> 0.13"
|
44
44
|
spec.add_dependency "hashie", ">= 3.4", "< 6.0"
|
@@ -55,6 +55,13 @@ Source code obtained from the Chef GitHub repository is made available under Apa
|
|
55
55
|
spec.add_dependency "semverse", "~> 3.0"
|
56
56
|
spec.add_dependency "multipart-post", "~> 2.0"
|
57
57
|
|
58
|
+
# cookstyle support for inspec check
|
59
|
+
# This was initially included in 'inspec.gemspec' to keep 'chef-client' lightweight.
|
60
|
+
# However, it has been moved to 'inspec-core.gemspec' due to a dependency on the 'ast' gem,
|
61
|
+
# which was causing a LoadError ('cannot load such file -- ast') for users/applications using 'inspec-core'.
|
62
|
+
spec.add_dependency "cookstyle"
|
63
|
+
|
58
64
|
spec.add_dependency "train-core", ">= 3.11.0"
|
59
|
-
|
65
|
+
# Minimum major version 1 is required for Chef licensing telemetry
|
66
|
+
spec.add_dependency "chef-licensing", ">= 1.0.2"
|
60
67
|
end
|
data/lib/inspec/base_cli.rb
CHANGED
@@ -47,7 +47,7 @@ module Inspec
|
|
47
47
|
license_keys = ChefLicensing.fetch_and_persist
|
48
48
|
|
49
49
|
# Only if EULA acceptance or license key args are present. And licenses are successfully persisted, do clean exit.
|
50
|
-
if ARGV.select { |arg| !(arg.include? "--chef-license") }.empty? && !license_keys.
|
50
|
+
if ARGV.select { |arg| !(arg.include? "--chef-license") }.empty? && !(license_keys.nil? || license_keys.empty?)
|
51
51
|
Inspec::UI.new.exit
|
52
52
|
end
|
53
53
|
end
|
data/lib/inspec/cli.rb
CHANGED
@@ -57,7 +57,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
57
57
|
desc: "Disable loading all plugins that the user installed."
|
58
58
|
|
59
59
|
class_option :enable_telemetry, type: :boolean,
|
60
|
-
desc: "Allow or disable telemetry", default:
|
60
|
+
desc: "Allow or disable telemetry", default: true
|
61
61
|
|
62
62
|
require "license_acceptance/cli_flags/thor"
|
63
63
|
include LicenseAcceptance::CLIFlags::Thor
|
data/lib/inspec/config.rb
CHANGED
@@ -470,6 +470,15 @@ module Inspec
|
|
470
470
|
# Reporter options may be defined top-level.
|
471
471
|
options.merge!(config_file_reporter_options)
|
472
472
|
|
473
|
+
# when sent reporter from compliance-mode (via chef-client), the reporter is a symbol
|
474
|
+
if @cli_opts.key?(:reporter) && @cli_opts["reporter"].nil?
|
475
|
+
@cli_opts["reporter"] = @cli_opts[:reporter]
|
476
|
+
@cli_opts.delete(:reporter)
|
477
|
+
elsif @cli_opts.key?(:reporter) && @cli_opts.key?("reporter") && @cli_opts["reporter"].is_a?(Array)
|
478
|
+
# combine reporter and "reporter" options into "reporter" option
|
479
|
+
@cli_opts["reporter"] = @cli_opts[:reporter] + @cli_opts["reporter"]
|
480
|
+
end
|
481
|
+
|
473
482
|
if @cli_opts["reporter"]
|
474
483
|
# Add reporter_cli_opts in options to capture reporter cli opts separately
|
475
484
|
options.merge!({ "reporter_cli_opts" => @cli_opts["reporter"] })
|
@@ -26,7 +26,7 @@ module Inspec
|
|
26
26
|
dep_list = {}
|
27
27
|
dependencies.each do |d|
|
28
28
|
# if depedent profile does not have a source version then only name is used in dependency hash
|
29
|
-
key_name = (d.source_version.
|
29
|
+
key_name = ((d.source_version.nil? || d.source_version.empty?) ? "#{d.name}" : "#{d.name}-#{d.source_version}") rescue "#{d.name}"
|
30
30
|
dep_list[key_name] = d
|
31
31
|
end
|
32
32
|
new(cwd, cache, dep_list, backend)
|
@@ -42,7 +42,7 @@ module Inspec
|
|
42
42
|
dep_list = {}
|
43
43
|
dep_tree.each do |d|
|
44
44
|
# if depedent profile does not have a source version then only name is used in dependency hash
|
45
|
-
key_name = (d.source_version.
|
45
|
+
key_name = ((d.source_version.nil? || d.source_version.empty?) ? "#{d.name}" : "#{d.name}-#{d.source_version}") rescue "#{d.name}"
|
46
46
|
dep_list[key_name] = d
|
47
47
|
dep_list.merge!(flatten_dep_tree(d.dependencies))
|
48
48
|
end
|
data/lib/inspec/dsl.rb
CHANGED
@@ -95,7 +95,7 @@ module Inspec::DSL
|
|
95
95
|
# 1. Fetching VERSION from a profile dependency name which is in a format NAME-VERSION.
|
96
96
|
# 2. Matching original profile dependency name with profile name used with include or require control DSL.
|
97
97
|
source_version = value.source_version
|
98
|
-
unless source_version.
|
98
|
+
unless source_version.nil? || source_version.empty?
|
99
99
|
profile_id_key = key.split("-#{source_version}")[0]
|
100
100
|
new_profile_id = key if profile_id_key == profile_id
|
101
101
|
end
|
@@ -11,7 +11,10 @@ module Inspec
|
|
11
11
|
# Validate that the feature is recognized
|
12
12
|
feature = config[feature_name]
|
13
13
|
unless feature
|
14
|
-
|
14
|
+
# Avoid warning for custom plugins
|
15
|
+
user_plugins = Inspec::Plugin::V2::Registry.instance.plugin_statuses.select { |status| status.installation_type == :user_gem }
|
16
|
+
user_plugin_names = user_plugins.collect { |a| a.name.to_s }
|
17
|
+
logger.warn "Unrecognized feature name '#{feature_name}'" unless user_plugin_names.include?(feature_name)
|
15
18
|
end
|
16
19
|
|
17
20
|
# If the feature is not recognized
|
data/lib/inspec/feature.rb
CHANGED
@@ -8,11 +8,15 @@ module Inspec
|
|
8
8
|
|
9
9
|
class Feature
|
10
10
|
attr_reader :name, :description, :env_preview
|
11
|
+
|
12
|
+
@@features_invoked = []
|
13
|
+
|
11
14
|
def initialize(feature_name, feature_yaml_opts)
|
12
15
|
@name = feature_name
|
13
16
|
feature_yaml_opts ||= {}
|
14
17
|
@description = feature_yaml_opts["description"]
|
15
18
|
@env_preview = feature_yaml_opts["env_preview"]
|
19
|
+
@@features_invoked << feature_name
|
16
20
|
end
|
17
21
|
|
18
22
|
def previewable?
|
@@ -30,5 +34,9 @@ module Inspec
|
|
30
34
|
env_preview_feature_name = name.to_s.split("inspec-")[-1]
|
31
35
|
ENV["CHEF_PREVIEW_#{env_preview_feature_name.gsub("-", "_").upcase}"]
|
32
36
|
end
|
37
|
+
|
38
|
+
def self.list_all_invoked_features
|
39
|
+
@@features_invoked.uniq
|
40
|
+
end
|
33
41
|
end
|
34
42
|
end
|
data/lib/inspec/fetcher/url.rb
CHANGED
@@ -93,7 +93,7 @@ module Inspec::Fetcher
|
|
93
93
|
end
|
94
94
|
|
95
95
|
if transformed_target
|
96
|
-
Inspec::Log.
|
96
|
+
Inspec::Log.debug("URL target #{target} transformed to #{transformed_target}. Consider using the git fetcher")
|
97
97
|
transformed_target
|
98
98
|
else
|
99
99
|
target
|
@@ -133,12 +133,14 @@ module Inspec::Fetcher
|
|
133
133
|
class << self
|
134
134
|
def default_ref(match_data, repo_url)
|
135
135
|
remote_url = "#{repo_url}/#{match_data[:user]}/#{match_data[:repo]}.git"
|
136
|
-
command_string = "git remote
|
136
|
+
command_string = "git ls-remote #{remote_url} HEAD"
|
137
137
|
cmd = shellout(command_string)
|
138
138
|
unless cmd.exitstatus == 0
|
139
139
|
raise(Inspec::FetcherFailure, "Profile git dependency failed with default reference - #{remote_url} - error running '#{command_string}': #{cmd.stderr}")
|
140
140
|
else
|
141
|
-
|
141
|
+
# cmd.stdout of "git ls-remote #{remote_url} HEAD" looks like this:
|
142
|
+
# "457d14843ab7c1c3740169eb47cf129a6f417964\tHEAD\n"
|
143
|
+
ref = cmd.stdout.split("\t").first
|
142
144
|
unless ref
|
143
145
|
raise(Inspec::FetcherFailure, "Profile git dependency failed with default reference - #{remote_url} - error running '#{command_string}': NULL reference")
|
144
146
|
end
|
@@ -246,10 +248,30 @@ module Inspec::Fetcher
|
|
246
248
|
@temp_archive_path = archive.path
|
247
249
|
end
|
248
250
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
251
|
+
# Opens a URI or local file specified by `target` with options `opts`.
|
252
|
+
# If `target` is a valid URI (http://, https://, ftp://), opens it using URI.open.
|
253
|
+
# If `target` is a local file path, opens it using File.open.
|
254
|
+
# Raises ArgumentError for invalid `target` that is neither a valid URI nor a local file path.
|
255
|
+
# Logs or handles exceptions gracefully using `pretty_handle_exception`.
|
256
|
+
def open(target, opts)
|
257
|
+
if valid_uri?(target)
|
258
|
+
URI(target).open(opts) # Open URI if it's a valid HTTP, HTTPS, or FTP URI
|
259
|
+
elsif File.file?(target)
|
260
|
+
File.open(target, opts) # Open local file if it exists
|
261
|
+
else
|
262
|
+
raise ArgumentError, "Invalid target: #{target}. Must be a valid URI or a local file path."
|
263
|
+
end
|
264
|
+
rescue StandardError => e
|
265
|
+
raise Inspec::FetcherFailure, "Profile URL dependency #{target} could not be fetched: #{e.message}"
|
266
|
+
end
|
267
|
+
|
268
|
+
# Checks if the given `target` string is a valid URI by attempting to parse it.
|
269
|
+
# Returns true if `target` is a valid HTTP, HTTPS, or FTP URI; false otherwise.
|
270
|
+
def valid_uri?(target)
|
271
|
+
uri = URI.parse(target)
|
272
|
+
uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS) || uri.is_a?(URI::FTP)
|
273
|
+
rescue URI::InvalidURIError
|
274
|
+
false
|
253
275
|
end
|
254
276
|
|
255
277
|
def open_via_uri(target)
|
data/lib/inspec/iaf_file.rb
CHANGED
@@ -34,8 +34,9 @@ module Inspec
|
|
34
34
|
raise Inspec::Exceptions::ProfileValidationKeyNotFound.new("Validation key #{keyname} not found")
|
35
35
|
end
|
36
36
|
|
37
|
-
def self.find_signing_key(keyname)
|
38
|
-
|
37
|
+
def self.find_signing_key(keyname, config_dir = nil)
|
38
|
+
config_dir ||= Inspec.config_dir
|
39
|
+
[".", File.join(config_dir, "keys")].each do |path|
|
39
40
|
filename = File.join(path, "#{keyname}.pem.key")
|
40
41
|
return filename if File.exist?(filename)
|
41
42
|
end
|
@@ -189,7 +189,11 @@ module Inspec
|
|
189
189
|
def parse_cli_input_value(input_name, given_value)
|
190
190
|
value = given_value.chomp(",") # Trim trailing comma if any
|
191
191
|
case value
|
192
|
-
|
192
|
+
# Changed regex to use \A and \z instead of ^ and $ for stricter start and end of string matching.
|
193
|
+
# This prevents potential bypass issues with multi-line input and ensures the entire string
|
194
|
+
# is exactly "true" or "false", enhancing security when dealing with untrusted input.
|
195
|
+
# Issue detected here: https://github.com/inspec/inspec/security/code-scanning/41
|
196
|
+
when /\A(true|false)\z/i
|
193
197
|
value = !!(value =~ /true/i)
|
194
198
|
when /^-?\d+$/
|
195
199
|
value = value.to_i
|
data/lib/inspec/profile.rb
CHANGED
@@ -291,7 +291,7 @@ module Inspec
|
|
291
291
|
## Find the waivers file
|
292
292
|
# - TODO: cli_opts and instance_variable_get could be exposed
|
293
293
|
waiver_paths = cfg.instance_variable_get(:@cli_opts)["waiver_file"]
|
294
|
-
if waiver_paths.
|
294
|
+
if waiver_paths.nil? || waiver_paths.empty?
|
295
295
|
Inspec::Log.error "Must use --waiver-file with --filter-waived-controls"
|
296
296
|
Inspec::UI.new.exit(:usage_error)
|
297
297
|
end
|
@@ -319,7 +319,7 @@ module Inspec
|
|
319
319
|
# be processed and rendered
|
320
320
|
tests.each do |control_filename, source_code|
|
321
321
|
cleared_tests = source_code.scan(/control\s+['"].+?['"].+?(?=(?:control\s+['"].+?['"])|\z)/m).collect do |element|
|
322
|
-
next if element.
|
322
|
+
next if element.nil? || element.empty?
|
323
323
|
|
324
324
|
if element&.match?(waived_control_id_regex)
|
325
325
|
splitlines = element.split("\n")
|
data/lib/inspec/reporters/cli.rb
CHANGED
@@ -135,7 +135,20 @@ module Inspec::Resources
|
|
135
135
|
cmd = inspec.command(nftables_cmd)
|
136
136
|
return [] if cmd.exit_status.to_i != 0
|
137
137
|
|
138
|
-
|
138
|
+
# https://github.com/inspec/inspec/security/code-scanning/10
|
139
|
+
# Update @nftables_cache with sanitized command output
|
140
|
+
@nftables_cache[idx] = cmd.stdout.gsub("\t", "").split("\n")
|
141
|
+
.reject { |line| line =~ /^(table|set|type|size|flags|typeof|auto-merge)/ || line =~ /^}$/ } # Reject lines that match certain patterns
|
142
|
+
.map { |line| line.gsub("elements = {", "").gsub("}", "").split(",") } # Use gsub to replace all occurrences of specified strings
|
143
|
+
.flatten # Flatten the array of arrays into a single array
|
144
|
+
.map(&:strip) # Remove leading and trailing whitespace from each element
|
145
|
+
.map { |element| sanitize_input(element) } # Sanitize each element to prevent injection attacks
|
146
|
+
end
|
147
|
+
|
148
|
+
# Method to sanitize input
|
149
|
+
def sanitize_input(input)
|
150
|
+
# Replace potentially dangerous characters with their escaped counterparts
|
151
|
+
input.gsub(/([\\'";])/, '\\\\\1')
|
139
152
|
end
|
140
153
|
|
141
154
|
def retrieve_chain_rules
|
@@ -96,8 +96,7 @@ module Inspec::Resources
|
|
96
96
|
if @db_role.nil? || @su_user.nil?
|
97
97
|
verified_query = verify_query(query)
|
98
98
|
else
|
99
|
-
escaped_query = query
|
100
|
-
escaped_query = escaped_query.gsub("$", '\\$') unless escaped_query.include? "\\$"
|
99
|
+
escaped_query = escape_query(query)
|
101
100
|
verified_query = verify_query(escaped_query)
|
102
101
|
end
|
103
102
|
|
@@ -134,11 +133,21 @@ module Inspec::Resources
|
|
134
133
|
query
|
135
134
|
end
|
136
135
|
|
136
|
+
def escape_query(query)
|
137
|
+
# https://github.com/inspec/inspec/security/code-scanning/7
|
138
|
+
# https://github.com/inspec/inspec/security/code-scanning/8
|
139
|
+
escaped_query = query.gsub(/["\\]/) { |match| match == '"' ? '\\"' : "\\\\" } # Escape backslashes and double quotes
|
140
|
+
escaped_query.gsub!("$", '\\$') unless escaped_query.include? "\\$" # Escape dollar signs, but only if not already escaped
|
141
|
+
escaped_query
|
142
|
+
end
|
143
|
+
|
137
144
|
def parse_csv_result(stdout)
|
138
145
|
output = stdout.split("oracle_query_string")[-1]
|
139
146
|
# comma_query_sub replaces the csv delimiter "," in the output.
|
140
147
|
# Handles CSV parsing of data like this (DROP,3) etc
|
141
|
-
|
148
|
+
# Replace all occurrences of the target pattern using gsub instead of sub
|
149
|
+
# Issue detected: https://github.com/inspec/inspec/security/code-scanning/9
|
150
|
+
output = output.gsub(/\r/, "").strip.gsub(",", "comma_query_sub")
|
142
151
|
converter = ->(header) { header.downcase }
|
143
152
|
CSV.parse(output, headers: true, header_converters: converter).map do |row|
|
144
153
|
next if row.entries.flatten.empty?
|
@@ -38,16 +38,13 @@ module Inspec::Resources
|
|
38
38
|
|
39
39
|
def convert_hash(hash)
|
40
40
|
new_hash = {}
|
41
|
-
hash.each
|
42
|
-
new_hash[k.downcase] ||= v
|
43
|
-
end
|
41
|
+
hash.each { |k, v| new_hash[k.downcase] ||= v }
|
44
42
|
new_hash
|
45
43
|
end
|
46
44
|
|
47
45
|
def method_missing(name)
|
48
46
|
param = read_params[name.to_s.downcase]
|
49
47
|
return nil if param.nil?
|
50
|
-
# extract first value if we have only one value in array
|
51
48
|
return param[0] if param.length == 1
|
52
49
|
|
53
50
|
param
|
@@ -73,11 +70,12 @@ module Inspec::Resources
|
|
73
70
|
return @params if defined?(@params)
|
74
71
|
return @params = {} if read_content.nil?
|
75
72
|
|
76
|
-
conf =
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
73
|
+
conf =
|
74
|
+
SimpleConfig.new(
|
75
|
+
read_content,
|
76
|
+
assignment_regex: /^\s*(\S+?)\s+(.*?)\s*$/,
|
77
|
+
multiple_values: true
|
78
|
+
)
|
81
79
|
@params = convert_hash(conf.params)
|
82
80
|
end
|
83
81
|
|
@@ -121,4 +119,97 @@ module Inspec::Resources
|
|
121
119
|
"/etc/ssh/#{type}"
|
122
120
|
end
|
123
121
|
end
|
122
|
+
|
123
|
+
class SshdActiveConfig < SshdConfig
|
124
|
+
name "sshd_active_config"
|
125
|
+
supports platform: "unix"
|
126
|
+
supports platform: "windows"
|
127
|
+
desc "Use the sshd_active_config InSpec audit resource to test configuration data for the Open SSH daemon located at /etc/ssh/sshd_config on Linux and UNIX platforms. sshd---the Open SSH daemon---listens on dedicated ports, starts a daemon for each incoming connection, and then handles encryption, authentication, key exchanges, command execution, and data exchanges."
|
128
|
+
example <<~EXAMPLE
|
129
|
+
describe sshd_active_config do
|
130
|
+
its('Protocol') { should eq '2' }
|
131
|
+
end
|
132
|
+
EXAMPLE
|
133
|
+
|
134
|
+
attr_reader :active_path
|
135
|
+
|
136
|
+
def initialize
|
137
|
+
@active_path = dynamic_sshd_config_path
|
138
|
+
super(@active_path)
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_s
|
142
|
+
"SSHD Active Configuration (active path: #{@conf_path})"
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def ssh_config_file(type)
|
148
|
+
if inspec.os.windows?
|
149
|
+
programdata = inspec.os_env("programdata").content
|
150
|
+
return "#{programdata}\\ssh\\#{type}"
|
151
|
+
end
|
152
|
+
|
153
|
+
"/etc/ssh/#{type}"
|
154
|
+
end
|
155
|
+
|
156
|
+
def dynamic_sshd_config_path
|
157
|
+
if inspec.os.windows?
|
158
|
+
script = <<-EOH
|
159
|
+
$sshdPath = (Get-Command sshd.exe).Source
|
160
|
+
if ($sshdPath -ne $null) {
|
161
|
+
Write-Output $sshdPath
|
162
|
+
} else {
|
163
|
+
Write-Error "sshd.exe not found"
|
164
|
+
}
|
165
|
+
EOH
|
166
|
+
sshd_path_result = inspec.powershell(script).stdout.strip
|
167
|
+
sshd_path = "\"#{sshd_path_result}\""
|
168
|
+
if !sshd_path_result.empty? && sshd_path_result != "sshd.exe not found"
|
169
|
+
command_output = inspec.command("sudo #{sshd_path} -dd 2>&1").stdout
|
170
|
+
dynamic_path =
|
171
|
+
command_output
|
172
|
+
.lines
|
173
|
+
.find { |line| line.include?("filename") }
|
174
|
+
&.split("filename")
|
175
|
+
&.last
|
176
|
+
&.strip
|
177
|
+
env_var_name = dynamic_path.match(/__(.*?)__/)[1]
|
178
|
+
if env_var_name?
|
179
|
+
dynamic_path =
|
180
|
+
dynamic_path.gsub(
|
181
|
+
/__#{env_var_name}__/,
|
182
|
+
inspec.os_env(env_var_name).content
|
183
|
+
)
|
184
|
+
end
|
185
|
+
else
|
186
|
+
Inspec::Log.error("sshd.exe not found using PowerShell script block.")
|
187
|
+
return nil
|
188
|
+
end
|
189
|
+
elsif inspec.os.unix?
|
190
|
+
sshd_path = "/usr/sbin/sshd"
|
191
|
+
command_output = inspec.command("sudo #{sshd_path} -dd 2>&1").stdout
|
192
|
+
dynamic_path =
|
193
|
+
command_output
|
194
|
+
.lines
|
195
|
+
.find { |line| line.include?("filename") }
|
196
|
+
&.split("filename")
|
197
|
+
&.last
|
198
|
+
&.strip
|
199
|
+
else
|
200
|
+
Inspec::Log.error(
|
201
|
+
"Unable to determine sshd configuration path on Windows using -T flag."
|
202
|
+
)
|
203
|
+
return nil
|
204
|
+
end
|
205
|
+
|
206
|
+
if dynamic_path.nil? || dynamic_path.empty?
|
207
|
+
Inspec::Log.warn(
|
208
|
+
"No active SSHD configuration found. Using default configuration."
|
209
|
+
)
|
210
|
+
return ssh_config_file("sshd_config")
|
211
|
+
end
|
212
|
+
dynamic_path
|
213
|
+
end
|
214
|
+
end
|
124
215
|
end
|