inspec-core 4.12.0 → 4.16.0
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/etc/plugin_filters.json +0 -4
- data/lib/fetchers/git.rb +2 -0
- data/lib/inspec/base_cli.rb +2 -0
- data/lib/inspec/cli.rb +2 -2
- data/lib/inspec/config.rb +49 -2
- data/lib/inspec/input_registry.rb +30 -0
- data/lib/inspec/metadata.rb +4 -0
- data/lib/inspec/plugin/v1/plugin_types/resource.rb +5 -11
- data/lib/inspec/plugin/v2/filter.rb +33 -0
- data/lib/inspec/plugin/v2/installer.rb +10 -7
- data/lib/inspec/plugin/v2/loader.rb +64 -20
- data/lib/inspec/profile.rb +12 -2
- data/lib/inspec/resources.rb +1 -0
- data/lib/inspec/resources/postfix_conf.rb +31 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +88 -53
- data/lib/source_readers/inspec.rb +14 -12
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ff3612b0be834f75c0bd4e457652ee6736aaff5787519e28c8733c114ecc330
|
4
|
+
data.tar.gz: 58b2c9c7ddcf0bd09ce2e4d9cdf34e67ca0786cb3b97453253e375ec3fe6c29d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d23d441a6db5edc44f754717a6e86b581065b8739d8ee68c657055f2ab053fcbecaed2b800938840a5d7fd8fb9879c27076862e9875258ae9c091778f5b8d99a
|
7
|
+
data.tar.gz: 3edba9eccd97749bb2661f1ab9dde985fbba0f3524e349383967d8e6517df36adad8969be7a7129e05bd96cdd35a49516c9b754fdc92ac3840630f135b1f05fb
|
data/etc/plugin_filters.json
CHANGED
@@ -25,10 +25,6 @@
|
|
25
25
|
"plugin_name": "inspec-release",
|
26
26
|
"rationale": "This gem is currently only a placeholder, waiting to be built."
|
27
27
|
},
|
28
|
-
{
|
29
|
-
"plugin_name": "inspec-vault",
|
30
|
-
"rationale": "This gem is currently only a placeholder, waiting to be built."
|
31
|
-
},
|
32
28
|
{
|
33
29
|
"plugin_name": "train-vault",
|
34
30
|
"rationale": "This gem is currently only a placeholder, waiting to be built."
|
data/lib/fetchers/git.rb
CHANGED
@@ -52,6 +52,7 @@ module Fetchers
|
|
52
52
|
# processing, but then again, if you passed a relative path
|
53
53
|
# to an on-disk repo, you probably expect it to exist.
|
54
54
|
return url_or_file_path unless File.exist?(url_or_file_path)
|
55
|
+
|
55
56
|
# It's important to expand this path, because it may be specified
|
56
57
|
# locally in the metadata files, and when we clone, we will be
|
57
58
|
# in a temp dir.
|
@@ -97,6 +98,7 @@ module Fetchers
|
|
97
98
|
|
98
99
|
def cache_key
|
99
100
|
return resolved_ref unless @relative_path
|
101
|
+
|
100
102
|
OpenSSL::Digest::SHA256.hexdigest(resolved_ref + @relative_path)
|
101
103
|
end
|
102
104
|
|
data/lib/inspec/base_cli.rb
CHANGED
@@ -133,6 +133,8 @@ module Inspec
|
|
133
133
|
option :reporter, type: :array,
|
134
134
|
banner: "one two:/output/file/path",
|
135
135
|
desc: "Enable one or more output reporters: cli, documentation, html, progress, json, json-min, json-rspec, junit, yaml"
|
136
|
+
option :input, type: :array, banner: "name1=value1 name2=value2",
|
137
|
+
desc: "Specify one or more inputs directly on the command line, as --input NAME=VALUE"
|
136
138
|
option :input_file, type: :array,
|
137
139
|
desc: "Load one or more input files, a YAML file with values for the profile to use"
|
138
140
|
option :attrs, type: :array,
|
data/lib/inspec/cli.rb
CHANGED
@@ -124,8 +124,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
124
124
|
else
|
125
125
|
%w{location profile controls timestamp valid}.each do |item|
|
126
126
|
prepared_string = format("%-12s %s",
|
127
|
-
|
128
|
-
|
127
|
+
"#{item.to_s.capitalize} :",
|
128
|
+
result[:summary][item.to_sym])
|
129
129
|
ui.plain_line(prepared_string)
|
130
130
|
end
|
131
131
|
puts
|
data/lib/inspec/config.rb
CHANGED
@@ -7,9 +7,12 @@ require "forwardable"
|
|
7
7
|
require "thor"
|
8
8
|
require "base64"
|
9
9
|
require "inspec/base_cli"
|
10
|
+
require "inspec/plugin/v2/filter"
|
10
11
|
|
11
12
|
module Inspec
|
12
13
|
class Config
|
14
|
+
include Inspec::Plugin::V2::FilterPredicates
|
15
|
+
|
13
16
|
# These are options that apply to any transport
|
14
17
|
GENERIC_CREDENTIALS = %w{
|
15
18
|
backend
|
@@ -23,6 +26,11 @@ module Inspec
|
|
23
26
|
shell_command
|
24
27
|
}.freeze
|
25
28
|
|
29
|
+
KNOWN_VERSIONS = [
|
30
|
+
"1.1",
|
31
|
+
"1.2",
|
32
|
+
].freeze
|
33
|
+
|
26
34
|
extend Forwardable
|
27
35
|
|
28
36
|
# Many parts of InSpec expect to treat the Config as a Hash
|
@@ -48,6 +56,7 @@ module Inspec
|
|
48
56
|
def initialize(cli_opts = {}, cfg_io = nil, command_name = nil)
|
49
57
|
@command_name = command_name || (ARGV.empty? ? nil : ARGV[0].to_sym)
|
50
58
|
@defaults = Defaults.for_command(@command_name)
|
59
|
+
@plugin_cfg = {}
|
51
60
|
|
52
61
|
@cli_opts = cli_opts.dup
|
53
62
|
cfg_io = resolve_cfg_io(@cli_opts, cfg_io)
|
@@ -119,6 +128,13 @@ module Inspec
|
|
119
128
|
end
|
120
129
|
end
|
121
130
|
|
131
|
+
#-----------------------------------------------------------------------#
|
132
|
+
# Fetching Plugin Data
|
133
|
+
#-----------------------------------------------------------------------#
|
134
|
+
def fetch_plugin_config(plugin_name)
|
135
|
+
Thor::CoreExt::HashWithIndifferentAccess.new(@plugin_cfg[plugin_name] || {})
|
136
|
+
end
|
137
|
+
|
122
138
|
private
|
123
139
|
|
124
140
|
def _utc_merge_transport_options(credentials, transport_name)
|
@@ -285,16 +301,24 @@ module Inspec
|
|
285
301
|
# Assume legacy format, which is unconstrained
|
286
302
|
return unless version
|
287
303
|
|
288
|
-
unless version
|
289
|
-
raise Inspec::ConfigError::Invalid, "Unsupported config file version '#{version}' - currently supported versions:
|
304
|
+
unless KNOWN_VERSIONS.include?(version)
|
305
|
+
raise Inspec::ConfigError::Invalid, "Unsupported config file version '#{version}' - currently supported versions: #{KNOWN_VERSIONS.join(",")}"
|
290
306
|
end
|
291
307
|
|
308
|
+
# Use Gem::Version for comparision operators
|
309
|
+
cfg_version = Gem::Version.new(version)
|
310
|
+
version_1_2 = Gem::Version.new("1.2")
|
311
|
+
|
312
|
+
# TODO: proper schema version loading and validation
|
292
313
|
valid_fields = %w{version cli_options credentials compliance reporter}.sort
|
314
|
+
valid_fields << "plugins" if cfg_version >= version_1_2
|
293
315
|
@cfg_file_contents.keys.each do |seen_field|
|
294
316
|
unless valid_fields.include?(seen_field)
|
295
317
|
raise Inspec::ConfigError::Invalid, "Unrecognized top-level configuration field #{seen_field}. Recognized fields: #{valid_fields.join(", ")}"
|
296
318
|
end
|
297
319
|
end
|
320
|
+
|
321
|
+
validate_plugins! if cfg_version >= version_1_2
|
298
322
|
end
|
299
323
|
|
300
324
|
def validate_reporters!(reporters)
|
@@ -334,6 +358,29 @@ module Inspec
|
|
334
358
|
raise ArgumentError, "The option --reporter can only have a single report outputting to stdout." if stdout_reporters > 1
|
335
359
|
end
|
336
360
|
|
361
|
+
def validate_plugins!
|
362
|
+
return unless @cfg_file_contents.key? "plugins"
|
363
|
+
|
364
|
+
data = @cfg_file_contents["plugins"]
|
365
|
+
unless data.is_a?(Hash)
|
366
|
+
raise Inspec::ConfigError::Invalid, "The 'plugin' field in your config file must be a hash (key-value list), not an array."
|
367
|
+
end
|
368
|
+
|
369
|
+
data.each do |plugin_name, plugin_settings|
|
370
|
+
# Enforce that every key is a valid inspec or train plugin name
|
371
|
+
unless valid_plugin_name?(plugin_name)
|
372
|
+
raise Inspec::ConfigError::Invalid, "Plugin settings should ne named after the the InSpec or Train plugin. Valid names must begin with inspec- or train-, not '#{plugin_name}' "
|
373
|
+
end
|
374
|
+
|
375
|
+
# Enforce that every entry is hash-valued
|
376
|
+
unless plugin_settings.is_a?(Hash)
|
377
|
+
raise Inspec::ConfigError::Invalid, "The plugin settings for '#{plugin_name}' in your config file should be a Hash (key-value list)."
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
@plugin_cfg = data
|
382
|
+
end
|
383
|
+
|
337
384
|
#-----------------------------------------------------------------------#
|
338
385
|
# Merging Options
|
339
386
|
#-----------------------------------------------------------------------#
|
@@ -64,6 +64,9 @@ module Inspec
|
|
64
64
|
#-------------------------------------------------------------#
|
65
65
|
|
66
66
|
def find_or_register_input(input_name, profile_name, options = {})
|
67
|
+
input_name = input_name.to_s
|
68
|
+
profile_name = profile_name.to_s
|
69
|
+
|
67
70
|
if profile_alias?(profile_name) && !profile_aliases[profile_name].nil?
|
68
71
|
alias_name = profile_name
|
69
72
|
profile_name = profile_aliases[profile_name]
|
@@ -132,10 +135,37 @@ module Inspec
|
|
132
135
|
bind_inputs_from_metadata(profile_name, sources[:profile_metadata])
|
133
136
|
bind_inputs_from_input_files(profile_name, sources[:cli_input_files])
|
134
137
|
bind_inputs_from_runner_api(profile_name, sources[:runner_api])
|
138
|
+
bind_inputs_from_cli_args(profile_name, sources[:cli_input_arg])
|
135
139
|
end
|
136
140
|
|
137
141
|
private
|
138
142
|
|
143
|
+
def bind_inputs_from_cli_args(profile_name, input_list)
|
144
|
+
# TODO: move this into a core plugin
|
145
|
+
|
146
|
+
return if input_list.nil?
|
147
|
+
return if input_list.empty?
|
148
|
+
|
149
|
+
# These arrive as an array of "name=value" strings
|
150
|
+
# If the user used a comma, we'll see unfortunately see it as "name=value," pairs
|
151
|
+
input_list.each do |pair|
|
152
|
+
unless pair.include?("=")
|
153
|
+
if pair.end_with?(".yaml")
|
154
|
+
raise ArgumentError, "ERROR: --input is used for individual input values, as --input name=value. Use --input-file to load a YAML file."
|
155
|
+
else
|
156
|
+
raise ArgumentError, "ERROR: An '=' is required when using --input. Usage: --input input_name1=input_value1 input2=value2"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
input_name, input_value = pair.split("=")
|
160
|
+
evt = Inspec::Input::Event.new(
|
161
|
+
value: input_value.chomp(","), # Trim trailing comma if any
|
162
|
+
provider: :cli,
|
163
|
+
priority: 50
|
164
|
+
)
|
165
|
+
find_or_register_input(input_name, profile_name, event: evt)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
139
169
|
def bind_inputs_from_runner_api(profile_name, input_hash)
|
140
170
|
# TODO: move this into a core plugin
|
141
171
|
|
data/lib/inspec/metadata.rb
CHANGED
@@ -88,6 +88,10 @@ module Inspec
|
|
88
88
|
errors.push("Version needs to be in SemVer format")
|
89
89
|
end
|
90
90
|
|
91
|
+
unless supports_runtime?
|
92
|
+
warnings.push("The current inspec version #{Inspec::VERSION} cannot satisfy profile inspec_version constraint #{params[:inspec_version]}")
|
93
|
+
end
|
94
|
+
|
91
95
|
%w{title summary maintainer copyright license}.each do |field|
|
92
96
|
next unless params[field.to_sym].nil?
|
93
97
|
|
@@ -81,17 +81,13 @@ module Inspec
|
|
81
81
|
@resource_skipped = false
|
82
82
|
@resource_failed = false
|
83
83
|
@supports = Inspec::Resource.supports[name]
|
84
|
+
@resource_exception_message = nil
|
84
85
|
|
85
86
|
# attach the backend to this instance
|
86
87
|
@__backend_runner__ = backend
|
87
88
|
@__resource_name__ = name
|
88
89
|
|
89
|
-
#
|
90
|
-
supported = true
|
91
|
-
supported = check_supports unless @supports.nil?
|
92
|
-
test_backend = defined?(Train::Transports::Mock::Connection) && backend.backend.class == Train::Transports::Mock::Connection
|
93
|
-
# do not return if we are supported, or for tests
|
94
|
-
return unless supported || test_backend
|
90
|
+
check_supports unless @supports.nil? # this has side effects
|
95
91
|
|
96
92
|
# call the resource initializer
|
97
93
|
begin
|
@@ -100,12 +96,10 @@ module Inspec
|
|
100
96
|
skip_resource(e.message)
|
101
97
|
rescue Inspec::Exceptions::ResourceFailed => e
|
102
98
|
fail_resource(e.message)
|
99
|
+
rescue NotImplementedError => e
|
100
|
+
fail_resource(e.message) unless @resource_failed
|
103
101
|
rescue NoMethodError => e
|
104
|
-
|
105
|
-
# for inspec check to work we need to skip these train errors
|
106
|
-
raise unless test_backend && e.receiver.class == Train::Transports::Mock::Connection
|
107
|
-
|
108
|
-
skip_resource(e.message)
|
102
|
+
skip_resource(e.message) unless @resource_failed
|
109
103
|
end
|
110
104
|
end
|
111
105
|
|
@@ -2,6 +2,8 @@ require "singleton"
|
|
2
2
|
require "json"
|
3
3
|
require "inspec/globals"
|
4
4
|
|
5
|
+
module Inspec::Plugin; end
|
6
|
+
|
5
7
|
module Inspec::Plugin::V2
|
6
8
|
Exclusion = Struct.new(:plugin_name, :rationale)
|
7
9
|
|
@@ -60,4 +62,35 @@ module Inspec::Plugin::V2
|
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
65
|
+
|
66
|
+
# To be a valid plugin name, the plugin must beign with either
|
67
|
+
# inspec- or train-, AND ALSO not be on the exclusion list.
|
68
|
+
# We maintain this exclusion list to avoid confusing users.
|
69
|
+
# For example, we want to have a real gem named inspec-test-fixture,
|
70
|
+
# but we don't want the users to see that.
|
71
|
+
module FilterPredicates
|
72
|
+
def train_plugin_name?(name)
|
73
|
+
valid_plugin_name?(name, :train)
|
74
|
+
end
|
75
|
+
|
76
|
+
def inspec_plugin_name?(name)
|
77
|
+
valid_plugin_name?(name, :inspec)
|
78
|
+
end
|
79
|
+
|
80
|
+
def valid_plugin_name?(name, kind = :either)
|
81
|
+
# Must have a permitted prefix.
|
82
|
+
return false unless case kind
|
83
|
+
when :inspec
|
84
|
+
name.to_s.start_with?("inspec-")
|
85
|
+
when :train
|
86
|
+
name.to_s.start_with?("train-")
|
87
|
+
when :either
|
88
|
+
name.to_s.match(/^(inspec|train)-/)
|
89
|
+
else false
|
90
|
+
end # rubocop: disable Layout/EndAlignment
|
91
|
+
|
92
|
+
# And must not be on the exclusion list.
|
93
|
+
! Inspec::Plugin::V2::PluginFilter.exclude?(name)
|
94
|
+
end
|
95
|
+
end
|
63
96
|
end
|
@@ -60,14 +60,15 @@ module Inspec::Plugin::V2
|
|
60
60
|
# TODO: - check plugins.json for validity before trying anything that needs to modify it.
|
61
61
|
validate_installation_opts(plugin_name, opts)
|
62
62
|
|
63
|
-
# TODO: change all of these to return installed spec/gem/thingy
|
64
63
|
# TODO: return installed thingy
|
65
64
|
if opts[:path]
|
66
65
|
install_from_path(plugin_name, opts)
|
67
66
|
elsif opts[:gem_file]
|
68
|
-
install_from_gem_file(plugin_name, opts)
|
67
|
+
gem_version = install_from_gem_file(plugin_name, opts)
|
68
|
+
opts[:version] = gem_version.to_s
|
69
69
|
else
|
70
|
-
install_from_remote_gems(plugin_name, opts)
|
70
|
+
gem_version = install_from_remote_gems(plugin_name, opts)
|
71
|
+
opts[:version] = gem_version.to_s
|
71
72
|
end
|
72
73
|
|
73
74
|
update_plugin_config_file(plugin_name, opts.merge({ action: :install }))
|
@@ -88,9 +89,9 @@ module Inspec::Plugin::V2
|
|
88
89
|
|
89
90
|
# TODO: Handle installing from a local file
|
90
91
|
# TODO: Perform dependency checks to make sure the new solution is valid
|
91
|
-
install_from_remote_gems(plugin_name, opts)
|
92
|
+
gem_version = install_from_remote_gems(plugin_name, opts)
|
92
93
|
|
93
|
-
update_plugin_config_file(plugin_name, opts.merge({ action: :update }))
|
94
|
+
update_plugin_config_file(plugin_name, opts.merge({ action: :update, version: gem_version.to_s }))
|
94
95
|
end
|
95
96
|
|
96
97
|
# Uninstalls (removes) a plugin. Refers to plugin.json to determine if it
|
@@ -335,13 +336,15 @@ module Inspec::Plugin::V2
|
|
335
336
|
# not obliged to during packaging.)
|
336
337
|
# So, after each install, run a scan for all gem(specs) we manage, and copy in their gemspec file
|
337
338
|
# into the exploded gem source area if absent.
|
338
|
-
|
339
339
|
loader.list_managed_gems.each do |spec|
|
340
340
|
path_inside_source = File.join(spec.gem_dir, "#{spec.name}.gemspec")
|
341
341
|
unless File.exist?(path_inside_source)
|
342
342
|
File.write(path_inside_source, spec.to_ruby)
|
343
343
|
end
|
344
344
|
end
|
345
|
+
|
346
|
+
# Locate the GemVersion for the new dependency and return it
|
347
|
+
solution.detect { |g| g.name == new_plugin_dependency.name }.version
|
345
348
|
end
|
346
349
|
|
347
350
|
#===================================================================#
|
@@ -365,7 +368,7 @@ module Inspec::Plugin::V2
|
|
365
368
|
# excluding any that are path-or-core-based, excluding the gem to be removed
|
366
369
|
plugin_deps_we_still_must_satisfy = registry.plugin_statuses
|
367
370
|
plugin_deps_we_still_must_satisfy = plugin_deps_we_still_must_satisfy.select do |status|
|
368
|
-
status.installation_type == :
|
371
|
+
status.installation_type == :user_gem && status.name != plugin_name_to_be_removed.to_sym
|
369
372
|
end
|
370
373
|
plugin_deps_we_still_must_satisfy = plugin_deps_we_still_must_satisfy.map do |status|
|
371
374
|
constraint = status.version || "> 0"
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "inspec/log"
|
2
2
|
require "inspec/plugin/v2/config_file"
|
3
|
+
require "inspec/plugin/v2/filter"
|
3
4
|
|
4
5
|
# Add the current directory of the process to the load path
|
5
6
|
$LOAD_PATH.unshift(".") unless $LOAD_PATH.include?(".")
|
@@ -11,9 +12,16 @@ module Inspec::Plugin::V2
|
|
11
12
|
class Loader
|
12
13
|
attr_reader :conf_file, :registry, :options
|
13
14
|
|
15
|
+
# For {inspec|train}_plugin_name?
|
16
|
+
include Inspec::Plugin::V2::FilterPredicates
|
17
|
+
extend Inspec::Plugin::V2::FilterPredicates
|
18
|
+
|
14
19
|
def initialize(options = {})
|
15
20
|
@options = options
|
16
21
|
@registry = Inspec::Plugin::V2::Registry.instance
|
22
|
+
|
23
|
+
# User plugins are those installed by the user via `inspec plugin install`
|
24
|
+
# and are installed under ~/.inspec/gems
|
17
25
|
unless options[:omit_user_plugins]
|
18
26
|
@conf_file = Inspec::Plugin::V2::ConfigFile.new
|
19
27
|
read_conf_file_into_registry
|
@@ -27,9 +35,8 @@ module Inspec::Plugin::V2
|
|
27
35
|
# and may be safely loaded
|
28
36
|
detect_core_plugins unless options[:omit_core_plugins]
|
29
37
|
|
30
|
-
#
|
31
|
-
|
32
|
-
accommodate_train_plugins
|
38
|
+
# Identify plugins that inspec is co-installed with
|
39
|
+
detect_system_plugins unless options[:omit_sys_plugins]
|
33
40
|
end
|
34
41
|
|
35
42
|
def load_all
|
@@ -46,7 +53,7 @@ module Inspec::Plugin::V2
|
|
46
53
|
begin
|
47
54
|
# We could use require, but under testing, we need to repeatedly reload the same
|
48
55
|
# plugin. However, gems only work with require (rubygems dooes not overload `load`)
|
49
|
-
if plugin_details.installation_type == :
|
56
|
+
if plugin_details.installation_type == :user_gem
|
50
57
|
activate_managed_gems_for_plugin(plugin_name)
|
51
58
|
require plugin_details.entry_point
|
52
59
|
else
|
@@ -130,10 +137,11 @@ module Inspec::Plugin::V2
|
|
130
137
|
end
|
131
138
|
|
132
139
|
# Lists all plugin gems found in the plugin_gem_path.
|
133
|
-
# This is simply all gems that begin with train- or inspec
|
140
|
+
# This is simply all gems that begin with train- or inspec-
|
141
|
+
# and are not on the exclusion list.
|
134
142
|
# @return [Array[Gem::Specification]] Specs of all gems found.
|
135
143
|
def self.list_installed_plugin_gems
|
136
|
-
list_managed_gems.select { |spec| spec.name
|
144
|
+
list_managed_gems.select { |spec| valid_plugin_name?(spec.name) }
|
137
145
|
end
|
138
146
|
|
139
147
|
def list_installed_plugin_gems
|
@@ -234,34 +242,70 @@ module Inspec::Plugin::V2
|
|
234
242
|
end
|
235
243
|
end
|
236
244
|
|
237
|
-
def accommodate_train_plugins
|
238
|
-
registry.plugin_names.map(&:to_s).grep(/^train-/).each do |train_plugin_name|
|
239
|
-
status = registry[train_plugin_name.to_sym]
|
240
|
-
status.api_generation = :'train-1'
|
241
|
-
|
242
|
-
if status.installation_type == :gem
|
243
|
-
# Activate the gem. This allows train to 'require' the gem later.
|
244
|
-
activate_managed_gems_for_plugin(train_plugin_name)
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
245
|
def read_conf_file_into_registry
|
250
246
|
conf_file.each do |plugin_entry|
|
251
247
|
status = Inspec::Plugin::V2::Status.new
|
252
248
|
status.name = plugin_entry[:name]
|
253
249
|
status.loaded = false
|
254
|
-
status.installation_type = (plugin_entry[:installation_type] || :
|
250
|
+
status.installation_type = (plugin_entry[:installation_type] || :user_gem)
|
255
251
|
case status.installation_type
|
256
|
-
when :
|
252
|
+
when :user_gem
|
257
253
|
status.entry_point = status.name.to_s
|
258
254
|
status.version = plugin_entry[:version]
|
259
255
|
when :path
|
260
256
|
status.entry_point = plugin_entry[:installation_path]
|
261
257
|
end
|
262
258
|
|
259
|
+
# Train plugins are not true InSpec plugins; we need to decorate them a
|
260
|
+
# bit more to integrate them.
|
261
|
+
fixup_train_plugin_status(status) if train_plugin_name?(plugin_entry[:name])
|
262
|
+
|
263
263
|
registry[status.name] = status
|
264
264
|
end
|
265
265
|
end
|
266
|
+
|
267
|
+
def fixup_train_plugin_status(status)
|
268
|
+
status.api_generation = :'train-1'
|
269
|
+
if status.installation_type == :user_gem
|
270
|
+
# Activate the gem. This allows train to 'require' the gem later.
|
271
|
+
activate_managed_gems_for_plugin(status.entry_point)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def detect_system_plugins
|
276
|
+
# Find the gemspec for inspec
|
277
|
+
inspec_gemspec = Gem::Specification.find_by_name("inspec", "=#{Inspec::VERSION}")
|
278
|
+
|
279
|
+
# Make a RequestSet that represents the dependencies of inspec
|
280
|
+
inspec_deps_request_set = Gem::RequestSet.new(*inspec_gemspec.dependencies)
|
281
|
+
inspec_deps_request_set.remote = false
|
282
|
+
|
283
|
+
# Resolve the request against the installed gem universe
|
284
|
+
gem_resolver = Gem::Resolver::CurrentSet.new
|
285
|
+
runtime_solution = inspec_deps_request_set.resolve(gem_resolver)
|
286
|
+
|
287
|
+
inspec_gemspec.dependencies.each do |inspec_dep|
|
288
|
+
next unless inspec_plugin_name?(inspec_dep.name) || train_plugin_name?(inspec_dep.name)
|
289
|
+
|
290
|
+
plugin_spec = runtime_solution.detect { |s| s.name == inspec_dep.name }.spec
|
291
|
+
|
292
|
+
status = Inspec::Plugin::V2::Status.new
|
293
|
+
status.name = inspec_dep.name
|
294
|
+
status.entry_point = inspec_dep.name # gem-based, just 'require' the name
|
295
|
+
status.version = plugin_spec.version.to_s
|
296
|
+
status.loaded = false
|
297
|
+
status.installation_type = :system_gem
|
298
|
+
|
299
|
+
if train_plugin_name?(status[:name])
|
300
|
+
# Train plugins are not true InSpec plugins; we need to decorate them a
|
301
|
+
# bit more to integrate them.
|
302
|
+
fixup_train_plugin_status(status)
|
303
|
+
else
|
304
|
+
status.api_generation = 2
|
305
|
+
end
|
306
|
+
|
307
|
+
registry[status.name.to_sym] = status
|
308
|
+
end
|
309
|
+
end
|
266
310
|
end
|
267
311
|
end
|
data/lib/inspec/profile.rb
CHANGED
@@ -116,9 +116,19 @@ module Inspec
|
|
116
116
|
# we can create any inputs that were provided by various mechanisms.
|
117
117
|
options[:runner_conf] ||= Inspec::Config.cached
|
118
118
|
|
119
|
+
# Catch legacy CLI input option usage
|
119
120
|
if options[:runner_conf].key?(:attrs)
|
120
121
|
Inspec.deprecate(:rename_attributes_to_inputs, "Use --input-file on the command line instead of --attrs.")
|
121
122
|
options[:runner_conf][:input_file] = options[:runner_conf].delete(:attrs)
|
123
|
+
elsif options[:runner_conf].key?(:input_files)
|
124
|
+
# The kitchen-inspec docs say to use plural. Our CLI and internal expectations are singular.
|
125
|
+
options[:runner_conf][:input_file] = options[:runner_conf].delete(:input_files)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Catch legacy kitchen-inspec input usage
|
129
|
+
if options[:runner_conf].key?(:attributes)
|
130
|
+
Inspec.deprecate(:rename_attributes_to_inputs, "Use :inputs in your kitchen.yml verifier config instead of :attributes.")
|
131
|
+
options[:runner_conf][:inputs] = options[:runner_conf].delete(:attributes)
|
122
132
|
end
|
123
133
|
|
124
134
|
Inspec::InputRegistry.bind_profile_inputs(
|
@@ -127,8 +137,8 @@ module Inspec
|
|
127
137
|
# Remaining args are possible sources of inputs
|
128
138
|
cli_input_files: options[:runner_conf][:input_file], # From CLI --input-file
|
129
139
|
profile_metadata: metadata,
|
130
|
-
|
131
|
-
|
140
|
+
runner_api: options[:runner_conf][:inputs], # This is the route the audit_cookbook and kitchen-inspec take
|
141
|
+
cli_input_arg: options[:runner_conf][:input] # The --input name=value CLI option
|
132
142
|
)
|
133
143
|
|
134
144
|
@runner_context =
|
data/lib/inspec/resources.rb
CHANGED
@@ -84,6 +84,7 @@ require "inspec/resources/passwd"
|
|
84
84
|
require "inspec/resources/pip"
|
85
85
|
require "inspec/resources/platform"
|
86
86
|
require "inspec/resources/port"
|
87
|
+
require "inspec/resources/postfix_conf"
|
87
88
|
require "inspec/resources/postgres"
|
88
89
|
require "inspec/resources/postgres_conf"
|
89
90
|
require "inspec/resources/postgres_hba_conf"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "inspec/resources/ini"
|
2
|
+
require "inspec/utils/simpleconfig"
|
3
|
+
|
4
|
+
module Inspec::Resources
|
5
|
+
class PostfixConf < IniConfig
|
6
|
+
name "postfix_conf"
|
7
|
+
supports platform: "linux"
|
8
|
+
desc "Use the postfix_conf Inspec audit resource to test the configuration of the Postfix Mail Transfer Agent"
|
9
|
+
|
10
|
+
# Allow user to specify a custom configuration path, use default Postfix configuration path if no custom path is provided
|
11
|
+
def initialize(*opts)
|
12
|
+
@params = {}
|
13
|
+
if opts.length == 1
|
14
|
+
@raw_content = load_raw_content(opts)
|
15
|
+
else
|
16
|
+
@raw_content = load_raw_content("/etc/postfix/main.cf")
|
17
|
+
end
|
18
|
+
@params = parse(@raw_content)
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse(content)
|
22
|
+
SimpleConfig.new(content).params
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def resource_base_name
|
28
|
+
"POSTFIX_CONF"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/inspec/version.rb
CHANGED
@@ -6,6 +6,14 @@ require "inspec/dist"
|
|
6
6
|
module InspecPlugins
|
7
7
|
module PluginManager
|
8
8
|
class CliCommand < Inspec.plugin(2, :cli_command)
|
9
|
+
INSTALL_TYPE_LABELS = {
|
10
|
+
bundle: "core", # Calling this core, too - not much of a distinction
|
11
|
+
core: "core",
|
12
|
+
path: "path",
|
13
|
+
user_gem: "gem (user)",
|
14
|
+
system_gem: "gem (system)",
|
15
|
+
}.freeze
|
16
|
+
|
9
17
|
include Inspec::Dist
|
10
18
|
|
11
19
|
subcommand_desc "plugin SUBCOMMAND", "Manage #{PRODUCT_NAME} and Train plugins"
|
@@ -15,22 +23,36 @@ module InspecPlugins
|
|
15
23
|
#==================================================================#
|
16
24
|
|
17
25
|
desc "list [options]", "Lists user-installed #{PRODUCT_NAME} plugins."
|
18
|
-
option :all, desc: "
|
26
|
+
option :all, desc: "List all types of plugins (default)", type: :boolean, default: true, aliases: [:a]
|
27
|
+
option :user, desc: "List user plugins, from ~/.inspec/gems", banner: "", type: :boolean, default: false, aliases: [:u]
|
28
|
+
option :system, desc: "List system plugins, those InSpec depends on", banner: "", type: :boolean, default: false, aliases: [:s]
|
29
|
+
option :core, desc: "List core plugins, those InSpec ships with", banner: "", type: :boolean, default: false, aliases: [:c]
|
30
|
+
|
19
31
|
def list
|
20
32
|
plugin_statuses = Inspec::Plugin::V2::Registry.instance.plugin_statuses
|
21
|
-
|
33
|
+
options[:all] = false if options[:core] || options[:user] || options[:system]
|
34
|
+
plugin_statuses.select! do |status|
|
35
|
+
type = status.installation_type
|
36
|
+
options[:all] ||
|
37
|
+
(options[:core] && %i{core bundle}.include?(type)) ||
|
38
|
+
(options[:user] && %i{user_gem path}.include?(type)) ||
|
39
|
+
(options[:system] && :system_gem == type)
|
40
|
+
end
|
22
41
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
42
|
+
unless plugin_statuses.empty?
|
43
|
+
ui.table do |t|
|
44
|
+
t.header = ["Plugin Name", "Version", "Via", "ApiVer"]
|
45
|
+
plugin_statuses.sort_by { |s| s.name.to_s }.each do |status|
|
46
|
+
t << [
|
47
|
+
status.name,
|
48
|
+
make_pretty_version(status),
|
49
|
+
make_pretty_install_type(status),
|
50
|
+
status.api_generation,
|
51
|
+
]
|
52
|
+
end
|
53
|
+
end
|
31
54
|
end
|
32
|
-
ui.
|
33
|
-
ui.plain(" #{plugin_statuses.count} plugin(s) total")
|
55
|
+
ui.plain_line(" #{plugin_statuses.count} plugin(s) total")
|
34
56
|
puts
|
35
57
|
end
|
36
58
|
|
@@ -60,15 +82,15 @@ module InspecPlugins
|
|
60
82
|
end
|
61
83
|
|
62
84
|
puts
|
63
|
-
ui.bold(format(" %-30s%-50s", "Plugin Name", "Versions Available"))
|
85
|
+
ui.bold(format(" %-30s%-50s\n", "Plugin Name", "Versions Available"))
|
64
86
|
ui.line
|
65
87
|
search_results.keys.sort.each do |plugin_name|
|
66
88
|
versions = options[:all] ? search_results[plugin_name] : [search_results[plugin_name].first]
|
67
89
|
versions = "(" + versions.join(", ") + ")"
|
68
|
-
ui.
|
90
|
+
ui.plain_line(format(" %-30s%-50s", plugin_name, versions))
|
69
91
|
end
|
70
92
|
ui.line
|
71
|
-
ui.
|
93
|
+
ui.plain_line(" #{search_results.count} plugin(s) found")
|
72
94
|
puts
|
73
95
|
|
74
96
|
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR if search_results.empty?
|
@@ -118,14 +140,14 @@ module InspecPlugins
|
|
118
140
|
begin
|
119
141
|
installer.update(plugin_name)
|
120
142
|
rescue Inspec::Plugin::V2::UpdateError => ex
|
121
|
-
ui.
|
143
|
+
ui.plain_line("#{ui.red("Update error:", print: false)} #{ex.message} - update failed")
|
122
144
|
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
123
145
|
end
|
124
146
|
post_update_versions = installer.list_installed_plugin_gems.select { |spec| spec.name == plugin_name }.map { |spec| spec.version.to_s }
|
125
147
|
new_version = (post_update_versions - pre_update_versions).first
|
126
148
|
|
127
149
|
ui.bold(plugin_name + " plugin, version #{old_version} -> " \
|
128
|
-
"#{new_version}, updated from rubygems.org")
|
150
|
+
"#{new_version}, updated from rubygems.org\n")
|
129
151
|
end
|
130
152
|
|
131
153
|
#--------------------------
|
@@ -144,7 +166,7 @@ module InspecPlugins
|
|
144
166
|
def uninstall(plugin_name)
|
145
167
|
status = Inspec::Plugin::V2::Registry.instance[plugin_name.to_sym]
|
146
168
|
unless status
|
147
|
-
ui.
|
169
|
+
ui.plain_line("#{ui.red("No such plugin installed:", print: false)} #{plugin_name} is not " \
|
148
170
|
"installed - uninstall failed")
|
149
171
|
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
150
172
|
end
|
@@ -157,11 +179,12 @@ module InspecPlugins
|
|
157
179
|
|
158
180
|
if status.installation_type == :path
|
159
181
|
ui.bold(plugin_name + " path-based plugin install has been " \
|
160
|
-
"uninstalled")
|
182
|
+
"uninstalled\n")
|
161
183
|
else
|
162
184
|
ui.bold(plugin_name + " plugin, version #{old_version}, has " \
|
163
|
-
"been uninstalled")
|
185
|
+
"been uninstalled\n")
|
164
186
|
end
|
187
|
+
|
165
188
|
ui.exit Inspec::UI::EXIT_NORMAL
|
166
189
|
end
|
167
190
|
|
@@ -174,7 +197,7 @@ module InspecPlugins
|
|
174
197
|
|
175
198
|
def install_from_gemfile(gem_file)
|
176
199
|
unless File.exist? gem_file
|
177
|
-
ui.red("No such plugin gem file #{gem_file} - installation failed
|
200
|
+
ui.red("No such plugin gem file #{gem_file} - installation failed.\n")
|
178
201
|
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
179
202
|
end
|
180
203
|
|
@@ -186,13 +209,13 @@ module InspecPlugins
|
|
186
209
|
installer.install(plugin_name, gem_file: gem_file)
|
187
210
|
|
188
211
|
ui.bold("#{plugin_name} plugin, version #{version}, installed from " \
|
189
|
-
"local .gem file")
|
212
|
+
"local .gem file\n")
|
190
213
|
ui.exit Inspec::UI::EXIT_NORMAL
|
191
214
|
end
|
192
215
|
|
193
216
|
def install_from_path(path)
|
194
217
|
unless File.exist? path
|
195
|
-
ui.red("No such source code path #{path} - installation failed
|
218
|
+
ui.red("No such source code path #{path} - installation failed.\n")
|
196
219
|
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
197
220
|
end
|
198
221
|
|
@@ -209,7 +232,7 @@ module InspecPlugins
|
|
209
232
|
if registry.known_plugin?(plugin_name.to_sym)
|
210
233
|
ui.red("Plugin already installed - #{plugin_name} - Use '#{EXEC_NAME} " \
|
211
234
|
"plugin list' to see previously installed plugin - " \
|
212
|
-
"installation failed
|
235
|
+
"installation failed.\n")
|
213
236
|
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
214
237
|
end
|
215
238
|
|
@@ -223,7 +246,7 @@ module InspecPlugins
|
|
223
246
|
installer.install(plugin_name, path: entry_point)
|
224
247
|
|
225
248
|
ui.bold("#{plugin_name} plugin installed via source path reference, " \
|
226
|
-
"resolved to entry point #{entry_point}")
|
249
|
+
"resolved to entry point #{entry_point}\n")
|
227
250
|
ui.exit Inspec::UI::EXIT_NORMAL
|
228
251
|
end
|
229
252
|
|
@@ -288,7 +311,7 @@ module InspecPlugins
|
|
288
311
|
# Give up.
|
289
312
|
ui.red("Unrecognizable plugin structure - #{parts[2]} - When " \
|
290
313
|
"installing from a path, please provide the path of the " \
|
291
|
-
"entry point file - installation failed
|
314
|
+
"entry point file - installation failed.\n")
|
292
315
|
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
293
316
|
end
|
294
317
|
|
@@ -299,8 +322,8 @@ module InspecPlugins
|
|
299
322
|
rescue LoadError => ex
|
300
323
|
ui.red("Plugin contains errors - #{plugin_name} - Encountered " \
|
301
324
|
"errors while trying to test load the plugin entry point, " \
|
302
|
-
"resolved to #{entry_point} - installation failed")
|
303
|
-
ui.
|
325
|
+
"resolved to #{entry_point} - installation failed\n")
|
326
|
+
ui.plain_line ex.message
|
304
327
|
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
305
328
|
end
|
306
329
|
|
@@ -313,7 +336,7 @@ module InspecPlugins
|
|
313
336
|
ui.red("Does not appear to be a plugin - #{plugin_name} - After " \
|
314
337
|
"probe-loading the supposed plugin, it did not register " \
|
315
338
|
"itself to Train. Ensure something inherits from " \
|
316
|
-
"'Train.plugin(1)' - installation failed
|
339
|
+
"'Train.plugin(1)' - installation failed.\n")
|
317
340
|
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
318
341
|
end
|
319
342
|
else
|
@@ -321,7 +344,7 @@ module InspecPlugins
|
|
321
344
|
ui.red("Does not appear to be a plugin - #{plugin_name} - After " \
|
322
345
|
"probe-loading the supposed plugin, it did not register " \
|
323
346
|
"itself to InSpec. Ensure something inherits from " \
|
324
|
-
"'Inspec.plugin(2)' - installation failed
|
347
|
+
"'Inspec.plugin(2)' - installation failed.\n")
|
325
348
|
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
326
349
|
end
|
327
350
|
end
|
@@ -343,7 +366,7 @@ module InspecPlugins
|
|
343
366
|
new_version = (post_installed_versions - pre_installed_versions).first
|
344
367
|
|
345
368
|
ui.bold("#{plugin_name} plugin, version #{new_version}, installed " \
|
346
|
-
"from rubygems.org")
|
369
|
+
"from rubygems.org\n")
|
347
370
|
ui.exit Inspec::UI::EXIT_NORMAL
|
348
371
|
end
|
349
372
|
|
@@ -367,16 +390,16 @@ module InspecPlugins
|
|
367
390
|
what_we_would_install_is_already_installed = pre_installed_versions.include?(requested_version)
|
368
391
|
if what_we_would_install_is_already_installed && they_explicitly_asked_for_a_version
|
369
392
|
ui.red("Plugin already installed at requested version - plugin " \
|
370
|
-
"#{plugin_name} #{requested_version} - refusing to install
|
393
|
+
"#{plugin_name} #{requested_version} - refusing to install.\n")
|
371
394
|
elsif what_we_would_install_is_already_installed && !they_explicitly_asked_for_a_version
|
372
395
|
ui.red("Plugin already installed at latest version - plugin " \
|
373
|
-
"#{plugin_name} #{requested_version} - refusing to install
|
396
|
+
"#{plugin_name} #{requested_version} - refusing to install.\n")
|
374
397
|
else
|
375
398
|
# There are existing versions installed, but none of them are what was requested
|
376
399
|
ui.red("Update required - plugin #{plugin_name}, requested " \
|
377
400
|
"#{requested_version}, have " \
|
378
|
-
"#{pre_installed_versions.join(
|
379
|
-
"plugin update` - refusing to install
|
401
|
+
"#{pre_installed_versions.join(", ")}; use `inspec " \
|
402
|
+
"plugin update` - refusing to install.\n")
|
380
403
|
end
|
381
404
|
|
382
405
|
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
@@ -387,11 +410,11 @@ module InspecPlugins
|
|
387
410
|
installer.install(plugin_name, version: options[:version])
|
388
411
|
rescue Inspec::Plugin::V2::PluginExcludedError => ex
|
389
412
|
ui.red("Plugin on Exclusion List - #{plugin_name} is listed as an " \
|
390
|
-
"incompatible gem - refusing to install
|
391
|
-
ui.
|
392
|
-
ui.
|
413
|
+
"incompatible gem - refusing to install.\n")
|
414
|
+
ui.plain_line("Rationale: #{ex.details.rationale}")
|
415
|
+
ui.plain_line("Exclusion list location: " +
|
393
416
|
File.join(Inspec.src_root, "etc", "plugin_filters.json"))
|
394
|
-
ui.
|
417
|
+
ui.plain_line("If you disagree with this determination, please accept " \
|
395
418
|
"our apologies for the misunderstanding, and open an issue " \
|
396
419
|
"at https://github.com/inspec/inspec/issues/new")
|
397
420
|
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
@@ -401,13 +424,13 @@ module InspecPlugins
|
|
401
424
|
results = installer.search(plugin_name, exact: true)
|
402
425
|
if results.empty?
|
403
426
|
ui.red("No such plugin gem #{plugin_name} could be found on " \
|
404
|
-
"rubygems.org - installation failed
|
427
|
+
"rubygems.org - installation failed.\n")
|
405
428
|
elsif options[:version] && !results[plugin_name].include?(options[:version])
|
406
429
|
ui.red("No such version - #{plugin_name} exists, but no such " \
|
407
430
|
"version #{options[:version]} found on rubygems.org - " \
|
408
|
-
"installation failed
|
431
|
+
"installation failed.\n")
|
409
432
|
else
|
410
|
-
ui.red("Unknown error occured - installation failed
|
433
|
+
ui.red("Unknown error occured - installation failed.\n")
|
411
434
|
end
|
412
435
|
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
413
436
|
end
|
@@ -420,10 +443,10 @@ module InspecPlugins
|
|
420
443
|
# Check for path install
|
421
444
|
status = Inspec::Plugin::V2::Registry.instance[plugin_name.to_sym]
|
422
445
|
if !status
|
423
|
-
ui.
|
446
|
+
ui.plain_line("#{ui.red("No such plugin installed:", print: false)} #{plugin_name} - update failed")
|
424
447
|
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
425
448
|
elsif status.installation_type == :path
|
426
|
-
ui.
|
449
|
+
ui.plain_line("#{ui.red("Cannot update path-based install:", print: false)} " \
|
427
450
|
"#{plugin_name} is installed via path reference; " \
|
428
451
|
"use `inspec plugin uninstall` to remove - refusing to" \
|
429
452
|
"update")
|
@@ -436,7 +459,7 @@ module InspecPlugins
|
|
436
459
|
latest_version = latest_version[plugin_name]&.last
|
437
460
|
|
438
461
|
if pre_update_versions.include?(latest_version)
|
439
|
-
ui.
|
462
|
+
ui.plain_line("#{ui.red("Already installed at latest version:", print: false)} " \
|
440
463
|
"#{plugin_name} is at #{latest_version}, which the " \
|
441
464
|
"latest - refusing to update")
|
442
465
|
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
@@ -458,7 +481,7 @@ module InspecPlugins
|
|
458
481
|
unless plugin_name =~ /^(inspec|train)-/
|
459
482
|
ui.red("Invalid plugin name - #{plugin_name} - All inspec " \
|
460
483
|
"plugins must begin with either 'inspec-' or 'train-' " \
|
461
|
-
"- #{action} failed
|
484
|
+
"- #{action} failed.\n")
|
462
485
|
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
463
486
|
end
|
464
487
|
end
|
@@ -467,17 +490,29 @@ module InspecPlugins
|
|
467
490
|
case status.installation_type
|
468
491
|
when :core, :bundle
|
469
492
|
Inspec::VERSION
|
470
|
-
when :
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
493
|
+
when :user_gem, :system_gem
|
494
|
+
if status.version.nil?
|
495
|
+
"(unknown)"
|
496
|
+
elsif status.version =~ /^\d+\.\d+\.\d+$/
|
497
|
+
status.version
|
498
|
+
else
|
499
|
+
# Assume it is a version constraint string and try to resolve
|
500
|
+
# TODO: this is naive, and assumes the latest version is the one that will be used. Logged on #3317
|
501
|
+
# In fact, the logic to determine "what version would be used" belongs in the Loader.
|
502
|
+
plugin_name = status.name.to_s
|
503
|
+
Inspec::Plugin::V2::Loader.list_installed_plugin_gems
|
504
|
+
.select { |spec| spec.name == plugin_name }
|
505
|
+
.sort_by(&:version)
|
506
|
+
.last.version
|
507
|
+
end
|
477
508
|
when :path
|
478
509
|
"src"
|
479
510
|
end
|
480
511
|
end
|
512
|
+
|
513
|
+
def make_pretty_install_type(status)
|
514
|
+
INSTALL_TYPE_LABELS[status.installation_type]
|
515
|
+
end
|
481
516
|
end
|
482
517
|
end
|
483
518
|
end
|
@@ -40,25 +40,27 @@ module SourceReaders
|
|
40
40
|
raise "Unable to parse #{metadata_source}: #{e.class} -- #{e.message}"
|
41
41
|
end
|
42
42
|
|
43
|
+
def find_all(regexp)
|
44
|
+
@target.files.grep(regexp)
|
45
|
+
end
|
46
|
+
|
47
|
+
def load_all(regexp)
|
48
|
+
find_all(regexp)
|
49
|
+
.map { |path| file = @target.read(path); [path, file] if file }
|
50
|
+
.compact
|
51
|
+
.to_h
|
52
|
+
end
|
53
|
+
|
43
54
|
def load_tests
|
44
|
-
|
45
|
-
path.start_with?("controls") && path.end_with?(".rb")
|
46
|
-
end
|
47
|
-
Hash[tests.map { |x| [x, @target.read(x)] }.delete_if { |_file, contents| contents.nil? }]
|
55
|
+
load_all(%r{^controls/.*\.rb$})
|
48
56
|
end
|
49
57
|
|
50
58
|
def load_libs
|
51
|
-
|
52
|
-
path.start_with?("libraries") && path.end_with?(".rb")
|
53
|
-
end
|
54
|
-
Hash[tests.map { |x| [x, @target.read(x)] }.delete_if { |_file, contents| contents.nil? }]
|
59
|
+
load_all(%r{^libraries/.*\.rb$})
|
55
60
|
end
|
56
61
|
|
57
62
|
def load_data_files
|
58
|
-
files
|
59
|
-
path.start_with?("files" + File::SEPARATOR)
|
60
|
-
end
|
61
|
-
Hash[files.map { |x| [x, @target.read(x)] }.delete_if { |_file, contents| contents.nil? }]
|
63
|
+
load_all(%r{^files/})
|
62
64
|
end
|
63
65
|
end
|
64
66
|
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.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominik Richter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: train-core
|
@@ -536,6 +536,7 @@ files:
|
|
536
536
|
- lib/inspec/resources/pip.rb
|
537
537
|
- lib/inspec/resources/platform.rb
|
538
538
|
- lib/inspec/resources/port.rb
|
539
|
+
- lib/inspec/resources/postfix_conf.rb
|
539
540
|
- lib/inspec/resources/postgres.rb
|
540
541
|
- lib/inspec/resources/postgres_conf.rb
|
541
542
|
- lib/inspec/resources/postgres_hba_conf.rb
|