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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f6f86730baadd988c363a823e5e46ba68c318e48b27bbaaba614ce7c33bb71c
|
4
|
+
data.tar.gz: f02ca42e9d4e525b82e9cfa61a04b122dc3b09c1e3c96f2ec4440c3fb3053f25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 597fed943b00ed280a749f05c97d01e29b4d5a85034835e9f242990588b35b740bf56a886b65202777d68b79b5cbd1faf1a48a69c1a4f1f8a00a83ecdece3527
|
7
|
+
data.tar.gz: 13aa012d46677b3cd31614dcc118c62b1aa1656f3007d6b105f7822a3c25a45b1b1284eef9fb9e761cf5a03cd8209ffe8518d54ed355c189a2f141788a000694
|
data/Gemfile
CHANGED
@@ -23,13 +23,12 @@ group :omnibus do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
group :test do
|
26
|
-
gem "chefstyle", "~> 2.
|
26
|
+
gem "chefstyle", "~> 2.2.2"
|
27
27
|
gem "concurrent-ruby", "~> 1.0"
|
28
|
-
gem "html-proofer", platforms: :ruby # do not attempt to run proofer on windows
|
29
28
|
gem "json_schemer", ">= 0.2.1", "< 0.2.19"
|
30
29
|
gem "m"
|
31
30
|
gem "minitest-sprint", "~> 1.0"
|
32
|
-
gem "minitest", "
|
31
|
+
gem "minitest", "5.15.0"
|
33
32
|
gem "mocha", "~> 1.1"
|
34
33
|
gem "nokogiri", "~> 1.9"
|
35
34
|
gem "pry-byebug"
|
@@ -39,26 +38,30 @@ group :test do
|
|
39
38
|
gem "simplecov", "~> 0.21"
|
40
39
|
gem "simplecov_json_formatter"
|
41
40
|
gem "webmock", "~> 3.0"
|
41
|
+
|
42
|
+
if Gem.ruby_version >= Gem::Version.new("3.0.0")
|
43
|
+
# html-proofer has a dep on io-event, which is ruby-3 only
|
44
|
+
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.
|
45
|
+
end
|
42
46
|
end
|
43
47
|
|
44
48
|
group :deploy do
|
45
49
|
gem "inquirer"
|
46
50
|
end
|
47
51
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
gem "
|
54
|
-
|
55
|
-
|
56
|
-
gem "
|
57
|
-
gem "kitchen-dokken", ">= 2.11"
|
58
|
-
gem "git"
|
52
|
+
group :kitchen do
|
53
|
+
gem "berkshelf"
|
54
|
+
|
55
|
+
# Chef 18 requires ruby 3
|
56
|
+
if Gem.ruby_version >= Gem::Version.new("3.0.0")
|
57
|
+
gem "chef", ">= 17.0"
|
58
|
+
else
|
59
|
+
# Ruby 2.7 presumably - TODO remove this when 2.7 is sunsetted
|
60
|
+
gem "chef", "~> 16.0"
|
59
61
|
end
|
60
|
-
end
|
61
62
|
|
62
|
-
|
63
|
-
gem "
|
63
|
+
gem "test-kitchen", ">= 2.8"
|
64
|
+
gem "kitchen-inspec", ">= 2.0"
|
65
|
+
gem "kitchen-dokken", ">= 2.11"
|
66
|
+
gem "git"
|
64
67
|
end
|
data/etc/deprecations.json
CHANGED
@@ -121,6 +121,10 @@
|
|
121
121
|
"cli_option_target_id":{
|
122
122
|
"action": "warn",
|
123
123
|
"prefix": "The --target-id option is deprecated in InSpec 5. Its value will be ignored."
|
124
|
+
},
|
125
|
+
"renamed_to_inspec_export":{
|
126
|
+
"action": "ignore",
|
127
|
+
"prefix": "The `inspec json` command is deprecated in InSpec 5 and replaced with `inspec export` command."
|
124
128
|
}
|
125
129
|
}
|
126
130
|
}
|
data/inspec-core.gemspec
CHANGED
@@ -18,32 +18,32 @@ Gem::Specification.new do |spec|
|
|
18
18
|
# the gemfile and gemspec are necessary for appbundler so don't remove it
|
19
19
|
spec.files =
|
20
20
|
Dir.glob("{{lib,etc}/**/*,LICENSE,Gemfile,inspec-core.gemspec}")
|
21
|
-
.grep_v(%r{(?<!inspec-init/templates/profiles/)(aws|azure|gcp)})
|
21
|
+
.grep_v(%r{(?<!inspec-init/templates/profiles/)(aws|azure|gcp|alicloud)})
|
22
22
|
.grep_v(%r{lib/plugins/.*/test/})
|
23
23
|
.reject { |f| File.directory?(f) }
|
24
24
|
|
25
25
|
# Implementation dependencies
|
26
|
-
spec.add_dependency "chef-telemetry",
|
27
|
-
spec.add_dependency "license-acceptance",
|
28
|
-
spec.add_dependency "thor",
|
29
|
-
spec.add_dependency "method_source",
|
30
|
-
spec.add_dependency "rubyzip",
|
31
|
-
spec.add_dependency "rspec",
|
32
|
-
spec.add_dependency "rspec-its",
|
33
|
-
spec.add_dependency "pry",
|
34
|
-
spec.add_dependency "hashie",
|
35
|
-
spec.add_dependency "mixlib-log",
|
36
|
-
spec.add_dependency "sslshake",
|
37
|
-
spec.add_dependency "parallel",
|
38
|
-
spec.add_dependency "faraday",
|
39
|
-
spec.add_dependency "
|
40
|
-
spec.add_dependency "tty-table",
|
41
|
-
spec.add_dependency "tty-prompt",
|
42
|
-
spec.add_dependency "tomlrb",
|
43
|
-
spec.add_dependency "addressable",
|
44
|
-
spec.add_dependency "parslet",
|
45
|
-
spec.add_dependency "semverse",
|
46
|
-
spec.add_dependency "multipart-post",
|
26
|
+
spec.add_dependency "chef-telemetry", "~> 1.0", ">= 1.0.8" # 1.0.8+ removes the http dep
|
27
|
+
spec.add_dependency "license-acceptance", ">= 0.2.13", "< 3.0"
|
28
|
+
spec.add_dependency "thor", ">= 0.20", "< 2.0"
|
29
|
+
spec.add_dependency "method_source", ">= 0.8", "< 2.0"
|
30
|
+
spec.add_dependency "rubyzip", ">= 1.2.2", "< 3.0"
|
31
|
+
spec.add_dependency "rspec", ">= 3.9", "<= 3.11"
|
32
|
+
spec.add_dependency "rspec-its", "~> 1.2"
|
33
|
+
spec.add_dependency "pry", "~> 0.13"
|
34
|
+
spec.add_dependency "hashie", ">= 3.4", "< 5.0"
|
35
|
+
spec.add_dependency "mixlib-log", "~> 3.0"
|
36
|
+
spec.add_dependency "sslshake", "~> 1.2"
|
37
|
+
spec.add_dependency "parallel", "~> 1.9"
|
38
|
+
spec.add_dependency "faraday", ">= 1", "< 3"
|
39
|
+
spec.add_dependency "faraday-follow_redirects", "~> 0.3"
|
40
|
+
spec.add_dependency "tty-table", "~> 0.10"
|
41
|
+
spec.add_dependency "tty-prompt", "~> 0.17"
|
42
|
+
spec.add_dependency "tomlrb", ">= 1.2", "< 2.1"
|
43
|
+
spec.add_dependency "addressable", "~> 2.4"
|
44
|
+
spec.add_dependency "parslet", ">= 1.5", "< 2.0" # Pinned < 2.0, see #5389
|
45
|
+
spec.add_dependency "semverse", "~> 3.0"
|
46
|
+
spec.add_dependency "multipart-post", "~> 2.0"
|
47
47
|
|
48
|
-
spec.add_dependency "train-core", "~> 3.
|
48
|
+
spec.add_dependency "train-core", "~> 3.10"
|
49
49
|
end
|
data/lib/inspec/base_cli.rb
CHANGED
@@ -138,6 +138,8 @@ module Inspec
|
|
138
138
|
desc: "Provides path to Docker API endpoint (Docker)"
|
139
139
|
option :ssh_config_file, type: :array,
|
140
140
|
desc: "A list of paths to the ssh config file, e.g ~/.ssh/config or /etc/ssh/ssh_config"
|
141
|
+
option :podman_url, type: :string,
|
142
|
+
desc: "Provides path to Podman API endpoint"
|
141
143
|
end
|
142
144
|
|
143
145
|
def self.profile_options
|
@@ -203,6 +205,8 @@ module Inspec
|
|
203
205
|
long_desc: "Maximum seconds to allow commands to run during execution. A timed out command is considered an error."
|
204
206
|
option :reporter_include_source, type: :boolean, default: false,
|
205
207
|
desc: "Include full source code of controls in the CLI report"
|
208
|
+
option :enhanced_outcomes, type: :boolean,
|
209
|
+
desc: "Show enhanced outcomes in output"
|
206
210
|
end
|
207
211
|
|
208
212
|
def self.help(*args)
|
@@ -323,6 +327,9 @@ module Inspec
|
|
323
327
|
|
324
328
|
def pretty_handle_exception(exception)
|
325
329
|
case exception
|
330
|
+
when Inspec::InvalidProfileSignature
|
331
|
+
$stderr.puts exception.message
|
332
|
+
Inspec::UI.new.exit(:bad_signature)
|
326
333
|
when Inspec::Error
|
327
334
|
$stderr.puts exception.message
|
328
335
|
exit(1)
|
data/lib/inspec/cli.rb
CHANGED
@@ -5,6 +5,7 @@ require "inspec/dist"
|
|
5
5
|
require "inspec/backend"
|
6
6
|
require "inspec/dependencies/cache"
|
7
7
|
require "inspec/utils/json_profile_summary"
|
8
|
+
require "inspec/utils/yaml_profile_summary"
|
8
9
|
|
9
10
|
module Inspec # TODO: move this somewhere "better"?
|
10
11
|
autoload :BaseCLI, "inspec/base_cli"
|
@@ -69,25 +70,77 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
69
70
|
desc: "A list of tags to filter controls and include only those. Ignore all other tests."
|
70
71
|
profile_options
|
71
72
|
def json(target)
|
72
|
-
|
73
|
+
# This deprecation warning is ignored currently.
|
74
|
+
Inspec.deprecate(:renamed_to_inspec_export)
|
75
|
+
export(target, true)
|
76
|
+
end
|
73
77
|
|
78
|
+
desc "export PATH", "read the profile in PATH and generate a summary in the given format."
|
79
|
+
option :what, type: :string,
|
80
|
+
desc: "What to export: profile (default), readme, metadata."
|
81
|
+
option :format, type: :string,
|
82
|
+
desc: "The output format to use: json, raw, yaml. If valid format is not provided then it will use the default for the given 'what'."
|
83
|
+
option :output, aliases: :o, type: :string,
|
84
|
+
desc: "Save the created output to a path"
|
85
|
+
option :controls, type: :array,
|
86
|
+
desc: "For --what=profile, a list of controls to include. Ignore all other tests."
|
87
|
+
option :tags, type: :array,
|
88
|
+
desc: "For --what=profile, a list of tags to filter controls and include only those. Ignore all other tests."
|
89
|
+
profile_options
|
90
|
+
def export(target, as_json = false)
|
74
91
|
o = config
|
75
92
|
diagnose(o)
|
76
93
|
o["log_location"] = $stderr
|
77
94
|
configure_logger(o)
|
78
95
|
|
96
|
+
# using dup to resolve "can't modify frozen String" error.
|
97
|
+
what = o[:what].dup || "profile"
|
98
|
+
what.downcase!
|
99
|
+
raise Inspec::Error.new("Unrecognized option '#{what}' for --what - expected one of profile, readme, or metadata.") unless %w{profile readme metadata}.include?(what)
|
100
|
+
|
101
|
+
default_format_for_what = {
|
102
|
+
"profile" => "yaml",
|
103
|
+
"metadata" => "raw",
|
104
|
+
"readme" => "raw",
|
105
|
+
}
|
106
|
+
valid_formats_for_what = {
|
107
|
+
"profile" => %w{yaml json},
|
108
|
+
"metadata" => %w{yaml raw}, # not going to argue
|
109
|
+
"readme" => ["raw"],
|
110
|
+
}
|
111
|
+
format = o[:format] || default_format_for_what[what]
|
112
|
+
# default is json if we were called as old json command
|
113
|
+
format = "json" if as_json
|
114
|
+
raise Inspec::Error.new("Invalid option '#{format}' for --format and --what combination") unless format && valid_formats_for_what[what].include?(format)
|
115
|
+
|
79
116
|
o[:backend] = Inspec::Backend.create(Inspec::Config.mock)
|
80
117
|
o[:check_mode] = true
|
81
118
|
o[:vendor_cache] = Inspec::Cache.new(o[:vendor_cache])
|
82
|
-
|
83
119
|
profile = Inspec::Profile.for_target(target, o)
|
84
120
|
dst = o[:output].to_s
|
85
121
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
122
|
+
case what
|
123
|
+
when "profile"
|
124
|
+
if format == "json"
|
125
|
+
require "json" unless defined?(JSON)
|
126
|
+
# Write JSON
|
127
|
+
Inspec::Utils::JsonProfileSummary.produce_json(
|
128
|
+
info: profile.info,
|
129
|
+
write_path: dst
|
130
|
+
)
|
131
|
+
elsif format == "yaml"
|
132
|
+
Inspec::Utils::YamlProfileSummary.produce_yaml(
|
133
|
+
info: profile.info,
|
134
|
+
write_path: dst
|
135
|
+
)
|
136
|
+
end
|
137
|
+
when "readme"
|
138
|
+
out = dst.empty? ? $stdout : File.open(dst, "w")
|
139
|
+
out.write(profile.readme)
|
140
|
+
when "metadata"
|
141
|
+
out = dst.empty? ? $stdout : File.open(dst, "w")
|
142
|
+
out.write(profile.metadata_src)
|
143
|
+
end
|
91
144
|
rescue StandardError => e
|
92
145
|
pretty_handle_exception(e)
|
93
146
|
end
|
@@ -189,12 +242,12 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
189
242
|
desc: "Fallback to using local archives if fetching fails."
|
190
243
|
option :ignore_errors, type: :boolean, default: false,
|
191
244
|
desc: "Ignore profile warnings."
|
192
|
-
def archive(path)
|
245
|
+
def archive(path, log_level = nil)
|
193
246
|
o = config
|
194
247
|
diagnose(o)
|
195
248
|
|
196
249
|
o[:logger] = Logger.new($stdout)
|
197
|
-
o[:logger].level = get_log_level(o[:log_level])
|
250
|
+
o[:logger].level = get_log_level(log_level || o[:log_level])
|
198
251
|
o[:backend] = Inspec::Backend.create(Inspec::Config.mock)
|
199
252
|
|
200
253
|
# Force vendoring with overwrite when archiving
|
@@ -362,6 +415,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
362
415
|
desc: "Load one or more input files, a YAML file with values for the shell to use"
|
363
416
|
option :input, type: :array, banner: "name1=value1 name2=value2",
|
364
417
|
desc: "Specify one or more inputs directly on the command line to the shell, as --input NAME=VALUE. Accepts single-quoted YAML and JSON structures."
|
418
|
+
option :enhanced_outcomes, type: :boolean,
|
419
|
+
desc: "Show enhanced outcomes in output"
|
365
420
|
def shell_func
|
366
421
|
o = config
|
367
422
|
deprecate_target_id(config)
|
@@ -408,11 +463,13 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
408
463
|
pretty_handle_exception(e)
|
409
464
|
end
|
410
465
|
|
466
|
+
option :enhanced_outcomes, type: :boolean,
|
467
|
+
desc: "Show enhanced outcomes output"
|
411
468
|
desc "schema NAME", "print the JSON schema", hide: true
|
412
469
|
def schema(name)
|
413
470
|
require "inspec/schema/output_schema"
|
414
|
-
|
415
|
-
puts Inspec::Schema::OutputSchema.json(name)
|
471
|
+
o = config
|
472
|
+
puts Inspec::Schema::OutputSchema.json(name, o)
|
416
473
|
rescue StandardError => e
|
417
474
|
puts e
|
418
475
|
puts "Valid schemas are #{Inspec::Schema::OutputSchema.names.join(", ")}"
|
@@ -25,7 +25,9 @@ module Inspec
|
|
25
25
|
def self.from_array(dependencies, cwd, cache, backend)
|
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 ? "#{d.name}-#{d.source_version}" : "#{d.name}") rescue "#{d.name}"
|
30
|
+
dep_list[key_name] = d
|
29
31
|
end
|
30
32
|
new(cwd, cache, dep_list, backend)
|
31
33
|
end
|
@@ -39,7 +41,9 @@ module Inspec
|
|
39
41
|
def self.flatten_dep_tree(dep_tree)
|
40
42
|
dep_list = {}
|
41
43
|
dep_tree.each do |d|
|
42
|
-
|
44
|
+
# if depedent profile does not have a source version then only name is used in dependency hash
|
45
|
+
key_name = (d.source_version ? "#{d.name}-#{d.source_version}" : "#{d.name}") rescue d.name
|
46
|
+
dep_list[key_name] = d
|
43
47
|
dep_list.merge!(flatten_dep_tree(d.dependencies))
|
44
48
|
end
|
45
49
|
dep_list
|
data/lib/inspec/dsl.rb
CHANGED
@@ -6,13 +6,13 @@ require "inspec/utils/deprecated_cloud_resources_list"
|
|
6
6
|
module Inspec::DSL
|
7
7
|
attr_accessor :backend
|
8
8
|
|
9
|
-
def require_controls(id, &block)
|
10
|
-
opts = { profile_id: id, include_all: false, backend: @backend, conf: @conf, dependencies: @dependencies }
|
9
|
+
def require_controls(id, version = nil, &block)
|
10
|
+
opts = { profile_id: id, include_all: false, backend: @backend, conf: @conf, dependencies: @dependencies, profile_version: version }
|
11
11
|
::Inspec::DSL.load_spec_files_for_profile(self, opts, &block)
|
12
12
|
end
|
13
13
|
|
14
|
-
def include_controls(id, &block)
|
15
|
-
opts = { profile_id: id, include_all: true, backend: @backend, conf: @conf, dependencies: @dependencies }
|
14
|
+
def include_controls(id, version = nil, &block)
|
15
|
+
opts = { profile_id: id, include_all: true, backend: @backend, conf: @conf, dependencies: @dependencies, profile_version: version }
|
16
16
|
::Inspec::DSL.load_spec_files_for_profile(self, opts, &block)
|
17
17
|
end
|
18
18
|
|
@@ -85,7 +85,26 @@ module Inspec::DSL
|
|
85
85
|
def self.load_spec_files_for_profile(bind_context, opts, &block)
|
86
86
|
dependencies = opts[:dependencies]
|
87
87
|
profile_id = opts[:profile_id]
|
88
|
-
|
88
|
+
profile_version = opts[:profile_version]
|
89
|
+
|
90
|
+
new_profile_id = nil
|
91
|
+
if profile_version
|
92
|
+
new_profile_id = "#{profile_id}-#{profile_version}"
|
93
|
+
else
|
94
|
+
# This scary regex is used to match version following semantic Versioning (SemVer). Thanks to https://ihateregex.io/expr/semver/
|
95
|
+
regex_for_semver = /(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?/
|
96
|
+
dependencies.list.keys.each do |key|
|
97
|
+
# 1. Fetching VERSION from a profile dependency name which is in a format NAME-VERSION.
|
98
|
+
# 2. Matching original profile dependency name with profile name used with include or require control DSL.
|
99
|
+
fetching_semver = key.match(regex_for_semver).to_s
|
100
|
+
unless fetching_semver.nil? || fetching_semver.empty?
|
101
|
+
profile_id_key = key.split("-#{fetching_semver}")[0]
|
102
|
+
new_profile_id = key if profile_id_key == profile_id
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
# If dep profile does not contain a source version, key does not contain a version as well. In that case new_profile_id will be always nil and instead profile_id would be used to fetch profile from dependency list.
|
107
|
+
dep_entry = new_profile_id ? dependencies.list[new_profile_id] : dependencies.list[profile_id]
|
89
108
|
|
90
109
|
if dep_entry.nil?
|
91
110
|
raise <<~EOF
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Inspec
|
2
|
+
module EnhancedOutcomes
|
3
|
+
|
4
|
+
def self.determine_status(results, impact)
|
5
|
+
# No-op exception occurs in case of not_applicable_if
|
6
|
+
if results.any? { |r| !r[:exception].nil? && !r[:backtrace].nil? && r[:resource_class] != "noop" }
|
7
|
+
"error"
|
8
|
+
elsif !impact.nil? && impact.to_f == 0.0
|
9
|
+
"not_applicable"
|
10
|
+
elsif results.all? { |r| r[:status] == "skipped" }
|
11
|
+
"not_reviewed"
|
12
|
+
elsif results.any? { |r| r[:status] == "failed" }
|
13
|
+
"failed"
|
14
|
+
else
|
15
|
+
"passed"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/inspec/env_printer.rb
CHANGED
@@ -35,7 +35,7 @@ module Inspec
|
|
35
35
|
private
|
36
36
|
|
37
37
|
def print_completion_for_shell
|
38
|
-
erb = ERB.new(File.read(completion_template_path),
|
38
|
+
erb = ERB.new(File.read(completion_template_path), trim_mode: "-")
|
39
39
|
puts erb.result(TemplateContext.new(@command_class).get_bindings)
|
40
40
|
end
|
41
41
|
|
data/lib/inspec/errors.rb
CHANGED
data/lib/inspec/exceptions.rb
CHANGED
@@ -8,5 +8,9 @@ module Inspec
|
|
8
8
|
class ResourceFailed < StandardError; end
|
9
9
|
class ResourceSkipped < StandardError; end
|
10
10
|
class SecretsBackendNotFound < ArgumentError; end
|
11
|
+
class ProfileValidationKeyNotFound < ArgumentError; end
|
12
|
+
class ProfileSigningKeyNotFound < ArgumentError; end
|
13
|
+
class WaiversFileNotReadable < ArgumentError; end
|
14
|
+
class WaiversFileDoesNotExist < ArgumentError; end
|
11
15
|
end
|
12
16
|
end
|
data/lib/inspec/fetcher/url.rb
CHANGED
@@ -262,7 +262,7 @@ module Inspec::Fetcher
|
|
262
262
|
|
263
263
|
open(target, opts)
|
264
264
|
|
265
|
-
rescue SocketError, Errno::ECONNREFUSED, OpenURI::HTTPError => e
|
265
|
+
rescue SocketError, Net::OpenTimeout, Errno::ECONNREFUSED, OpenURI::HTTPError => e
|
266
266
|
raise Inspec::FetcherFailure, "Profile URL dependency #{target} could not be fetched: #{e.message}"
|
267
267
|
end
|
268
268
|
|
data/lib/inspec/file_provider.rb
CHANGED
@@ -2,6 +2,7 @@ require "rubygems/package" unless defined?(Gem::Package)
|
|
2
2
|
require "pathname" unless defined?(Pathname)
|
3
3
|
require "zlib" unless defined?(Zlib)
|
4
4
|
require "zip" unless defined?(Zip)
|
5
|
+
require "inspec/iaf_file"
|
5
6
|
|
6
7
|
module Inspec
|
7
8
|
class FileProvider
|
@@ -14,6 +15,13 @@ module Inspec
|
|
14
15
|
TarProvider.new(path)
|
15
16
|
elsif File.exist?(path) && path.end_with?(".zip")
|
16
17
|
ZipProvider.new(path)
|
18
|
+
elsif File.exist?(path) && path.end_with?(".iaf")
|
19
|
+
iaf_file = IafFile.new(path)
|
20
|
+
if iaf_file.valid?
|
21
|
+
IafProvider.new(path)
|
22
|
+
else
|
23
|
+
raise Inspec::InvalidProfileSignature, "Profile signature is invalid."
|
24
|
+
end
|
17
25
|
elsif File.exist?(path)
|
18
26
|
DirProvider.new(path)
|
19
27
|
else
|
@@ -216,6 +224,34 @@ module Inspec
|
|
216
224
|
end
|
217
225
|
end # class TarProvider
|
218
226
|
|
227
|
+
class IafProvider < TarProvider
|
228
|
+
attr_reader :files
|
229
|
+
|
230
|
+
def initialize(path)
|
231
|
+
f = File.open(path, "rb")
|
232
|
+
version = f.readline.strip!
|
233
|
+
if version == "INSPEC-PROFILE-1"
|
234
|
+
while f.readline != "\n" do end
|
235
|
+
content = f.read
|
236
|
+
f.close
|
237
|
+
elsif version == "INSPEC-PROFILE-2"
|
238
|
+
f.readline.strip!
|
239
|
+
content = f.read
|
240
|
+
f.close
|
241
|
+
content = content.slice(490, content.length).lstrip
|
242
|
+
else
|
243
|
+
raise Inspec::InvalidProfileSignature, "Unrecognized IAF version."
|
244
|
+
end
|
245
|
+
|
246
|
+
tmpfile = nil
|
247
|
+
Dir.mktmpdir do |workdir|
|
248
|
+
tmpfile = Pathname.new(workdir).join("temp_profile.tar.gz")
|
249
|
+
File.open(tmpfile, "wb") { |fl| fl.write(content) }
|
250
|
+
super(tmpfile)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end # class IafProvider
|
254
|
+
|
219
255
|
class RelativeFileProvider
|
220
256
|
BLACKLIST_FILES = [
|
221
257
|
"/pax_global_header",
|
@@ -1,12 +1,13 @@
|
|
1
1
|
require "rspec/core"
|
2
2
|
require "rspec/core/formatters/base_formatter"
|
3
3
|
require "set" unless defined?(Set)
|
4
|
+
require "inspec/enhanced_outcomes"
|
4
5
|
|
5
6
|
module Inspec::Formatters
|
6
7
|
class Base < RSpec::Core::Formatters::BaseFormatter
|
7
8
|
RSpec::Core::Formatters.register self, :close, :dump_summary, :stop
|
8
9
|
|
9
|
-
attr_accessor :backend, :run_data
|
10
|
+
attr_accessor :backend, :run_data, :enhanced_outcomes
|
10
11
|
|
11
12
|
def initialize(output)
|
12
13
|
super(output)
|
@@ -17,6 +18,7 @@ module Inspec::Formatters
|
|
17
18
|
@backend = nil
|
18
19
|
@all_controls_count = nil
|
19
20
|
@control_checks_count_map = {}
|
21
|
+
@enhanced_outcomes = nil
|
20
22
|
end
|
21
23
|
|
22
24
|
# RSpec Override: #dump_summary
|
@@ -50,7 +52,6 @@ module Inspec::Formatters
|
|
50
52
|
else
|
51
53
|
hash[:message] = exception_message(e)
|
52
54
|
end
|
53
|
-
|
54
55
|
next if e.is_a? RSpec::Expectations::ExpectationNotMetError
|
55
56
|
|
56
57
|
hash[:exception] = e.class.name
|
@@ -68,6 +69,8 @@ module Inspec::Formatters
|
|
68
69
|
# flesh out the profiles key with additional profile information
|
69
70
|
run_data[:profiles] = profiles_info
|
70
71
|
|
72
|
+
add_enhanced_outcomes_to_controls if enhanced_outcomes
|
73
|
+
|
71
74
|
# add the platform information for this particular target
|
72
75
|
run_data[:platform] = {
|
73
76
|
name: platform(:name),
|
@@ -110,6 +113,20 @@ module Inspec::Formatters
|
|
110
113
|
|
111
114
|
private
|
112
115
|
|
116
|
+
def add_enhanced_outcomes_to_controls
|
117
|
+
all_unique_controls.each do |control|
|
118
|
+
control[:status] = determine_control_enhanced_outcome(control)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def determine_control_enhanced_outcome(control)
|
123
|
+
if control[:results]
|
124
|
+
Inspec::EnhancedOutcomes.determine_status(control[:results], control[:impact])
|
125
|
+
else
|
126
|
+
"passed"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
113
130
|
def all_unique_controls
|
114
131
|
unique_controls = Set.new
|
115
132
|
run_data[:profiles].each do |profile|
|
@@ -120,25 +137,59 @@ module Inspec::Formatters
|
|
120
137
|
end
|
121
138
|
|
122
139
|
def statistics
|
140
|
+
error = 0
|
141
|
+
not_applicable = 0
|
142
|
+
not_reviewed = 0
|
123
143
|
failed = 0
|
124
|
-
skipped = 0
|
125
144
|
passed = 0
|
145
|
+
skipped = 0
|
146
|
+
enhanced_outcomes_summary = {}
|
147
|
+
if enhanced_outcomes
|
148
|
+
all_unique_controls.each do |control|
|
149
|
+
|
150
|
+
if control[:status] == "error"
|
151
|
+
error += 1
|
152
|
+
elsif control[:status] == "not_applicable"
|
153
|
+
not_applicable += 1
|
154
|
+
elsif control[:status] == "not_reviewed"
|
155
|
+
not_reviewed += 1
|
156
|
+
elsif control[:status] == "failed"
|
157
|
+
failed += 1
|
158
|
+
elsif control[:status] == "passed"
|
159
|
+
passed += 1
|
160
|
+
end
|
126
161
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
if control[:results].any? { |r| r[:status] == "failed" }
|
131
|
-
failed += 1
|
132
|
-
elsif control[:results].any? { |r| r[:status] == "skipped" }
|
133
|
-
skipped += 1
|
134
|
-
else
|
135
|
-
passed += 1
|
136
|
-
end
|
137
|
-
end
|
162
|
+
# added this additionally because stats summary is also used for determining exit code in runner rspec
|
163
|
+
skipped += 1 if control[:results].any? { |r| r[:status] == "skipped" }
|
138
164
|
|
139
|
-
|
165
|
+
end
|
166
|
+
total = error + not_applicable + not_reviewed + failed + passed
|
167
|
+
enhanced_outcomes_summary = {
|
168
|
+
not_applicable: {
|
169
|
+
total: not_applicable,
|
170
|
+
},
|
171
|
+
not_reviewed: {
|
172
|
+
total: not_reviewed,
|
173
|
+
},
|
174
|
+
error: {
|
175
|
+
total: error,
|
176
|
+
},
|
177
|
+
}
|
178
|
+
else
|
179
|
+
all_unique_controls.each do |control|
|
180
|
+
next unless control[:results]
|
140
181
|
|
141
|
-
|
182
|
+
if control[:results].any? { |r| r[:status] == "failed" }
|
183
|
+
failed += 1
|
184
|
+
elsif control[:results].any? { |r| r[:status] == "skipped" }
|
185
|
+
skipped += 1
|
186
|
+
else
|
187
|
+
passed += 1
|
188
|
+
end
|
189
|
+
end
|
190
|
+
total = failed + passed + skipped
|
191
|
+
end
|
192
|
+
final_summary = {
|
142
193
|
total: total,
|
143
194
|
passed: {
|
144
195
|
total: passed,
|
@@ -150,6 +201,8 @@ module Inspec::Formatters
|
|
150
201
|
total: failed,
|
151
202
|
},
|
152
203
|
}
|
204
|
+
|
205
|
+
final_summary.merge!(enhanced_outcomes_summary)
|
153
206
|
end
|
154
207
|
|
155
208
|
def exception_message(exception)
|