inspec-core 4.18.104 → 4.19.2
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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/inspec-core.gemspec +2 -2
- data/lib/inspec/base_cli.rb +4 -0
- data/lib/inspec/cli.rb +7 -17
- data/lib/inspec/config.rb +28 -6
- data/lib/inspec/fetcher/git.rb +1 -1
- data/lib/inspec/fetcher/local.rb +1 -1
- data/lib/inspec/fetcher/url.rb +1 -1
- data/lib/inspec/input.rb +9 -9
- data/lib/inspec/plugin/v2/plugin_types/reporter.rb +68 -0
- data/lib/inspec/profile.rb +16 -4
- data/lib/inspec/reporters.rb +4 -1
- data/lib/inspec/reporters/base.rb +22 -0
- data/lib/inspec/resources/x509_certificate.rb +1 -1
- data/lib/inspec/rule.rb +8 -4
- data/lib/inspec/run_data.rb +64 -0
- data/lib/inspec/run_data/control.rb +83 -0
- data/lib/inspec/run_data/profile.rb +109 -0
- data/lib/inspec/run_data/result.rb +40 -0
- data/lib/inspec/run_data/statistics.rb +36 -0
- data/lib/inspec/shell.rb +8 -3
- data/lib/inspec/utils/json_profile_summary.rb +35 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb +18 -1
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/api.rb +4 -0
- data/lib/plugins/inspec-init/lib/inspec-init/cli_plugin.rb +28 -6
- data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/plugin.rb +18 -0
- data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/reporter.rb +27 -0
- metadata +20 -6
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d3f655ad7598f4a71bab9caff608eca6990e6c66242d1c11519d105c89168fcb
         | 
| 4 | 
            +
              data.tar.gz: f6679028fc6283e7482143368d09edf70cb74d648bd45ede5d2bb8e4eb6ec165
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ea24f149c474dc40974f05d017d3544ce2f4e3b762f1474f7c9146d01cf3c074a8526406bc7bb1b325cd973251f0ffc5cad06a86d7686dda0e7bf6a226f834c0
         | 
| 7 | 
            +
              data.tar.gz: cb74991d735738e58dbf04ed6c0dc5e32c923d83fe61cc7143a8af611050f001bb0d174949ed34a8ba7f97cd16735ca96e8d845e970abda579a12f44dec6fc22
         | 
    
        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"] # 1.13 does not work on Windows: https://github.com/ffi/ffi/issues/784
         | 
| 13 13 |  | 
| 14 14 | 
             
            group :omnibus do
         | 
| 15 15 | 
             
              gem "rb-readline"
         | 
    
        data/README.md
    CHANGED
    
    
    
        data/inspec-core.gemspec
    CHANGED
    
    | @@ -27,11 +27,11 @@ Gem::Specification.new do |spec| | |
| 27 27 | 
             
              spec.add_dependency "license-acceptance", ">= 0.2.13", "< 2.0"
         | 
| 28 28 | 
             
              spec.add_dependency "thor",               ">= 0.20", "< 2.0"
         | 
| 29 29 | 
             
              spec.add_dependency "json_schemer",       "~> 0.2.1"
         | 
| 30 | 
            -
              spec.add_dependency "method_source",      " | 
| 30 | 
            +
              spec.add_dependency "method_source",      ">= 0.8", "< 2.0"
         | 
| 31 31 | 
             
              spec.add_dependency "rubyzip",            "~> 1.2", ">= 1.2.2"
         | 
| 32 32 | 
             
              spec.add_dependency "rspec",              "~> 3.9"
         | 
| 33 33 | 
             
              spec.add_dependency "rspec-its",          "~> 1.2"
         | 
| 34 | 
            -
              spec.add_dependency "pry",                "~> 0"
         | 
| 34 | 
            +
              spec.add_dependency "pry",                "~> 0.13"
         | 
| 35 35 | 
             
              spec.add_dependency "hashie",             "~> 3.4"
         | 
| 36 36 | 
             
              spec.add_dependency "mixlib-log",         "~> 3.0"
         | 
| 37 37 | 
             
              spec.add_dependency "sslshake",           "~> 1.2"
         | 
    
        data/lib/inspec/base_cli.rb
    CHANGED
    
    | @@ -135,6 +135,10 @@ module Inspec | |
| 135 135 | 
             
                  option :reporter, type: :array,
         | 
| 136 136 | 
             
                    banner: "one two:/output/file/path",
         | 
| 137 137 | 
             
                    desc: "Enable one or more output reporters: cli, documentation, html, progress, json, json-min, json-rspec, junit, yaml"
         | 
| 138 | 
            +
                  option :reporter_message_truncation, type: :string,
         | 
| 139 | 
            +
                    desc: "Number of characters to truncate failure messages in report data to (default: no truncation)"
         | 
| 140 | 
            +
                  option :reporter_backtrace_inclusion, type: :boolean,
         | 
| 141 | 
            +
                    desc: "Include a code backtrace in report data (default: true)"
         | 
| 138 142 | 
             
                  option :input, type: :array, banner: "name1=value1 name2=value2",
         | 
| 139 143 | 
             
                    desc: "Specify one or more inputs directly on the command line, as --input NAME=VALUE"
         | 
| 140 144 | 
             
                  option :input_file, type: :array,
         | 
    
        data/lib/inspec/cli.rb
    CHANGED
    
    | @@ -4,6 +4,7 @@ require "inspec/utils/deprecation/deprecator" | |
| 4 4 | 
             
            require "inspec/dist"
         | 
| 5 5 | 
             
            require "inspec/backend"
         | 
| 6 6 | 
             
            require "inspec/dependencies/cache"
         | 
| 7 | 
            +
            require "inspec/utils/json_profile_summary"
         | 
| 7 8 |  | 
| 8 9 | 
             
            module Inspec # TODO: move this somewhere "better"?
         | 
| 9 10 | 
             
              autoload :BaseCLI,       "inspec/base_cli"
         | 
| @@ -77,24 +78,13 @@ class Inspec::InspecCLI < Inspec::BaseCLI | |
| 77 78 | 
             
                o[:vendor_cache] = Inspec::Cache.new(o[:vendor_cache])
         | 
| 78 79 |  | 
| 79 80 | 
             
                profile = Inspec::Profile.for_target(target, o)
         | 
| 80 | 
            -
                info = profile.info
         | 
| 81 | 
            -
                # add in inspec version
         | 
| 82 | 
            -
                info[:generator] = {
         | 
| 83 | 
            -
                  name: "inspec",
         | 
| 84 | 
            -
                  version: Inspec::VERSION,
         | 
| 85 | 
            -
                }
         | 
| 86 81 | 
             
                dst = o[:output].to_s
         | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
                 | 
| 90 | 
            -
                   | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
                    puts "----> creating #{dst}"
         | 
| 94 | 
            -
                  end
         | 
| 95 | 
            -
                  fdst = File.expand_path(dst)
         | 
| 96 | 
            -
                  File.write(fdst, JSON.dump(info))
         | 
| 97 | 
            -
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                # Write JSON
         | 
| 84 | 
            +
                Inspec::Utils::JsonProfileSummary.produce_json(
         | 
| 85 | 
            +
                  info: profile.info,
         | 
| 86 | 
            +
                  write_path: dst
         | 
| 87 | 
            +
                )
         | 
| 98 88 | 
             
              rescue StandardError => e
         | 
| 99 89 | 
             
                pretty_handle_exception(e)
         | 
| 100 90 | 
             
              end
         | 
    
        data/lib/inspec/config.rb
    CHANGED
    
    | @@ -328,21 +328,36 @@ module Inspec | |
| 328 328 | 
             
                def validate_reporters!(reporters)
         | 
| 329 329 | 
             
                  return if reporters.nil?
         | 
| 330 330 |  | 
| 331 | 
            -
                  #  | 
| 332 | 
            -
                   | 
| 333 | 
            -
             | 
| 334 | 
            -
                    cli
         | 
| 331 | 
            +
                  # These "reporters" are actually RSpec Formatters.
         | 
| 332 | 
            +
                  # json-rspec is our alias for RSpec's json formatter.
         | 
| 333 | 
            +
                  rspec_built_in_formatters = %w{
         | 
| 335 334 | 
             
                    documentation
         | 
| 336 335 | 
             
                    html
         | 
| 336 | 
            +
                    json-rspec
         | 
| 337 | 
            +
                    progress
         | 
| 338 | 
            +
                  }
         | 
| 339 | 
            +
             | 
| 340 | 
            +
                  # These are true reporters, but have not been migrated to be plugins yet.
         | 
| 341 | 
            +
                  # Tracked on https://github.com/inspec/inspec/issues/3667
         | 
| 342 | 
            +
                  inspec_reporters_that_are_not_yet_plugins = %w{
         | 
| 343 | 
            +
                    automate
         | 
| 344 | 
            +
                    cli
         | 
| 337 345 | 
             
                    json
         | 
| 338 346 | 
             
                    json-automate
         | 
| 339 347 | 
             
                    json-min
         | 
| 340 | 
            -
                    json-rspec
         | 
| 341 348 | 
             
                    junit
         | 
| 342 | 
            -
                    progress
         | 
| 343 349 | 
             
                    yaml
         | 
| 344 350 | 
             
                  }
         | 
| 345 351 |  | 
| 352 | 
            +
                  # Additional reporters may be loaded via plugins. They will have already been detected at
         | 
| 353 | 
            +
                  # this point (see v2_loader.load_all in cli.rb) but they may not (and need not) be
         | 
| 354 | 
            +
                  # activated at this point. We only care about their existance and their name, for validation's sake.
         | 
| 355 | 
            +
                  plugin_reporters = Inspec::Plugin::V2::Registry.instance\
         | 
| 356 | 
            +
                    .find_activators(plugin_type: :reporter)\
         | 
| 357 | 
            +
                    .map(&:activator_name).map(&:to_s)
         | 
| 358 | 
            +
             | 
| 359 | 
            +
                  valid_types = rspec_built_in_formatters + inspec_reporters_that_are_not_yet_plugins + plugin_reporters
         | 
| 360 | 
            +
             | 
| 346 361 | 
             
                  reporters.each do |reporter_name, reporter_config|
         | 
| 347 362 | 
             
                    raise NotImplementedError, "'#{reporter_name}' is not a valid reporter type." unless valid_types.include?(reporter_name)
         | 
| 348 363 |  | 
| @@ -360,6 +375,13 @@ module Inspec | |
| 360 375 | 
             
                  end
         | 
| 361 376 |  | 
| 362 377 | 
             
                  raise ArgumentError, "The option --reporter can only have a single report outputting to stdout." if stdout_reporters > 1
         | 
| 378 | 
            +
             | 
| 379 | 
            +
                  # reporter_message_truncation needs to either be the string "ALL", an Integer, or a string representing an integer
         | 
| 380 | 
            +
                  if (truncation = @merged_options["reporter_message_truncation"])
         | 
| 381 | 
            +
                    unless truncation == "ALL" || truncation.is_a?(Integer) || truncation.to_i.to_s == truncation
         | 
| 382 | 
            +
                      raise ArgumentError, "reporter_message_truncation is set to #{truncation}. It must be set to an integer value or ALL to indicate no truncation."
         | 
| 383 | 
            +
                    end
         | 
| 384 | 
            +
                  end
         | 
| 363 385 | 
             
                end
         | 
| 364 386 |  | 
| 365 387 | 
             
                def validate_plugins!
         | 
    
        data/lib/inspec/fetcher/git.rb
    CHANGED
    
    | @@ -99,7 +99,7 @@ module Inspec::Fetcher | |
| 99 99 | 
             
                def cache_key
         | 
| 100 100 | 
             
                  return resolved_ref unless @relative_path
         | 
| 101 101 |  | 
| 102 | 
            -
                  OpenSSL::Digest | 
| 102 | 
            +
                  OpenSSL::Digest.hexdigest("SHA256", resolved_ref + @relative_path)
         | 
| 103 103 | 
             
                end
         | 
| 104 104 |  | 
| 105 105 | 
             
                def archive_path
         | 
    
        data/lib/inspec/fetcher/local.rb
    CHANGED
    
    | @@ -104,7 +104,7 @@ module Inspec::Fetcher | |
| 104 104 | 
             
                  return @archive_shasum if @archive_shasum
         | 
| 105 105 | 
             
                  raise(Inspec::FetcherFailure, "Profile dependency local path '#{target}' does not exist") unless File.exist?(target)
         | 
| 106 106 |  | 
| 107 | 
            -
                  @archive_shasum = OpenSSL::Digest | 
| 107 | 
            +
                  @archive_shasum = OpenSSL::Digest.digest("SHA256", File.read(target)).unpack("H*")[0]
         | 
| 108 108 | 
             
                end
         | 
| 109 109 |  | 
| 110 110 | 
             
                def resolved_source
         | 
    
        data/lib/inspec/fetcher/url.rb
    CHANGED
    
    | @@ -127,7 +127,7 @@ module Inspec::Fetcher | |
| 127 127 | 
             
                end
         | 
| 128 128 |  | 
| 129 129 | 
             
                def sha256
         | 
| 130 | 
            -
                  @archive_shasum ||= OpenSSL::Digest | 
| 130 | 
            +
                  @archive_shasum ||= OpenSSL::Digest.digest("SHA256", File.read(@archive_path || temp_archive_path)).unpack("H*")[0]
         | 
| 131 131 | 
             
                end
         | 
| 132 132 |  | 
| 133 133 | 
             
                def file_type_from_remote(remote)
         | 
    
        data/lib/inspec/input.rb
    CHANGED
    
    | @@ -98,15 +98,15 @@ module Inspec | |
| 98 98 | 
             
                # not been assigned a value. This allows a user to explicitly assign nil
         | 
| 99 99 | 
             
                # to an input.
         | 
| 100 100 | 
             
                class NO_VALUE_SET # rubocop: disable Naming/ClassAndModuleCamelCase
         | 
| 101 | 
            -
                  def initialize(name)
         | 
| 101 | 
            +
                  def initialize(name, warn_on_create = true)
         | 
| 102 102 | 
             
                    @name = name
         | 
| 103 103 |  | 
| 104 104 | 
             
                    # output warn message if we are in a exec call
         | 
| 105 | 
            -
                    if Inspec::BaseCLI.inspec_cli_command == :exec
         | 
| 105 | 
            +
                    if warn_on_create && Inspec::BaseCLI.inspec_cli_command == :exec
         | 
| 106 106 | 
             
                      Inspec::Log.warn(
         | 
| 107 107 | 
             
                        "Input '#{@name}' does not have a value. "\
         | 
| 108 | 
            -
                        "Use --input-file to provide a value for '#{@name}' or specify a  "\
         | 
| 109 | 
            -
                        "value with ` | 
| 108 | 
            +
                        "Use --input-file or --input to provide a value for '#{@name}' or specify a  "\
         | 
| 109 | 
            +
                        "value with `input('#{@name}', value: 'somevalue', ...)`."
         | 
| 110 110 | 
             
                      )
         | 
| 111 111 | 
             
                    end
         | 
| 112 112 | 
             
                  end
         | 
| @@ -277,7 +277,7 @@ module Inspec | |
| 277 277 | 
             
                end
         | 
| 278 278 |  | 
| 279 279 | 
             
                # Determine the current winning value, but don't validate it
         | 
| 280 | 
            -
                def current_value
         | 
| 280 | 
            +
                def current_value(warn_on_missing = true)
         | 
| 281 281 | 
             
                  # Examine the events to determine highest-priority value. Tie-break
         | 
| 282 282 | 
             
                  # by using the last one set.
         | 
| 283 283 | 
             
                  events_that_set_a_value = events.select(&:value_has_been_set?)
         | 
| @@ -287,7 +287,7 @@ module Inspec | |
| 287 287 |  | 
| 288 288 | 
             
                  if winning_event.nil?
         | 
| 289 289 | 
             
                    # No value has been set - return special no value object
         | 
| 290 | 
            -
                    NO_VALUE_SET.new(name)
         | 
| 290 | 
            +
                    NO_VALUE_SET.new(name, warn_on_missing)
         | 
| 291 291 | 
             
                  else
         | 
| 292 292 | 
             
                    winning_event.value # May still be nil
         | 
| 293 293 | 
             
                  end
         | 
| @@ -315,7 +315,7 @@ module Inspec | |
| 315 315 | 
             
                end
         | 
| 316 316 |  | 
| 317 317 | 
             
                def has_value?
         | 
| 318 | 
            -
                  !current_value.is_a? NO_VALUE_SET
         | 
| 318 | 
            +
                  !current_value(false).is_a? NO_VALUE_SET
         | 
| 319 319 | 
             
                end
         | 
| 320 320 |  | 
| 321 321 | 
             
                def to_hash
         | 
| @@ -348,7 +348,7 @@ module Inspec | |
| 348 348 | 
             
                  # skip if we are not doing an exec call (archive/vendor/check)
         | 
| 349 349 | 
             
                  return unless Inspec::BaseCLI.inspec_cli_command == :exec
         | 
| 350 350 |  | 
| 351 | 
            -
                  proposed_value = current_value
         | 
| 351 | 
            +
                  proposed_value = current_value(false)
         | 
| 352 352 | 
             
                  if proposed_value.nil? || proposed_value.is_a?(NO_VALUE_SET)
         | 
| 353 353 | 
             
                    error = Inspec::Input::RequiredError.new
         | 
| 354 354 | 
             
                    error.input_name = name
         | 
| @@ -363,7 +363,7 @@ module Inspec | |
| 363 363 | 
             
                  type_req = type
         | 
| 364 364 | 
             
                  return if type_req == "Any"
         | 
| 365 365 |  | 
| 366 | 
            -
                  proposed_value = current_value
         | 
| 366 | 
            +
                  proposed_value = current_value(false)
         | 
| 367 367 |  | 
| 368 368 | 
             
                  invalid_type = false
         | 
| 369 369 | 
             
                  if type_req == "Regexp"
         | 
| @@ -0,0 +1,68 @@ | |
| 1 | 
            +
            require_relative "../../../run_data"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Inspec::Plugin::V2::PluginType
         | 
| 4 | 
            +
              class Reporter < Inspec::Plugin::V2::PluginBase
         | 
| 5 | 
            +
                register_plugin_type(:reporter)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                attr_reader :run_data
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def initialize(config)
         | 
| 10 | 
            +
                  @config = config
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  # Trim the run_data while still a Hash; if it is huge, this
         | 
| 13 | 
            +
                  # saves on conversion time
         | 
| 14 | 
            +
                  @run_data = config[:run_data] || {}
         | 
| 15 | 
            +
                  apply_report_resize_options
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  unless Inspec::RunData.compatible_schema?(self.class.run_data_schema_constraints)
         | 
| 18 | 
            +
                    # Best we can do is warn here, the InSpec run has finished
         | 
| 19 | 
            +
                    # TODO: one day, perhaps switch RunData implementations to try to satisfy constraints?
         | 
| 20 | 
            +
                    Inspec::Log.warn "Reporter does not support RunData API (#{Inspec::RunData::SCHEMA_VERSION}), Reporter constraints: '#{self.class.run_data_schema_constraints}'"
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                  # Convert to RunData object for consumption by Reporter
         | 
| 23 | 
            +
                  @run_data = Inspec::RunData.new(@run_data)
         | 
| 24 | 
            +
                  @output = ""
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                # This is a temporary duplication of code from lib/inspec/reporters/base.rb
         | 
| 28 | 
            +
                # To be DRY'd up once the core reporters become plugins...
         | 
| 29 | 
            +
                # Apply options such as message truncation and removal of backtraces
         | 
| 30 | 
            +
                def apply_report_resize_options
         | 
| 31 | 
            +
                  runtime_config = Inspec::Config.cached.respond_to?(:final_options) ? Inspec::Config.cached.final_options : {}
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  message_truncation = runtime_config[:reporter_message_truncation] || "ALL"
         | 
| 34 | 
            +
                  trunc = message_truncation == "ALL" ? -1 : message_truncation.to_i
         | 
| 35 | 
            +
                  include_backtrace = runtime_config[:reporter_backtrace_inclusion].nil? ? true : runtime_config[:reporter_backtrace_inclusion]
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  @run_data[:profiles]&.each do |p|
         | 
| 38 | 
            +
                    p[:controls].each do |c|
         | 
| 39 | 
            +
                      c[:results]&.map! do |r|
         | 
| 40 | 
            +
                        r.delete(:backtrace) unless include_backtrace
         | 
| 41 | 
            +
                        if r.key?(:message) && r[:message] != "" && trunc > -1
         | 
| 42 | 
            +
                          r[:message] = r[:message][0...trunc] + "[Truncated to #{trunc} characters]"
         | 
| 43 | 
            +
                        end
         | 
| 44 | 
            +
                        r
         | 
| 45 | 
            +
                      end
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def output(str, newline = true)
         | 
| 51 | 
            +
                  @output << str
         | 
| 52 | 
            +
                  @output << "\n" if newline
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def rendered_output
         | 
| 56 | 
            +
                  @output
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                # each reporter must implement #render
         | 
| 60 | 
            +
                def render
         | 
| 61 | 
            +
                  raise NotImplementedError, "#{self.class} must implement a `#render` method to format its output."
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                def self.run_data_schema_constraints
         | 
| 65 | 
            +
                  raise NotImplementedError, "#{self.class} must implement a `run_data_schema_constraints` class method to declare its compatibiltity with the RunData API."
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
            end
         | 
    
        data/lib/inspec/profile.rb
    CHANGED
    
    | @@ -12,6 +12,7 @@ require "inspec/method_source" | |
| 12 12 | 
             
            require "inspec/dependencies/cache"
         | 
| 13 13 | 
             
            require "inspec/dependencies/lockfile"
         | 
| 14 14 | 
             
            require "inspec/dependencies/dependency_set"
         | 
| 15 | 
            +
            require "inspec/utils/json_profile_summary"
         | 
| 15 16 |  | 
| 16 17 | 
             
            module Inspec
         | 
| 17 18 | 
             
              class Profile
         | 
| @@ -465,28 +466,39 @@ module Inspec | |
| 465 466 | 
             
                  end
         | 
| 466 467 |  | 
| 467 468 | 
             
                  # remove existing archive
         | 
| 468 | 
            -
                   | 
| 469 | 
            +
                  FileUtils.rm_f(dst) if dst.exist?
         | 
| 469 470 | 
             
                  @logger.info "Generate archive #{dst}."
         | 
| 470 471 |  | 
| 471 472 | 
             
                  # filter files that should not be part of the profile
         | 
| 472 473 | 
             
                  # TODO ignore all .files, but add the files to debug output
         | 
| 473 474 |  | 
| 475 | 
            +
                  # Generate temporary inspec.json for archive
         | 
| 476 | 
            +
                  Inspec::Utils::JsonProfileSummary.produce_json(
         | 
| 477 | 
            +
                    info: info,
         | 
| 478 | 
            +
                    write_path: "#{root_path}inspec.json",
         | 
| 479 | 
            +
                    suppress_output: true
         | 
| 480 | 
            +
                  )
         | 
| 481 | 
            +
             | 
| 474 482 | 
             
                  # display all files that will be part of the archive
         | 
| 475 483 | 
             
                  @logger.debug "Add the following files to archive:"
         | 
| 476 484 | 
             
                  files.each { |f| @logger.debug "    " + f }
         | 
| 485 | 
            +
                  @logger.debug "    inspec.json"
         | 
| 477 486 |  | 
| 478 487 | 
             
                  if opts[:zip]
         | 
| 479 488 | 
             
                    # generate zip archive
         | 
| 480 489 | 
             
                    require "inspec/archive/zip"
         | 
| 481 490 | 
             
                    zag = Inspec::Archive::ZipArchiveGenerator.new
         | 
| 482 | 
            -
                    zag.archive(root_path, files, dst)
         | 
| 491 | 
            +
                    zag.archive(root_path, files.push("inspec.json"), dst)
         | 
| 483 492 | 
             
                  else
         | 
| 484 493 | 
             
                    # generate tar archive
         | 
| 485 494 | 
             
                    require "inspec/archive/tar"
         | 
| 486 495 | 
             
                    tag = Inspec::Archive::TarArchiveGenerator.new
         | 
| 487 | 
            -
                    tag.archive(root_path, files, dst)
         | 
| 496 | 
            +
                    tag.archive(root_path, files.push("inspec.json"), dst)
         | 
| 488 497 | 
             
                  end
         | 
| 489 498 |  | 
| 499 | 
            +
                  # Cleanup
         | 
| 500 | 
            +
                  FileUtils.rm_f("#{root_path}inspec.json")
         | 
| 501 | 
            +
             | 
| 490 502 | 
             
                  @logger.info "Finished archive generation."
         | 
| 491 503 | 
             
                  true
         | 
| 492 504 | 
             
                end
         | 
| @@ -559,7 +571,7 @@ module Inspec | |
| 559 571 | 
             
                  # get all dependency checksums
         | 
| 560 572 | 
             
                  deps = Hash[locked_dependencies.list.map { |k, v| [k, v.profile.sha256] }]
         | 
| 561 573 |  | 
| 562 | 
            -
                  res = OpenSSL::Digest | 
| 574 | 
            +
                  res = OpenSSL::Digest.new("SHA256")
         | 
| 563 575 | 
             
                  files = source_reader.tests.to_a + source_reader.libraries.to_a +
         | 
| 564 576 | 
             
                    source_reader.data_files.to_a +
         | 
| 565 577 | 
             
                    [["inspec.yml", source_reader.metadata.content]] +
         | 
    
        data/lib/inspec/reporters.rb
    CHANGED
    
    | @@ -30,7 +30,10 @@ module Inspec::Reporters | |
| 30 30 | 
             
                when "yaml"
         | 
| 31 31 | 
             
                  reporter = Inspec::Reporters::Yaml.new(config)
         | 
| 32 32 | 
             
                else
         | 
| 33 | 
            -
                   | 
| 33 | 
            +
                  # If we made it here, it must be a plugin, and we know it exists (because we validated it in config.rb)
         | 
| 34 | 
            +
                  activator = Inspec::Plugin::V2::Registry.instance.find_activator(plugin_type: :reporter, activator_name: name.to_sym)
         | 
| 35 | 
            +
                  activator.activate!
         | 
| 36 | 
            +
                  reporter = activator.implementation_class.new(config)
         | 
| 34 37 | 
             
                end
         | 
| 35 38 |  | 
| 36 39 | 
             
                # optional send_report method on reporter
         | 
| @@ -5,9 +5,31 @@ module Inspec::Reporters | |
| 5 5 | 
             
                def initialize(config)
         | 
| 6 6 | 
             
                  @config = config
         | 
| 7 7 | 
             
                  @run_data = config[:run_data]
         | 
| 8 | 
            +
                  apply_report_resize_options unless @run_data.nil?
         | 
| 8 9 | 
             
                  @output = ""
         | 
| 9 10 | 
             
                end
         | 
| 10 11 |  | 
| 12 | 
            +
                # Apply options such as message truncation and removal of backtraces
         | 
| 13 | 
            +
                def apply_report_resize_options
         | 
| 14 | 
            +
                  runtime_config = Inspec::Config.cached.respond_to?(:final_options) ? Inspec::Config.cached.final_options : {}
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  message_truncation = runtime_config[:reporter_message_truncation] || "ALL"
         | 
| 17 | 
            +
                  trunc = message_truncation == "ALL" ? -1 : message_truncation.to_i
         | 
| 18 | 
            +
                  include_backtrace = runtime_config[:reporter_backtrace_inclusion].nil? ? true : runtime_config[:reporter_backtrace_inclusion]
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  @run_data[:profiles]&.each do |p|
         | 
| 21 | 
            +
                    p[:controls].each do |c|
         | 
| 22 | 
            +
                      c[:results]&.map! do |r|
         | 
| 23 | 
            +
                        r.delete(:backtrace) unless include_backtrace
         | 
| 24 | 
            +
                        if r.key?(:message) && r[:message] != "" && trunc > -1
         | 
| 25 | 
            +
                          r[:message] = r[:message][0...trunc] + "[Truncated to #{trunc} characters]"
         | 
| 26 | 
            +
                        end
         | 
| 27 | 
            +
                        r
         | 
| 28 | 
            +
                      end
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 11 33 | 
             
                def output(str, newline = true)
         | 
| 12 34 | 
             
                  @output << str
         | 
| 13 35 | 
             
                  @output << "\n" if newline
         | 
    
        data/lib/inspec/rule.rb
    CHANGED
    
    | @@ -332,7 +332,7 @@ module Inspec | |
| 332 332 | 
             
                  input_name = @__rule_id # TODO: control ID slugging
         | 
| 333 333 | 
             
                  registry = Inspec::InputRegistry.instance
         | 
| 334 334 | 
             
                  input = registry.inputs_by_profile.dig(__profile_id, input_name)
         | 
| 335 | 
            -
                  return unless input
         | 
| 335 | 
            +
                  return unless input && input.has_value? && input.value.is_a?(Hash)
         | 
| 336 336 |  | 
| 337 337 | 
             
                  # An InSpec Input is a datastructure that tracks a profile parameter
         | 
| 338 338 | 
             
                  # over time. Its value can be set by many sources, and it keeps a
         | 
| @@ -353,9 +353,13 @@ module Inspec | |
| 353 353 | 
             
                  # if so, is it in the future?
         | 
| 354 354 | 
             
                  expiry = __waiver_data["expiration_date"]
         | 
| 355 355 | 
             
                  if expiry
         | 
| 356 | 
            -
                     | 
| 357 | 
            -
             | 
| 358 | 
            -
             | 
| 356 | 
            +
                    # YAML will automagically give us a Date or a Time.
         | 
| 357 | 
            +
                    # If transcoding YAML between languages (e.g. Go) the date might have also ended up as a String.
         | 
| 358 | 
            +
                    # A string that does not represent a valid time results in the date 0000-01-01.
         | 
| 359 | 
            +
                    if [Date, Time].include?(expiry.class) || (expiry.is_a?(String) && Time.new(expiry).year != 0)
         | 
| 360 | 
            +
                      expiry = expiry.to_time if expiry.is_a? Date
         | 
| 361 | 
            +
                      expiry = Time.new(expiry) if expiry.is_a? String
         | 
| 362 | 
            +
                      if expiry < Time.now # If the waiver expired, return - no skip applied
         | 
| 359 363 | 
             
                        __waiver_data["message"] = "Waiver expired on #{expiry}, evaluating control normally"
         | 
| 360 364 | 
             
                        return
         | 
| 361 365 | 
             
                      end
         | 
| @@ -0,0 +1,64 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            module Inspec
         | 
| 3 | 
            +
              module HashLikeStruct
         | 
| 4 | 
            +
                def keys
         | 
| 5 | 
            +
                  members
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def key?(item)
         | 
| 9 | 
            +
                  members.include?(item)
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              RunData = Struct.new(
         | 
| 14 | 
            +
                :controls,     # Array of Inspec::RunData::Control (flattened)
         | 
| 15 | 
            +
                :other_checks,
         | 
| 16 | 
            +
                :profiles,     # Array of Inspec::RunData::Profile
         | 
| 17 | 
            +
                :platform,     # Inspec::RunData::Platform
         | 
| 18 | 
            +
                :statistics,   # Inspec::RunData::Statistics
         | 
| 19 | 
            +
                :version       # String
         | 
| 20 | 
            +
              ) do
         | 
| 21 | 
            +
                include HashLikeStruct
         | 
| 22 | 
            +
                def initialize(raw_run_data)
         | 
| 23 | 
            +
                  self.controls   = raw_run_data[:controls].map { |c| Inspec::RunData::Control.new(c) }
         | 
| 24 | 
            +
                  self.profiles   = raw_run_data[:profiles].map { |p| Inspec::RunData::Profile.new(p) }
         | 
| 25 | 
            +
                  self.statistics = Inspec::RunData::Statistics.new(raw_run_data[:statistics])
         | 
| 26 | 
            +
                  self.platform   = Inspec::RunData::Platform.new(raw_run_data[:platform])
         | 
| 27 | 
            +
                  self.version    = raw_run_data[:version]
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              class RunData
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                # This is the data layout version of RunData.
         | 
| 34 | 
            +
                # We plan to follow a data-oriented version of semver:
         | 
| 35 | 
            +
                #  patch: fixing a bug in the provenance or description of a data element, no key changes
         | 
| 36 | 
            +
                #  minor: adding new data elements
         | 
| 37 | 
            +
                #  major: deleting or renaming data elements
         | 
| 38 | 
            +
                # Less than major version 1.0.0, the API is considered unstable.
         | 
| 39 | 
            +
                # The current plan is to bump the major version to 1.0.0 when all of the existing
         | 
| 40 | 
            +
                # core reporters have been migrated to plugins. It is probable that new data elements
         | 
| 41 | 
            +
                # and new Hash compatibility behavior will be added during the core reporter plugin
         | 
| 42 | 
            +
                # conversion process.
         | 
| 43 | 
            +
                SCHEMA_VERSION = "0.1.0".freeze
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                def self.compatible_schema?(constraints)
         | 
| 46 | 
            +
                  reqs = Gem::Requirement.create(constraints)
         | 
| 47 | 
            +
                  reqs.satisfied_by?(Gem::Version.new(SCHEMA_VERSION))
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                Platform = Struct.new(
         | 
| 51 | 
            +
                  :name, :release, :target
         | 
| 52 | 
            +
                ) do
         | 
| 53 | 
            +
                  include HashLikeStruct
         | 
| 54 | 
            +
                  def initialize(raw_plat_data)
         | 
| 55 | 
            +
                    %i{name release target}.each { |f| self[f] = raw_plat_data[f] || "" }
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
            end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            require_relative "run_data/result"
         | 
| 62 | 
            +
            require_relative "run_data/control"
         | 
| 63 | 
            +
            require_relative "run_data/profile"
         | 
| 64 | 
            +
            require_relative "run_data/statistics"
         | 
| @@ -0,0 +1,83 @@ | |
| 1 | 
            +
            module Inspec
         | 
| 2 | 
            +
              class RunData
         | 
| 3 | 
            +
                Control = Struct.new(
         | 
| 4 | 
            +
                  :code,            # String
         | 
| 5 | 
            +
                  :desc,            # String
         | 
| 6 | 
            +
                  :descriptions,    # Hash with custom keys
         | 
| 7 | 
            +
                  :id,              # String
         | 
| 8 | 
            +
                  :impact,          # Float
         | 
| 9 | 
            +
                  :refs,            # Complex local
         | 
| 10 | 
            +
                  :results,         # complex standalone
         | 
| 11 | 
            +
                  :source_location, # Complex local
         | 
| 12 | 
            +
                  :tags,            # Hash with custom keys
         | 
| 13 | 
            +
                  :title,           # String
         | 
| 14 | 
            +
                  :waiver_data      # Complex local
         | 
| 15 | 
            +
                ) do
         | 
| 16 | 
            +
                  include HashLikeStruct
         | 
| 17 | 
            +
                  def initialize(raw_ctl_data)
         | 
| 18 | 
            +
                    self.refs = (raw_ctl_data[:refs] || []).map { |r| Inspec::RunData::Control::Ref.new(r) }
         | 
| 19 | 
            +
                    self.results = (raw_ctl_data[:results] || []).map { |r| Inspec::RunData::Result.new(r) }
         | 
| 20 | 
            +
                    self.source_location = Inspec::RunData::Control::SourceLocation.new(raw_ctl_data[:source_location] || {})
         | 
| 21 | 
            +
                    self.waiver_data = Inspec::RunData::Control::WaiverData.new(raw_ctl_data[:waiver_data] || {})
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    [
         | 
| 24 | 
            +
                      :code,            # String
         | 
| 25 | 
            +
                      :desc,            # String
         | 
| 26 | 
            +
                      :descriptions,    # Hash with custom keys
         | 
| 27 | 
            +
                      :id,              # String
         | 
| 28 | 
            +
                      :impact,          # Float
         | 
| 29 | 
            +
                      :tags,            # Hash with custom keys
         | 
| 30 | 
            +
                      :title,           # String
         | 
| 31 | 
            +
                    ].each do |field|
         | 
| 32 | 
            +
                      self[field] = raw_ctl_data[field]
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                class Control
         | 
| 38 | 
            +
                  Ref = Struct.new(
         | 
| 39 | 
            +
                    :url, :ref
         | 
| 40 | 
            +
                  ) do
         | 
| 41 | 
            +
                    include HashLikeStruct
         | 
| 42 | 
            +
                    def initialize(raw_ref_data)
         | 
| 43 | 
            +
                      %i{url ref}.each { |f| self[f] = raw_ref_data[f] }
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  SourceLocation = Struct.new(
         | 
| 48 | 
            +
                    :line, :ref
         | 
| 49 | 
            +
                  ) do
         | 
| 50 | 
            +
                    include HashLikeStruct
         | 
| 51 | 
            +
                    def initialize(raw_sl_data)
         | 
| 52 | 
            +
                      %i{line ref}.each { |f| self[f] = raw_sl_data[f] }
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  # {
         | 
| 57 | 
            +
                  #   "expiration_date"=>#<Date: 2077-06-01 ((2479821j,0s,0n),+0s,2299161j)>,
         | 
| 58 | 
            +
                  #   "justification"=>"Lack of imagination",
         | 
| 59 | 
            +
                  #   "run"=>false,
         | 
| 60 | 
            +
                  #   "skipped_due_to_waiver"=>true,
         | 
| 61 | 
            +
                  #   "message"=>""}
         | 
| 62 | 
            +
                  WaiverData = Struct.new(
         | 
| 63 | 
            +
                    :expiration_date,
         | 
| 64 | 
            +
                    :justification,
         | 
| 65 | 
            +
                    :run,
         | 
| 66 | 
            +
                    :skipped_due_to_waiver,
         | 
| 67 | 
            +
                    :message
         | 
| 68 | 
            +
                  ) do
         | 
| 69 | 
            +
                    include HashLikeStruct
         | 
| 70 | 
            +
                    def initialize(raw_wv_data)
         | 
| 71 | 
            +
                      # These have string keys in the raw data!
         | 
| 72 | 
            +
                      %i{
         | 
| 73 | 
            +
                        expiration_date
         | 
| 74 | 
            +
                        justification
         | 
| 75 | 
            +
                        run
         | 
| 76 | 
            +
                        skipped_due_to_waiver
         | 
| 77 | 
            +
                        message
         | 
| 78 | 
            +
                      }.each { |f| self[f] = raw_wv_data[f.to_s] }
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
              end
         | 
| 83 | 
            +
            end
         | 
| @@ -0,0 +1,109 @@ | |
| 1 | 
            +
            module Inspec
         | 
| 2 | 
            +
              class RunData
         | 
| 3 | 
            +
                Profile = Struct.new(
         | 
| 4 | 
            +
                  :controls,         # complex standalone
         | 
| 5 | 
            +
                  :copyright,
         | 
| 6 | 
            +
                  :copyright_email,
         | 
| 7 | 
            +
                  :depends,          # complex local
         | 
| 8 | 
            +
                  :groups,           # complex local
         | 
| 9 | 
            +
                  :inputs,           # complex local
         | 
| 10 | 
            +
                  :license,
         | 
| 11 | 
            +
                  :maintainer,
         | 
| 12 | 
            +
                  :name,
         | 
| 13 | 
            +
                  :sha256,
         | 
| 14 | 
            +
                  :status,
         | 
| 15 | 
            +
                  :summary,
         | 
| 16 | 
            +
                  :supports,         # complex local
         | 
| 17 | 
            +
                  :parent_profile,
         | 
| 18 | 
            +
                  :skip_message,
         | 
| 19 | 
            +
                  :waiver_data,      # Undocumented but used in JSON reporter - should not be?
         | 
| 20 | 
            +
                  :title,
         | 
| 21 | 
            +
                  :version
         | 
| 22 | 
            +
                ) do
         | 
| 23 | 
            +
                  include HashLikeStruct
         | 
| 24 | 
            +
                  def initialize(raw_prof_data)
         | 
| 25 | 
            +
                    self.controls = (raw_prof_data[:controls] || []).map { |c| Inspec::RunData::Control.new(c) }
         | 
| 26 | 
            +
                    self.depends  = (raw_prof_data[:depends]  || []).map { |d| Inspec::RunData::Profile::Dependency.new(d) }
         | 
| 27 | 
            +
                    self.groups   = (raw_prof_data[:groups]   || []).map { |g| Inspec::RunData::Profile::Group.new(g) }
         | 
| 28 | 
            +
                    self.inputs   = (raw_prof_data[:inputs]   || []).map { |i| Inspec::RunData::Profile::Input.new(i) }
         | 
| 29 | 
            +
                    self.supports = (raw_prof_data[:supports] || []).map { |s| Inspec::RunData::Profile::Support.new(s) }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    %i{
         | 
| 32 | 
            +
                      copyright
         | 
| 33 | 
            +
                      copyright_email
         | 
| 34 | 
            +
                      license
         | 
| 35 | 
            +
                      maintainer
         | 
| 36 | 
            +
                      name
         | 
| 37 | 
            +
                      sha256
         | 
| 38 | 
            +
                      status
         | 
| 39 | 
            +
                      summary
         | 
| 40 | 
            +
                      title
         | 
| 41 | 
            +
                      version
         | 
| 42 | 
            +
                      parent_profile
         | 
| 43 | 
            +
                      skip_message
         | 
| 44 | 
            +
                      waiver_data
         | 
| 45 | 
            +
                    }.each do |field|
         | 
| 46 | 
            +
                      self[field] = raw_prof_data[field]
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                class Profile
         | 
| 52 | 
            +
                  # Good candidate for keyword_init, but that is not in 2.4
         | 
| 53 | 
            +
                  Dependency = Struct.new(
         | 
| 54 | 
            +
                    :name, :path, :status, :skip_message, :git, :url, :compliance, :supermarket, :branch, :tag, :commit, :version, :relative_path
         | 
| 55 | 
            +
                  ) do
         | 
| 56 | 
            +
                    include HashLikeStruct
         | 
| 57 | 
            +
                    def initialize(raw_dep_data)
         | 
| 58 | 
            +
                      %i{name path status skip_message git url supermarket compliance branch tag commit version relative_path}.each { |f| self[f] = raw_dep_data[f] }
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  Support = Struct.new(
         | 
| 63 | 
            +
                    #  snake case
         | 
| 64 | 
            +
                    :platform_family, :platform_name, :release, :platform
         | 
| 65 | 
            +
                  ) do
         | 
| 66 | 
            +
                    include HashLikeStruct
         | 
| 67 | 
            +
                    def initialize(raw_sup_data)
         | 
| 68 | 
            +
                      %i{release platform}.each { |f| self[f] = raw_sup_data[f] }
         | 
| 69 | 
            +
                      self.platform_family = raw_sup_data[:"platform-family"]
         | 
| 70 | 
            +
                      self.platform_name = raw_sup_data[:"platform-name"]
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  # Good candidate for keyword_init, but that is not in 2.4
         | 
| 75 | 
            +
                  Group = Struct.new(
         | 
| 76 | 
            +
                    :title, :controls, :id
         | 
| 77 | 
            +
                  ) do
         | 
| 78 | 
            +
                    include HashLikeStruct
         | 
| 79 | 
            +
                    def initialize(raw_grp_data)
         | 
| 80 | 
            +
                      %i{title id}.each { |f| self[f] = raw_grp_data[f] }
         | 
| 81 | 
            +
                      [:controls].each { |f| self[f] = raw_grp_data[f] || [] }
         | 
| 82 | 
            +
                    end
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  Input = Struct.new(
         | 
| 86 | 
            +
                    :name, :options
         | 
| 87 | 
            +
                  ) do
         | 
| 88 | 
            +
                    include HashLikeStruct
         | 
| 89 | 
            +
                    def initialize(raw_input_data)
         | 
| 90 | 
            +
                      self.name = raw_input_data[:name]
         | 
| 91 | 
            +
                      self.options = Inspec::RunData::Profile::Input::Options.new(raw_input_data[:options])
         | 
| 92 | 
            +
                    end
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
                  class Input
         | 
| 95 | 
            +
                    Options = Struct.new(
         | 
| 96 | 
            +
                      # There are probably others
         | 
| 97 | 
            +
                      :value,
         | 
| 98 | 
            +
                      :type,
         | 
| 99 | 
            +
                      :required
         | 
| 100 | 
            +
                    ) do
         | 
| 101 | 
            +
                      include HashLikeStruct
         | 
| 102 | 
            +
                      def initialize(raw_opts_data)
         | 
| 103 | 
            +
                        %i{value type required}.each { |f| self[f] = raw_opts_data[f] }
         | 
| 104 | 
            +
                      end
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
              end
         | 
| 109 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            module Inspec
         | 
| 2 | 
            +
              class RunData
         | 
| 3 | 
            +
                Result = Struct.new(
         | 
| 4 | 
            +
                  :message,             # Human-friendly test failure message
         | 
| 5 | 
            +
                  :code_desc,           # Generated test description
         | 
| 6 | 
            +
                  :expectation_message, # a substring of code_desc
         | 
| 7 | 
            +
                  :resource_name,       # We try to determine this
         | 
| 8 | 
            +
                  :run_time,            # Float seconds execution time
         | 
| 9 | 
            +
                  :skip_message,        # String
         | 
| 10 | 
            +
                  :start_time,          # DateTime
         | 
| 11 | 
            +
                  :status, # String
         | 
| 12 | 
            +
                  :resource_title, # Ugly internals
         | 
| 13 | 
            +
                  # :waiver_data,       # Undocumented tramp data / not exposed in this API
         | 
| 14 | 
            +
                  :resource, # Undocumented, what is this
         | 
| 15 | 
            +
                  :exception,
         | 
| 16 | 
            +
                  :backtrace
         | 
| 17 | 
            +
                ) do
         | 
| 18 | 
            +
                  include HashLikeStruct
         | 
| 19 | 
            +
                  def initialize(raw_res_data)
         | 
| 20 | 
            +
                    [
         | 
| 21 | 
            +
                      :status,              # String
         | 
| 22 | 
            +
                      :code_desc,           # Generated test description
         | 
| 23 | 
            +
                      :expectation_message, # a substring of code_desc
         | 
| 24 | 
            +
                      :skip_message,        # String
         | 
| 25 | 
            +
                      :run_time,
         | 
| 26 | 
            +
                      :start_time,
         | 
| 27 | 
            +
                      :resource_title,
         | 
| 28 | 
            +
                      :resource,
         | 
| 29 | 
            +
                      :exception,
         | 
| 30 | 
            +
                      :backtrace,
         | 
| 31 | 
            +
                      :message,
         | 
| 32 | 
            +
                    ].each do |field|
         | 
| 33 | 
            +
                      self[field] = raw_res_data[field]
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    self.resource_name = raw_res_data[:resource_title].instance_variable_get(:@__resource_name__)&.to_s
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
            end
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            module Inspec
         | 
| 2 | 
            +
              class RunData
         | 
| 3 | 
            +
                # {:duration=>0.018407, :controls=>{:total=>3, :passed=>{:total=>3}, :skipped=>{:total=>0}, :failed=>{:total=>0}}}
         | 
| 4 | 
            +
                Statistics = Struct.new(
         | 
| 5 | 
            +
                  :duration,
         | 
| 6 | 
            +
                  :controls
         | 
| 7 | 
            +
                ) do
         | 
| 8 | 
            +
                  include HashLikeStruct
         | 
| 9 | 
            +
                  def initialize(raw_stat_data)
         | 
| 10 | 
            +
                    self.controls = Inspec::RunData::Statistics::Controls.new(raw_stat_data[:controls])
         | 
| 11 | 
            +
                    self.duration = raw_stat_data[:duration]
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
                class Statistics
         | 
| 15 | 
            +
                  Controls = Struct.new(
         | 
| 16 | 
            +
                    :total,
         | 
| 17 | 
            +
                    :passed,
         | 
| 18 | 
            +
                    :skipped,
         | 
| 19 | 
            +
                    :failed
         | 
| 20 | 
            +
                  ) do
         | 
| 21 | 
            +
                    include HashLikeStruct
         | 
| 22 | 
            +
                    def initialize(raw_stat_ctl_data)
         | 
| 23 | 
            +
                      self.total = raw_stat_ctl_data[:total]
         | 
| 24 | 
            +
                      self.passed = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:passed][:total])
         | 
| 25 | 
            +
                      self.skipped = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:skipped][:total])
         | 
| 26 | 
            +
                      self.failed = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:failed][:total])
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                  class Controls
         | 
| 30 | 
            +
                    Total = Struct.new(:total) do
         | 
| 31 | 
            +
                      include HashLikeStruct
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
    
        data/lib/inspec/shell.rb
    CHANGED
    
    | @@ -36,8 +36,13 @@ module Inspec | |
| 36 36 | 
             
                  end
         | 
| 37 37 |  | 
| 38 38 | 
             
                  # configure pry shell prompt
         | 
| 39 | 
            -
                  Pry. | 
| 40 | 
            -
             | 
| 39 | 
            +
                  Pry::Prompt.add(
         | 
| 40 | 
            +
                    :inspec,
         | 
| 41 | 
            +
                    "inspec custom prompt"
         | 
| 42 | 
            +
                  ) do |_context, _nesting, _pry_instance, _sep|
         | 
| 43 | 
            +
                    "#{readline_ignore("\e[1m\e[32m")}inspec> #{readline_ignore("\e[0m")}"
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
                  Pry.config.prompt = Pry::Prompt[:inspec]
         | 
| 41 46 |  | 
| 42 47 | 
             
                  # Add a help menu as the default intro
         | 
| 43 48 | 
             
                  Pry.hooks.add_hook(:before_session, "inspec_intro") do
         | 
| @@ -64,7 +69,7 @@ module Inspec | |
| 64 69 |  | 
| 65 70 | 
             
                    pry.pager.open do |pager|
         | 
| 66 71 | 
             
                      pager.print pry.config.output_prefix
         | 
| 67 | 
            -
                      Pry::ColorPrinter.pp(value, pager, Pry:: | 
| 72 | 
            +
                      Pry::ColorPrinter.pp(value, pager, Pry::Output.new(pry).width - 1)
         | 
| 68 73 | 
             
                    end
         | 
| 69 74 | 
             
                  end
         | 
| 70 75 | 
             
                end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Inspec
         | 
| 4 | 
            +
              module Utils
         | 
| 5 | 
            +
                #
         | 
| 6 | 
            +
                # Inspec::Utils::JsonProfileSummary takes in certain information to identify a
         | 
| 7 | 
            +
                # profile and then produces a JSON-formatted summary of that profile. It can
         | 
| 8 | 
            +
                # return the results to STDOUT or a file. It is currently used in several
         | 
| 9 | 
            +
                # places in the CLI such as `json`, `archive` and `artifact`.
         | 
| 10 | 
            +
                #
         | 
| 11 | 
            +
                #
         | 
| 12 | 
            +
                module JsonProfileSummary
         | 
| 13 | 
            +
                  def self.produce_json(info:, write_path: "", suppress_output: false)
         | 
| 14 | 
            +
                    # add in inspec version
         | 
| 15 | 
            +
                    info[:generator] = {
         | 
| 16 | 
            +
                      name: "inspec",
         | 
| 17 | 
            +
                      version: Inspec::VERSION,
         | 
| 18 | 
            +
                    }
         | 
| 19 | 
            +
                    if write_path.empty?
         | 
| 20 | 
            +
                      puts JSON.dump(info)
         | 
| 21 | 
            +
                    else
         | 
| 22 | 
            +
                      unless suppress_output
         | 
| 23 | 
            +
                        if File.exist? write_path
         | 
| 24 | 
            +
                          Inspec::Log.info "----> updating #{write_path}"
         | 
| 25 | 
            +
                        else
         | 
| 26 | 
            +
                          Inspec::Log.info "----> creating #{write_path}"
         | 
| 27 | 
            +
                        end
         | 
| 28 | 
            +
                      end
         | 
| 29 | 
            +
                      full_write_path = File.expand_path(write_path)
         | 
| 30 | 
            +
                      File.write(full_write_path, JSON.dump(info))
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
    
        data/lib/inspec/version.rb
    CHANGED
    
    
| @@ -5,6 +5,7 @@ require "set" | |
| 5 5 | 
             
            require "tempfile"
         | 
| 6 6 | 
             
            require "yaml"
         | 
| 7 7 | 
             
            require "inspec/dist"
         | 
| 8 | 
            +
            require "inspec/utils/json_profile_summary"
         | 
| 8 9 |  | 
| 9 10 | 
             
            module InspecPlugins
         | 
| 10 11 | 
             
              module Artifact
         | 
| @@ -40,9 +41,13 @@ module InspecPlugins | |
| 40 41 |  | 
| 41 42 | 
             
                  def self.profile_sign(options)
         | 
| 42 43 | 
             
                    artifact = new
         | 
| 44 | 
            +
                    path_to_profile = options["profile"]
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    # Write inspec.json file within artifact
         | 
| 47 | 
            +
                    write_inspec_json(path_to_profile, options)
         | 
| 48 | 
            +
             | 
| 43 49 | 
             
                    Dir.mktmpdir do |workdir|
         | 
| 44 50 | 
             
                      puts "Signing #{options["profile"]} with key #{options["keyname"]}"
         | 
| 45 | 
            -
                      path_to_profile = options["profile"]
         | 
| 46 51 | 
             
                      profile_md = artifact.read_profile_metadata(path_to_profile)
         | 
| 47 52 | 
             
                      artifact_filename = "#{profile_md["name"]}-#{profile_md["version"]}.#{SIGNED_PROFILE_SUFFIX}"
         | 
| 48 53 | 
             
                      tarfile = artifact.profile_compress(path_to_profile, profile_md, workdir)
         | 
| @@ -63,6 +68,9 @@ module InspecPlugins | |
| 63 68 | 
             
                      end
         | 
| 64 69 | 
             
                      puts "Successfully generated #{artifact_filename}"
         | 
| 65 70 | 
             
                    end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    # Cleanup
         | 
| 73 | 
            +
                    File.delete("#{path_to_profile}/inspec.json")
         | 
| 66 74 | 
             
                  end
         | 
| 67 75 |  | 
| 68 76 | 
             
                  def self.profile_verify(options)
         | 
| @@ -165,6 +173,15 @@ module InspecPlugins | |
| 165 173 | 
             
                      raise "Artifact is invalid"
         | 
| 166 174 | 
             
                    end
         | 
| 167 175 | 
             
                  end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                  def self.write_inspec_json(root_path, opts)
         | 
| 178 | 
            +
                    profile = Inspec::Profile.for_path(root_path, opts)
         | 
| 179 | 
            +
                    Inspec::Utils::JsonProfileSummary.produce_json(
         | 
| 180 | 
            +
                      info: profile.info,
         | 
| 181 | 
            +
                      write_path: "#{root_path}/inspec.json",
         | 
| 182 | 
            +
                      suppress_output: true
         | 
| 183 | 
            +
                    )
         | 
| 184 | 
            +
                  end
         | 
| 168 185 | 
             
                end
         | 
| 169 186 | 
             
              end
         | 
| 170 187 | 
             
            end
         | 
| @@ -41,8 +41,9 @@ module InspecPlugins | |
| 41 41 | 
             
                      templates_path: TEMPLATES_PATH,
         | 
| 42 42 | 
             
                      overwrite: options[:overwrite],
         | 
| 43 43 | 
             
                      file_rename_map: make_rename_map(plugin_type, plugin_name, snake_case),
         | 
| 44 | 
            -
                      skip_files: make_skip_list,
         | 
| 44 | 
            +
                      skip_files: make_skip_list(template_vars["hooks"].keys),
         | 
| 45 45 | 
             
                    }
         | 
| 46 | 
            +
             | 
| 46 47 | 
             
                    renderer = InspecPlugins::Init::Renderer.new(ui, render_opts)
         | 
| 47 48 |  | 
| 48 49 | 
             
                    renderer.render_with_values(template_path, plugin_type + " plugin", template_vars)
         | 
| @@ -72,6 +73,7 @@ module InspecPlugins | |
| 72 73 | 
             
                      File.join("lib", "inspec-plugin-template") => File.join("lib", plugin_name),
         | 
| 73 74 | 
             
                      File.join("lib", "inspec-plugin-template.rb") => File.join("lib", plugin_name + ".rb"),
         | 
| 74 75 | 
             
                      File.join("lib", "inspec-plugin-template", "cli_command.rb") => File.join("lib", plugin_name, "cli_command.rb"),
         | 
| 76 | 
            +
                      File.join("lib", "inspec-plugin-template", "reporter.rb") => File.join("lib", plugin_name, "reporter.rb"),
         | 
| 75 77 | 
             
                      File.join("lib", "inspec-plugin-template", "plugin.rb") => File.join("lib", plugin_name, "plugin.rb"),
         | 
| 76 78 | 
             
                      File.join("lib", "inspec-plugin-template", "version.rb") => File.join("lib", plugin_name, "version.rb"),
         | 
| 77 79 | 
             
                      File.join("test", "functional", "inspec_plugin_template_test.rb") => File.join("test", "functional", snake_case + "_test.rb"),
         | 
| @@ -168,6 +170,9 @@ module InspecPlugins | |
| 168 170 | 
             
                    if hooks_by_type.key?(:cli_command)
         | 
| 169 171 | 
             
                      vars[:command_name_dashes] = hooks_by_type[:cli_command].tr("_", "-")
         | 
| 170 172 | 
             
                      vars[:command_name_snake] = hooks_by_type[:cli_command].tr("-", "_")
         | 
| 173 | 
            +
                    elsif hooks_by_type.key?(:reporter)
         | 
| 174 | 
            +
                      vars[:reporter_name_dashes] = hooks_by_type[:reporter].tr("_", "-")
         | 
| 175 | 
            +
                      vars[:reporter_name_snake] = hooks_by_type[:reporter].tr("-", "_")
         | 
| 171 176 | 
             
                    end
         | 
| 172 177 | 
             
                    vars
         | 
| 173 178 | 
             
                  end
         | 
| @@ -205,19 +210,20 @@ module InspecPlugins | |
| 205 210 | 
             
                    end
         | 
| 206 211 | 
             
                  end
         | 
| 207 212 |  | 
| 208 | 
            -
                  def make_skip_list
         | 
| 213 | 
            +
                  def make_skip_list(requested_hooks)
         | 
| 214 | 
            +
                    skips = []
         | 
| 209 215 | 
             
                    case options[:detail]
         | 
| 210 | 
            -
                    when "full"
         | 
| 211 | 
            -
                       | 
| 216 | 
            +
                    when "full" # rubocop: disable Lint/EmptyWhen
         | 
| 217 | 
            +
                      # Do nothing but allow this case for validation
         | 
| 212 218 | 
             
                    when "core"
         | 
| 213 | 
            -
                      [
         | 
| 219 | 
            +
                      skips += [
         | 
| 214 220 | 
             
                        "Gemfile",
         | 
| 215 221 | 
             
                        "inspec-plugin-template.gemspec",
         | 
| 216 222 | 
             
                        "LICENSE",
         | 
| 217 223 | 
             
                        "Rakefile",
         | 
| 218 224 | 
             
                      ]
         | 
| 219 225 | 
             
                    when "test-fixture"
         | 
| 220 | 
            -
                      [
         | 
| 226 | 
            +
                      skips += [
         | 
| 221 227 | 
             
                        "Gemfile",
         | 
| 222 228 | 
             
                        "inspec-plugin-template.gemspec",
         | 
| 223 229 | 
             
                        "LICENSE",
         | 
| @@ -237,6 +243,22 @@ module InspecPlugins | |
| 237 243 | 
             
                      ui.error "Unrecognized value for 'detail': #{options[:detail]} - expected one of full, core, test-fixture"
         | 
| 238 244 | 
             
                      ui.exit(:usage_error)
         | 
| 239 245 | 
             
                    end
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                    # Remove hook-specific files
         | 
| 248 | 
            +
                    unless requested_hooks.include?(:cli_command)
         | 
| 249 | 
            +
                      skips += [
         | 
| 250 | 
            +
                        File.join("lib", "inspec-plugin-template", "cli_command.rb"),
         | 
| 251 | 
            +
                        File.join("test", "unit", "cli_args_test.rb"),
         | 
| 252 | 
            +
                        File.join("test", "functional", "inspec_plugin_template_test.rb"),
         | 
| 253 | 
            +
                      ]
         | 
| 254 | 
            +
                    end
         | 
| 255 | 
            +
                    unless requested_hooks.include?(:reporter)
         | 
| 256 | 
            +
                      skips += [
         | 
| 257 | 
            +
                        File.join("lib", "inspec-plugin-template", "reporter.rb"),
         | 
| 258 | 
            +
                      ]
         | 
| 259 | 
            +
                    end
         | 
| 260 | 
            +
             | 
| 261 | 
            +
                    skips.uniq
         | 
| 240 262 | 
             
                  end
         | 
| 241 263 | 
             
                end
         | 
| 242 264 | 
             
              end
         | 
| @@ -28,6 +28,7 @@ module InspecPlugins | |
| 28 28 | 
             
                  # Internal machine name of the plugin. InSpec will use this in errors, etc.
         | 
| 29 29 | 
             
                  plugin_name :'<%= plugin_name %>'
         | 
| 30 30 |  | 
| 31 | 
            +
                  <% if hooks[:cli_command] %>
         | 
| 31 32 | 
             
                  # Define a new CLI subcommand.
         | 
| 32 33 | 
             
                  # The argument here will be used to match against the command line args,
         | 
| 33 34 | 
             
                  # and if the user said `inspec list-resources`, this hook will get called.
         | 
| @@ -48,6 +49,23 @@ module InspecPlugins | |
| 48 49 | 
             
                    # CLI engine tap into it.
         | 
| 49 50 | 
             
                    InspecPlugins::<%= module_name %>::CliCommand
         | 
| 50 51 | 
             
                  end
         | 
| 52 | 
            +
                  <% end %>
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  <% if hooks[:reporter] %>
         | 
| 55 | 
            +
                  # Define a new Reporter.
         | 
| 56 | 
            +
                  # The argument here will be used to match against the CLI --reporter option.
         | 
| 57 | 
            +
                  # `--reporter <%= reporter_name_snake %>` will load your reporter and call its renderer.
         | 
| 58 | 
            +
                  reporter :<%= reporter_name_snake %> do
         | 
| 59 | 
            +
                    # Calling this hook doesn't mean the reporter is being executed - just
         | 
| 60 | 
            +
                    # that we should be ready to do so. So, load the file that defines the
         | 
| 61 | 
            +
                    # functionality.
         | 
| 62 | 
            +
                    require '<%= plugin_name %>/reporter'
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    # Having loaded our functionality, return a class that will let the
         | 
| 65 | 
            +
                    # reporting engine tap into it.
         | 
| 66 | 
            +
                    InspecPlugins::<%= module_name %>::Reporter
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                  <% end %>
         | 
| 51 69 | 
             
                end
         | 
| 52 70 | 
             
              end
         | 
| 53 71 | 
             
            end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            module InspecPlugins::<%= module_name %>
         | 
| 2 | 
            +
              # This class will provide the actual Reporter implementation.
         | 
| 3 | 
            +
              # Its superclass is provided by another call to Inspec.plugin,
         | 
| 4 | 
            +
              # this time with two args.  The first arg specifies we are requesting
         | 
| 5 | 
            +
              # version 2 of the Plugins API.  The second says we are making a
         | 
| 6 | 
            +
              # Reporter plugin component, so please make available any DSL needed
         | 
| 7 | 
            +
              # for that.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              class Reporter < Inspec.plugin(2, :reporter)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                # All a Reporter *must* do is define a render() method that calls
         | 
| 12 | 
            +
                # output(). You should access the run_data accessor to read off the
         | 
| 13 | 
            +
                # results of the run.
         | 
| 14 | 
            +
                def render
         | 
| 15 | 
            +
                  # There is much more to explore in the run_data structure!
         | 
| 16 | 
            +
                  run_data[:profiles].each do |profile|
         | 
| 17 | 
            +
                    output(profile[:title])
         | 
| 18 | 
            +
                    profile[:controls].each do |control|
         | 
| 19 | 
            +
                      output(control[:title])
         | 
| 20 | 
            +
                      control[:results].each do |test|
         | 
| 21 | 
            +
                        output(test[:status])
         | 
| 22 | 
            +
                      end
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            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. | 
| 4 | 
            +
              version: 4.19.2
         | 
| 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-04 | 
| 11 | 
            +
            date: 2020-06-04 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: chef-telemetry
         | 
| @@ -82,16 +82,22 @@ dependencies: | |
| 82 82 | 
             
              name: method_source
         | 
| 83 83 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 84 84 | 
             
                requirements:
         | 
| 85 | 
            -
                - - " | 
| 85 | 
            +
                - - ">="
         | 
| 86 86 | 
             
                  - !ruby/object:Gem::Version
         | 
| 87 87 | 
             
                    version: '0.8'
         | 
| 88 | 
            +
                - - "<"
         | 
| 89 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 90 | 
            +
                    version: '2.0'
         | 
| 88 91 | 
             
              type: :runtime
         | 
| 89 92 | 
             
              prerelease: false
         | 
| 90 93 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 91 94 | 
             
                requirements:
         | 
| 92 | 
            -
                - - " | 
| 95 | 
            +
                - - ">="
         | 
| 93 96 | 
             
                  - !ruby/object:Gem::Version
         | 
| 94 97 | 
             
                    version: '0.8'
         | 
| 98 | 
            +
                - - "<"
         | 
| 99 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 100 | 
            +
                    version: '2.0'
         | 
| 95 101 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 96 102 | 
             
              name: rubyzip
         | 
| 97 103 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -146,14 +152,14 @@ dependencies: | |
| 146 152 | 
             
                requirements:
         | 
| 147 153 | 
             
                - - "~>"
         | 
| 148 154 | 
             
                  - !ruby/object:Gem::Version
         | 
| 149 | 
            -
                    version: '0'
         | 
| 155 | 
            +
                    version: '0.13'
         | 
| 150 156 | 
             
              type: :runtime
         | 
| 151 157 | 
             
              prerelease: false
         | 
| 152 158 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 153 159 | 
             
                requirements:
         | 
| 154 160 | 
             
                - - "~>"
         | 
| 155 161 | 
             
                  - !ruby/object:Gem::Version
         | 
| 156 | 
            -
                    version: '0'
         | 
| 162 | 
            +
                    version: '0.13'
         | 
| 157 163 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 158 164 | 
             
              name: hashie
         | 
| 159 165 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -465,6 +471,7 @@ files: | |
| 465 471 | 
             
            - lib/inspec/plugin/v2/plugin_types/dsl.rb
         | 
| 466 472 | 
             
            - lib/inspec/plugin/v2/plugin_types/input.rb
         | 
| 467 473 | 
             
            - lib/inspec/plugin/v2/plugin_types/mock.rb
         | 
| 474 | 
            +
            - lib/inspec/plugin/v2/plugin_types/reporter.rb
         | 
| 468 475 | 
             
            - lib/inspec/plugin/v2/registry.rb
         | 
| 469 476 | 
             
            - lib/inspec/plugin/v2/status.rb
         | 
| 470 477 | 
             
            - lib/inspec/profile.rb
         | 
| @@ -607,6 +614,11 @@ files: | |
| 607 614 | 
             
            - lib/inspec/resources/zfs_pool.rb
         | 
| 608 615 | 
             
            - lib/inspec/rspec_extensions.rb
         | 
| 609 616 | 
             
            - lib/inspec/rule.rb
         | 
| 617 | 
            +
            - lib/inspec/run_data.rb
         | 
| 618 | 
            +
            - lib/inspec/run_data/control.rb
         | 
| 619 | 
            +
            - lib/inspec/run_data/profile.rb
         | 
| 620 | 
            +
            - lib/inspec/run_data/result.rb
         | 
| 621 | 
            +
            - lib/inspec/run_data/statistics.rb
         | 
| 610 622 | 
             
            - lib/inspec/runner.rb
         | 
| 611 623 | 
             
            - lib/inspec/runner_mock.rb
         | 
| 612 624 | 
             
            - lib/inspec/runner_rspec.rb
         | 
| @@ -642,6 +654,7 @@ files: | |
| 642 654 | 
             
            - lib/inspec/utils/hash.rb
         | 
| 643 655 | 
             
            - lib/inspec/utils/install_context.rb
         | 
| 644 656 | 
             
            - lib/inspec/utils/json_log.rb
         | 
| 657 | 
            +
            - lib/inspec/utils/json_profile_summary.rb
         | 
| 645 658 | 
             
            - lib/inspec/utils/modulator.rb
         | 
| 646 659 | 
             
            - lib/inspec/utils/nginx_parser.rb
         | 
| 647 660 | 
             
            - lib/inspec/utils/object_traversal.rb
         | 
| @@ -691,6 +704,7 @@ files: | |
| 691 704 | 
             
            - lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template.rb
         | 
| 692 705 | 
             
            - lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/cli_command.rb
         | 
| 693 706 | 
             
            - lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/plugin.rb
         | 
| 707 | 
            +
            - lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/reporter.rb
         | 
| 694 708 | 
             
            - lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/version.rb
         | 
| 695 709 | 
             
            - lib/plugins/inspec-init/templates/profiles/aws/README.md
         | 
| 696 710 | 
             
            - lib/plugins/inspec-init/templates/profiles/aws/attributes.yml
         |