inspec-core 5.22.50 → 6.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Chef-EULA +9 -0
- data/Gemfile +14 -4
- data/etc/features.sig +6 -0
- data/etc/features.yaml +97 -0
- data/inspec-core.gemspec +17 -7
- data/lib/inspec/backend.rb +2 -0
- data/lib/inspec/base_cli.rb +80 -4
- data/lib/inspec/cached_fetcher.rb +24 -3
- data/lib/inspec/cli.rb +293 -236
- data/lib/inspec/config.rb +24 -2
- data/lib/inspec/dependencies/cache.rb +33 -0
- data/lib/inspec/enhanced_outcomes.rb +1 -0
- data/lib/inspec/errors.rb +5 -0
- data/lib/inspec/exceptions.rb +2 -0
- data/lib/inspec/feature/config.rb +75 -0
- data/lib/inspec/feature/runner.rb +29 -0
- data/lib/inspec/feature.rb +42 -0
- data/lib/inspec/fetcher/git.rb +5 -0
- data/lib/inspec/fetcher/url.rb +24 -4
- data/lib/inspec/globals.rb +6 -0
- data/lib/inspec/iaf_file.rb +3 -2
- data/lib/inspec/input_registry.rb +5 -1
- data/lib/inspec/plugin/v1/plugin_types/fetcher.rb +7 -0
- data/lib/inspec/plugin/v2/plugin_types/streaming_reporter.rb +30 -2
- data/lib/inspec/profile.rb +44 -1
- data/lib/inspec/reporters.rb +67 -54
- 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.rb +1 -0
- data/lib/inspec/rule.rb +6 -6
- data/lib/inspec/run_data.rb +7 -5
- data/lib/inspec/runner.rb +43 -6
- data/lib/inspec/runner_rspec.rb +12 -9
- data/lib/inspec/secrets/yaml.rb +9 -3
- data/lib/inspec/shell.rb +10 -0
- data/lib/inspec/ui.rb +4 -0
- data/lib/inspec/utils/licensing_config.rb +9 -0
- 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/version.rb +1 -1
- data/lib/inspec/waiver_file_reader.rb +68 -27
- data/lib/inspec.rb +2 -2
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/cli.rb +189 -168
- data/lib/plugins/inspec-habitat/lib/inspec-habitat/cli.rb +10 -3
- data/lib/plugins/inspec-init/lib/inspec-init/cli.rb +1 -0
- data/lib/plugins/inspec-init/lib/inspec-init/cli_plugin.rb +23 -21
- data/lib/plugins/inspec-init/lib/inspec-init/cli_profile.rb +15 -13
- data/lib/plugins/inspec-init/lib/inspec-init/cli_resource.rb +15 -13
- data/lib/plugins/inspec-license/README.md +16 -0
- data/lib/plugins/inspec-license/inspec-license.gemspec +6 -0
- data/lib/plugins/inspec-license/lib/inspec-license/cli.rb +26 -0
- data/lib/plugins/inspec-license/lib/inspec-license.rb +14 -0
- data/lib/plugins/inspec-parallel/README.md +27 -0
- data/lib/plugins/inspec-parallel/inspec-parallel.gemspec +6 -0
- data/lib/plugins/inspec-parallel/lib/inspec-parallel/child_status_reporter.rb +61 -0
- data/lib/plugins/inspec-parallel/lib/inspec-parallel/cli.rb +39 -0
- data/lib/plugins/inspec-parallel/lib/inspec-parallel/command.rb +219 -0
- data/lib/plugins/inspec-parallel/lib/inspec-parallel/runner.rb +270 -0
- data/lib/plugins/inspec-parallel/lib/inspec-parallel/super_reporter/base.rb +24 -0
- data/lib/plugins/inspec-parallel/lib/inspec-parallel/super_reporter/silent.rb +7 -0
- data/lib/plugins/inspec-parallel/lib/inspec-parallel/super_reporter/status.rb +125 -0
- data/lib/plugins/inspec-parallel/lib/inspec-parallel/super_reporter/text.rb +23 -0
- data/lib/plugins/inspec-parallel/lib/inspec-parallel/validator.rb +170 -0
- data/lib/plugins/inspec-parallel/lib/inspec-parallel.rb +18 -0
- data/lib/plugins/inspec-sign/lib/inspec-sign/base.rb +20 -8
- data/lib/plugins/inspec-sign/lib/inspec-sign/cli.rb +11 -4
- data/lib/plugins/inspec-streaming-reporter-progress-bar/lib/inspec-streaming-reporter-progress-bar/streaming_reporter.rb +6 -13
- metadata +61 -19
- 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
@@ -0,0 +1,149 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "chef-licensing"
|
3
|
+
require "securerandom" unless defined?(SecureRandom)
|
4
|
+
require "digest" unless defined?(Digest)
|
5
|
+
require_relative "../../dist"
|
6
|
+
module Inspec
|
7
|
+
class Telemetry
|
8
|
+
class Base
|
9
|
+
VERSION = 2.0
|
10
|
+
TYPE = "job"
|
11
|
+
JOB_TYPE = "InSpec"
|
12
|
+
|
13
|
+
attr_accessor :scratch
|
14
|
+
|
15
|
+
def fetch_license_ids
|
16
|
+
Inspec::Log.debug "Fetching license IDs for telemetry"
|
17
|
+
@license_keys ||= ChefLicensing.license_keys
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_wrapper
|
21
|
+
Inspec::Log.debug "Initialising wrapper for telemetry"
|
22
|
+
{
|
23
|
+
version: VERSION,
|
24
|
+
createdTimeUTC: Time.now.getutc.iso8601,
|
25
|
+
environment: Inspec::Telemetry::RunContextProbe.guess_run_context,
|
26
|
+
licenseIds: fetch_license_ids,
|
27
|
+
source: "#{Inspec::Dist::EXEC_NAME}:#{Inspec::VERSION}",
|
28
|
+
type: TYPE,
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def note_feature_usage(feature_name)
|
33
|
+
@scratch ||= {}
|
34
|
+
@scratch[:features] ||= []
|
35
|
+
@scratch[:features] << feature_name
|
36
|
+
end
|
37
|
+
|
38
|
+
def run_starting(_opts = {})
|
39
|
+
Inspec::Log.debug "Initiating telemetry for InSpec"
|
40
|
+
@scratch ||= {}
|
41
|
+
@scratch[:features] ||= []
|
42
|
+
@scratch[:run_start_time] = Time.now.getutc.iso8601
|
43
|
+
end
|
44
|
+
|
45
|
+
def run_ending(opts)
|
46
|
+
note_per_run_features(opts)
|
47
|
+
|
48
|
+
payload = create_wrapper
|
49
|
+
|
50
|
+
train_platform = opts[:runner].backend.backend.platform
|
51
|
+
payload[:platform] = train_platform.name
|
52
|
+
|
53
|
+
payload[:jobs] = [{
|
54
|
+
type: JOB_TYPE,
|
55
|
+
|
56
|
+
# Target platform info
|
57
|
+
environment: {
|
58
|
+
host: obscure(URI(opts[:runner].backend.backend.uri).host) || "unknown",
|
59
|
+
os: train_platform.name,
|
60
|
+
version: train_platform.release,
|
61
|
+
architecture: train_platform.arch || "",
|
62
|
+
id: train_platform.uuid,
|
63
|
+
},
|
64
|
+
|
65
|
+
runtime: Inspec::VERSION,
|
66
|
+
content: [], # one content == one profile
|
67
|
+
steps: [], # one step == one control
|
68
|
+
}]
|
69
|
+
|
70
|
+
opts[:run_data][:profiles].each do |profile|
|
71
|
+
payload[:jobs][0][:content] << {
|
72
|
+
name: obscure(profile[:name]),
|
73
|
+
version: profile[:version],
|
74
|
+
sha256: profile[:sha256],
|
75
|
+
maintainer: profile[:maintainer] || "",
|
76
|
+
type: "profile",
|
77
|
+
}
|
78
|
+
|
79
|
+
profile[:controls].each do |control|
|
80
|
+
payload[:jobs][0][:steps] << {
|
81
|
+
id: obscure(control[:id]),
|
82
|
+
name: "inspec-control",
|
83
|
+
description: control[:desc] || "",
|
84
|
+
target: {
|
85
|
+
mode: opts[:runner].backend.backend.backend_type,
|
86
|
+
id: opts[:runner].backend.backend.platform.uuid,
|
87
|
+
},
|
88
|
+
resources: [],
|
89
|
+
features: [],
|
90
|
+
tags: format_control_tags(control[:tags]),
|
91
|
+
}
|
92
|
+
|
93
|
+
control[:results]&.each do |resource_block|
|
94
|
+
payload[:jobs][0][:steps].last[:resources] << {
|
95
|
+
type: "inspec-resource",
|
96
|
+
name: resource_block[:resource_class],
|
97
|
+
id: obscure(resource_block[:resource_title].respond_to?(:resource_id) ? resource_block[:resource_title].resource_id : nil) || "unknown",
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
# Per-control features.
|
102
|
+
payload[:jobs][0][:steps].last[:features] = scratch[:features].dup
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
Inspec::Log.debug "Final data for telemetry upload -> #{payload}"
|
107
|
+
Inspec::Log.debug "Finishing telemetry for InSpec"
|
108
|
+
# Return payload object for testing
|
109
|
+
payload
|
110
|
+
end
|
111
|
+
|
112
|
+
def format_control_tags(tags)
|
113
|
+
tags_list = []
|
114
|
+
tags.each do |key, value|
|
115
|
+
tags_list << { name: key.to_s, value: (value || "").to_s }
|
116
|
+
end
|
117
|
+
tags_list
|
118
|
+
end
|
119
|
+
|
120
|
+
# Hash text if non-nil
|
121
|
+
def obscure(cleartext)
|
122
|
+
return nil if cleartext.nil?
|
123
|
+
return nil if cleartext.empty?
|
124
|
+
|
125
|
+
Digest::SHA2.new(256).hexdigest(cleartext)
|
126
|
+
end
|
127
|
+
|
128
|
+
def note_per_run_features(opts)
|
129
|
+
note_all_invoked_features
|
130
|
+
note_gem_dependency_usage(opts)
|
131
|
+
end
|
132
|
+
|
133
|
+
def note_all_invoked_features
|
134
|
+
Inspec::Feature.list_all_invoked_features.each do |feature|
|
135
|
+
Inspec::Telemetry.note_feature_usage(feature.to_s)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def note_gem_dependency_usage(opts)
|
140
|
+
unless opts[:runner].target_profiles.map do |tp|
|
141
|
+
tp.metadata.gem_dependencies + \
|
142
|
+
tp.locked_dependencies.list.map { |_k, v| v.profile.metadata.gem_dependencies }.flatten
|
143
|
+
end.flatten.empty?
|
144
|
+
Inspec::Telemetry.note_feature_usage("inspec-gem-deps-in-profiles")
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "base"
|
3
|
+
require "faraday" unless defined?(Faraday)
|
4
|
+
require "inspec/utils/licensing_config"
|
5
|
+
module Inspec
|
6
|
+
class Telemetry
|
7
|
+
class HTTP < Base
|
8
|
+
TELEMETRY_JOBS_PATH = "v1/job"
|
9
|
+
TELEMETRY_URL = if ChefLicensing::Config.license_server_url&.match?("acceptance")
|
10
|
+
ENV["CHEF_TELEMETRY_URL"]
|
11
|
+
else
|
12
|
+
"https://services.chef.io/telemetry/"
|
13
|
+
end
|
14
|
+
def run_ending(opts)
|
15
|
+
payload = super
|
16
|
+
response = connection.post(TELEMETRY_JOBS_PATH) do |req|
|
17
|
+
req.body = payload.to_json
|
18
|
+
end
|
19
|
+
if response.success?
|
20
|
+
Inspec::Log.debug "HTTP connection with Telemetry Client successful."
|
21
|
+
Inspec::Log.debug "HTTP response from Telemetry Client -> #{response.to_hash}"
|
22
|
+
true
|
23
|
+
else
|
24
|
+
Inspec::Log.debug "HTTP connection with Telemetry Client faced an error."
|
25
|
+
Inspec::Log.debug "HTTP error -> #{response.to_hash[:body]["error"]}" if response.to_hash[:body] && response.to_hash[:body]["error"]
|
26
|
+
false
|
27
|
+
end
|
28
|
+
rescue Faraday::ConnectionFailed
|
29
|
+
Inspec::Log.debug "HTTP connection failure with telemetry url -> #{TELEMETRY_URL}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def connection
|
33
|
+
Faraday.new(url: TELEMETRY_URL) do |config|
|
34
|
+
config.request :json
|
35
|
+
config.response :json
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,9 +1,21 @@
|
|
1
1
|
module Inspec
|
2
|
-
|
2
|
+
class Telemetry
|
3
3
|
# Guesses the run context of InSpec - how were we invoked?
|
4
4
|
# All stack values here are determined experimentally
|
5
5
|
|
6
6
|
class RunContextProbe
|
7
|
+
# Guess if we are running under Automate
|
8
|
+
def self.under_automate?
|
9
|
+
# Currently assume we are under automate if we have an automate-based reporter
|
10
|
+
Inspec::Config.cached[:reporter]
|
11
|
+
.keys
|
12
|
+
.map(&:to_s)
|
13
|
+
.any? { |n| n =~ /automate/ }
|
14
|
+
end
|
15
|
+
|
16
|
+
# Guess, using stack introspection, if we were called under
|
17
|
+
# test-kitchen, cli, audit-cookbook, or otherwise.
|
18
|
+
# TODO add compliance-phase of chef-infra
|
7
19
|
def self.guess_run_context(stack = nil)
|
8
20
|
stack ||= caller_locations
|
9
21
|
return "test-kitchen" if kitchen?(stack)
|
@@ -1,3 +1,74 @@
|
|
1
|
-
require "
|
2
|
-
require "
|
3
|
-
|
1
|
+
require "time" unless defined?(Time.zone_offset)
|
2
|
+
require "chef-licensing"
|
3
|
+
require_relative "telemetry/null"
|
4
|
+
require_relative "telemetry/http"
|
5
|
+
require_relative "telemetry/run_context_probe"
|
6
|
+
|
7
|
+
module Inspec
|
8
|
+
class Telemetry
|
9
|
+
|
10
|
+
@@instance = nil
|
11
|
+
@@config = nil
|
12
|
+
|
13
|
+
def self.instance
|
14
|
+
@@instance ||= determine_backend_class.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.determine_backend_class
|
18
|
+
# Don't perform telemetry action for other InSpec distros
|
19
|
+
# Don't perform telemetry action if running under Automate - Automate does LDC tracking for us
|
20
|
+
# Don't perform telemetry action if license is a commercial license
|
21
|
+
|
22
|
+
if Inspec::Dist::EXEC_NAME != "inspec" ||
|
23
|
+
Inspec::Telemetry::RunContextProbe.under_automate? ||
|
24
|
+
license&.license_type&.downcase == "commercial"
|
25
|
+
|
26
|
+
Inspec::Log.debug "Determined telemetry operation is not applicable and hence aborting it."
|
27
|
+
return Inspec::Telemetry::Null
|
28
|
+
end
|
29
|
+
|
30
|
+
if Inspec::Dist::EXEC_NAME == "inspec" && telemetry_disabled?
|
31
|
+
# Issue a warning if an InSpec user is explicitly trying to opt out of telemetry using cli option
|
32
|
+
Inspec::Log.warn "Telemetry opt-out is not permissible."
|
33
|
+
end
|
34
|
+
|
35
|
+
Inspec::Log.debug "Determined HTTP instance for telemetry"
|
36
|
+
|
37
|
+
Inspec::Telemetry::HTTP
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.license
|
41
|
+
Inspec::Log.debug "Fetching license context for telemetry check"
|
42
|
+
@license = ChefLicensing.license_context
|
43
|
+
end
|
44
|
+
|
45
|
+
######
|
46
|
+
# These class methods make it convenient to call from anywhere within the InSpec codebase.
|
47
|
+
######
|
48
|
+
def self.run_starting(opts)
|
49
|
+
@@config ||= opts[:conf]
|
50
|
+
instance.run_starting(opts)
|
51
|
+
rescue StandardError => e
|
52
|
+
Inspec::Log.debug "Encountered error in Telemetry start run call -> #{e.message}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.run_ending(opts)
|
56
|
+
@@config ||= opts[:conf]
|
57
|
+
instance.run_ending(opts)
|
58
|
+
rescue StandardError => e
|
59
|
+
Inspec::Log.debug "Encountered error in Telemetry end run call -> #{e.message}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.note_feature_usage(feature_name)
|
63
|
+
instance.note_feature_usage(feature_name)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.config
|
67
|
+
@@config
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.telemetry_disabled?
|
71
|
+
config.telemetry_options["enable_telemetry"].nil? ? false : !config.telemetry_options["enable_telemetry"]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/inspec/version.rb
CHANGED
@@ -15,49 +15,90 @@ module Inspec
|
|
15
15
|
output = {}
|
16
16
|
|
17
17
|
files.each do |file_path|
|
18
|
-
|
19
|
-
data = nil
|
20
|
-
if [".yaml", ".yml"].include? file_extension
|
21
|
-
data = Secrets::YAML.resolve(file_path)
|
22
|
-
unless data.nil?
|
23
|
-
data = data.inputs
|
24
|
-
validate_json_yaml(data)
|
25
|
-
end
|
26
|
-
elsif file_extension == ".csv"
|
27
|
-
data = Waivers::CSVFileReader.resolve(file_path)
|
28
|
-
headers = Waivers::CSVFileReader.headers
|
29
|
-
validate_headers(headers)
|
30
|
-
elsif file_extension == ".json"
|
31
|
-
data = Waivers::JSONFileReader.resolve(file_path)
|
32
|
-
validate_json_yaml(data) unless data.nil?
|
33
|
-
end
|
18
|
+
data = read_from_file(file_path)
|
34
19
|
output.merge!(data) if !data.nil? && data.is_a?(Hash)
|
35
20
|
|
36
21
|
if data.nil?
|
37
22
|
raise Inspec::Exceptions::WaiversFileNotReadable,
|
38
|
-
"Cannot find parser for waivers file
|
23
|
+
"Cannot find parser for waivers file." \
|
39
24
|
"Check to make sure file has the appropriate extension."
|
40
25
|
end
|
26
|
+
rescue Inspec::Exceptions::WaiversFileNotReadable, Inspec::Exceptions::WaiversFileInvalidFormatting => e
|
27
|
+
Inspec::Log.error "Error reading waivers file #{file_path}. #{e.message}"
|
28
|
+
Inspec::UI.new.exit(:usage_error)
|
41
29
|
end
|
42
30
|
|
43
31
|
@waivers_data[profile_id] = output
|
44
32
|
end
|
45
33
|
|
46
|
-
def self.
|
47
|
-
|
48
|
-
|
34
|
+
def self.read_from_file(file_path)
|
35
|
+
data = nil
|
36
|
+
file_extension = File.extname(file_path)
|
37
|
+
if [".yaml", ".yml"].include? file_extension
|
38
|
+
data = Secrets::YAML.resolve(file_path)
|
39
|
+
data = data.inputs unless data.nil?
|
40
|
+
validate_json_yaml(data)
|
41
|
+
elsif file_extension == ".csv"
|
42
|
+
data = Waivers::CSVFileReader.resolve(file_path)
|
43
|
+
headers = Waivers::CSVFileReader.headers
|
44
|
+
validate_csv_headers(headers)
|
45
|
+
elsif file_extension == ".json"
|
46
|
+
data = Waivers::JSONFileReader.resolve(file_path)
|
47
|
+
validate_json_yaml(data) unless data.nil?
|
48
|
+
end
|
49
|
+
data
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.all_fields
|
53
|
+
%w{control_id justification expiration_date run}
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.validate_csv_headers(headers)
|
57
|
+
invalid_headers_info = fetch_invalid_headers_info(headers)
|
58
|
+
# Warn if blank column found in csv file
|
59
|
+
Inspec::Log.warn "Invalid column headers: Column can't be nil" if invalid_headers_info[:blank_column]
|
60
|
+
# Warn if extra header found in csv file
|
61
|
+
Inspec::Log.warn "Extra header/s #{invalid_headers_info[:extra_headers]}" unless invalid_headers_info[:extra_headers].empty?
|
62
|
+
unless invalid_headers_info[:missing_required_fields].empty?
|
63
|
+
raise Inspec::Exceptions::WaiversFileInvalidFormatting,
|
64
|
+
"Missing required header/s #{invalid_headers_info[:missing_required_fields]}. Fix headers in file to proceed."
|
65
|
+
end
|
66
|
+
end
|
49
67
|
|
50
|
-
|
51
|
-
|
52
|
-
|
68
|
+
def self.fetch_invalid_headers_info(headers, json_yaml = false)
|
69
|
+
required_fields = json_yaml ? %w{justification} : %w{control_id justification}
|
70
|
+
data = {}
|
71
|
+
data[:missing_required_fields] = []
|
72
|
+
# Finds missing required fields
|
73
|
+
unless (required_fields - headers).empty?
|
74
|
+
data[:missing_required_fields] = required_fields - headers
|
75
|
+
end
|
76
|
+
# If column with no header found set the blank_column flag. Only applicable for csv
|
77
|
+
data[:blank_column] = headers.include?(nil) ? true : false
|
78
|
+
# Find extra headers/parameters
|
79
|
+
data[:extra_headers] = (headers - all_fields)
|
80
|
+
data
|
53
81
|
end
|
54
82
|
|
55
83
|
def self.validate_json_yaml(data)
|
56
|
-
|
57
|
-
data.
|
58
|
-
headers
|
84
|
+
missing_required_field = false
|
85
|
+
data.each do |key, value|
|
86
|
+
# In case of yaml or json we need to validate headers/parametes for each value
|
87
|
+
invalid_headers_info = fetch_invalid_headers_info(value.keys, true)
|
88
|
+
# WARN in case of extra parameters found in each waived control
|
89
|
+
Inspec::Log.warn "Control ID #{key}: extra parameter/s #{invalid_headers_info[:extra_headers]}" unless invalid_headers_info[:extra_headers].empty?
|
90
|
+
unless invalid_headers_info[:missing_required_fields].empty?
|
91
|
+
missing_required_field = true
|
92
|
+
# Log error for each waived control
|
93
|
+
Inspec::Log.error "Control ID #{key}: missing required parameter/s #{invalid_headers_info[:missing_required_fields]}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Raise error if any of the waived control has missing required filed
|
98
|
+
if missing_required_field
|
99
|
+
raise Inspec::Exceptions::WaiversFileInvalidFormatting,
|
100
|
+
"Missing required parameter [justification]. Fix parameters in file to proceed."
|
59
101
|
end
|
60
|
-
validate_headers(headers.flatten.uniq, true)
|
61
102
|
end
|
62
103
|
end
|
63
104
|
end
|
data/lib/inspec.rb
CHANGED
@@ -4,6 +4,7 @@ libdir = File.dirname(__FILE__)
|
|
4
4
|
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
5
5
|
|
6
6
|
require "inspec/version"
|
7
|
+
require "inspec/utils/licensing_config"
|
7
8
|
require "inspec/exceptions"
|
8
9
|
require "inspec/utils/deprecation"
|
9
10
|
require "inspec/profile"
|
@@ -18,7 +19,6 @@ require "inspec/rspec_extensions"
|
|
18
19
|
require "inspec/globals"
|
19
20
|
require "inspec/impact"
|
20
21
|
require "inspec/utils/telemetry"
|
21
|
-
require "inspec/utils/telemetry/global_methods"
|
22
22
|
|
23
23
|
require "inspec/plugin/v2"
|
24
24
|
require "inspec/plugin/v1"
|
@@ -30,4 +30,4 @@ require "inspec/source_reader"
|
|
30
30
|
require "inspec/resource"
|
31
31
|
|
32
32
|
require "inspec/dependency_loader"
|
33
|
-
require "inspec/dependency_installer"
|
33
|
+
require "inspec/dependency_installer"
|