inspec-core 5.18.14 → 5.22.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +19 -17
  3. data/inspec-core.gemspec +22 -22
  4. data/lib/inspec/base_cli.rb +19 -17
  5. data/lib/inspec/cli.rb +27 -25
  6. data/lib/inspec/dependencies/dependency_set.rb +2 -2
  7. data/lib/inspec/dsl.rb +9 -5
  8. data/lib/inspec/enhanced_outcomes.rb +19 -0
  9. data/lib/inspec/env_printer.rb +1 -1
  10. data/lib/inspec/exceptions.rb +2 -0
  11. data/lib/inspec/formatters/base.rb +69 -16
  12. data/lib/inspec/plugin/v2/loader.rb +19 -8
  13. data/lib/inspec/plugin/v2/plugin_types/reporter.rb +1 -0
  14. data/lib/inspec/plugin/v2/plugin_types/streaming_reporter.rb +54 -0
  15. data/lib/inspec/profile.rb +9 -8
  16. data/lib/inspec/reporters/base.rb +1 -0
  17. data/lib/inspec/reporters/cli.rb +94 -3
  18. data/lib/inspec/reporters/json.rb +3 -1
  19. data/lib/inspec/reporters/yaml.rb +3 -1
  20. data/lib/inspec/reporters.rb +2 -1
  21. data/lib/inspec/resources/file.rb +1 -1
  22. data/lib/inspec/resources/http.rb +5 -5
  23. data/lib/inspec/resources/lxc.rb +65 -9
  24. data/lib/inspec/resources/mongodb_session.rb +5 -0
  25. data/lib/inspec/resources/nftables.rb +251 -0
  26. data/lib/inspec/resources/oracledb_session.rb +13 -4
  27. data/lib/inspec/resources/podman.rb +353 -0
  28. data/lib/inspec/resources/podman_container.rb +84 -0
  29. data/lib/inspec/resources/podman_image.rb +108 -0
  30. data/lib/inspec/resources/podman_network.rb +81 -0
  31. data/lib/inspec/resources/podman_pod.rb +101 -0
  32. data/lib/inspec/resources/podman_volume.rb +87 -0
  33. data/lib/inspec/resources/postgres_session.rb +2 -1
  34. data/lib/inspec/resources/service.rb +1 -1
  35. data/lib/inspec/resources.rb +1 -0
  36. data/lib/inspec/rule.rb +54 -17
  37. data/lib/inspec/run_data/control.rb +6 -0
  38. data/lib/inspec/run_data/statistics.rb +8 -2
  39. data/lib/inspec/runner.rb +18 -8
  40. data/lib/inspec/runner_rspec.rb +3 -2
  41. data/lib/inspec/schema/exec_json.rb +78 -2
  42. data/lib/inspec/schema/output_schema.rb +4 -1
  43. data/lib/inspec/schema/profile_json.rb +46 -0
  44. data/lib/inspec/schema.rb +91 -0
  45. data/lib/inspec/utils/convert.rb +8 -0
  46. data/lib/inspec/utils/podman.rb +24 -0
  47. data/lib/inspec/utils/simpleconfig.rb +10 -2
  48. data/lib/inspec/utils/waivers/csv_file_reader.rb +34 -0
  49. data/lib/inspec/utils/waivers/excel_file_reader.rb +39 -0
  50. data/lib/inspec/utils/waivers/json_file_reader.rb +15 -0
  51. data/lib/inspec/version.rb +1 -1
  52. data/lib/inspec/waiver_file_reader.rb +61 -0
  53. data/lib/matchers/matchers.rb +15 -2
  54. data/lib/plugins/inspec-init/templates/profiles/alicloud/README.md +27 -0
  55. data/lib/plugins/inspec-init/templates/profiles/alicloud/controls/example.rb +10 -0
  56. data/lib/plugins/inspec-init/templates/profiles/alicloud/inputs.yml +1 -0
  57. data/lib/plugins/inspec-init/templates/profiles/alicloud/inspec.yml +14 -0
  58. data/lib/plugins/inspec-reporter-html2/README.md +1 -1
  59. data/lib/plugins/inspec-reporter-html2/templates/body.html.erb +7 -1
  60. data/lib/plugins/inspec-reporter-html2/templates/control.html.erb +10 -6
  61. data/lib/plugins/inspec-reporter-html2/templates/default.css +12 -0
  62. data/lib/plugins/inspec-reporter-html2/templates/selector.html.erb +7 -1
  63. data/lib/plugins/inspec-sign/lib/inspec-sign/base.rb +5 -2
  64. data/lib/plugins/inspec-streaming-reporter-progress-bar/lib/inspec-streaming-reporter-progress-bar/streaming_reporter.rb +39 -13
  65. metadata +26 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba97ee3e25e02fba9b85f797fa1a773d2e8fa7628112be422d187c0e46cfce40
4
- data.tar.gz: a82f51e5c6ba3e1db8c4580f92a33d91bcc2e0c2a8339850e1f168c1569b8818
3
+ metadata.gz: 257ccbe0a55a1779ee75f8d6e9e8e0ff612990c123e5cdb10d8cf1e19dbade54
4
+ data.tar.gz: 820f9a0ec86451f48f65f229befe175cf937648ddb5669df1c8a7c27ebfb234b
5
5
  SHA512:
6
- metadata.gz: beb78893376f0b92b9cf33741f8fab471f66dd328fa1f28c87b05737da7f73266327eded07ca67f0b91a747625dfcb61011b42c06a25914d01f727b07a962456
7
- data.tar.gz: 193aeef4576e2af4466a176b80e107cd45fe0c0c0f6db290d17696cec1eb7dbf6b58b555bf8c0df4b9bb4a9d5aa8d26f542993b5be1d600a296c3ec50e531d09
6
+ metadata.gz: 8150cdd9aca6ac14ae762dd4b6d09867dab6651f0a0705a28f7256a94683a1fd59b7841bfc69e1a362c253d6c2a847d2e9a03b901dd20118ecc1566b4496a8a9
7
+ data.tar.gz: a3469cb7fa6786e1d9416e9493fed402ccfb6c8e6ac0a2d40a0029ab63c09b09671cf6729736899ed1a039ca75e36a6a57428deba9a8c5d6dbf0975711a06d13
data/Gemfile CHANGED
@@ -23,9 +23,8 @@ group :omnibus do
23
23
  end
24
24
 
25
25
  group :test do
26
- gem "chefstyle", "~> 2.0.3"
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"
@@ -35,30 +34,33 @@ group :test do
35
34
  gem "pry-byebug"
36
35
  gem "pry", "~> 0.10"
37
36
  gem "rake", ">= 10"
38
- gem "ruby-progressbar", "~> 1.8"
39
37
  gem "simplecov", "~> 0.21"
40
38
  gem "simplecov_json_formatter"
41
39
  gem "webmock", "~> 3.0"
40
+
41
+ if Gem.ruby_version >= Gem::Version.new("3.0.0")
42
+ # html-proofer has a dep on io-event, which is ruby-3 only
43
+ 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.
44
+ end
42
45
  end
43
46
 
44
47
  group :deploy do
45
48
  gem "inquirer"
46
49
  end
47
50
 
48
- # Only include Test Kitchen support if we are on Ruby 2.7 or higher
49
- # as chef-zero support requires Ruby 2.6
50
- # See https://github.com/inspec/inspec/pull/5341
51
- if Gem.ruby_version >= Gem::Version.new("2.7.0")
52
- group :kitchen do
53
- gem "berkshelf"
54
- gem "chef", ">= 16.0" # Required to allow net-ssh > 6
55
- gem "test-kitchen", ">= 2.8"
56
- gem "kitchen-inspec", ">= 2.0"
57
- gem "kitchen-dokken", ">= 2.11"
58
- gem "git"
51
+ group :kitchen do
52
+ gem "berkshelf"
53
+
54
+ # Chef 18 requires ruby 3
55
+ if Gem.ruby_version >= Gem::Version.new("3.0.0")
56
+ gem "chef", ">= 17.0"
57
+ else
58
+ # Ruby 2.7 presumably - TODO remove this when 2.7 is sunsetted
59
+ gem "chef", "~> 16.0"
59
60
  end
60
- end
61
61
 
62
- if Gem.ruby_version < Gem::Version.new("2.7.0")
63
- gem "activesupport", "6.1.4.4"
62
+ gem "test-kitchen", ">= 2.8"
63
+ gem "kitchen-inspec", ">= 2.0"
64
+ gem "kitchen-dokken", ">= 2.11"
65
+ gem "git"
64
66
  end
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", "~> 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", ">= 0.9.0", "< 1.5"
39
- spec.add_dependency "faraday_middleware", "~> 1.0"
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"
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
48
  spec.add_dependency "train-core", "~> 3.10"
49
49
  end
@@ -100,11 +100,11 @@ module Inspec
100
100
  option :ssl, type: :boolean,
101
101
  desc: "Use SSL for transport layer encryption (WinRM)."
102
102
  option :ssl_peer_fingerprint, type: :string,
103
- desc: "Specify peer fingerprint for SSL authentication, used in lieu of certificates"
103
+ desc: "Specify SSL peer fingerprint in place of certificates for SSL authentication (WinRM)."
104
104
  option :self_signed, type: :boolean,
105
105
  desc: "Allow remote scans with self-signed certificates (WinRM)."
106
106
  option :ca_trust_file, type: :string,
107
- desc: "Specify CA trust file for SSL authentication"
107
+ desc: "Specify CA certificate required for SSL authentication (WinRM)."
108
108
  option :client_cert, type: :string,
109
109
  desc: "Specify client certificate for SSL authentication"
110
110
  option :client_key, type: :string,
@@ -121,32 +121,32 @@ module Inspec
121
121
  desc: "Read configuration from JSON file (`-` reads from stdin)."
122
122
  option :json_config, type: :string, hide: true
123
123
  option :proxy_command, type: :string,
124
- desc: "Specifies the command to use to connect to the server"
124
+ desc: "Specifies the command to use to connect to the server."
125
125
  option :bastion_host, type: :string,
126
- desc: "Specifies the bastion host if applicable"
126
+ desc: "Specifies the bastion host if applicable."
127
127
  option :bastion_user, type: :string,
128
- desc: "Specifies the bastion user if applicable"
128
+ desc: "Specifies the bastion user if applicable."
129
129
  option :bastion_port, type: :string,
130
- desc: "Specifies the bastion port if applicable"
130
+ desc: "Specifies the bastion port if applicable."
131
131
  option :insecure, type: :boolean, default: false,
132
- desc: "Disable SSL verification on select targets"
132
+ desc: "Disable SSL verification on select targets."
133
133
  option :target_id, type: :string,
134
- desc: "Provide a ID which will be included on reports - deprecated"
134
+ desc: "Provide an ID which will be included on reports - deprecated"
135
135
  option :winrm_shell_type, type: :string, default: "powershell",
136
- desc: "Specify a shell type for winrm (eg. 'elevated' or 'powershell')"
136
+ desc: "Specify which shell type to use (powershell, elevated, or cmd), which defaults to powershell (WinRM)."
137
137
  option :docker_url, type: :string,
138
- desc: "Provides path to Docker API endpoint (Docker)"
138
+ desc: "Provides path to Docker API endpoint (Docker). Defaults to unix:///var/run/docker.sock on Unix systems and tcp://localhost:2375 on Windows."
139
139
  option :ssh_config_file, type: :array,
140
- desc: "A list of paths to the ssh config file, e.g ~/.ssh/config or /etc/ssh/ssh_config"
140
+ desc: "A list of paths to the ssh config file, e.g ~/.ssh/config or /etc/ssh/ssh_config."
141
141
  option :podman_url, type: :string,
142
- desc: "Provides path to Podman API endpoint"
142
+ desc: "Provides the path to the Podman API endpoint. Defaults to unix:///run/user/$UID/podman/podman.sock for rootless container, unix:///run/podman/podman.sock for rootful container (for this you need to execute inspec as root user)."
143
143
  end
144
144
 
145
145
  def self.profile_options
146
146
  option :profiles_path, type: :string,
147
147
  desc: "Folder which contains referenced profiles."
148
148
  option :vendor_cache, type: :string,
149
- desc: "Use the given path for caching dependencies. (default: ~/.inspec/cache)"
149
+ desc: "Use the given path for caching dependencies, (default: ~/.inspec/cache)."
150
150
  option :auto_install_gems, type: :boolean, default: false,
151
151
  desc: "Auto installs gem dependencies of the profile or resource pack."
152
152
  end
@@ -174,7 +174,7 @@ module Inspec
174
174
  option :input, type: :array, banner: "name1=value1 name2=value2",
175
175
  desc: "Specify one or more inputs directly on the command line, as --input NAME=VALUE. Accepts single-quoted YAML and JSON structures."
176
176
  option :input_file, type: :array,
177
- desc: "Load one or more input files, a YAML file with values for the profile to use"
177
+ desc: "Load one or more input files, a YAML file with values for the profile to use."
178
178
  option :waiver_file, type: :array,
179
179
  desc: "Load one or more waiver files."
180
180
  option :attrs, type: :array,
@@ -182,14 +182,14 @@ module Inspec
182
182
  option :create_lockfile, type: :boolean,
183
183
  desc: "Write out a lockfile based on this execution (unless one already exists)"
184
184
  option :backend_cache, type: :boolean,
185
- desc: "Allow caching for backend command output. (default: true)"
185
+ desc: "Allow caching for backend command output. (default: true)."
186
186
  option :show_progress, type: :boolean,
187
187
  desc: "Show progress while executing tests."
188
188
  option :distinct_exit, type: :boolean, default: true,
189
189
  desc: "Exit with code 101 if any tests fail, and 100 if any are skipped (default). If disabled, exit 0 on skips and 1 for failures."
190
190
  option :silence_deprecations, type: :array,
191
191
  banner: "[all]|[GROUP GROUP...]",
192
- desc: "Suppress deprecation warnings. See install_dir/etc/deprecations.json for list of GROUPs or use 'all'."
192
+ desc: "Suppress deprecation warnings. See install_dir/etc/deprecations.json for a list of GROUPs or use 'all'."
193
193
  option :diff, type: :boolean, default: true,
194
194
  desc: "Use --no-diff to suppress 'diff' output of failed textual test results."
195
195
  option :sort_results_by, type: :string, default: "file", banner: "--sort-results-by=none|control|file|random",
@@ -197,7 +197,7 @@ module Inspec
197
197
  option :filter_empty_profiles, type: :boolean, default: false,
198
198
  desc: "Filter empty profiles (profiles without controls) from the report."
199
199
  option :filter_waived_controls, type: :boolean,
200
- desc: "Do not execute waived controls in InSpec at all. Must use with --waiver-file. Ignores `run` setting of waiver file."
200
+ desc: "Do not execute waived controls in InSpec at all. Must use with --waiver-file. Ignores the `run` setting of the waiver file."
201
201
  option :retain_waiver_data, type: :boolean,
202
202
  desc: "EXPERIMENTAL: Only works in conjunction with --filter-waived-controls, retains waiver data about controls that were skipped"
203
203
  option :command_timeout, type: :numeric,
@@ -205,6 +205,8 @@ module Inspec
205
205
  long_desc: "Maximum seconds to allow commands to run during execution. A timed out command is considered an error."
206
206
  option :reporter_include_source, type: :boolean, default: false,
207
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"
208
210
  end
209
211
 
210
212
  def self.help(*args)
data/lib/inspec/cli.rb CHANGED
@@ -61,9 +61,9 @@ class Inspec::InspecCLI < Inspec::BaseCLI
61
61
  require "license_acceptance/cli_flags/thor"
62
62
  include LicenseAcceptance::CLIFlags::Thor
63
63
 
64
- desc "json PATH", "read all tests in PATH and generate a JSON summary"
64
+ desc "json PATH", "read all tests in the PATH and generate a JSON summary."
65
65
  option :output, aliases: :o, type: :string,
66
- desc: "Save the created profile to a path"
66
+ desc: "Save the created profile to a path."
67
67
  option :controls, type: :array,
68
68
  desc: "A list of controls to include. Ignore all other tests."
69
69
  option :tags, type: :array,
@@ -81,7 +81,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
81
81
  option :format, type: :string,
82
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
83
  option :output, aliases: :o, type: :string,
84
- desc: "Save the created output to a path"
84
+ desc: "Save the created output to a path."
85
85
  option :controls, type: :array,
86
86
  desc: "For --what=profile, a list of controls to include. Ignore all other tests."
87
87
  option :tags, type: :array,
@@ -145,9 +145,11 @@ class Inspec::InspecCLI < Inspec::BaseCLI
145
145
  pretty_handle_exception(e)
146
146
  end
147
147
 
148
- desc "check PATH", "verify all tests at the specified PATH"
148
+ desc "check PATH", "Verify the metadata in the `inspec.yml` file,\
149
+ verify that control blocks have the correct fields (title, description, impact),\
150
+ and define that all controls have visible tests and the controls are not using deprecated InSpec DSL code"
149
151
  option :format, type: :string,
150
- desc: "The output format to use doc (default), json. If valid format is not provided then it will use the default."
152
+ desc: "The output format to use. Valid values: `json` and `doc`. Default value: `doc`."
151
153
  option :with_cookstyle, type: :boolean,
152
154
  desc: "Enable or disable cookstyle checks.", default: false
153
155
  profile_options
@@ -228,10 +230,10 @@ class Inspec::InspecCLI < Inspec::BaseCLI
228
230
  vendor_deps(path, o)
229
231
  end
230
232
 
231
- desc "archive PATH", "archive a profile to tar.gz (default) or zip"
233
+ desc "archive PATH", "Archive a profile to a tar file (default) or zip file."
232
234
  profile_options
233
235
  option :output, aliases: :o, type: :string,
234
- desc: "Save the archive to a path"
236
+ desc: "Save the archive to a path."
235
237
  option :zip, type: :boolean, default: false,
236
238
  desc: "Generates a zip archive."
237
239
  option :tar, type: :boolean, default: false,
@@ -275,14 +277,10 @@ class Inspec::InspecCLI < Inspec::BaseCLI
275
277
  pretty_handle_exception(e)
276
278
  end
277
279
 
278
- desc "exec LOCATIONS", "Run all tests at LOCATIONS."
280
+ desc "exec LOCATIONS", "Run all test files at the specified locations."
279
281
  long_desc <<~EOT
280
- Run all test files at the specified LOCATIONS.
281
-
282
- Loads the given profile(s) and fetches their dependencies if needed. Then
283
- connects to the target and executes any controls contained in the profiles.
284
- One or more reporters are used to generate output.
285
-
282
+ The subcommand loads the given profiles, fetches their dependencies if needed, then connects to the target and executes any controls in the profiles.
283
+ One or more reporters are used to generate the output.
286
284
  ```
287
285
  Exit codes:
288
286
  0 Normal exit, all tests passed
@@ -296,7 +294,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
296
294
 
297
295
  Below are some examples of using `exec` with different test LOCATIONS:
298
296
 
299
- Automate:
297
+ Chef Automate:
300
298
  ```
301
299
  #{Inspec::Dist::EXEC_NAME} automate login
302
300
  #{Inspec::Dist::EXEC_NAME} exec compliance://username/linux-baseline
@@ -306,7 +304,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
306
304
  #{Inspec::Dist::EXEC_NAME} compliance login
307
305
  ```
308
306
 
309
- Supermarket:
307
+ Chef Supermarket:
310
308
  ```
311
309
  #{Inspec::Dist::EXEC_NAME} exec supermarket://username/linux-baseline
312
310
  ```
@@ -343,12 +341,12 @@ class Inspec::InspecCLI < Inspec::BaseCLI
343
341
  #{Inspec::Dist::EXEC_NAME} exec https://github.com/dev-sec/linux-baseline.git
344
342
  ```
345
343
 
346
- Web hosted fileshare (also supports .zip):
344
+ Web hosted file (also supports .zip):
347
345
  ```
348
346
  #{Inspec::Dist::EXEC_NAME} exec https://webserver/linux-baseline.tar.gz
349
347
  ```
350
348
 
351
- Web hosted fileshare with basic authentication (supports .zip):
349
+ Web hosted file with basic authentication (supports .zip):
352
350
  ```
353
351
  #{Inspec::Dist::EXEC_NAME} exec https://username:password@webserver/linux-baseline.tar.gz
354
352
  ```
@@ -371,7 +369,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
371
369
  pretty_handle_exception(e)
372
370
  end
373
371
 
374
- desc "detect", "detect the target OS"
372
+ desc "detect", "detects the target OS."
375
373
  target_options
376
374
  option :format, type: :string
377
375
  def detect
@@ -396,7 +394,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
396
394
  pretty_handle_exception(e)
397
395
  end
398
396
 
399
- desc "shell", "open an interactive debugging shell"
397
+ desc "shell", "open an interactive debugging shell."
400
398
  target_options
401
399
  option :command, aliases: :c,
402
400
  desc: "A single command string to run instead of launching the shell"
@@ -415,6 +413,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI
415
413
  desc: "Load one or more input files, a YAML file with values for the shell to use"
416
414
  option :input, type: :array, banner: "name1=value1 name2=value2",
417
415
  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."
416
+ option :enhanced_outcomes, type: :boolean,
417
+ desc: "Show enhanced outcomes in output"
418
418
  def shell_func
419
419
  o = config
420
420
  deprecate_target_id(config)
@@ -453,7 +453,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
453
453
  pretty_handle_exception(e)
454
454
  end
455
455
 
456
- desc "env", "Output shell-appropriate completion configuration"
456
+ desc "env", "Outputs shell-appropriate completion configuration."
457
457
  def env(shell = nil)
458
458
  p = Inspec::EnvPrinter.new(self.class, shell)
459
459
  p.print_and_exit!
@@ -461,11 +461,13 @@ class Inspec::InspecCLI < Inspec::BaseCLI
461
461
  pretty_handle_exception(e)
462
462
  end
463
463
 
464
+ option :enhanced_outcomes, type: :boolean,
465
+ desc: "Show enhanced outcomes output"
464
466
  desc "schema NAME", "print the JSON schema", hide: true
465
467
  def schema(name)
466
468
  require "inspec/schema/output_schema"
467
-
468
- puts Inspec::Schema::OutputSchema.json(name)
469
+ o = config
470
+ puts Inspec::Schema::OutputSchema.json(name, o)
469
471
  rescue StandardError => e
470
472
  puts e
471
473
  puts "Valid schemas are #{Inspec::Schema::OutputSchema.names.join(", ")}"
@@ -477,7 +479,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
477
479
  puts Inspec::Telemetry::RunContextProbe.guess_run_context
478
480
  end
479
481
 
480
- desc "version", "prints the version of this tool"
482
+ desc "version", "prints the version of this tool."
481
483
  option :format, type: :string
482
484
  def version
483
485
  if config["format"] == "json"
@@ -491,7 +493,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
491
493
 
492
494
  desc "clear_cache", "clears the InSpec cache. Useful for debugging."
493
495
  option :vendor_cache, type: :string,
494
- desc: "Use the given path for caching dependencies. (default: ~/.inspec/cache)"
496
+ desc: "Use the given path for caching dependencies, (default: `~/.inspec/cache`)."
495
497
  def clear_cache
496
498
  o = config
497
499
  configure_logger(o)
@@ -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 ? "#{d.name}-#{d.source_version}" : "#{d.name}") rescue "#{d.name}"
29
+ key_name = (d.source_version.blank? ? "#{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 ? "#{d.name}-#{d.source_version}" : "#{d.name}") rescue d.name
45
+ key_name = (d.source_version.blank? ? "#{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
@@ -91,13 +91,17 @@ module Inspec::DSL
91
91
  if profile_version
92
92
  new_profile_id = "#{profile_id}-#{profile_version}"
93
93
  else
94
- dependencies.list.keys.each do |key|
95
- # 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.
96
- profile_id_key = key.split("-")
97
- profile_id_key.pop
98
- new_profile_id = key if profile_id_key.join("-") == profile_id
94
+ dependencies.list.each do |key, value|
95
+ # 1. Fetching VERSION from a profile dependency name which is in a format NAME-VERSION.
96
+ # 2. Matching original profile dependency name with profile name used with include or require control DSL.
97
+ source_version = value.source_version
98
+ unless source_version.blank?
99
+ profile_id_key = key.split("-#{source_version}")[0]
100
+ new_profile_id = key if profile_id_key == profile_id
101
+ end
99
102
  end
100
103
  end
104
+ # 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.
101
105
  dep_entry = new_profile_id ? dependencies.list[new_profile_id] : dependencies.list[profile_id]
102
106
 
103
107
  if dep_entry.nil?
@@ -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
@@ -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), nil, "-")
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
 
@@ -10,5 +10,7 @@ module Inspec
10
10
  class SecretsBackendNotFound < ArgumentError; end
11
11
  class ProfileValidationKeyNotFound < ArgumentError; end
12
12
  class ProfileSigningKeyNotFound < ArgumentError; end
13
+ class WaiversFileNotReadable < ArgumentError; end
14
+ class WaiversFileDoesNotExist < ArgumentError; end
13
15
  end
14
16
  end
@@ -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
- all_unique_controls.each do |control|
128
- next unless control[:results]
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
- total = failed + passed + skipped
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)