inspec-core 3.2.6 → 3.3.14

Sign up to get free protection for your applications and to get access to all the features.
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