inspec-core 4.22.22 → 4.23.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: feb9a92b579da111caf36845c7ba22e6d0831233d59c5f6f5de0212aa8ef529c
4
- data.tar.gz: 945341a0aa073b969ce15e35d058246af5584d3ddfb94a5b7ffbd86cb8162254
3
+ metadata.gz: a2786d0d36c3218a4d79f4578c4a814469115787d4470fa81d422b05b2025462
4
+ data.tar.gz: a0d30c7b81dbb4e58e6b9e8c0447f0855ce1f94f223c1f4f5861a03dfce2ce6c
5
5
  SHA512:
6
- metadata.gz: 148281428e3b5d2855a2c89eccb3a29e4b159933b025049d9852eab4336b9ffb0f267bb48701b208c06fc71ce2c173fe175466622b3ec535ddb4a2692d3d927f
7
- data.tar.gz: ac2e46f5dc21b7359b76df729d6b47c0f51f1f8bd272872121477204f3422d49028982a39a01df60a4ae796f03ccb41f6a448a994e22e2feb7e4d946b574cc27
6
+ metadata.gz: 915bbf9f4302c5fe2e8a41bc131b935bc42861cd4f76d0163ef1aeddc231cdbaf1f653ffd621bb79e5a531baa941e59852b34550d114bf30d95d4eb2ff5aa876
7
+ data.tar.gz: d7b5f80f550bf092aaa0faaf660225f99e3e4d6b600d9a89a45c0648b752a00cac5e30aaaf74fdb940bb135b2ae2ae02112f9617adbe6c25abc46c10d9492c5d
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  # Implementation dependencies
26
26
  spec.add_dependency "chef-telemetry", "~> 1.0"
27
- spec.add_dependency "license-acceptance", ">= 0.2.13", "< 2.0"
27
+ spec.add_dependency "license-acceptance", ">= 0.2.13", "< 3.0"
28
28
  spec.add_dependency "thor", ">= 0.20", "< 2.0"
29
29
  spec.add_dependency "json_schemer", ">= 0.2.1", "< 0.2.12"
30
30
  spec.add_dependency "method_source", ">= 0.8", "< 2.0"
@@ -158,6 +158,10 @@ module Inspec
158
158
  option :silence_deprecations, type: :array,
159
159
  banner: "[all]|[GROUP GROUP...]",
160
160
  desc: "Suppress deprecation warnings. See install_dir/etc/deprecations.json for list of GROUPs or use 'all'."
161
+ option :diff, type: :boolean, default: true,
162
+ desc: "Use --no-diff to suppress 'diff' output of failed textual test results."
163
+ option :sort_results_by, type: :string, default: "file", banner: "--sort-results-by=none|control|file|random",
164
+ desc: "After normal execution order, results are sorted by control ID, or by file (default), or randomly. None uses legacy unsorted mode."
161
165
  end
162
166
 
163
167
  def self.format_platform_info(params: {}, indent: 0, color: 39)
@@ -405,6 +405,18 @@ module Inspec
405
405
  @plugin_cfg = data
406
406
  end
407
407
 
408
+ def validate_sort_results_by!(option_value)
409
+ expected = %w{
410
+ none
411
+ control
412
+ file
413
+ random
414
+ }
415
+ return if expected.include? option_value
416
+
417
+ raise Inspec::ConfigError::Invalid, "--sort-results-by must be one of #{expected.join(", ")}"
418
+ end
419
+
408
420
  #-----------------------------------------------------------------------#
409
421
  # Merging Options
410
422
  #-----------------------------------------------------------------------#
@@ -435,6 +447,7 @@ module Inspec
435
447
  finalize_parse_reporters(options)
436
448
  finalize_handle_sudo(options)
437
449
  finalize_compliance_login(options)
450
+ finalize_sort_results(options)
438
451
 
439
452
  Thor::CoreExt::HashWithIndifferentAccess.new(options)
440
453
  end
@@ -509,6 +522,12 @@ module Inspec
509
522
  end
510
523
  end
511
524
 
525
+ def finalize_sort_results(options)
526
+ if options.key?("sort_results_by")
527
+ validate_sort_results_by!(options["sort_results_by"])
528
+ end
529
+ end
530
+
512
531
  class Defaults
513
532
  DEFAULTS = {
514
533
  exec: {
@@ -171,7 +171,7 @@ module Inspec
171
171
  # are free to go higher.
172
172
  DEFAULT_PRIORITY_FOR_VALUE_SET = 60
173
173
 
174
- attr_reader :description, :events, :identifier, :name, :required, :title, :type
174
+ attr_reader :description, :events, :identifier, :name, :required, :sensitive, :title, :type
175
175
 
176
176
  def initialize(name, options = {})
177
177
  @name = name
@@ -264,6 +264,7 @@ module Inspec
264
264
  @required = options[:required] if options.key?(:required)
265
265
  @identifier = options[:identifier] if options.key?(:identifier) # TODO: determine if this is ever used
266
266
  @type = options[:type] if options.key?(:type)
267
+ @sensitive = options[:sensitive] if options.key?(:sensitive)
267
268
  end
268
269
 
269
270
  def make_creation_event(options)
@@ -320,7 +321,7 @@ module Inspec
320
321
 
321
322
  def to_hash
322
323
  as_hash = { name: name, options: {} }
323
- %i{description title identifier type required value}.each do |field|
324
+ %i{description title identifier type required value sensitive}.each do |field|
324
325
  val = send(field)
325
326
  next if val.nil?
326
327
 
@@ -334,7 +335,7 @@ module Inspec
334
335
  #--------------------------------------------------------------------------#
335
336
 
336
337
  def to_s
337
- "Input #{name} with #{current_value}"
338
+ "Input #{name} with value " + (sensitive ? "*** (senstive)" : "#{current_value}")
338
339
  end
339
340
 
340
341
  #--------------------------------------------------------------------------#
@@ -29,6 +29,8 @@ module Inspec
29
29
  def_delegator :inputs_by_profile, :select
30
30
  def_delegator :profile_aliases, :key?, :profile_alias?
31
31
 
32
+ attr_accessor :cache_inputs
33
+
32
34
  def initialize
33
35
  # Keyed on String profile_name => Hash of String input_name => Input object
34
36
  @inputs_by_profile = {}
@@ -43,6 +45,9 @@ module Inspec
43
45
  activator.activate!
44
46
  activator.implementation_class.new
45
47
  end
48
+
49
+ # Activate caching for inputs by default
50
+ @cache_inputs = true
46
51
  end
47
52
 
48
53
  #-------------------------------------------------------------#
@@ -84,7 +89,7 @@ module Inspec
84
89
 
85
90
  # Find or create the input
86
91
  inputs_by_profile[profile_name] ||= {}
87
- if inputs_by_profile[profile_name].key?(input_name)
92
+ if inputs_by_profile[profile_name].key?(input_name) && cache_inputs
88
93
  inputs_by_profile[profile_name][input_name].update(options)
89
94
  else
90
95
  inputs_by_profile[profile_name][input_name] = Inspec::Input.new(input_name, options)
@@ -316,6 +321,7 @@ module Inspec
316
321
  profile_name,
317
322
  type: input_options[:type],
318
323
  required: input_options[:required],
324
+ sensitive: input_options[:sensitive],
319
325
  event: evt
320
326
  )
321
327
  end
@@ -1,18 +1,20 @@
1
1
  require_relative "../../../run_data"
2
+ require_relative "../../../utils/run_data_filters"
2
3
 
3
4
  module Inspec::Plugin::V2::PluginType
4
5
  class Reporter < Inspec::Plugin::V2::PluginBase
5
6
  register_plugin_type(:reporter)
7
+ include Inspec::Utils::RunDataFilters
6
8
 
7
9
  attr_reader :run_data
8
10
 
9
11
  def initialize(config)
10
12
  @config = config
11
13
 
12
- # Trim the run_data while still a Hash; if it is huge, this
14
+ # Filter the run_data while still a Hash; if it is huge, this
13
15
  # saves on conversion time
14
16
  @run_data = config[:run_data] || {}
15
- apply_report_resize_options
17
+ apply_run_data_filters_to_hash
16
18
 
17
19
  unless Inspec::RunData.compatible_schema?(self.class.run_data_schema_constraints)
18
20
  # Best we can do is warn here, the InSpec run has finished
@@ -24,26 +26,6 @@ module Inspec::Plugin::V2::PluginType
24
26
  @output = ""
25
27
  end
26
28
 
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
- process_message_truncation(r)
42
- end
43
- end
44
- end
45
- end
46
-
47
29
  def output(str, newline = true)
48
30
  @output << str
49
31
  @output << "\n" if newline
@@ -61,14 +43,5 @@ module Inspec::Plugin::V2::PluginType
61
43
  def self.run_data_schema_constraints
62
44
  raise NotImplementedError, "#{self.class} must implement a `run_data_schema_constraints` class method to declare its compatibiltity with the RunData API."
63
45
  end
64
-
65
- private
66
-
67
- def process_message_truncation(result)
68
- if result.key?(:message) && result[:message] != "" && @trunc > -1 && result[:message].length > @trunc
69
- result[:message] = result[:message][0...@trunc] + "[Truncated to #{@trunc} characters]"
70
- end
71
- result
72
- end
73
46
  end
74
47
  end
@@ -1,30 +1,17 @@
1
+ require_relative "../utils/run_data_filters"
2
+
1
3
  module Inspec::Reporters
2
4
  class Base
5
+ include Inspec::Utils::RunDataFilters
6
+
3
7
  attr_reader :run_data
4
8
 
5
9
  def initialize(config)
6
10
  @config = config
7
- @run_data = config[:run_data]
8
- apply_report_resize_options unless @run_data.nil?
9
- @output = ""
10
- end
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 : {}
11
+ @run_data = config[:run_data] || {}
12
+ apply_run_data_filters_to_hash
15
13
 
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
- process_message_truncation(r)
25
- end
26
- end
27
- end
14
+ @output = ""
28
15
  end
29
16
 
30
17
  def output(str, newline = true)
@@ -40,14 +27,5 @@ module Inspec::Reporters
40
27
  def render
41
28
  raise NotImplementedError, "#{self.class} must implement a `#render` method to format its output."
42
29
  end
43
-
44
- private
45
-
46
- def process_message_truncation(result)
47
- if result.key?(:message) && result[:message] != "" && @trunc > -1 && result[:message].length > @trunc
48
- result[:message] = result[:message][0...@trunc] + "[Truncated to #{@trunc} characters]"
49
- end
50
- result
51
- end
52
30
  end
53
31
  end
@@ -26,12 +26,13 @@ module Inspec::Resources
26
26
  supports platform: "windows"
27
27
  desc "Use the postgres_session InSpec audit resource to test SQL commands run against a PostgreSQL database."
28
28
  example <<~EXAMPLE
29
- sql = postgres_session('username', 'password', 'host')
29
+ sql = postgres_session('username', 'password', 'host', 'port')
30
30
  query('sql_query', ['database_name'])` contains the query and (optional) database to execute
31
31
 
32
32
  # default values:
33
33
  # username: 'postgres'
34
34
  # host: 'localhost'
35
+ # port: 5432
35
36
  # db: databse == db_user running the sql query
36
37
 
37
38
  describe sql.query('SELECT * FROM pg_shadow WHERE passwd IS NULL;') do
@@ -39,10 +40,11 @@ module Inspec::Resources
39
40
  end
40
41
  EXAMPLE
41
42
 
42
- def initialize(user, pass, host = nil)
43
+ def initialize(user, pass, host = nil, port = nil)
43
44
  @user = user || "postgres"
44
45
  @pass = pass
45
46
  @host = host || "localhost"
47
+ @port = port || 5432
46
48
  end
47
49
 
48
50
  def query(query, db = [])
@@ -64,7 +66,7 @@ module Inspec::Resources
64
66
 
65
67
  def create_psql_cmd(query, db = [])
66
68
  dbs = db.map { |x| "-d #{x}" }.join(" ")
67
- "PGPASSWORD='#{@pass}' psql -U #{@user} #{dbs} -h #{@host} -A -t -c #{escaped_query(query)}"
69
+ "PGPASSWORD='#{@pass}' psql -U #{@user} #{dbs} -h #{@host} -p #{@port} -A -t -c #{escaped_query(query)}"
68
70
  end
69
71
  end
70
72
  end
@@ -138,7 +138,7 @@ module Inspec::Resources
138
138
  command: 8,
139
139
  }
140
140
  else
141
- command = "ps axo label,pid,pcpu,pmem,vsz,rss,tty,stat,start,time,user:32,command"
141
+ command = "ps wwaxo label,pid,pcpu,pmem,vsz,rss,tty,stat,start,time,user:32,command"
142
142
  regex = /^(.+?)\s+(\d+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+(\w{3} \d{2}|\d{2}:\d{2}:\d{2})\s+([^ ]+)\s+([^ ]+)\s+(.*)$/
143
143
  field_map = {
144
144
  label: 1,
@@ -96,11 +96,12 @@ module Inspec
96
96
  # There are probably others
97
97
  :value,
98
98
  :type,
99
- :required
99
+ :required,
100
+ :sensitive
100
101
  ) do
101
102
  include HashLikeStruct
102
103
  def initialize(raw_opts_data)
103
- %i{value type required}.each { |f| self[f] = raw_opts_data[f] }
104
+ %i{value type required sensitive}.each { |f| self[f] = raw_opts_data[f] }
104
105
  end
105
106
  end
106
107
  end
@@ -0,0 +1,104 @@
1
+ module Inspec
2
+ module Utils
3
+ # RunDataFilters is a mixin for core Reporters and plugin reporters.
4
+ # The methods operate on the run_data Hash (prior to any conversion to a
5
+ # full RunData object).
6
+ # All methods here operate using the run_data accessor and modify
7
+ # its contents in place (if needed).
8
+ module RunDataFilters
9
+
10
+ # Long name, but we want to be clear this operates on the Hash
11
+ # This is the only method that client libraries need to call; any future
12
+ # feature growth should be handled internally here.
13
+ def apply_run_data_filters_to_hash
14
+ @config[:runtime_config] = Inspec::Config.cached || {}
15
+ apply_report_resize_options
16
+ redact_sensitive_inputs
17
+ suppress_diff_output
18
+ sort_controls
19
+ end
20
+
21
+ # Apply options such as message truncation and removal of backtraces
22
+ def apply_report_resize_options
23
+ runtime_config = @config[:runtime_config]
24
+
25
+ message_truncation = runtime_config[:reporter_message_truncation] || "ALL"
26
+ @trunc = message_truncation == "ALL" ? -1 : message_truncation.to_i
27
+ include_backtrace = runtime_config[:reporter_backtrace_inclusion].nil? ? true : runtime_config[:reporter_backtrace_inclusion]
28
+
29
+ @run_data[:profiles]&.each do |p|
30
+ p[:controls].each do |c|
31
+ c[:results]&.map! do |r|
32
+ r.delete(:backtrace) unless include_backtrace
33
+ process_message_truncation(r)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ # Find any inputs with :sensitive = true and replace their values with "***"
40
+ def redact_sensitive_inputs
41
+ @run_data[:profiles]&.each do |p|
42
+ p[:inputs]&.each do |i|
43
+ next unless i[:options][:sensitive]
44
+
45
+ i[:options][:value] = "***"
46
+ end
47
+ end
48
+ end
49
+
50
+ # Optionally suppress diff output in the message field
51
+ def suppress_diff_output
52
+ return if @config[:runtime_config][:diff]
53
+
54
+ @run_data[:profiles]&.each do |p|
55
+ p[:controls]&.each do |c|
56
+ c[:results]&.each do |r|
57
+ next unless r[:message] # :message only set on failure
58
+
59
+ pos = r[:message].index("\n\nDiff:")
60
+ next unless pos # Only textual tests get Diffs
61
+
62
+ r[:message] = r[:message].slice(0, pos)
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ # Optionally sort controls within each profile in report
69
+ def sort_controls
70
+ sort_type = @config[:runtime_config][:sort_results_by]
71
+ return unless sort_type
72
+ return if sort_type == "none"
73
+
74
+ @run_data[:profiles]&.each do |p|
75
+ p[:controls] ||= []
76
+ p[:groups] ||= []
77
+
78
+ case sort_type
79
+ when "control"
80
+ p[:controls].sort_by! { |c| c[:id] }
81
+ when "random"
82
+ p[:controls].shuffle!
83
+ when "file"
84
+ # Sort the controls by file, but preserve order within the file.
85
+ # Files are called "groups" in the run_data, and the filename is in the id.
86
+ sorted_control_ids = p[:groups].sort_by { |g| g[:id] }.map { |g| g[:controls] }.flatten
87
+ controls_by_id = {}
88
+ p[:controls].each { |c| controls_by_id[c[:id]] = c }
89
+ p[:controls] = sorted_control_ids.map { |cid| controls_by_id[cid] }
90
+ end
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def process_message_truncation(result)
97
+ if result.key?(:message) && result[:message] != "" && @trunc > -1 && result[:message].length > @trunc
98
+ result[:message] = result[:message][0...@trunc] + "[Truncated to #{@trunc} characters]"
99
+ end
100
+ result
101
+ end
102
+ end
103
+ end
104
+ end
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "4.22.22".freeze
2
+ VERSION = "4.23.4".freeze
3
3
  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.22.22
4
+ version: 4.23.4
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-08-26 00:00:00.000000000 Z
11
+ date: 2020-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: 0.2.13
34
34
  - - "<"
35
35
  - !ruby/object:Gem::Version
36
- version: '2.0'
36
+ version: '3.0'
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: 0.2.13
44
44
  - - "<"
45
45
  - !ruby/object:Gem::Version
46
- version: '2.0'
46
+ version: '3.0'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: thor
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -638,6 +638,7 @@ files:
638
638
  - lib/inspec/utils/object_traversal.rb
639
639
  - lib/inspec/utils/parser.rb
640
640
  - lib/inspec/utils/pkey_reader.rb
641
+ - lib/inspec/utils/run_data_filters.rb
641
642
  - lib/inspec/utils/simpleconfig.rb
642
643
  - lib/inspec/utils/spdx.rb
643
644
  - lib/inspec/utils/spdx.txt