inspec-core 6.6.0 → 6.8.11
Sign up to get free protection for your applications and to get access to all the features.
- 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 +4 -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 +9 -3
- data/lib/inspec/resources/postgres_session.rb +1 -1
- 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 +24 -4
- data/lib/inspec/utils/licensing_config.rb +14 -0
- 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 +37 -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 +76 -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
- data/lib/source_readers/inspec.rb +1 -1
- 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: 6ef08c3443267ae12f42004936c21dd9c06a2a2405981efa57d5ab26a3a58e38
|
4
|
+
data.tar.gz: 16ba90c68c5f4168b1c1e3178b0b974992d27d5529ada5c34f51fda029539806
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6915602a57ac2c952ba963ded31d7e20a2aca7c0f8e49cf1f3109d85042864d7e69e390aa886937cd2d26a062716da9388a71bf9a67940578c4ccd783e8feb3d
|
7
|
+
data.tar.gz: ffb31db9833ffca067688360cdbd73eb8ddd8da55e0a0cbcc33c860a2475f43715fcd4603b04cab3adba771f9cfc6231a88ec594a2947b7d4781bf899123b575
|
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,13 +47,16 @@ 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
|
54
54
|
rescue ChefLicensing::LicenseKeyFetcher::LicenseKeyNotFetchedError
|
55
55
|
Inspec::Log.error "#{Inspec::Dist::PRODUCT_NAME} cannot execute without valid licenses."
|
56
56
|
Inspec::UI.new.exit(:license_not_set)
|
57
|
+
rescue ChefLicensing::SoftwareNotEntitled
|
58
|
+
Inspec::Log.error "License is not entitled to use InSpec."
|
59
|
+
Inspec::UI.new.exit(:license_not_entitled)
|
57
60
|
rescue ChefLicensing::Error => e
|
58
61
|
Inspec::Log.error e.message
|
59
62
|
Inspec::UI.new.exit(:usage_error)
|
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
|
@@ -57,7 +57,7 @@ module Inspec::Resources
|
|
57
57
|
inspec_cmd = inspec.command(command)
|
58
58
|
out = inspec_cmd.stdout + "\n" + inspec_cmd.stderr
|
59
59
|
|
60
|
-
if inspec_cmd.exit_status != 0 ||
|
60
|
+
if inspec_cmd.exit_status != 0 || out.downcase =~ /^error.*/
|
61
61
|
raise Inspec::Exceptions::ResourceFailed, "Oracle query with errors: #{out}"
|
62
62
|
else
|
63
63
|
begin
|
@@ -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,10 +133,17 @@ module Inspec::Resources
|
|
134
133
|
query
|
135
134
|
end
|
136
135
|
|
136
|
+
def escape_query(query)
|
137
|
+
escaped_query = query.gsub(/\\\\/, "\\").gsub(/"/, '\\"')
|
138
|
+
escaped_query = escaped_query.gsub("$", '\\$') unless escaped_query.include? "\\$"
|
139
|
+
escaped_query
|
140
|
+
end
|
141
|
+
|
137
142
|
def parse_csv_result(stdout)
|
138
143
|
output = stdout.split("oracle_query_string")[-1]
|
139
144
|
# comma_query_sub replaces the csv delimiter "," in the output.
|
140
145
|
# Handles CSV parsing of data like this (DROP,3) etc
|
146
|
+
|
141
147
|
output = output.sub(/\r/, "").strip.gsub(",", "comma_query_sub")
|
142
148
|
converter = ->(header) { header.downcase }
|
143
149
|
CSV.parse(output, headers: true, header_converters: converter).map do |row|
|
@@ -55,7 +55,7 @@ module Inspec::Resources
|
|
55
55
|
psql_cmd = create_psql_cmd(query, db)
|
56
56
|
cmd = inspec.command(psql_cmd, redact_regex: %r{(:\/\/[a-z]*:).*(@)})
|
57
57
|
out = cmd.stdout + "\n" + cmd.stderr
|
58
|
-
if cmd.exit_status != 0 && ( out =~ /could not connect to/ || out =~ /password authentication failed/ ) && out.downcase =~ /error:/
|
58
|
+
if cmd.exit_status != 0 && ( out =~ /could not connect to/ || out =~ /password authentication failed/ ) && (out.downcase =~ /error:/ || out.downcase =~ /fatal:/)
|
59
59
|
raise Inspec::Exceptions::ResourceFailed, "PostgreSQL connection error: #{out}"
|
60
60
|
elsif cmd.exit_status != 0 && out.downcase =~ /error:/
|
61
61
|
Lines.new(out, "PostgreSQL query with error: #{query}", cmd.exit_status)
|
@@ -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
|