inspec-core 5.17.4 → 5.21.29
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +20 -17
- data/etc/deprecations.json +4 -0
- data/inspec-core.gemspec +23 -23
- data/lib/inspec/base_cli.rb +7 -0
- data/lib/inspec/cli.rb +68 -11
- data/lib/inspec/dependencies/dependency_set.rb +6 -2
- data/lib/inspec/dsl.rb +24 -5
- data/lib/inspec/enhanced_outcomes.rb +19 -0
- data/lib/inspec/env_printer.rb +1 -1
- data/lib/inspec/errors.rb +2 -0
- data/lib/inspec/exceptions.rb +4 -0
- data/lib/inspec/fetcher/url.rb +1 -1
- data/lib/inspec/file_provider.rb +36 -0
- data/lib/inspec/formatters/base.rb +69 -16
- data/lib/inspec/iaf_file.rb +127 -0
- data/lib/inspec/plugin/v2/loader.rb +19 -8
- data/lib/inspec/plugin/v2/plugin_types/reporter.rb +1 -0
- data/lib/inspec/plugin/v2/plugin_types/streaming_reporter.rb +54 -0
- data/lib/inspec/profile.rb +17 -7
- data/lib/inspec/reporters/base.rb +1 -0
- data/lib/inspec/reporters/cli.rb +94 -3
- data/lib/inspec/reporters/json.rb +3 -1
- data/lib/inspec/reporters/yaml.rb +3 -1
- data/lib/inspec/reporters.rb +2 -1
- data/lib/inspec/resources/aide_conf.rb +4 -0
- data/lib/inspec/resources/apache.rb +4 -0
- data/lib/inspec/resources/apache_conf.rb +4 -0
- data/lib/inspec/resources/apt.rb +6 -1
- data/lib/inspec/resources/audit_policy.rb +5 -0
- data/lib/inspec/resources/auditd_conf.rb +4 -0
- data/lib/inspec/resources/bash.rb +4 -0
- data/lib/inspec/resources/bond.rb +4 -0
- data/lib/inspec/resources/bridge.rb +4 -0
- data/lib/inspec/resources/cassandradb_conf.rb +5 -0
- data/lib/inspec/resources/cassandradb_session.rb +8 -3
- data/lib/inspec/resources/chocolatey_package.rb +4 -0
- data/lib/inspec/resources/chrony_conf.rb +4 -0
- data/lib/inspec/resources/command.rb +5 -0
- data/lib/inspec/resources/cpan.rb +4 -0
- data/lib/inspec/resources/cran.rb +4 -0
- data/lib/inspec/resources/cron.rb +5 -0
- data/lib/inspec/resources/csv.rb +6 -1
- data/lib/inspec/resources/dh_params.rb +4 -0
- data/lib/inspec/resources/docker_container.rb +4 -0
- data/lib/inspec/resources/docker_image.rb +4 -0
- data/lib/inspec/resources/docker_plugin.rb +4 -0
- data/lib/inspec/resources/docker_service.rb +4 -0
- data/lib/inspec/resources/etc_group.rb +4 -0
- data/lib/inspec/resources/etc_hosts_allow_deny.rb +5 -0
- data/lib/inspec/resources/file.rb +7 -2
- data/lib/inspec/resources/filesystem.rb +4 -0
- data/lib/inspec/resources/gem.rb +4 -0
- data/lib/inspec/resources/groups.rb +4 -0
- data/lib/inspec/resources/grub_conf.rb +4 -0
- data/lib/inspec/resources/host.rb +4 -0
- data/lib/inspec/resources/http.rb +6 -2
- data/lib/inspec/resources/ibmdb2_conf.rb +8 -0
- data/lib/inspec/resources/ibmdb2_session.rb +12 -3
- data/lib/inspec/resources/iis_app.rb +4 -0
- data/lib/inspec/resources/iis_app_pool.rb +4 -0
- data/lib/inspec/resources/iis_site.rb +4 -0
- data/lib/inspec/resources/inetd_conf.rb +4 -0
- data/lib/inspec/resources/interface.rb +4 -0
- data/lib/inspec/resources/ip6tables.rb +4 -0
- data/lib/inspec/resources/ipfilter.rb +4 -0
- data/lib/inspec/resources/ipnat.rb +4 -0
- data/lib/inspec/resources/iptables.rb +4 -0
- data/lib/inspec/resources/json.rb +4 -0
- data/lib/inspec/resources/kernel_module.rb +4 -0
- data/lib/inspec/resources/kernel_parameter.rb +4 -0
- data/lib/inspec/resources/key_rsa.rb +4 -0
- data/lib/inspec/resources/ksh.rb +4 -0
- data/lib/inspec/resources/limits_conf.rb +4 -0
- data/lib/inspec/resources/login_defs.rb +4 -0
- data/lib/inspec/resources/lxc.rb +65 -9
- data/lib/inspec/resources/mongodb.rb +4 -0
- data/lib/inspec/resources/mongodb_conf.rb +5 -0
- data/lib/inspec/resources/mongodb_session.rb +6 -1
- data/lib/inspec/resources/mount.rb +4 -0
- data/lib/inspec/resources/mssql_session.rb +4 -0
- data/lib/inspec/resources/mssql_sys_conf.rb +7 -0
- data/lib/inspec/resources/mysql_conf.rb +4 -0
- data/lib/inspec/resources/mysql_session.rb +8 -1
- data/lib/inspec/resources/nginx.rb +6 -1
- data/lib/inspec/resources/nginx_conf.rb +4 -0
- data/lib/inspec/resources/noop.rb +4 -0
- data/lib/inspec/resources/npm.rb +4 -0
- data/lib/inspec/resources/ntp_conf.rb +4 -0
- data/lib/inspec/resources/oneget.rb +4 -0
- data/lib/inspec/resources/opa_api.rb +10 -0
- data/lib/inspec/resources/opa_cli.rb +14 -0
- data/lib/inspec/resources/oracledb_conf.rb +5 -0
- data/lib/inspec/resources/oracledb_listener_conf.rb +4 -0
- data/lib/inspec/resources/oracledb_session.rb +23 -4
- data/lib/inspec/resources/os.rb +4 -0
- data/lib/inspec/resources/os_env.rb +4 -0
- data/lib/inspec/resources/package.rb +4 -0
- data/lib/inspec/resources/parse_config.rb +10 -1
- data/lib/inspec/resources/pip.rb +4 -0
- data/lib/inspec/resources/platform.rb +4 -0
- data/lib/inspec/resources/podman.rb +353 -0
- data/lib/inspec/resources/podman_container.rb +84 -0
- data/lib/inspec/resources/podman_image.rb +108 -0
- data/lib/inspec/resources/podman_network.rb +81 -0
- data/lib/inspec/resources/podman_pod.rb +101 -0
- data/lib/inspec/resources/podman_volume.rb +87 -0
- data/lib/inspec/resources/postfix_conf.rb +4 -0
- data/lib/inspec/resources/postgres_conf.rb +4 -0
- data/lib/inspec/resources/postgres_session.rb +8 -4
- data/lib/inspec/resources/powershell.rb +4 -0
- data/lib/inspec/resources/processes.rb +6 -4
- data/lib/inspec/resources/rabbitmq_config.rb +4 -0
- data/lib/inspec/resources/registry_key.rb +4 -0
- data/lib/inspec/resources/security_identifier.rb +4 -0
- data/lib/inspec/resources/security_policy.rb +4 -0
- data/lib/inspec/resources/service.rb +5 -1
- data/lib/inspec/resources/ssh_config.rb +4 -0
- data/lib/inspec/resources/sybase_conf.rb +4 -0
- data/lib/inspec/resources/sybase_session.rb +4 -0
- data/lib/inspec/resources/sys_info.rb +4 -0
- data/lib/inspec/resources/timezone.rb +4 -0
- data/lib/inspec/resources/users.rb +4 -0
- data/lib/inspec/resources/vbscript.rb +5 -0
- data/lib/inspec/resources/virtualization.rb +4 -0
- data/lib/inspec/resources/windows_feature.rb +5 -1
- data/lib/inspec/resources/windows_firewall.rb +4 -0
- data/lib/inspec/resources/windows_firewall_rule.rb +4 -0
- data/lib/inspec/resources/windows_hotfix.rb +4 -0
- data/lib/inspec/resources/windows_task.rb +4 -0
- data/lib/inspec/resources/wmi.rb +4 -0
- data/lib/inspec/resources/x509_certificate.rb +59 -0
- data/lib/inspec/resources/yum.rb +4 -0
- data/lib/inspec/resources/zfs_dataset.rb +4 -0
- data/lib/inspec/resources/zfs_pool.rb +4 -0
- data/lib/inspec/rule.rb +55 -18
- data/lib/inspec/run_data/control.rb +6 -0
- data/lib/inspec/run_data/statistics.rb +8 -2
- data/lib/inspec/runner.rb +18 -8
- data/lib/inspec/runner_rspec.rb +3 -2
- data/lib/inspec/schema/exec_json.rb +78 -2
- data/lib/inspec/schema/output_schema.rb +4 -1
- data/lib/inspec/schema/profile_json.rb +46 -0
- data/lib/inspec/schema.rb +91 -0
- data/lib/inspec/secrets/yaml.rb +7 -1
- data/lib/inspec/ui.rb +1 -0
- data/lib/inspec/utils/convert.rb +8 -0
- data/lib/inspec/utils/podman.rb +24 -0
- data/lib/inspec/utils/waivers/csv_file_reader.rb +34 -0
- data/lib/inspec/utils/waivers/excel_file_reader.rb +39 -0
- data/lib/inspec/utils/waivers/json_file_reader.rb +15 -0
- data/lib/inspec/utils/yaml_profile_summary.rb +34 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/inspec/waiver_file_reader.rb +61 -0
- data/lib/matchers/matchers.rb +7 -1
- data/lib/plugins/inspec-init/templates/profiles/alicloud/README.md +27 -0
- data/lib/plugins/inspec-init/templates/profiles/alicloud/controls/example.rb +10 -0
- data/lib/plugins/inspec-init/templates/profiles/alicloud/inputs.yml +1 -0
- data/lib/plugins/inspec-init/templates/profiles/alicloud/inspec.yml +14 -0
- data/lib/plugins/inspec-reporter-html2/README.md +1 -1
- data/lib/plugins/inspec-reporter-html2/templates/body.html.erb +11 -5
- data/lib/plugins/inspec-reporter-html2/templates/control.html.erb +11 -7
- data/lib/plugins/inspec-reporter-html2/templates/default.css +12 -0
- data/lib/plugins/inspec-reporter-html2/templates/profile.html.erb +1 -1
- data/lib/plugins/inspec-reporter-html2/templates/selector.html.erb +7 -1
- data/lib/plugins/{inspec-artifact/inspec-artifact.gemspec → inspec-sign/inspec-sign.gemspec} +2 -2
- data/lib/plugins/inspec-sign/lib/inspec-sign/base.rb +164 -0
- data/lib/plugins/{inspec-artifact/lib/inspec-artifact → inspec-sign/lib/inspec-sign}/cli.rb +14 -23
- data/lib/plugins/inspec-sign/lib/inspec-sign.rb +12 -0
- data/lib/plugins/inspec-streaming-reporter-progress-bar/lib/inspec-streaming-reporter-progress-bar/streaming_reporter.rb +39 -13
- data/lib/source_readers/inspec.rb +8 -2
- metadata +33 -15
- data/lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb +0 -187
- data/lib/plugins/inspec-artifact/lib/inspec-artifact.rb +0 -12
@@ -0,0 +1,127 @@
|
|
1
|
+
require "base64" unless defined?(Base64)
|
2
|
+
require "openssl" unless defined?(OpenSSL)
|
3
|
+
require "set" unless defined?(Set)
|
4
|
+
require "uri" unless defined?(URI)
|
5
|
+
|
6
|
+
module Inspec
|
7
|
+
class IafFile
|
8
|
+
KEY_ALG = OpenSSL::PKey::RSA
|
9
|
+
INSPEC_PROFILE_VERSION_1 = "INSPEC-PROFILE-1".freeze
|
10
|
+
INSPEC_PROFILE_VERSION_2 = "INSPEC-PROFILE-2".freeze
|
11
|
+
|
12
|
+
ARTIFACT_DIGEST = OpenSSL::Digest::SHA512
|
13
|
+
ARTIFACT_DIGEST_NAME = "SHA512".freeze
|
14
|
+
|
15
|
+
VALID_PROFILE_VERSIONS = Set.new [INSPEC_PROFILE_VERSION_1, INSPEC_PROFILE_VERSION_2]
|
16
|
+
VALID_PROFILE_DIGESTS = Set.new [ARTIFACT_DIGEST_NAME]
|
17
|
+
|
18
|
+
def self.find_validation_key(keyname)
|
19
|
+
[
|
20
|
+
".",
|
21
|
+
File.join(Inspec.config_dir, "keys"),
|
22
|
+
File.join(Inspec.src_root, "etc", "keys"),
|
23
|
+
].each do |path|
|
24
|
+
filename = File.join(path, "#{keyname}.pem.pub")
|
25
|
+
return filename if File.exist?(filename)
|
26
|
+
rescue ArgumentError => e
|
27
|
+
puts e
|
28
|
+
raise Inspec::Exceptions::ProfileValidationKeyNotFound.new("Validation key #{keyname} not found")
|
29
|
+
end
|
30
|
+
|
31
|
+
# Retry if we can fetch it from github
|
32
|
+
return find_validation_key(keyname) if fetch_validation_key_from_github(keyname)
|
33
|
+
|
34
|
+
raise Inspec::Exceptions::ProfileValidationKeyNotFound.new("Validation key #{keyname} not found")
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.find_signing_key(keyname)
|
38
|
+
[".", File.join(Inspec.config_dir, "keys")].each do |path|
|
39
|
+
filename = File.join(path, "#{keyname}.pem.key")
|
40
|
+
return filename if File.exist?(filename)
|
41
|
+
end
|
42
|
+
raise Inspec::Exceptions::ProfileSigningKeyNotFound.new("Signing key #{keyname} not found")
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.fetch_validation_key_from_github(keyname)
|
46
|
+
URI.open("https://raw.githubusercontent.com/inspec/inspec/main/etc/keys/#{keyname}.pem.pub") do |r|
|
47
|
+
puts "Fetching validation key '#{keyname}' from github"
|
48
|
+
dir = File.join(Inspec.config_dir, "keys")
|
49
|
+
FileUtils.mkdir_p dir
|
50
|
+
key_file = File.join(dir, "#{keyname}.pem.pub")
|
51
|
+
File.open(key_file, "w") do |f|
|
52
|
+
r.each_line do |line|
|
53
|
+
f.puts line
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
true
|
58
|
+
rescue OpenURI::HTTPError
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_reader :key_name, :version
|
63
|
+
|
64
|
+
def initialize(path)
|
65
|
+
@path = path
|
66
|
+
@key_name = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def valid?
|
70
|
+
header = []
|
71
|
+
valid = true
|
72
|
+
f = File.open(@path, "rb")
|
73
|
+
@version = f.readline.strip!
|
74
|
+
if version == INSPEC_PROFILE_VERSION_1
|
75
|
+
header << version
|
76
|
+
header << f.readline.strip!
|
77
|
+
header << f.readline.strip!
|
78
|
+
|
79
|
+
file_sig = ""
|
80
|
+
# the signature is multi-line
|
81
|
+
while (line = f.readline) != "\n"
|
82
|
+
file_sig += line
|
83
|
+
end
|
84
|
+
header << file_sig.strip!
|
85
|
+
f.close
|
86
|
+
|
87
|
+
f = File.open(@path, "rb")
|
88
|
+
while f.readline != "\n" do end
|
89
|
+
content = f.read
|
90
|
+
f.close
|
91
|
+
elsif version == INSPEC_PROFILE_VERSION_2
|
92
|
+
header << version
|
93
|
+
header << f.readline.strip!
|
94
|
+
content = f.read
|
95
|
+
f.close
|
96
|
+
|
97
|
+
header_content = content.unpack("h*").pack("H*")
|
98
|
+
header << header_content.slice(0, 100).rstrip
|
99
|
+
header << header_content.slice(100, 20).rstrip
|
100
|
+
header << header_content.slice(120, 370).rstrip + "\n" # \n at the end is require in this field
|
101
|
+
content = content.slice(490, content.length).lstrip
|
102
|
+
else
|
103
|
+
valid = false
|
104
|
+
end
|
105
|
+
|
106
|
+
@key_name = header[2]
|
107
|
+
validation_key_path = Inspec::IafFile.find_validation_key(@key_name)
|
108
|
+
|
109
|
+
unless valid_header?(header)
|
110
|
+
valid = false
|
111
|
+
end
|
112
|
+
|
113
|
+
verification_key = KEY_ALG.new File.read validation_key_path
|
114
|
+
signature = Base64.decode64(header[4])
|
115
|
+
digest = ARTIFACT_DIGEST.new
|
116
|
+
unless verification_key.verify digest, signature, content
|
117
|
+
valid = false
|
118
|
+
end
|
119
|
+
|
120
|
+
valid
|
121
|
+
end
|
122
|
+
|
123
|
+
def valid_header?(header)
|
124
|
+
VALID_PROFILE_VERSIONS.member?(header[0]) && VALID_PROFILE_DIGESTS.member?(header[3])
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -178,7 +178,19 @@ module Inspec::Plugin::V2
|
|
178
178
|
# TODO: enforce first-level version pinning
|
179
179
|
plugin_deps = [Gem::Dependency.new(plugin_gem_name.to_s, version_constraint)]
|
180
180
|
managed_gem_set = Gem::Resolver::VendorSet.new
|
181
|
-
|
181
|
+
|
182
|
+
list_managed_gems.each do |spec|
|
183
|
+
if Gem::Specification.load spec.gem_dir
|
184
|
+
managed_gem_set.add_vendor_gem(spec.name, spec.gem_dir)
|
185
|
+
else
|
186
|
+
# In case of invalid gemspec as mentioned in this PR https://github.com/brianmario/yajl-ruby/pull/223
|
187
|
+
# the add_vendor_gem breaks. So this is patch to fix the loading issue.
|
188
|
+
# Horribly, chdir to gemspec path to honor . in gemspec
|
189
|
+
Dir.chdir(spec.gem_dir) do |dir|
|
190
|
+
managed_gem_set.add_vendor_gem(spec.name, spec.gem_dir)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
182
194
|
|
183
195
|
# TODO: Next two lines merge our managed gems with the other gems available
|
184
196
|
# in our "local universe" - which may be the system, or it could be in a Bundler microcosm,
|
@@ -278,7 +290,12 @@ module Inspec::Plugin::V2
|
|
278
290
|
when :user_gem
|
279
291
|
status.entry_point = status.name.to_s
|
280
292
|
status.version = plugin_entry[:version]
|
281
|
-
|
293
|
+
# Fetch the summary of the gem from local gemspec file instead of remote call using Gem::SpecFetcher.fetcher.
|
294
|
+
unless plugin_entry[:version].nil? # safe check very rare case.
|
295
|
+
version_string = plugin_entry[:version].gsub(/[=,~,>,<]/, "").strip
|
296
|
+
plugin_name_with_version = "#{status.name}-#{version_string}"
|
297
|
+
status.description = fetch_gemspec(File.join(plugin_gem_path, "gems", plugin_name_with_version, "/", status.name.to_s + ".gemspec"))&.summary
|
298
|
+
end
|
282
299
|
when :path
|
283
300
|
status.entry_point = plugin_entry[:installation_path]
|
284
301
|
end
|
@@ -287,12 +304,6 @@ module Inspec::Plugin::V2
|
|
287
304
|
end
|
288
305
|
end
|
289
306
|
|
290
|
-
def fetch_plugin_specs(plugin_name)
|
291
|
-
fetcher = Gem::SpecFetcher.fetcher
|
292
|
-
plugin_dependency = Gem::Dependency.new(plugin_name)
|
293
|
-
fetcher.spec_for_dependency(plugin_dependency).flatten.first
|
294
|
-
end
|
295
|
-
|
296
307
|
def fixup_train_plugin_status(status)
|
297
308
|
status.api_generation = :'train-1'
|
298
309
|
if status.installation_type == :user_gem
|
@@ -11,6 +11,7 @@ module Inspec::Plugin::V2::PluginType
|
|
11
11
|
@running_controls_list = []
|
12
12
|
@control_checks_count_map = {}
|
13
13
|
@controls_count = nil
|
14
|
+
@notifications = {}
|
14
15
|
end
|
15
16
|
|
16
17
|
private
|
@@ -49,5 +50,58 @@ module Inspec::Plugin::V2::PluginType
|
|
49
50
|
@control_checks_count_map = RSpec.configuration.formatters.grep(Inspec::Formatters::Base).first.get_control_checks_count_map
|
50
51
|
end
|
51
52
|
end
|
53
|
+
|
54
|
+
def enhanced_outcomes
|
55
|
+
@enhanced_outcomes ||= RSpec.configuration.formatters.grep(Inspec::Formatters::Base).first.enhanced_outcomes
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_enhanced_outcomes(control_id)
|
59
|
+
if control_has_error(@notifications[control_id])
|
60
|
+
"error"
|
61
|
+
elsif control_has_impact_zero(@notifications[control_id])
|
62
|
+
"not_applicable"
|
63
|
+
elsif control_has_all_tests_skipped(@notifications[control_id])
|
64
|
+
"not_reviewed"
|
65
|
+
elsif control_has_any_tests_failed(@notifications[control_id])
|
66
|
+
"failed"
|
67
|
+
else
|
68
|
+
"passed"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def control_has_error(notifications)
|
73
|
+
notifications.any? do |notification_data|
|
74
|
+
notification, _status = notification_data
|
75
|
+
!notification.example.exception.nil? && !(notification.example.exception.is_a? RSpec::Expectations::ExpectationNotMetError) && !notification.example.exception.backtrace.nil? && (!notification.description.include? "No-op") # No-op exception occurs in case of not_applicable_if
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def control_has_all_tests_skipped(notifications)
|
80
|
+
notifications.all? do |notification_data|
|
81
|
+
_notification, status = notification_data
|
82
|
+
status == "skipped"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def control_has_any_tests_failed(notifications)
|
87
|
+
notifications.any? do |notification_data|
|
88
|
+
_notification, status = notification_data
|
89
|
+
status == "failed"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def control_has_impact_zero(notifications)
|
94
|
+
notification_data = notifications.first
|
95
|
+
notification_impact = notification_data.first.example.metadata[:impact]
|
96
|
+
notification_data && !notification_impact.nil? && notification_impact.to_f == 0.0
|
97
|
+
end
|
98
|
+
|
99
|
+
def collect_notifications(notification, control_id, status)
|
100
|
+
if @notifications[control_id].nil?
|
101
|
+
@notifications[control_id] = [[notification, status]]
|
102
|
+
else
|
103
|
+
@notifications[control_id].push([notification, status])
|
104
|
+
end
|
105
|
+
end
|
52
106
|
end
|
53
107
|
end
|
data/lib/inspec/profile.rb
CHANGED
@@ -350,22 +350,24 @@ module Inspec
|
|
350
350
|
def load_libraries
|
351
351
|
return @runner_context if @libraries_loaded
|
352
352
|
|
353
|
-
locked_dependencies.dep_list.each_with_index do |(_name, dep),
|
353
|
+
locked_dependencies.dep_list.each_with_index do |(_name, dep), index|
|
354
354
|
d = dep.profile
|
355
355
|
# this will force a dependent profile load so we are only going to add
|
356
356
|
# this metadata if the parent profile is supported.
|
357
357
|
if @supports_platform && !d.supports_platform?
|
358
358
|
# since ruby 1.9 hashes are ordered so we can just use index values here
|
359
359
|
# TODO: NO! this is a violation of encapsulation to an extreme
|
360
|
-
metadata.dependencies[
|
361
|
-
|
362
|
-
|
363
|
-
|
360
|
+
if metadata.dependencies[index]
|
361
|
+
metadata.dependencies[index][:status] = "skipped"
|
362
|
+
msg = "Skipping profile: '#{d.name}' on unsupported platform: '#{d.backend.platform.name}/#{d.backend.platform.release}'."
|
363
|
+
metadata.dependencies[index][:status_message] = msg
|
364
|
+
metadata.dependencies[index][:skip_message] = msg # Repeat as skip_message for backward compatibility
|
365
|
+
end
|
364
366
|
next
|
365
|
-
elsif metadata.dependencies[
|
367
|
+
elsif metadata.dependencies[index]
|
366
368
|
# Currently wrapper profiles will load all dependencies, and then we
|
367
369
|
# load them again when we dive down. This needs to be re-done.
|
368
|
-
metadata.dependencies[
|
370
|
+
metadata.dependencies[index][:status] = "loaded"
|
369
371
|
end
|
370
372
|
|
371
373
|
# rubocop:disable Layout/ExtraSpacing
|
@@ -746,6 +748,14 @@ module Inspec
|
|
746
748
|
@source_reader.target.files
|
747
749
|
end
|
748
750
|
|
751
|
+
def readme
|
752
|
+
@source_reader.readme&.values&.first
|
753
|
+
end
|
754
|
+
|
755
|
+
def metadata_src
|
756
|
+
@source_reader.metadata_src
|
757
|
+
end
|
758
|
+
|
749
759
|
#
|
750
760
|
# TODO(ssd): Relative path handling really needs to be carefully
|
751
761
|
# thought through, especially with respect to relative paths in
|
data/lib/inspec/reporters/cli.rb
CHANGED
@@ -9,6 +9,9 @@ module Inspec::Reporters
|
|
9
9
|
"passed" => "\033[0;1;32m",
|
10
10
|
"skipped" => "\033[0;37m",
|
11
11
|
"reset" => "\033[0m",
|
12
|
+
"error" => "\033[34m",
|
13
|
+
"not_applicable" => "\033[36m",
|
14
|
+
"not_reviewed" => "\033[33m",
|
12
15
|
}.freeze
|
13
16
|
|
14
17
|
# Most currently available Windows terminals have poor support
|
@@ -18,6 +21,9 @@ module Inspec::Reporters
|
|
18
21
|
"skipped" => "[SKIP]",
|
19
22
|
"passed" => "[PASS]",
|
20
23
|
"unknown" => "[UNKN]",
|
24
|
+
"error" => "[ERR]",
|
25
|
+
"not_applicable" => "[N/A]",
|
26
|
+
"not_reviewed" => "[N/R]",
|
21
27
|
}.freeze
|
22
28
|
else
|
23
29
|
# Extended colors for everyone else
|
@@ -26,6 +32,9 @@ module Inspec::Reporters
|
|
26
32
|
"passed" => "\033[38;5;41m",
|
27
33
|
"skipped" => "\033[38;5;247m",
|
28
34
|
"reset" => "\033[0m",
|
35
|
+
"error" => "\033[0;38;5;21m",
|
36
|
+
"not_applicable" => "\033[0;38;5;117m",
|
37
|
+
"not_reviewed" => "\033[0;38;5;214m",
|
29
38
|
}.freeze
|
30
39
|
|
31
40
|
# Groovy UTF-8 characters for everyone else...
|
@@ -35,6 +44,9 @@ module Inspec::Reporters
|
|
35
44
|
"skipped" => "↺",
|
36
45
|
"passed" => "✔",
|
37
46
|
"unknown" => "?",
|
47
|
+
"error" => "ERR",
|
48
|
+
"not_applicable" => "N/A",
|
49
|
+
"not_reviewed" => "N/R",
|
38
50
|
}.freeze
|
39
51
|
end
|
40
52
|
|
@@ -63,7 +75,11 @@ module Inspec::Reporters
|
|
63
75
|
end
|
64
76
|
|
65
77
|
output("")
|
66
|
-
|
78
|
+
if enhanced_outcomes
|
79
|
+
print_control_outcomes_summary
|
80
|
+
else
|
81
|
+
print_profile_summary
|
82
|
+
end
|
67
83
|
print_tests_summary
|
68
84
|
end
|
69
85
|
|
@@ -88,6 +104,7 @@ module Inspec::Reporters
|
|
88
104
|
def print_standard_control_results(profile)
|
89
105
|
standard_controls_from_profile(profile).each do |control_from_profile|
|
90
106
|
control = Control.new(control_from_profile)
|
107
|
+
control.enhanced_outcomes = enhanced_outcomes
|
91
108
|
next if control.results.nil?
|
92
109
|
|
93
110
|
output(format_control_header(control))
|
@@ -122,7 +139,7 @@ module Inspec::Reporters
|
|
122
139
|
end
|
123
140
|
|
124
141
|
def format_control_header(control)
|
125
|
-
impact = control.impact_string
|
142
|
+
impact = enhanced_outcomes ? control.impact_string_for_enhanced_outcomes : control.impact_string
|
126
143
|
format_message(
|
127
144
|
color: impact,
|
128
145
|
indicator: impact,
|
@@ -292,6 +309,68 @@ module Inspec::Reporters
|
|
292
309
|
}
|
293
310
|
end
|
294
311
|
|
312
|
+
def control_outcomes_summary
|
313
|
+
failed = 0
|
314
|
+
passed = 0
|
315
|
+
error = 0
|
316
|
+
not_reviewed = 0
|
317
|
+
not_applicable = 0
|
318
|
+
|
319
|
+
all_unique_controls.each do |control|
|
320
|
+
next if control[:status].empty?
|
321
|
+
|
322
|
+
if control[:status] == "failed"
|
323
|
+
failed += 1
|
324
|
+
elsif control[:status] == "error"
|
325
|
+
error += 1
|
326
|
+
elsif control[:status] == "not_reviewed"
|
327
|
+
not_reviewed += 1
|
328
|
+
elsif control[:status] == "not_applicable"
|
329
|
+
not_applicable += 1
|
330
|
+
else
|
331
|
+
passed += 1
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
total = failed + passed + error + not_reviewed + not_applicable
|
336
|
+
|
337
|
+
{
|
338
|
+
"total" => total,
|
339
|
+
"failed" => failed,
|
340
|
+
"passed" => passed,
|
341
|
+
"error" => error,
|
342
|
+
"not_reviewed" => not_reviewed,
|
343
|
+
"not_applicable" => not_applicable,
|
344
|
+
}
|
345
|
+
end
|
346
|
+
|
347
|
+
def print_control_outcomes_summary
|
348
|
+
summary = control_outcomes_summary
|
349
|
+
return unless summary["total"] > 0
|
350
|
+
|
351
|
+
success_str = summary["passed"] == 1 ? "1 successful control" : "#{summary["passed"]} successful controls"
|
352
|
+
failed_str = summary["failed"] == 1 ? "1 control failure" : "#{summary["failed"]} control failures"
|
353
|
+
error_str = summary["error"] == 1 ? "1 control has error" : "#{summary["error"]} controls have error"
|
354
|
+
not_rev_str = summary["not_reviewed"] == 1 ? "1 control not reviewed" : "#{summary["not_reviewed"]} controls not reviewed"
|
355
|
+
not_app_str = summary["not_applicable"] == 1 ? "1 control not applicable" : "#{summary["not_applicable"]} controls not applicable"
|
356
|
+
|
357
|
+
success_color = summary["passed"] > 0 ? "passed" : "no_color"
|
358
|
+
failed_color = summary["failed"] > 0 ? "failed" : "no_color"
|
359
|
+
error_color = summary["error"] > 0 ? "error" : "no_color"
|
360
|
+
not_rev_color = summary["not_reviewed"] > 0 ? "not_reviewed" : "no_color"
|
361
|
+
not_app_color = summary["not_applicable"] > 0 ? "not_applicable" : "no_color"
|
362
|
+
|
363
|
+
s = format(
|
364
|
+
"Profile Summary: %s, %s, %s, %s, %s",
|
365
|
+
format_with_color(success_color, success_str),
|
366
|
+
format_with_color(failed_color, failed_str),
|
367
|
+
format_with_color(not_rev_color, not_rev_str),
|
368
|
+
format_with_color(not_app_color, not_app_str),
|
369
|
+
format_with_color(error_color, error_str)
|
370
|
+
)
|
371
|
+
output(s) if summary["total"] > 0
|
372
|
+
end
|
373
|
+
|
295
374
|
def print_profile_summary
|
296
375
|
summary = profile_summary
|
297
376
|
return unless summary["total"] > 0
|
@@ -350,6 +429,7 @@ module Inspec::Reporters
|
|
350
429
|
|
351
430
|
class Control
|
352
431
|
attr_reader :data
|
432
|
+
attr_accessor :enhanced_outcomes
|
353
433
|
|
354
434
|
def initialize(control_hash)
|
355
435
|
@data = control_hash
|
@@ -379,6 +459,10 @@ module Inspec::Reporters
|
|
379
459
|
id.start_with?("(generated from ")
|
380
460
|
end
|
381
461
|
|
462
|
+
def status
|
463
|
+
data[:status]
|
464
|
+
end
|
465
|
+
|
382
466
|
def title_for_report
|
383
467
|
# if this is an anonymous control, just grab the resource title from any result entry
|
384
468
|
return results.first[:resource_title] if anonymous?
|
@@ -392,10 +476,17 @@ module Inspec::Reporters
|
|
392
476
|
# append a failure summary if appropriate.
|
393
477
|
title_for_report += " (#{failure_count} failed)" if failure_count > 0
|
394
478
|
title_for_report += " (#{skipped_count} skipped)" if skipped_count > 0
|
395
|
-
|
396
479
|
title_for_report
|
397
480
|
end
|
398
481
|
|
482
|
+
def impact_string_for_enhanced_outcomes
|
483
|
+
if impact.nil?
|
484
|
+
"unknown"
|
485
|
+
else
|
486
|
+
status
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
399
490
|
def impact_string
|
400
491
|
if anonymous?
|
401
492
|
nil
|
@@ -114,7 +114,7 @@ module Inspec::Reporters
|
|
114
114
|
|
115
115
|
def profile_controls(profile)
|
116
116
|
(profile[:controls] || []).map { |c|
|
117
|
-
{
|
117
|
+
control_hash = {
|
118
118
|
id: c[:id],
|
119
119
|
title: c[:title],
|
120
120
|
desc: c.dig(:descriptions, :default),
|
@@ -130,6 +130,8 @@ module Inspec::Reporters
|
|
130
130
|
waiver_data: c[:waiver_data] || {},
|
131
131
|
results: profile_results(c),
|
132
132
|
}
|
133
|
+
control_hash.merge!({ status: c[:status] }) if enhanced_outcomes
|
134
|
+
control_hash
|
133
135
|
}
|
134
136
|
end
|
135
137
|
|
@@ -3,7 +3,9 @@ require "yaml"
|
|
3
3
|
module Inspec::Reporters
|
4
4
|
class Yaml < Base
|
5
5
|
def render
|
6
|
-
|
6
|
+
json_reporter_obj = Inspec::Reporters::Json.new({ run_data: run_data })
|
7
|
+
json_reporter_obj.enhanced_outcomes = enhanced_outcomes
|
8
|
+
output(json_reporter_obj.report.to_yaml, false)
|
7
9
|
end
|
8
10
|
|
9
11
|
def report
|
data/lib/inspec/reporters.rb
CHANGED
@@ -7,7 +7,7 @@ require "inspec/reporters/yaml"
|
|
7
7
|
|
8
8
|
module Inspec::Reporters
|
9
9
|
# rubocop:disable Metrics/CyclomaticComplexity
|
10
|
-
def self.render(reporter, run_data)
|
10
|
+
def self.render(reporter, run_data, enhanced_outcomes = false)
|
11
11
|
name, config = reporter.dup
|
12
12
|
config[:run_data] = run_data
|
13
13
|
case name
|
@@ -29,6 +29,7 @@ module Inspec::Reporters
|
|
29
29
|
activator.activate!
|
30
30
|
reporter = activator.implementation_class.new(config)
|
31
31
|
end
|
32
|
+
reporter.enhanced_outcomes = enhanced_outcomes
|
32
33
|
|
33
34
|
# optional send_report method on reporter
|
34
35
|
return reporter.send_report if defined?(reporter.send_report)
|
data/lib/inspec/resources/apt.rb
CHANGED
@@ -39,10 +39,11 @@ module Inspec::Resources
|
|
39
39
|
EXAMPLE
|
40
40
|
|
41
41
|
def initialize(ppa_name)
|
42
|
+
@ppa_name = ppa_name
|
42
43
|
@deb_url = nil
|
43
44
|
# check if the os is ubuntu or debian
|
44
45
|
if inspec.os.debian?
|
45
|
-
@deb_url = determine_ppa_url(ppa_name)
|
46
|
+
@deb_url = determine_ppa_url(@ppa_name)
|
46
47
|
else
|
47
48
|
# this resource is only supported on ubuntu and debian
|
48
49
|
skip_resource "The `apt` resource is not supported on your OS yet."
|
@@ -61,6 +62,10 @@ module Inspec::Resources
|
|
61
62
|
actives.size == 1 && actives[0] = true
|
62
63
|
end
|
63
64
|
|
65
|
+
def resource_id
|
66
|
+
@deb_url || @ppa_name || "apt repository"
|
67
|
+
end
|
68
|
+
|
64
69
|
def to_s
|
65
70
|
"Apt Repository #{@deb_url}"
|
66
71
|
end
|
@@ -31,6 +31,11 @@ module Inspec::Resources
|
|
31
31
|
super(@conf_path)
|
32
32
|
end
|
33
33
|
|
34
|
+
# if system unables to determine the cassandra conf path the @conf_path can be nil so in that case sending "" string as resource_id
|
35
|
+
def resource_id
|
36
|
+
@conf_path || "cassandradb_conf"
|
37
|
+
end
|
38
|
+
|
34
39
|
private
|
35
40
|
|
36
41
|
def parse(content)
|