inspec-core 4.19.0 → 4.21.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/inspec-core.gemspec +1 -1
  4. data/lib/inspec/base_cli.rb +4 -1
  5. data/lib/inspec/cli.rb +6 -5
  6. data/lib/inspec/config.rb +0 -1
  7. data/lib/inspec/input_registry.rb +33 -1
  8. data/lib/inspec/reporters.rb +12 -7
  9. data/lib/inspec/resources/interface.rb +55 -0
  10. data/lib/inspec/resources/interfaces.rb +119 -0
  11. data/lib/inspec/run_data.rb +9 -2
  12. data/lib/inspec/utils/deprecation/config_file.rb +21 -0
  13. data/lib/inspec/utils/telemetry/run_context_probe.rb +48 -0
  14. data/lib/inspec/version.rb +1 -1
  15. data/lib/plugins/inspec-reporter-html2/README.md +53 -0
  16. data/lib/plugins/inspec-reporter-html2/lib/inspec-reporter-html2.rb +18 -0
  17. data/lib/plugins/inspec-reporter-html2/lib/inspec-reporter-html2/reporter.rb +24 -0
  18. data/lib/plugins/inspec-reporter-html2/lib/inspec-reporter-html2/version.rb +8 -0
  19. data/lib/plugins/inspec-reporter-html2/templates/body.html.erb +46 -0
  20. data/lib/plugins/inspec-reporter-html2/templates/control.html.erb +77 -0
  21. data/lib/plugins/inspec-reporter-html2/templates/default.css +107 -0
  22. data/lib/plugins/inspec-reporter-html2/templates/default.js +79 -0
  23. data/lib/plugins/inspec-reporter-html2/templates/profile.html.erb +20 -0
  24. data/lib/plugins/inspec-reporter-html2/templates/result.html.erb +15 -0
  25. data/lib/plugins/inspec-reporter-html2/templates/selector.html.erb +8 -0
  26. data/lib/plugins/inspec-reporter-json-min/README.md +10 -0
  27. data/lib/plugins/inspec-reporter-json-min/lib/inspec-reporter-json-min.rb +13 -0
  28. data/lib/plugins/inspec-reporter-json-min/lib/inspec-reporter-json-min/reporter.rb +50 -0
  29. data/lib/plugins/inspec-reporter-json-min/lib/inspec-reporter-json-min/version.rb +5 -0
  30. metadata +21 -5
  31. data/lib/inspec/reporters/json_min.rb +0 -48
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c6037004db1c4ef1ba337ea6ef710938a2ce1d02c45e56b0bdfe7349b146a92
4
- data.tar.gz: 926e31bc929c5e5c76e3a5e89ed686218000a2ad5374c6b7901ac006ee2536a7
3
+ metadata.gz: f7be94754504cd2aeda9badd0701a9ac28691e0c62f76741db0c3b1b75988b2b
4
+ data.tar.gz: 314ce4bedf429cb87185f4903bcb5e47c93587fc1c125f9dcff112574f5dde72
5
5
  SHA512:
6
- metadata.gz: 36c0d1cf39247500f0bc33a633279c08bdaeab0c2dc848fc14f54405cb8c3b3fb1d86ae0ef0afc0ce1394c73b6de978fc61e4ff523b2dfc56d58536920caae47
7
- data.tar.gz: c385ff9ee77aca4689dc4a83c8bef4984a3b509e6a7f459655e44a5f1a1944792c2ac1f78b0626cde72697c2b6fee1d4c2eb05ae566d928596e447d5d08f2e34
6
+ metadata.gz: fa7f2ac74a61e23f82236d175b5adcc4236eb6b48316d7eaca9cfa85fe9f3917a22eb87fc56723ff56635348897e21f635816071fcf1c13a2f808df212388693
7
+ data.tar.gz: 17245f5ba3ca9aad13bba4870e52bf48c2e2cf2219b03ee569d0a1aa2e699bd2b6de447d30a2d23c44e01c72ded87c9dab596e564eb9206f7826ae72f6b4d366
data/Gemfile CHANGED
@@ -9,7 +9,7 @@ gem "inspec", path: "."
9
9
  # in it in order to package the executable. Hence the odd backwards dependency.
10
10
  gem "inspec-bin", path: "./inspec-bin"
11
11
 
12
- gem "ffi", ">= 1.9.14"
12
+ gem "ffi", ">= 1.9.14", "!= 1.13.0"
13
13
 
14
14
  group :omnibus do
15
15
  gem "rb-readline"
@@ -31,6 +31,7 @@ group :test do
31
31
  gem "m"
32
32
  gem "pry", "~> 0.10"
33
33
  gem "pry-byebug"
34
+ gem "html-proofer", platforms: :ruby # do not attempt to run proofer on windows
34
35
  end
35
36
 
36
37
  group :integration do
@@ -39,7 +39,7 @@ Gem::Specification.new do |spec|
39
39
  spec.add_dependency "faraday", ">= 0.9.0"
40
40
  spec.add_dependency "tty-table", "~> 0.10"
41
41
  spec.add_dependency "tty-prompt", "~> 0.17"
42
- spec.add_dependency "tomlrb", "~> 1.2"
42
+ spec.add_dependency "tomlrb", "~> 1.2.0"
43
43
  spec.add_dependency "addressable", "~> 2.4"
44
44
  spec.add_dependency "parslet", "~> 1.5"
45
45
  spec.add_dependency "semverse", "~> 3.0"
@@ -140,7 +140,7 @@ module Inspec
140
140
  option :reporter_backtrace_inclusion, type: :boolean,
141
141
  desc: "Include a code backtrace in report data (default: true)"
142
142
  option :input, type: :array, banner: "name1=value1 name2=value2",
143
- desc: "Specify one or more inputs directly on the command line, as --input NAME=VALUE"
143
+ desc: "Specify one or more inputs directly on the command line, as --input NAME=VALUE. Accepts single-quoted YAML and JSON structures."
144
144
  option :input_file, type: :array,
145
145
  desc: "Load one or more input files, a YAML file with values for the profile to use"
146
146
  option :waiver_file, type: :array,
@@ -155,6 +155,9 @@ module Inspec
155
155
  desc: "Show progress while executing tests."
156
156
  option :distinct_exit, type: :boolean, default: true,
157
157
  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."
158
+ option :silence_deprecations, type: :array,
159
+ banner: "[all]|[GROUP GROUP...]",
160
+ desc: "Suppress deprecation warnings. See install_dir/etc/deprecations.json for list of GROUPs or use 'all'."
158
161
  end
159
162
 
160
163
  def self.format_platform_info(params: {}, indent: 0, color: 39)
@@ -375,6 +375,12 @@ class Inspec::InspecCLI < Inspec::BaseCLI
375
375
  puts "Valid schemas are #{Inspec::Schema::OutputSchema.names.join(", ")}"
376
376
  end
377
377
 
378
+ desc "run_context", "used to test run-context detection", hide: true
379
+ def run_context
380
+ require "inspec/utils/telemetry/run_context_probe"
381
+ puts Inspec::Telemetry::RunContextProbe.guess_run_context
382
+ end
383
+
378
384
  desc "version", "prints the version of this tool"
379
385
  option :format, type: :string
380
386
  def version
@@ -387,11 +393,6 @@ class Inspec::InspecCLI < Inspec::BaseCLI
387
393
  end
388
394
  map %w{-v --version} => :version
389
395
 
390
- desc "nothing", "does nothing"
391
- def nothing
392
- puts "you did nothing"
393
- end
394
-
395
396
  private
396
397
 
397
398
  def run_command(opts)
@@ -344,7 +344,6 @@ module Inspec
344
344
  cli
345
345
  json
346
346
  json-automate
347
- json-min
348
347
  junit
349
348
  yaml
350
349
  }
@@ -166,8 +166,9 @@ module Inspec
166
166
  end
167
167
  end
168
168
  input_name, input_value = pair.split("=")
169
+ input_value = parse_cli_input_value(input_name, input_value)
169
170
  evt = Inspec::Input::Event.new(
170
- value: input_value.chomp(","), # Trim trailing comma if any
171
+ value: input_value,
171
172
  provider: :cli,
172
173
  priority: 50
173
174
  )
@@ -175,6 +176,37 @@ module Inspec
175
176
  end
176
177
  end
177
178
 
179
+ # Remove trailing commas, resolve type.
180
+ def parse_cli_input_value(input_name, given_value)
181
+ value = given_value.chomp(",") # Trim trailing comma if any
182
+ case value
183
+ when /^true|false$/i
184
+ value = !!(value =~ /true/i)
185
+ when /^-?\d+$/
186
+ value = value.to_i
187
+ when /^-?\d+\.\d+$/
188
+ value = value.to_f
189
+ when /^(\[|\{).*(\]|\})$/
190
+ # Look for complex values and try to parse them.
191
+ require "yaml"
192
+ begin
193
+ value = YAML.load(value)
194
+ rescue Psych::SyntaxError => yaml_error
195
+ # It could be that we just tried to run JSON through the YAML parser.
196
+ require "json"
197
+ begin
198
+ value = JSON.parse(value)
199
+ rescue JSON::ParserError => json_error
200
+ msg = "Unparseable value '#{value}' for --input #{input_name}.\n"
201
+ msg += "When treated as YAML, error: #{yaml_error.message}\n"
202
+ msg += "When treated as JSON, error: #{json_error.message}"
203
+ Inspec::Log.warn msg
204
+ end
205
+ end
206
+ end
207
+ value
208
+ end
209
+
178
210
  def bind_inputs_from_runner_api(profile_name, input_hash)
179
211
  # TODO: move this into a core plugin
180
212
 
@@ -2,7 +2,6 @@ require "inspec/reporters/base"
2
2
  require "inspec/reporters/cli"
3
3
  require "inspec/reporters/json"
4
4
  require "inspec/reporters/json_automate"
5
- require "inspec/reporters/json_min"
6
5
  require "inspec/reporters/junit"
7
6
  require "inspec/reporters/automate"
8
7
  require "inspec/reporters/yaml"
@@ -21,8 +20,6 @@ module Inspec::Reporters
21
20
  # right to introduce breaking changes to this reporter at any time.
22
21
  when "json-automate"
23
22
  reporter = Inspec::Reporters::JsonAutomate.new(config)
24
- when "json-min"
25
- reporter = Inspec::Reporters::JsonMin.new(config)
26
23
  when "junit"
27
24
  reporter = Inspec::Reporters::Junit.new(config)
28
25
  when "automate"
@@ -60,15 +57,23 @@ module Inspec::Reporters
60
57
  case name
61
58
  when "json"
62
59
  reporter = Inspec::Reporters::Json.new(config)
63
- when "json-min"
64
- reporter = Inspec::Reporters::JsonMin.new(config)
65
60
  when "json-automate"
66
61
  reporter = Inspec::Reporters::JsonAutomate.new(config)
67
62
  when "yaml"
68
63
  reporter = Inspec::Reporters::Yaml.new(config)
69
64
  else
70
- # use base run_data hash for any other report
71
- return run_data
65
+ # If we made it here, it might be a plugin
66
+ begin
67
+ activator = Inspec::Plugin::V2::Registry.instance.find_activator(plugin_type: :reporter, activator_name: name.to_sym)
68
+ activator.activate!
69
+ reporter = activator.implementation_class.new(config)
70
+ unless reporter.respond_to(:report?)
71
+ return run_data
72
+ end
73
+ rescue Inspec::Plugin::V2::LoadError
74
+ # Must not have been a plugin - just return the run_data
75
+ return run_data
76
+ end
72
77
  end
73
78
 
74
79
  reporter.report
@@ -47,10 +47,18 @@ module Inspec::Resources
47
47
  ipv6_addresses && !ipv6_addresses.empty?
48
48
  end
49
49
 
50
+ def ipv4_address
51
+ ipv4_addresses.first
52
+ end
53
+
50
54
  def ipv4_addresses
51
55
  ipv4_cidrs.map { |i| i.split("/")[0] }
52
56
  end
53
57
 
58
+ def ipv6_address
59
+ ipv6_addresses.first
60
+ end
61
+
54
62
  def ipv6_addresses
55
63
  ipv6_cidrs.map { |i| i.split("/")[0] }
56
64
  end
@@ -85,6 +93,7 @@ module Inspec::Resources
85
93
  @cache ||= begin
86
94
  provider = LinuxInterface.new(inspec) if inspec.os.linux?
87
95
  provider = WindowsInterface.new(inspec) if inspec.os.windows?
96
+ provider = BsdInterface.new(inspec) if inspec.os.bsd? # includes macOS
88
97
  Hash(provider && provider.interface_info(@iface))
89
98
  end
90
99
  end
@@ -98,6 +107,52 @@ module Inspec::Resources
98
107
  end
99
108
  end
100
109
 
110
+ class BsdInterface < InterfaceInfo
111
+ def interface_info(iface)
112
+ cmd = inspec.command("ifconfig #{iface}")
113
+ return nil if cmd.exit_status.to_i != 0
114
+
115
+ lines = cmd.stdout.split("\n")
116
+ iface_info = {
117
+ name: iface,
118
+ ipv4_addresses: [], # Actually CIDRs
119
+ ipv6_addresses: [], # are expected to go here
120
+ }
121
+
122
+ iface_info[:up] = lines[0].include?("UP")
123
+ lines.each do |line|
124
+ # IPv4 case
125
+ m = line.match(/^\s+inet\s+((?:\d{1,3}\.){3}\d{1,3})\s+netmask\s+(0x[a-f0-9]{8})/)
126
+ if m
127
+ ip = m[1]
128
+ hex_mask = m[2]
129
+ cidr = hex_mask.to_i(16).to_s(2).count("1")
130
+ iface_info[:ipv4_addresses] << "#{ip}/#{cidr}"
131
+ next
132
+ end
133
+
134
+ # IPv6 case
135
+ m = line.match(/^\s+inet6\s+([a-f0-9:]+)%#{iface}\s+prefixlen\s+(\d+)/)
136
+ if m
137
+ ip = m[1]
138
+ cidr = m[2]
139
+ iface_info[:ipv6_addresses] << "#{ip}/#{cidr}"
140
+ next
141
+ end
142
+
143
+ # Speed detect, crummy - can't detect wifi, finds any number in the string
144
+ # Ethernet autoselect (1000baseT <full-duplex>)
145
+ m = line.match(/^\s+media:\D+(\d+)/)
146
+ if m
147
+ iface_info[:speed] = m[1].to_i
148
+ next
149
+ end
150
+ end
151
+
152
+ iface_info
153
+ end
154
+ end
155
+
101
156
  class LinuxInterface < InterfaceInfo
102
157
  def interface_info(iface)
103
158
  # will return "[mtu]\n1500\n[type]\n1"
@@ -0,0 +1,119 @@
1
+ require "inspec/utils/filter"
2
+ require "inspec/resources/command"
3
+
4
+ module Inspec::Resources
5
+ class Interfaces < Inspec.resource(1)
6
+ name "interfaces"
7
+ supports platform: "unix"
8
+ supports platform: "windows"
9
+ desc "Use the interfaces InSpec audit resource to test properties for multiple network interfaces installed on the system"
10
+ example <<~EXAMPLE
11
+ describe interfaces do
12
+ its('names') { should include 'eth0' }
13
+ end
14
+ EXAMPLE
15
+
16
+ attr_reader :iface_data
17
+
18
+ def to_s
19
+ "Interfaces"
20
+ end
21
+
22
+ filter = FilterTable.create
23
+ filter.register_column(:names, field: "name")
24
+ .install_filter_methods_on_resource(self, :scan_interfaces)
25
+
26
+ def ipv4_address
27
+ require "ipaddr"
28
+
29
+ # Loop over interface names
30
+ # Select those that are up and have an ipv4 address
31
+ interfaces = names.map { |n| inspec.interface(n) }.select do |i|
32
+ i.ipv4_address? && i.up?
33
+ end
34
+
35
+ addrs = interfaces.map(&:ipv4_addresses).flatten.map { |a| IPAddr.new(a) }
36
+
37
+ # Look for progressively "better" IP addresses
38
+ [
39
+ # Loopback and private IP ranges
40
+ IPAddr.new("127.0.0.0/8"),
41
+ IPAddr.new("192.168.0.0/16"),
42
+ IPAddr.new("172.16.0.0/12"),
43
+ IPAddr.new("10.0.0.0/8"),
44
+ ].each do |private_range|
45
+ filtered_addrs = addrs.reject { |a| private_range.include?(a) }
46
+ if filtered_addrs.empty?
47
+ # Everything we had was a private or loopback IP. Return the "best" thing we were left with.
48
+ return addrs.first.to_s
49
+ end
50
+
51
+ addrs = filtered_addrs
52
+ end
53
+ addrs.first.to_s
54
+ end
55
+
56
+ private
57
+
58
+ def scan_interfaces
59
+ @iface_data ||= begin
60
+ provider = LinuxInterfaceLister.new(inspec) if inspec.os.linux?
61
+ provider = WindowsInterfaceLister.new(inspec) if inspec.os.windows?
62
+ provider = BsdInterfaceLister.new(inspec) if inspec.os.bsd? # includes macOS
63
+ Array(provider && provider.scan_interfaces)
64
+ end
65
+ end
66
+
67
+ class InterfaceLister
68
+ attr_reader :inspec
69
+ def initialize(inspec)
70
+ @inspec = inspec
71
+ end
72
+ end
73
+
74
+ class BsdInterfaceLister < InterfaceLister
75
+ def scan_interfaces
76
+ iface_data = []
77
+ cmd = inspec.command("ifconfig -a")
78
+ cmd.stdout.split("\n").each do |line|
79
+ # lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
80
+ m = line.match(/^(\S+):/)
81
+ if m
82
+ iface_data << { "name" => m[1] }
83
+ end
84
+ end
85
+ iface_data
86
+ end
87
+ end
88
+
89
+ class LinuxInterfaceLister < InterfaceLister
90
+ def scan_interfaces
91
+ iface_data = []
92
+ cmd = inspec.command("ls /sys/class/net")
93
+ cmd.stdout.split("\n").each do |iface|
94
+ iface_data << { "name" => iface }
95
+ end
96
+ iface_data
97
+ end
98
+ end
99
+
100
+ class WindowsInterfaceLister < InterfaceLister
101
+ def scan_interfaces
102
+ iface_data = []
103
+ cmd = inspec.command("Get-NetAdapter | Select-Object -Property Name | ConvertTo-Json")
104
+ begin
105
+ adapter_info = JSON.parse(cmd.stdout)
106
+ # May be a Hash if only one, or Array if multiple - normalize to Array
107
+ adapter_info = [ adapter_info ] if adapter_info.is_a? Hash
108
+ rescue JSON::ParserError => _e
109
+ return nil
110
+ end
111
+ adapter_info.each do |info|
112
+ iface_data << { "name" => info["Name"] }
113
+ end
114
+ iface_data
115
+ end
116
+ end
117
+
118
+ end
119
+ end
@@ -1,12 +1,19 @@
1
1
 
2
2
  module Inspec
3
3
  module HashLikeStruct
4
+ # Only list keys whose value are non-nil
4
5
  def keys
5
- members
6
+ members.reject { |k| self[k].nil? }
6
7
  end
7
8
 
9
+ # Only list non-nil members for backwards compatibility
8
10
  def key?(item)
9
- members.include?(item)
11
+ members.include?(item) && non_nil?(item)
12
+ end
13
+
14
+ # This is provided for clarity - many locations make this test
15
+ def non_nil?(item)
16
+ !self[item].nil?
10
17
  end
11
18
  end
12
19
 
@@ -1,6 +1,7 @@
1
1
  require "stringio"
2
2
  require "json"
3
3
  require "inspec/globals"
4
+ require "inspec/config"
4
5
 
5
6
  module Inspec
6
7
  module Deprecation
@@ -32,6 +33,7 @@ module Inspec
32
33
  @groups = {}
33
34
  @unknown_group_action = :warn
34
35
  validate!
36
+ silence_deprecations_from_cli
35
37
  end
36
38
 
37
39
  private
@@ -45,6 +47,25 @@ module Inspec
45
47
  File.open(default_path)
46
48
  end
47
49
 
50
+ def silence_deprecations_from_cli
51
+ # Read --silence-deprecations CLI option
52
+ cfg = Inspec::Config.cached
53
+ return unless cfg[:silence_deprecations]
54
+
55
+ groups_to_silence = cfg[:silence_deprecations]
56
+ silence_all = groups_to_silence.include?("all")
57
+
58
+ groups.each do |group_name, group|
59
+ # Only silence things that warn. Don't silence things that exit;
60
+ # those harsher measures are usually protecting removed code and ignoring
61
+ # and continuing regardless would be perilous and lead to errors.
62
+ if %i{warn fail_control}.include?(group.action) &&
63
+ (silence_all || groups_to_silence.include?(group_name.to_s))
64
+ group.action = :ignore
65
+ end
66
+ end
67
+ end
68
+
48
69
  #====================================================================================================#
49
70
  # Validation
50
71
  #====================================================================================================#
@@ -0,0 +1,48 @@
1
+ module Inspec
2
+ module Telemetry
3
+ # Guesses the run context of InSpec - how were we invoked?
4
+ # All stack values here are determined experimentally
5
+
6
+ class RunContextProbe
7
+ def self.guess_run_context(stack = nil)
8
+ stack ||= caller_locations
9
+ return "test-kitchen" if kitchen?(stack)
10
+ return "cli" if run_by_thor?(stack)
11
+ return "audit-cookbook" if audit_cookbook?(stack)
12
+
13
+ "unknown"
14
+ end
15
+
16
+ def self.run_by_thor?(stack)
17
+ stack_match(stack: stack, path: "thor/command", label: "run") &&
18
+ stack_match(stack: stack, path: "thor/invocation", label: "invoke_command")
19
+ end
20
+
21
+ def self.kitchen?(stack)
22
+ stack_match(stack: stack, path: "kitchen/instance", label: "verify_action") &&
23
+ stack_match(stack: stack, path: "kitchen/instance", label: "verify")
24
+ end
25
+
26
+ def self.audit_cookbook?(stack)
27
+ stack_match(stack: stack, path: "chef/handler", label: "run_report_handlers") &&
28
+ stack_match(stack: stack, path: "handler/audit_report", label: "report")
29
+ end
30
+
31
+ def self.stack_match(stack: [], label: nil, path: nil)
32
+ return false if stack.nil?
33
+
34
+ stack.any? do |frame|
35
+ if label && path
36
+ frame.label == label && frame.absolute_path.include?(path)
37
+ elsif label
38
+ frame.label == label
39
+ elsif path
40
+ frame.absolute_path.include?(path)
41
+ else
42
+ false
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "4.19.0".freeze
2
+ VERSION = "4.21.1".freeze
3
3
  end
@@ -0,0 +1,53 @@
1
+ # inspec-reporter-html2 Plugin
2
+
3
+ An "improved" HTML output reporter specifically for Chef InSpec. Unlike the default `html` reporter, which is RSpec-based, this reporter knows about Chef InSpec structures like Controls and Profiles, and includes full metadata such as control tags, etc.
4
+
5
+ ## To Install This Plugin
6
+
7
+ This plugin ships with Chef InSpec and requires no installation.
8
+
9
+ It should appear when you run:
10
+
11
+ ```
12
+ you@machine $ inspec plugin list
13
+ ```
14
+
15
+ ## How to use this plugin
16
+
17
+ To generate an HTML report using this plugin and save the output to a file named `report.html`, run:
18
+
19
+ ```
20
+ you@machine $ inspec exec some_profile --reporter html2:report.html
21
+ ```
22
+
23
+ Note the `2` in the reporter name. If you omit it and run `--reporter html` instead, you will run the legacy RSpec HTML reporter.
24
+
25
+ ## Configuring the Plugin
26
+
27
+ The `html2` reporter requires no configuration to function. However, two options--`alternate_css_file` and `alternate_js_file`--are available for customization. The options are set in the JSON-formatted configuration file that Chef InSpec consumes. For details, see [our configuration file documentation](https://www.inspec.io/docs/reference/config/).
28
+
29
+ For example:
30
+
31
+ ```json
32
+ {
33
+ "version": "1.2",
34
+ "plugins": {
35
+ "inspec-reporter-html2": {
36
+ "alternate_js_file":"/var/www/js/my-javascript.js",
37
+ "alternate_css_file":"/var/www/css/my-style.css"
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ ### alternate\_css\_file
44
+
45
+ Specifies the full path to the location of a CSS file that will be read and inlined into the HTML report. The default CSS will not be included.
46
+
47
+ ### alternate\_js\_file
48
+
49
+ Specifies the full path to the location of a JavaScript file that will be read and inlined into the HTML report. The default JavaScript will not be included. The JavaScript file should implement at least a `pageLoaded()` function, which will be called by the `onload` event of the HTML `body` element.
50
+
51
+ ## Developing This Plugin
52
+
53
+ This plugin is part of the Chef InSpec source code. While it has its own tests, the general contribution policy is dictated by the Chef InSpec project at https://github.com/inspec/inspec/blob/master/CONTRIBUTING.md
@@ -0,0 +1,18 @@
1
+ libdir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
+
4
+ require "inspec-reporter-html2/version"
5
+ module InspecPlugins
6
+ module Html2Reporter
7
+ class Plugin < ::Inspec.plugin(2)
8
+ # Internal machine name of the plugin. InSpec will use this in errors, etc.
9
+ plugin_name :'inspec-reporter-html2'
10
+
11
+ # Define a new Reporter.
12
+ reporter :html2 do
13
+ require "inspec-reporter-html2/reporter"
14
+ InspecPlugins::Html2Reporter::Reporter
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ require "erb"
2
+ require "inspec/config"
3
+
4
+ module InspecPlugins::Html2Reporter
5
+ class Reporter < Inspec.plugin(2, :reporter)
6
+ def render
7
+ template_path = File.expand_path(__FILE__ + "../../../../templates")
8
+
9
+ # Read config data from the user's config file. Supports two settings, both of which are absolute filesystem paths:
10
+ # alternate_css_file - contents will be used instead of default CSS
11
+ # alternate_js_file - contents will be used instead of default JavaScript
12
+ cfg = Inspec::Config.cached.fetch_plugin_config("inspec-reporter-html2")
13
+ js_path = cfg[:alternate_js_file] || (template_path + "/default.js")
14
+ css_path = cfg[:alternate_css_file] || (template_path + "/default.css")
15
+
16
+ template = ERB.new(File.read(template_path + "/body.html.erb"))
17
+ output(template.result(binding))
18
+ end
19
+
20
+ def self.run_data_schema_constraints
21
+ "~> 0.0"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,8 @@
1
+ # This file simply makes it easier for CI engines to update
2
+ # the version stamp, and provide a clean way for the gemspec
3
+ # to learn the current version.
4
+ module InspecPlugins
5
+ module Html2Reporter
6
+ VERSION = "0.1.0".freeze
7
+ end
8
+ end
@@ -0,0 +1,46 @@
1
+ <!DOCTYPE html>
2
+ <!-- saved from url=(0014)about:internet -->
3
+ <!-- prior comment allows JS to execute on IE when saved as a local file, "MOTW" -->
4
+ <html lang="en">
5
+ <head>
6
+ <title><%= Inspec::Dist::PRODUCT_NAME %> Results</title>
7
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8
+ <style type="text/css">
9
+ /* Must inline all CSS files, this is a single-file output that may be airgapped */
10
+ <%= ERB.new(File.read(css_path), nil, nil, "_css").result(binding) %>
11
+ </style>
12
+ <script type="text/javascript">
13
+ // <![CDATA[
14
+ /* Must inline all JavaScript files, this is a single-file output that may be airgapped */
15
+ <%= ERB.new(File.read(js_path), nil, nil, "_js").result(binding) %>
16
+ // ]]>
17
+ </script>
18
+ </head>
19
+ <body onload="pageLoaded()">
20
+ <%= ERB.new(File.read(template_path + "/selector.html.erb"), nil, nil, "_select").result(binding) %>
21
+ <div class="inspec-report">
22
+ <h1><%= Inspec::Dist::PRODUCT_NAME %> Report</h1>
23
+ <% run_data.profiles.each do |profile| %>
24
+ <%= ERB.new(File.read(template_path + "/profile.html.erb"), nil, nil, "_prof").result(binding) %>
25
+ <% end %>
26
+
27
+ <div class="inspec-summary">
28
+ <table id="platform" class="info">
29
+ <tr><th colspan=2><h4 id="platform-label">Platform Information</h4></th></tr>
30
+ <tr class= "name"><th>Name:</th><td><%= run_data.platform.name %></td></tr>
31
+ <tr class= "release"><th>Release:</th><td><%= run_data.platform.release %></td></tr>
32
+ <tr class= "target"><th>Target:</th><td><%= run_data.platform.target %></td></tr>
33
+ </table>
34
+ <table id="statistics" class="info">
35
+ <tr><th colspan="2"><h4 id="statistics-label">Control Statistics</h4></th></tr>
36
+ <tr class= "passed"><th>Passed:</th><td><%= run_data.statistics.controls.passed.total %></td></tr>
37
+ <tr class= "skipped"><th>Skipped:</th><td><%= run_data.statistics.controls.skipped.total %></td></tr>
38
+ <tr class= "failed"><th>Failed:</th><td><%= run_data.statistics.controls.failed.total %></td></tr>
39
+ <tr class= "duration"><th>Duration:</th><td><%= run_data.statistics.duration %> seconds</td></tr>
40
+ <tr class= "date"><th>Time Finished:</th><td><%= Time.now %></td></tr>
41
+ </table>
42
+ <span id="inspec-version"><%= Inspec::Dist::PRODUCT_NAME %> version <%= run_data.version %></span>
43
+ </div>
44
+ </div>
45
+ </body>
46
+ </html>
@@ -0,0 +1,77 @@
1
+ <% slugged_id = control.id.tr(" ", "_") %>
2
+ <%
3
+ # Determine status of control
4
+ status = "passed"
5
+ if control.results.any? { |r| r.status == "failed" }
6
+ status = "failed"
7
+ elsif control.results.any? { |r| r.status == "skipped" }
8
+ status = "skipped"
9
+ end
10
+ %>
11
+
12
+ <div class="control control-status-<%= status %>" id="control-<%= slugged_id %>">
13
+
14
+ <%
15
+ # Determine range of impact
16
+ i = control.impact || 0.0
17
+ impact_level = "none"
18
+ if i < 0.3
19
+ impact_level = "low"
20
+ elsif i < 0.7
21
+ impact_level = "medium"
22
+ else
23
+ impact_level = "high"
24
+ end
25
+ %>
26
+
27
+ <h3 class="control-title">Control <code><%= control.id %></code></h3>
28
+ <table class="control-metadata info" id="control-metadata-<%= slugged_id %>">
29
+ <tr class="status status-<%= status %>"><th>Status:</th><td><div><%= status.capitalize %></div></td></tr>
30
+ <% if control.title %><tr class="title"><th>Title:</th><td><%= control.title %></td></tr> <% end %>
31
+ <% if control.desc %><tr class="desc"><th>Description:</th><td><%= control.desc %></td></tr> <% end %>
32
+ <% if control.impact %><tr class="impact impact-<%= impact_level %>"><th>Impact:</th><td><%= control.impact %></td></tr> <% end %>
33
+ <% unless control.tags.empty? %>
34
+ <tr class="tags">
35
+ <th>Tags:</th>
36
+ <td>
37
+ <table class="tags">
38
+ <% control.tags.each do |tag_name, tag_text| %>
39
+ <tr><td><%= tag_name %></td><td><%= tag_text %></td></tr>
40
+ <% end %>
41
+ </table>
42
+ </td>
43
+ </tr>
44
+ <% end %>
45
+ <% unless control.refs.empty? %>
46
+ <tr class="refs">
47
+ <th>References:</th>
48
+ <td>
49
+ <ul>
50
+ <% control.refs.each do |r| %>
51
+ <li><a href="<%= r.url %>"><%= r.ref %></a></li>
52
+ <% end %>
53
+ </ul>
54
+ </td>
55
+ </tr>
56
+ <% end %>
57
+ <tr class="code">
58
+ <th>Source Code:</th>
59
+ <td>
60
+ <input type="button" class="show-source-code" id="show-code-<%= slugged_id %>" value="Show Source"/>
61
+ <input type="button" class="hide-source-code hidden" id="hide-code-<%= slugged_id %>" value="Hide Source"/>
62
+ <pre class="source-code hidden" id="source-code-<%= slugged_id %>">
63
+ <code>
64
+ <%= control.code %>
65
+ </code>
66
+ </pre>
67
+ </td>
68
+ </tr>
69
+ <!-- TODO waiver data -->
70
+
71
+ </table>
72
+
73
+ <% control.results.each do |result| %>
74
+ <%= ERB.new(File.read(template_path + "/result.html.erb"), nil, nil, "_rslt").result(binding) %>
75
+ <% end %>
76
+
77
+ </div>
@@ -0,0 +1,107 @@
1
+ body {
2
+ margin: 20px 10% 20px 10%;
3
+ padding: 0;
4
+ background: #fff;
5
+ }
6
+ h1, h2, h3, h4, h5 {
7
+ font-family: "Lucida Grande", Helvetica, sans-serif;
8
+ }
9
+ h1, h2 {
10
+ padding: 10px;
11
+ text-align: center
12
+ }
13
+ table.info th, table.info th {
14
+ padding: 2px;
15
+ }
16
+ table.info th {
17
+ text-align: right;
18
+ }
19
+ .hidden {
20
+ display: none;
21
+ }
22
+ pre code {
23
+ background-color: #eee;
24
+ border: 1px solid #999;
25
+ display: block;
26
+ padding: 20px;
27
+ }
28
+
29
+ .profile, .control, .profile-metadata {
30
+ border: 1px solid #ccc;
31
+ padding: 10px;
32
+ margin: 5px auto;
33
+ }
34
+
35
+ .resource-title {
36
+ margin-left: 2.5%;
37
+ }
38
+
39
+ .control-title code,
40
+ .resource-title code {
41
+ font-size: larger;
42
+ }
43
+ .control-metadata .status div,
44
+ .result-metadata .status div {
45
+ color: white;
46
+ font-weight: bold;
47
+ width: fit-content;
48
+ padding: 0px 2px;
49
+ }
50
+
51
+ .control-metadata .status-passed div,
52
+ .result-metadata .status-passed div {
53
+ background-color: darkgreen;
54
+ }
55
+ .control-metadata .status-failed div,
56
+ .result-metadata .status-failed div {
57
+ background-color: red;
58
+ }
59
+ .control-metadata .status-skipped div,
60
+ .result-metadata .status-skipped div {
61
+ background-color: grey;
62
+ }
63
+ .result-metadata,
64
+ .control-metadata {
65
+ margin: 0 0 0 5%;
66
+ }
67
+
68
+ .selector-panel {
69
+ position: fixed;
70
+ z-index: 100;
71
+ background-color: #ccc;
72
+ padding: 10px;
73
+ top: 0;
74
+ margin-left: -10%;
75
+ border-bottom-right-radius: 10px;
76
+ }
77
+
78
+ @media print {
79
+ .selector-panel {
80
+ visibility: hidden;
81
+ }
82
+ }
83
+
84
+ .inspec-summary {
85
+ border: 1px solid #ccc;
86
+ padding: 10px;
87
+ margin: 5px auto;
88
+ width: fit-content
89
+ }
90
+
91
+ .inspec-summary h4 {
92
+ margin-bottom: 0px;
93
+ }
94
+
95
+ .inspec-summary #platform, .inspec-summary #statistics {
96
+ display: inline;
97
+ }
98
+
99
+ #statistics .date td {
100
+ width: 100px
101
+ }
102
+
103
+ #inspec-version {
104
+ display: block;
105
+ text-align: center;
106
+ font-style: italic;
107
+ }
@@ -0,0 +1,79 @@
1
+
2
+ /* CSS primitives */
3
+ function addCssClass(id, cls) {
4
+ document.getElementById(id).className += (" " + cls);
5
+ }
6
+
7
+ function removeCssClass(id, cls) {
8
+ var el = document.getElementById(id);
9
+ var classes = el.className.replace(cls,'');
10
+ el.className = classes;
11
+ }
12
+
13
+ function handleShowSource(evt) {
14
+ var control_id = evt.srcElement.id.replace("show-code-", "")
15
+ addCssClass(evt.srcElement.id, "hidden")
16
+ removeCssClass("hide-code-" + control_id, "hidden")
17
+ removeCssClass("source-code-" + control_id, "hidden")
18
+ }
19
+
20
+ function handleHideSource(evt) {
21
+ var control_id = evt.srcElement.id.replace("hide-code-", "")
22
+ addCssClass(evt.srcElement.id, "hidden")
23
+ addCssClass("source-code-" + control_id, "hidden")
24
+ removeCssClass("show-code-" + control_id, "hidden")
25
+ }
26
+
27
+ function handleSelectorChange(evt) {
28
+ var should_show = evt.srcElement.checked
29
+ var which_group = evt.srcElement.id.replace("-checkbox","")
30
+ var controls = document.getElementsByClassName("control-status-" + which_group)
31
+ var i;
32
+ if (should_show) {
33
+ for (i = 0; i < controls.length; i++) {
34
+ removeCssClass(controls[i].id, "hidden")
35
+ }
36
+ } else {
37
+ for (i = 0; i < controls.length; i++) {
38
+ addCssClass(controls[i].id, "hidden")
39
+ }
40
+ }
41
+ }
42
+
43
+ function handleChildProfileChange(evt) {
44
+ var should_show = evt.srcElement.checked
45
+ var child_profiles = document.getElementsByClassName("child-profile")
46
+ var i;
47
+ if (should_show) {
48
+ for (i = 0; i < child_profiles.length; i++) {
49
+ removeCssClass(child_profiles[i].id, "hidden")
50
+ }
51
+ } else {
52
+ for (i = 0; i < child_profiles.length; i++) {
53
+ addCssClass(child_profiles[i].id, "hidden")
54
+ }
55
+ }
56
+ }
57
+
58
+ /* Main entry point */
59
+ function pageLoaded() {
60
+ var i;
61
+
62
+ // wire up show source links
63
+ var show_links = document.getElementsByClassName("show-source-code");
64
+ for (i = 0; i < show_links.length; i++) {
65
+ show_links[i].onclick = handleShowSource;
66
+ }
67
+ // wire up hide source links
68
+ var hide_links = document.getElementsByClassName("hide-source-code");
69
+ for (i = 0; i < hide_links.length; i++) {
70
+ hide_links[i].onclick = handleHideSource;
71
+ }
72
+ // wire up selector checkboxes
73
+ var selectors = document.getElementsByClassName("selector-checkbox");
74
+ for (i = 0; i < selectors.length; i++) {
75
+ selectors[i].onchange = handleSelectorChange;
76
+ }
77
+ // wire up child profile checkbox
78
+ document.getElementById("child-profile-checkbox").onchange = handleChildProfileChange;
79
+ }
@@ -0,0 +1,20 @@
1
+ <div class="profile <%= profile.parent_profile ? "child-profile hidden" : "" %>" id="profile-<%= profile.name %>">
2
+ <% display_name = profile.title || profile.name %>
3
+ <h2 class="profile_title">Profile <%= display_name %> (<%= profile.name %>)</h2>
4
+
5
+ <table class="profile-metadata info" id="profile-metadata-<%= profile.name %>">
6
+ <tr class="profile-version"><th>Version:</th><td><%= profile.version %></td></tr>
7
+ <% if profile.summary %>
8
+ <tr class="profile-summary"><th>Summary:</th><td><%= profile.summary %></td></tr>
9
+ <% end %>
10
+ <% if profile.skip_message %>
11
+ <tr class="profile-skip-message"><th>Skip Message:</th><td><%= profile.skip_message %></td></tr>
12
+ <% end %>
13
+ </table>
14
+
15
+ <% if profile.status == "loaded" %>
16
+ <% profile.controls.each do |control| %>
17
+ <%= ERB.new(File.read(template_path + "/control.html.erb"), nil, nil, "_ctl").result(binding) %>
18
+ <% end %>
19
+ <% end %>
20
+ </div>
@@ -0,0 +1,15 @@
1
+ <% slugged_id = result.resource_title.to_s.gsub(/\W/, "_") %>
2
+ <div class="result" id="result-<%= slugged_id %>">
3
+ <h4 class="resource-title">Resource <code><%= result.resource_title.to_s %></code></h4>
4
+ <table class="result-metadata info">
5
+ <tr class="expectation_message"><th>Test:</th><td><code><%= result.expectation_message %></code></td></tr>
6
+ <tr class="status status-<%= result.status %>"><th>Status:</th><td><div><%= result.status.capitalize %></div></td></tr>
7
+ <% if result.status == "failed" %>
8
+ <tr class="fail_message"><th>Failure Message:</th><td><code><%= result.message %></code></td></tr>
9
+ <% end %>
10
+ <% if result.status == "skipped" %>
11
+ <tr class="skip_message"><th>Skip Message:</th><td><%= result.skip_message %></td></tr>
12
+ <% end %>
13
+ <tr class="duration"><th>Duration:</th><td><%= result.run_time %> seconds</td></tr>
14
+ </table>
15
+ </div>
@@ -0,0 +1,8 @@
1
+ <div class="selector-panel">
2
+ <p id="selector-instructions">Display controls that are:</p>
3
+ <input class="selector-checkbox" id="passed-checkbox" type="checkbox" checked="checked"/><label for="passed-checkbox">Passed</label>
4
+ <input class="selector-checkbox" id="skipped-checkbox" type="checkbox" checked="checked"/><label for="skipped-checkbox">Skipped</label>
5
+ <input class="selector-checkbox" id="failed-checkbox" type="checkbox" checked="checked"/><label for="failed-checkbox">Failed</label>
6
+ <p id="selector-instructions">Display profiles that are:</p>
7
+ <input class="profile-selector-checkbox" id="child-profile-checkbox" type="checkbox" /><label for="child-profile-checkbox">Dependent Profiles</label>
8
+ </div>
@@ -0,0 +1,10 @@
1
+ # JSON Minimal Reporter Plugin
2
+
3
+ ## To Install This Plugin
4
+
5
+ This plugin is included with InSpec. There is no need to install it.
6
+
7
+ ## What This Plugin Does
8
+
9
+ This plugin provides the `json-min` reporter, which produces test output in JSON format with less detail than the `json` reporter.
10
+
@@ -0,0 +1,13 @@
1
+ require_relative "inspec-reporter-json-min/version"
2
+
3
+ module InspecPlugins
4
+ module JsonMinReporter
5
+ class Plugin < ::Inspec.plugin(2)
6
+ plugin_name :"inspec-reporter-json-min"
7
+ reporter :"json-min" do
8
+ require_relative "inspec-reporter-json-min/reporter"
9
+ InspecPlugins::JsonMinReporter::Reporter
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,50 @@
1
+ require "json"
2
+
3
+ module InspecPlugins::JsonMinReporter
4
+ class Reporter < Inspec.plugin(2, :reporter)
5
+ def self.run_data_schema_constraints
6
+ "~> 0.0"
7
+ end
8
+
9
+ def render
10
+ output(report.to_json, false)
11
+ end
12
+
13
+ def report # rubocop:disable Metrics/AbcSize
14
+ report = {
15
+ controls: [],
16
+ statistics: { duration: run_data.statistics.duration },
17
+ version: run_data.version,
18
+ }
19
+
20
+ # collect all test results and add them to the report
21
+ run_data.profiles.each do |profile|
22
+ profile_id = profile.name
23
+
24
+ profile.controls.each do |control|
25
+ control_id = control.id
26
+
27
+ control.results.each do |result|
28
+ result_for_report = {
29
+ id: control_id,
30
+ profile_id: profile_id,
31
+ profile_sha256: profile.sha256,
32
+ status: result.status,
33
+ code_desc: result.code_desc,
34
+ }
35
+
36
+ result_for_report[:skip_message] = result.skip_message if result.non_nil?(:skip_message)
37
+ result_for_report[:resource] = result.resource if result.non_nil?(:resource)
38
+ result_for_report[:message] = result.message if result.non_nil?(:message)
39
+ result_for_report[:exception] = result.exception if result.non_nil?(:exception)
40
+ result_for_report[:backtrace] = result.backtrace if result.non_nil?(:backtrace)
41
+
42
+ report[:controls] << result_for_report
43
+ end
44
+ end
45
+ end
46
+
47
+ report
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,5 @@
1
+ module InspecPlugins
2
+ module JsonMinReporter
3
+ VERSION = "0.1.0".freeze
4
+ end
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.19.0
4
+ version: 4.21.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef InSpec Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-27 00:00:00.000000000 Z
11
+ date: 2020-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry
@@ -264,14 +264,14 @@ dependencies:
264
264
  requirements:
265
265
  - - "~>"
266
266
  - !ruby/object:Gem::Version
267
- version: '1.2'
267
+ version: 1.2.0
268
268
  type: :runtime
269
269
  prerelease: false
270
270
  version_requirements: !ruby/object:Gem::Requirement
271
271
  requirements:
272
272
  - - "~>"
273
273
  - !ruby/object:Gem::Version
274
- version: '1.2'
274
+ version: 1.2.0
275
275
  - !ruby/object:Gem::Dependency
276
276
  name: addressable
277
277
  requirement: !ruby/object:Gem::Requirement
@@ -483,7 +483,6 @@ files:
483
483
  - lib/inspec/reporters/cli.rb
484
484
  - lib/inspec/reporters/json.rb
485
485
  - lib/inspec/reporters/json_automate.rb
486
- - lib/inspec/reporters/json_min.rb
487
486
  - lib/inspec/reporters/junit.rb
488
487
  - lib/inspec/reporters/yaml.rb
489
488
  - lib/inspec/require_loader.rb
@@ -537,6 +536,7 @@ files:
537
536
  - lib/inspec/resources/inetd_conf.rb
538
537
  - lib/inspec/resources/ini.rb
539
538
  - lib/inspec/resources/interface.rb
539
+ - lib/inspec/resources/interfaces.rb
540
540
  - lib/inspec/resources/ip6tables.rb
541
541
  - lib/inspec/resources/iptables.rb
542
542
  - lib/inspec/resources/json.rb
@@ -667,6 +667,7 @@ files:
667
667
  - lib/inspec/utils/telemetry/collector.rb
668
668
  - lib/inspec/utils/telemetry/data_series.rb
669
669
  - lib/inspec/utils/telemetry/global_methods.rb
670
+ - lib/inspec/utils/telemetry/run_context_probe.rb
670
671
  - lib/inspec/version.rb
671
672
  - lib/matchers/matchers.rb
672
673
  - lib/plugins/README.md
@@ -724,6 +725,21 @@ files:
724
725
  - lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli.rb
725
726
  - lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb
726
727
  - lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/plugin.rb
728
+ - lib/plugins/inspec-reporter-html2/README.md
729
+ - lib/plugins/inspec-reporter-html2/lib/inspec-reporter-html2.rb
730
+ - lib/plugins/inspec-reporter-html2/lib/inspec-reporter-html2/reporter.rb
731
+ - lib/plugins/inspec-reporter-html2/lib/inspec-reporter-html2/version.rb
732
+ - lib/plugins/inspec-reporter-html2/templates/body.html.erb
733
+ - lib/plugins/inspec-reporter-html2/templates/control.html.erb
734
+ - lib/plugins/inspec-reporter-html2/templates/default.css
735
+ - lib/plugins/inspec-reporter-html2/templates/default.js
736
+ - lib/plugins/inspec-reporter-html2/templates/profile.html.erb
737
+ - lib/plugins/inspec-reporter-html2/templates/result.html.erb
738
+ - lib/plugins/inspec-reporter-html2/templates/selector.html.erb
739
+ - lib/plugins/inspec-reporter-json-min/README.md
740
+ - lib/plugins/inspec-reporter-json-min/lib/inspec-reporter-json-min.rb
741
+ - lib/plugins/inspec-reporter-json-min/lib/inspec-reporter-json-min/reporter.rb
742
+ - lib/plugins/inspec-reporter-json-min/lib/inspec-reporter-json-min/version.rb
727
743
  - lib/plugins/shared/core_plugin_test_helper.rb
728
744
  - lib/plugins/things-for-train-integration.rb
729
745
  - lib/source_readers/flat.rb
@@ -1,48 +0,0 @@
1
- require "json"
2
-
3
- module Inspec::Reporters
4
- class JsonMin < Base
5
- def render
6
- output(report.to_json, false)
7
- end
8
-
9
- def report # rubocop:disable Metrics/AbcSize
10
- report = {
11
- controls: [],
12
- statistics: { duration: run_data[:statistics][:duration] },
13
- version: run_data[:version],
14
- }
15
-
16
- # collect all test results and add them to the report
17
- run_data[:profiles].each do |profile|
18
- profile_id = profile[:name]
19
- next unless profile[:controls]
20
-
21
- profile[:controls].each do |control|
22
- control_id = control[:id]
23
- next unless control[:results]
24
-
25
- control[:results].each do |result|
26
- result_for_report = {
27
- id: control_id,
28
- profile_id: profile_id,
29
- profile_sha256: profile[:sha256],
30
- status: result[:status],
31
- code_desc: result[:code_desc],
32
- }
33
-
34
- result_for_report[:skip_message] = result[:skip_message] if result.key?(:skip_message)
35
- result_for_report[:resource] = result[:resource] if result.key?(:resource)
36
- result_for_report[:message] = result[:message] if result.key?(:message)
37
- result_for_report[:exception] = result[:exception] if result.key?(:exception)
38
- result_for_report[:backtrace] = result[:backtrace] if result.key?(:backtrace)
39
-
40
- report[:controls] << result_for_report
41
- end
42
- end
43
- end
44
-
45
- report
46
- end
47
- end
48
- end