inspec-core 5.18.14 → 5.22.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)