inspec-core 3.2.6 → 3.3.14

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: 75673eea6201c540d308fe1456f1467dec32ee1cad3227745910cc37c642c3a6
4
- data.tar.gz: ab10f24b1fbbc1c3342591774d09ed7949a42dba19eb4fcf6c759a069f85fd2e
3
+ metadata.gz: 1d04bc72fe20e2d8fc67e39c6b2764735e0b175b152296913daa56a0d908da94
4
+ data.tar.gz: dc4c2c50a48330e7721138214a8b1499af493508620b26ebb19a270ca4f3d580
5
5
  SHA512:
6
- metadata.gz: ae3fbdc2fab1819fdcd769991e787a15c01af92f5771f47b2d3b5772f47f156796967f3bec8658459b05dfae24da2e02f35d0312bc0202cd4a603885c9eda512
7
- data.tar.gz: a681d287554346fdb7517bf035d34e190c6d89797cb246039bf0c9d1186898905dccb880b169a0810c1e890be570692d788aa794e561ed9cd43ec9e4eb55d8af
6
+ metadata.gz: cc16274a2aac2b4db029d53e52898ed728f16c1a3a7d14e87014e638b23e73f2226a3902887980c651da9759607c28d60bcf0e47b647a149c257a31f17ac9f42
7
+ data.tar.gz: 27108017d22fad18cba4396286099642f20622320d6d0b27809263da49ddd5f4b72b948e09f1a447de958fed30ca5da955766bf2e5f648cff5d0d7242194a6ca
@@ -0,0 +1,6 @@
1
+ {
2
+ "file_version": "1.0.0",
3
+ "unknown_group_action": "ignore",
4
+ "groups": {
5
+ }
6
+ }
data/lib/inspec.rb CHANGED
@@ -8,6 +8,7 @@ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
8
8
 
9
9
  require 'inspec/version'
10
10
  require 'inspec/exceptions'
11
+ require 'utils/deprecation'
11
12
  require 'inspec/profile'
12
13
  require 'inspec/rule'
13
14
  require 'matchers/matchers'
data/lib/inspec/cli.rb CHANGED
@@ -175,14 +175,21 @@ class Inspec::InspecCLI < Inspec::BaseCLI
175
175
  end
176
176
 
177
177
  desc 'exec LOCATIONS', 'run all test files at the specified LOCATIONS.'
178
+ # TODO: find a way for Thor not to butcher the formatting of this
178
179
  long_desc <<~EOT
179
180
  Loads the given profile(s) and fetches their dependencies if needed. Then
180
181
  connects to the target and executes any controls contained in the profiles.
181
- One or more reporters are used to generate output. If all tests passed
182
- (no fails, no skips) exit code 0 is returned. If some tests skipped but
183
- none failed, exit code 101 is returned. If at least one test failed, exit
184
- code 100 is returned. If inspec failed for any other reason, exit code 1
185
- is returned.
182
+ One or more reporters are used to generate output.
183
+
184
+ ```
185
+ Exit codes:
186
+ 0 Normal exit, all tests passed
187
+ 1 Usage or general error
188
+ 2 Error in plugin system
189
+ 3 Fatal deprecation encountered
190
+ 100 Normal exit, at least one test failed
191
+ 101 Normal exit, at least one test skipped but none failed
192
+ ```
186
193
 
187
194
  Below are some examples of using `exec` with different test LOCATIONS:
188
195
 
@@ -91,9 +91,9 @@ module Inspec
91
91
  warnings.push("Missing profile #{field} in #{ref}")
92
92
  end
93
93
 
94
- # if version is set, ensure it is in SPDX format
95
- if !params[:license].nil? && !Spdx.valid_license?(params[:license])
96
- warnings.push("License '#{params[:license]}' needs to be in SPDX format. See https://spdx.org/licenses/.")
94
+ # if license is set, ensure it is in SPDX format or marked as proprietary
95
+ if !params[:license].nil? && !valid_license?(params[:license])
96
+ warnings.push("License '#{params[:license]}' needs to be in SPDX format or marked as 'Proprietary'. See https://spdx.org/licenses/.")
97
97
  end
98
98
 
99
99
  [errors, warnings]
@@ -112,6 +112,10 @@ module Inspec
112
112
  false
113
113
  end
114
114
 
115
+ def valid_license?(value)
116
+ value =~ /^Proprietary[,;]?\b/ || Spdx.valid_license?(value)
117
+ end
118
+
115
119
  def method_missing(sth, *args)
116
120
  @logger.warn "#{ref} doesn't support: #{sth} #{args}"
117
121
  @missing_methods.push(sth)
@@ -8,6 +8,7 @@ require 'fileutils'
8
8
  require 'rubygems/package'
9
9
  require 'rubygems/name_tuple'
10
10
  require 'rubygems/uninstaller'
11
+ require 'rubygems/remote_fetcher'
11
12
 
12
13
  require 'inspec/plugin/v2/filter'
13
14
 
data/lib/inspec/ui.rb CHANGED
@@ -32,6 +32,7 @@ module Inspec
32
32
  EXIT_NORMAL = 0
33
33
  EXIT_USAGE_ERROR = 1
34
34
  EXIT_PLUGIN_ERROR = 2
35
+ EXIT_FATAL_DEPRECATION = 3
35
36
  EXIT_FAILED_TESTS = 100
36
37
  EXIT_SKIPPED_TESTS = 101
37
38
 
@@ -4,5 +4,5 @@
4
4
  # author: Christoph Hartmann
5
5
 
6
6
  module Inspec
7
- VERSION = '3.2.6'
7
+ VERSION = '3.3.14'
8
8
  end
@@ -41,7 +41,7 @@ module Inspec::Resources
41
41
  #
42
42
  # So make sure command output is converted to unicode, as it returns ASCII-8BIT by default
43
43
  utf8_stdout = cmd.stdout.chomp.force_encoding(Encoding::UTF_8)
44
- params = /^\[\d+\]\s+(?:\p{Initial_Punctuation})(.+)(?:\p{Final_Punctuation})$/.match(utf8_stdout)
44
+ params = /^\[\d+\]\s+(?:['\p{Initial_Punctuation}])(.+)(?:['\p{Final_Punctuation}])$/.match(utf8_stdout)
45
45
  @info[:installed] = !params.nil?
46
46
  return @info unless @info[:installed]
47
47
 
@@ -6,14 +6,15 @@
6
6
  class IisAppPool < Inspec.resource(1)
7
7
  name 'iis_app_pool'
8
8
  desc 'Tests IIS application pool configuration on windows.'
9
- example "
9
+ supports platform: 'windows'
10
+ example <<~EOH
10
11
  describe iis_app_pool('DefaultAppPool') do
11
12
  it { should exist }
12
13
  its('enable32bit') { should cmp 'True' }
13
14
  its('runtime_version') { should eq 'v4.0' }
14
15
  its('pipeline_mode') { should eq 'Integrated' }
15
16
  end
16
- "
17
+ EOH
17
18
 
18
19
  def initialize(pool_name)
19
20
  @pool_name = pool_name
@@ -77,18 +78,23 @@ class IisAppPool < Inspec.resource(1)
77
78
  end
78
79
 
79
80
  def to_s
80
- "iis_app_pool '#{@pool_name}'"
81
+ "IIS App Pool '#{@pool_name}'"
81
82
  end
82
83
 
83
84
  private
84
85
 
85
- # I cannot think of a way to shorten this method
86
- # rubocop:disable Metrics/AbcSize
87
86
  def iis_app_pool
88
87
  return @cache unless @cache.nil?
89
88
 
90
- command = "Import-Module WebAdministration; Get-Item '#{@pool_path}' | Select-Object * | ConvertTo-Json"
91
- cmd = inspec.command(command)
89
+ script = <<~EOH
90
+ Import-Module WebAdministration
91
+ If (Test-Path '#{@pool_path}') {
92
+ Get-Item '#{@pool_path}' | Select-Object * | ConvertTo-Json
93
+ } Else {
94
+ Write-Host '{}'
95
+ }
96
+ EOH
97
+ cmd = inspec.powershell(script)
92
98
 
93
99
  begin
94
100
  pool = JSON.parse(cmd.stdout)
@@ -96,21 +102,23 @@ class IisAppPool < Inspec.resource(1)
96
102
  raise Inspec::Exceptions::ResourceFailed, 'Unable to parse app pool JSON'
97
103
  end
98
104
 
105
+ process_model = pool.fetch('processModel', {})
106
+ idle_timeout = process_model.fetch('idleTimeout', {})
107
+
99
108
  # map our values to a hash table
100
109
  @cache = {
101
110
  pool_name: pool['name'],
102
111
  version: pool['managedRuntimeVersion'],
103
112
  e32b: pool['enable32BitAppOnWin64'],
104
113
  mode: pool['managedPipelineMode'],
105
- processes: pool['processModel']['maxProcesses'],
106
- timeout: "#{pool['processModel']['idleTimeout']['Hours']}:#{pool['processModel']['idleTimeout']['Minutes']}:#{pool['processModel']['idleTimeout']['Seconds']}",
107
- timeout_days: pool['processModel']['idleTimeout']['Days'],
108
- timeout_hours: pool['processModel']['idleTimeout']['Hours'],
109
- timeout_minutes: pool['processModel']['idleTimeout']['Minutes'],
110
- timeout_seconds: pool['processModel']['idleTimeout']['Seconds'],
111
- user_identity_type: pool['processModel']['identityType'],
112
- username: pool['processModel']['userName'],
114
+ processes: process_model['maxProcesses'],
115
+ timeout: "#{idle_timeout['Hours']}:#{idle_timeout['Minutes']}:#{idle_timeout['Seconds']}",
116
+ timeout_days: idle_timeout['Days'],
117
+ timeout_hours: idle_timeout['Hours'],
118
+ timeout_minutes: idle_timeout['Minutes'],
119
+ timeout_seconds: idle_timeout['Seconds'],
120
+ user_identity_type: process_model['identityType'],
121
+ username: process_model['userName'],
113
122
  }
114
123
  end
115
- # rubocop:enable Metrics/AbcSize
116
124
  end
@@ -69,7 +69,6 @@ module Inspec::Resources
69
69
  end
70
70
 
71
71
  def locate_data_dir_location_by_version(ver = @version)
72
- data_dir_loc = nil
73
72
  dir_list = [
74
73
  "/var/lib/pgsql/#{ver}/data",
75
74
  '/var/lib/pgsql/data',
@@ -77,10 +76,7 @@ module Inspec::Resources
77
76
  '/var/lib/postgresql/data',
78
77
  ]
79
78
 
80
- dir_list.each do |dir|
81
- data_dir_loc = dir if inspec.directory(dir).exist?
82
- break
83
- end
79
+ data_dir_loc = dir_list.detect { |i| inspec.directory(i).exist? }
84
80
 
85
81
  if data_dir_loc.nil?
86
82
  warn 'Unable to find the PostgreSQL data_dir in expected location(s), please
@@ -0,0 +1,6 @@
1
+ # A system to provide a unified deprecation facility for InSpec
2
+
3
+ require 'utils/deprecation/errors'
4
+ require 'utils/deprecation/config_file'
5
+ require 'utils/deprecation/deprecator'
6
+ require 'utils/deprecation/global_method'
@@ -0,0 +1,105 @@
1
+ require 'stringio'
2
+ require 'json'
3
+ require 'inspec/globals'
4
+
5
+ module Inspec
6
+ module Deprecation
7
+ class ConfigFile
8
+ GroupEntry = Struct.new(:name, :action, :prefix, :suffix, :exit_status)
9
+
10
+ # What actions may you specify to be taken when a deprecation is encountered?
11
+ VALID_ACTIONS = [
12
+ :exit, # Hard exit `inspec`, no stacktrace, exit code specified or Inspec::UI::EXIT_FATAL_DEPRECATION
13
+ :fail_control, # Fail the control with a message. If not in a control, do :warn action instead.
14
+ :ignore, # Do nothing.
15
+ :warn, # Issue a warning
16
+ ].freeze
17
+
18
+ # Note that 'comment' is ignored, but listed here so you can have it present
19
+ # and pass validation.
20
+ VALID_GROUP_FIELDS = %w{action suffix prefix exit_status comment}.freeze
21
+
22
+ attr_reader :groups, :unknown_group_action
23
+
24
+ def initialize(io = nil)
25
+ io ||= open_default_config_io
26
+ begin
27
+ @raw_data = JSON.parse(io.read)
28
+ rescue JSON::ParserError => e
29
+ raise Inspec::Deprecation::MalformedConfigFileError, "Could not parse deprecation config file: #{e.message}"
30
+ end
31
+
32
+ @groups = {}
33
+ @unknown_group_action = :warn
34
+ validate!
35
+ end
36
+
37
+ private
38
+
39
+ def open_default_config_io
40
+ default_path = File.join(Inspec.src_root, 'etc', 'deprecations.json')
41
+ unless File.exist?(default_path)
42
+ raise Inspec::Deprecation::MalformedConfigError, "Missing deprecation config file: #{default_path}"
43
+ end
44
+ File.open(default_path)
45
+ end
46
+
47
+ #====================================================================================================#
48
+ # Validation
49
+ #====================================================================================================#
50
+ def validate!
51
+ validate_file_version
52
+ validate_unknown_group_action
53
+
54
+ unless @raw_data.key?('groups')
55
+ raise Inspec::Deprecation::InvalidConfigFileError, 'Missing groups field'
56
+ end
57
+ unless @raw_data['groups'].is_a?(Hash)
58
+ raise Inspec::Deprecation::InvalidConfigFileError, 'Groups field must be a Hash'
59
+ end
60
+ @raw_data['groups'].each do |group_name, group_info|
61
+ validate_group_entry(group_name, group_info)
62
+ end
63
+ end
64
+
65
+ def validate_file_version
66
+ unless @raw_data.key?('file_version')
67
+ raise Inspec::Deprecation::InvalidConfigFileError, 'Missing file_version field'
68
+ end
69
+ unless @raw_data['file_version'] == '1.0.0'
70
+ raise Inspec::Deprecation::InvalidConfigFileError, "Unrecognized file_version '#{@raw_data['file_version']}' - supported versions: 1.0.0"
71
+ end
72
+ end
73
+
74
+ def validate_unknown_group_action
75
+ seen_action = (@raw_data['unknown_group_action'] || @unknown_group_action).to_sym
76
+ unless VALID_ACTIONS.include?(seen_action)
77
+ raise Inspec::Deprecation::UnrecognizedActionError, "Unrecognized value '#{seen_action}' for field 'unknown_group_action' - supported actions: #{VALID_ACTIONS.map(&:to_s).join(', ')}"
78
+ end
79
+ @unknown_group_action = seen_action
80
+ end
81
+
82
+ def validate_group_entry(name, opts)
83
+ opts.each do |seen_field, _value|
84
+ unless VALID_GROUP_FIELDS.include?(seen_field)
85
+ raise Inspec::Deprecation::InvalidConfigFileError, "Unrecognized field for group '#{name}' - saw '#{seen_field}', supported fields: #{VALID_GROUP_FIELDS.map(&:to_s).join(', ')}"
86
+ end
87
+ end
88
+
89
+ entry = GroupEntry.new(name.to_sym)
90
+
91
+ opts['action'] = (opts['action'] || :warn).to_sym
92
+ unless VALID_ACTIONS.include?(opts['action'])
93
+ raise Inspec::Deprecation::UnrecognizedActionError, "Unrecognized action for group '#{name}' - saw '#{opts['action']}', supported actions: #{VALID_ACTIONS.map(&:to_s).join(', ')}"
94
+ end
95
+ entry.action = opts['action']
96
+
97
+ entry.suffix = opts['suffix']
98
+ entry.prefix = opts['prefix']
99
+ entry.exit_status = opts['exit_status']
100
+
101
+ groups[name.to_sym] = entry
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,117 @@
1
+ require 'utils/deprecation/config_file'
2
+ require 'inspec/log'
3
+
4
+ module Inspec
5
+ module Deprecation
6
+ class Deprecator
7
+ attr_reader :config, :groups
8
+
9
+ def initialize(opts = {})
10
+ @config = Inspec::Deprecation::ConfigFile.new(opts[:config_io])
11
+ @groups = @config.groups
12
+ end
13
+
14
+ def handle_deprecation(group_name, message, opts = {})
15
+ group = groups[group_name.to_sym] || create_group_entry_for_unknown_group(group_name)
16
+ annotate_stack_information(opts)
17
+ assembled_message = assemble_message(message, group, opts)
18
+
19
+ action = group[:action] || :warn
20
+ action_method = ('handle_' + action.to_s + '_action').to_sym
21
+ send(action_method, assembled_message, group)
22
+ end
23
+
24
+ private
25
+
26
+ def create_group_entry_for_unknown_group(group_name)
27
+ group = ConfigFile::GroupEntry.new
28
+ group.name = group_name
29
+ group.action = config.unknown_group_action
30
+ group.suffix = "Additionally, the deprecation message is in an unknown group '#{group_name}'."
31
+ group
32
+ end
33
+
34
+ def annotate_stack_information(opts)
35
+ stack = caller_locations(1, 25)
36
+
37
+ # Attempt to give a meaningful stack location of the place
38
+ # where the deprecated functionality was used. This is likely
39
+ # user (profile) code.
40
+ used_at = nil
41
+
42
+ # If we are in a profile, call stack will first include RSpec its,
43
+ # then a single call from the profile that originated within a load_with_context.
44
+ # rspec-core surrounds these.
45
+
46
+ # First, purge the deprecation system frames
47
+ stack.reject! { |frame| frame.path && frame.path =~ %r{lib/utils/deprecation} }
48
+ # Next, purge all RSpec entries (at least rspec-core, rspec-support, rspec-its).
49
+ stack.reject! { |frame| frame.path && frame.path =~ %r{rspec-.+/lib/rspec} }
50
+ # Now look for the frame that includes load_with_context.
51
+ used_at ||= stack.detect { |frame| frame.label.include? 'load_with_context' }
52
+
53
+ opts[:used_at_stack_frame] = used_at if used_at
54
+ end
55
+
56
+ def assemble_message(message, group, opts)
57
+ prefix = group.prefix || ''
58
+ suffix = group.suffix || ''
59
+ prefix += ' ' unless prefix.empty?
60
+ suffix = ' ' + suffix unless suffix.empty?
61
+
62
+ suffix += (' (used at ' + opts[:used_at_stack_frame].path+ ':' + opts[:used_at_stack_frame].lineno.to_s + ')') if opts.key?(:used_at_stack_frame)
63
+
64
+ 'DEPRECATION: ' + prefix + message + suffix
65
+ end
66
+
67
+ def called_from_control?
68
+ # Heuristics for determining if the deprecation is coming from within a control
69
+ stack = caller_locations(10, 45)
70
+
71
+ # Within a control block, that is actually an RSpec:ExampleGroup
72
+ stack.each do |frame|
73
+ return true if frame.path.end_with?('rspec/core/example_group.rb')
74
+ end
75
+
76
+ false
77
+ end
78
+
79
+ def handle_ignore_action(message, _group)
80
+ handle_log_action(message, :debug)
81
+ end
82
+
83
+ def handle_log_action(message, level)
84
+ case level
85
+ when :debug
86
+ Inspec::Log.debug message
87
+ when :warn
88
+ Inspec::Log.warn message
89
+ when :error
90
+ Inspec::Log.error message
91
+ end
92
+ end
93
+
94
+ def handle_warn_action(message, _group)
95
+ handle_log_action(message, :warn)
96
+ end
97
+
98
+ def handle_error_action(message, _group)
99
+ handle_log_action(message, :error)
100
+ end
101
+
102
+ def handle_fail_control_action(message, group)
103
+ if called_from_control?
104
+ raise Inspec::Exceptions::ResourceFailed, message
105
+ else
106
+ handle_warn_action(message, group)
107
+ end
108
+ end
109
+
110
+ def handle_exit_action(message, group)
111
+ handle_error_action(message, group)
112
+ status = group[:exit_status] || :fatal_deprecation
113
+ Inspec::UI.new.exit(status)
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,14 @@
1
+ require 'inspec/errors'
2
+
3
+ module Inspec
4
+ module Deprecation
5
+ class Error < Inspec::Error; end
6
+
7
+ class NoSuchGroupError < Error; end
8
+
9
+ class InvalidConfigFileError < Error; end
10
+ class MalformedConfigFileError < InvalidConfigFileError; end
11
+ class UnrecognizedActionError < InvalidConfigFileError; end
12
+ class UnrecognizedOutputStreamError < InvalidConfigFileError; end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ require 'utils/deprecation/deprecator'
2
+
3
+ module Inspec
4
+ def self.deprecate(group, msg, opts = {})
5
+ config_io = opts.delete(:config_io)
6
+ deprecator = Inspec::Deprecation::Deprecator.new(config_io: config_io)
7
+ deprecator.handle_deprecation(group, msg, opts)
8
+ end
9
+ 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: 3.2.6
4
+ version: 3.3.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-20 00:00:00.000000000 Z
11
+ date: 2019-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: train-core
@@ -327,6 +327,7 @@ files:
327
327
  - LICENSE
328
328
  - README.md
329
329
  - bin/inspec
330
+ - etc/deprecations.json
330
331
  - etc/plugin_filters.json
331
332
  - lib/bundles/README.md
332
333
  - lib/bundles/inspec-compliance/api.rb
@@ -595,6 +596,11 @@ files:
595
596
  - lib/utils/command_wrapper.rb
596
597
  - lib/utils/convert.rb
597
598
  - lib/utils/database_helpers.rb
599
+ - lib/utils/deprecation.rb
600
+ - lib/utils/deprecation/config_file.rb
601
+ - lib/utils/deprecation/deprecator.rb
602
+ - lib/utils/deprecation/errors.rb
603
+ - lib/utils/deprecation/global_method.rb
598
604
  - lib/utils/enumerable_delegation.rb
599
605
  - lib/utils/erlang_parser.rb
600
606
  - lib/utils/file_reader.rb