inspec 2.2.61 → 2.2.64
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -15
- data/README.md +0 -1
- data/docs/dev/plugins.md +321 -0
- data/docs/profiles.md +20 -18
- data/lib/bundles/inspec-artifact/cli.rb +1 -0
- data/lib/bundles/inspec-compliance/cli.rb +1 -0
- data/lib/bundles/inspec-habitat/cli.rb +1 -0
- data/lib/bundles/inspec-init/cli.rb +1 -0
- data/lib/bundles/inspec-supermarket/cli.rb +1 -0
- data/lib/inspec.rb +4 -2
- data/lib/inspec/base_cli.rb +1 -0
- data/lib/inspec/cli.rb +35 -16
- data/lib/inspec/control_eval_context.rb +7 -6
- data/lib/inspec/dependencies/requirement.rb +0 -1
- data/lib/inspec/fetcher.rb +1 -2
- data/lib/inspec/library_eval_context.rb +1 -1
- data/lib/inspec/plugin/v1.rb +2 -0
- data/lib/inspec/{plugins → plugin/v1/plugin_types}/cli.rb +2 -0
- data/lib/inspec/{plugins → plugin/v1/plugin_types}/fetcher.rb +1 -1
- data/lib/inspec/{plugins → plugin/v1/plugin_types}/resource.rb +0 -0
- data/lib/inspec/{plugins → plugin/v1/plugin_types}/secret.rb +1 -1
- data/lib/inspec/{plugins → plugin/v1/plugin_types}/source_reader.rb +1 -1
- data/lib/inspec/{plugins.rb → plugin/v1/plugins.rb} +7 -5
- data/lib/{utils/plugin_registry.rb → inspec/plugin/v1/registry.rb} +0 -0
- data/lib/inspec/plugin/v2.rb +30 -0
- data/lib/inspec/plugin/v2/activator.rb +16 -0
- data/lib/inspec/plugin/v2/loader.rb +204 -0
- data/lib/inspec/plugin/v2/plugin_base.rb +98 -0
- data/lib/inspec/plugin/v2/plugin_types/cli.rb +27 -0
- data/lib/inspec/plugin/v2/plugin_types/mock.rb +12 -0
- data/lib/inspec/plugin/v2/registry.rb +76 -0
- data/lib/inspec/plugin/v2/status.rb +29 -0
- data/lib/inspec/reporters.rb +5 -1
- data/lib/inspec/reporters/automate.rb +1 -1
- data/lib/inspec/reporters/{json_merged.rb → json_automate.rb} +1 -1
- data/lib/inspec/resource.rb +1 -1
- data/lib/inspec/rule.rb +14 -8
- data/lib/inspec/secrets.rb +1 -2
- data/lib/inspec/source_reader.rb +1 -2
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/apache_conf.rb +1 -1
- metadata +20 -10
@@ -0,0 +1,98 @@
|
|
1
|
+
module Inspec::Plugin::V2
|
2
|
+
# Base class for all plugins. Specific plugin types *may* inherit from this; but they must register with it.
|
3
|
+
class PluginBase
|
4
|
+
# rubocop: disable Style/ClassVars
|
5
|
+
@@plugin_type_classes = {}
|
6
|
+
# rubocop: enable Style/ClassVars
|
7
|
+
|
8
|
+
#=====================================================================#
|
9
|
+
# Management Methods
|
10
|
+
#=====================================================================#
|
11
|
+
|
12
|
+
# The global registry.
|
13
|
+
# @returns [Inspec::Plugin::V2::Registry] the singleton Plugin Registry object.
|
14
|
+
def self.registry
|
15
|
+
Inspec::Plugin::V2::Registry.instance
|
16
|
+
end
|
17
|
+
|
18
|
+
# Inform the plugin system of a new plgin type.
|
19
|
+
# This has the following effects:
|
20
|
+
# * enables Inspec.plugin(2, :your_type_here) to return the plugin
|
21
|
+
# type base class
|
22
|
+
# * defines the DSL method with the same name as the plugin type.
|
23
|
+
#
|
24
|
+
# @param [Symbol] plugin_type_name
|
25
|
+
# @param [Class] the plugin type class, defaults to assuming inheritance
|
26
|
+
def self.register_plugin_type(plugin_type_name, new_plugin_type_base_class = self)
|
27
|
+
new_dsl_method_name = plugin_type_name
|
28
|
+
|
29
|
+
# This lets the Inspec.plugin(2,:your_plugin_type) work
|
30
|
+
@@plugin_type_classes[plugin_type_name] = new_plugin_type_base_class
|
31
|
+
|
32
|
+
# This part defines the DSL command to register a concrete plugin's implementation of a plugin type
|
33
|
+
Inspec::Plugin::V2::PluginBase.define_singleton_method(new_dsl_method_name) do |hook_name, &hook_body|
|
34
|
+
plugin_concrete_class = self
|
35
|
+
|
36
|
+
# Verify class is registered (i.e. plugin_name has been called)
|
37
|
+
status = registry.find_status_by_class(plugin_concrete_class)
|
38
|
+
if status.nil?
|
39
|
+
raise Inspec::Plugin::V2::LoadError, "You must call 'plugin_name' prior to calling #{plugin_type_name} for plugin class #{plugin_concrete_class}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Construct the Activator record
|
43
|
+
activator = Inspec::Plugin::V2::Activator.new
|
44
|
+
activator.plugin_name = plugin_concrete_class.plugin_name
|
45
|
+
activator.plugin_type = plugin_type_name
|
46
|
+
activator.activator_name = hook_name.to_sym
|
47
|
+
activator.activation_proc = hook_body
|
48
|
+
|
49
|
+
status.activators << activator
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Determine the base class for a given plugin type
|
54
|
+
# @param [Symbol] plugin_type_name
|
55
|
+
# @returns [Class] the plugin type base class
|
56
|
+
def self.base_class_for_type(plugin_type_name)
|
57
|
+
@@plugin_type_classes[plugin_type_name]
|
58
|
+
end
|
59
|
+
|
60
|
+
#=====================================================================#
|
61
|
+
# DSL Methods
|
62
|
+
#=====================================================================#
|
63
|
+
|
64
|
+
# If no name provided, looks up a known plugin by class and returns the name.
|
65
|
+
#
|
66
|
+
# DSL method to declare a plugin. Once this has been called, the plugin will certainly be
|
67
|
+
# registered (known) with the Registry, and is eligible to be activated.
|
68
|
+
# This mainly handles status annotation.
|
69
|
+
#
|
70
|
+
# @param [Symbol] Name of the plugin. If a string is provided, it is converted to a Symbol.
|
71
|
+
# @returns [Symbol] Name of the plugin
|
72
|
+
def self.plugin_name(name = nil)
|
73
|
+
reg = Inspec::Plugin::V2::Registry.instance
|
74
|
+
return reg.find_status_by_class(self).name if name.nil?
|
75
|
+
|
76
|
+
name = name.to_sym
|
77
|
+
|
78
|
+
# Typically our status will already exist in the registry, from loading the
|
79
|
+
# plugin.json. If we're being loaded, presumably entry_point,
|
80
|
+
# installation_type, version
|
81
|
+
# are known.
|
82
|
+
unless reg.known_plugin?(name)
|
83
|
+
# Under some testing situations, we may not pre-exist.
|
84
|
+
status = Inspec::Plugin::V2::Status.new
|
85
|
+
reg.register(name, status)
|
86
|
+
status.entry_point = 'inline'
|
87
|
+
status.installation_type = :mock_inline
|
88
|
+
end
|
89
|
+
|
90
|
+
status = reg[name]
|
91
|
+
status.api_generation = 2
|
92
|
+
status.plugin_class = self
|
93
|
+
status.name = name
|
94
|
+
|
95
|
+
name
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'inspec/base_cli'
|
2
|
+
|
3
|
+
module Inspec::Plugin::V2::PluginType
|
4
|
+
class CliCommand < Inspec::BaseCLI
|
5
|
+
# This class MUST inherit from Thor, which makes it a bit awkward to register the plugin subtype
|
6
|
+
# Since we can't inherit from PluginBase, we use the two-arg form of register_plugin_type
|
7
|
+
Inspec::Plugin::V2::PluginBase.register_plugin_type(:cli_command, self)
|
8
|
+
|
9
|
+
# Provide a description for the command group.
|
10
|
+
def self.subcommand_desc(usage_msg, desc_msg)
|
11
|
+
@usage_msg = usage_msg
|
12
|
+
@desc_msg = desc_msg
|
13
|
+
end
|
14
|
+
|
15
|
+
# Register the command group with Thor. This must be called on the implementation class AFTER
|
16
|
+
# the the cli_command activator has been called
|
17
|
+
def self.register_with_thor
|
18
|
+
# Figure out my activator name (= subcommand group name)
|
19
|
+
subcommand_name = Inspec::Plugin::V2::Registry.instance \
|
20
|
+
.find_activators(plugin_type: :cli_command, implementation_class: self) \
|
21
|
+
.first.activator_name.to_s
|
22
|
+
|
23
|
+
# Register with Thor
|
24
|
+
Inspec::InspecCLI.register(self, subcommand_name, @usage_msg, @desc_msg, {})
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Inspec::Plugin::V2::PluginType
|
2
|
+
# Test plugin type
|
3
|
+
class Mock < Inspec::Plugin::V2::PluginBase
|
4
|
+
register_plugin_type(:mock_plugin_type)
|
5
|
+
|
6
|
+
# This is the API for the mock plugin type: when a mock plugin is
|
7
|
+
# activated, it is expected to be able to respond to this, and "do something"
|
8
|
+
def mock_hook
|
9
|
+
raise NotImplementedError, 'Mock plugins must implement mock_hook'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'singleton'
|
3
|
+
require_relative 'status'
|
4
|
+
require_relative 'activator'
|
5
|
+
|
6
|
+
module Inspec::Plugin::V2
|
7
|
+
class Registry
|
8
|
+
include Singleton
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
attr_reader :registry
|
12
|
+
def_delegator :registry, :each
|
13
|
+
def_delegator :registry, :[]
|
14
|
+
def_delegator :registry, :key?, :known_plugin?
|
15
|
+
def_delegator :registry, :keys, :plugin_names
|
16
|
+
def_delegator :registry, :values, :plugin_statuses
|
17
|
+
def_delegator :registry, :select
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@registry = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def any_load_failures?
|
24
|
+
!plugin_statuses.select(&:load_exception).empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
def loaded_plugin?(name)
|
28
|
+
registry.dig(name, :loaded)
|
29
|
+
end
|
30
|
+
|
31
|
+
def loaded_count
|
32
|
+
registry.values.select(&:loaded).count
|
33
|
+
end
|
34
|
+
|
35
|
+
def known_count
|
36
|
+
registry.values.count
|
37
|
+
end
|
38
|
+
|
39
|
+
def loaded_plugin_names
|
40
|
+
registry.values.select(&:loaded).map(&:name)
|
41
|
+
end
|
42
|
+
|
43
|
+
def find_status_by_class(klass)
|
44
|
+
registry.values.detect { |status| status.plugin_class == klass }
|
45
|
+
end
|
46
|
+
|
47
|
+
# Finds Activators matching criteria (all optional) you specify as a Hash.
|
48
|
+
# @param [Symbol] plugin_name Restricts the search to the given plugin
|
49
|
+
# @param [Symbol] plugin_type Restricts the search to the given plugin type
|
50
|
+
# @param [Symbol] activator_name Name of the activator
|
51
|
+
# @param [Class] implementation_class Implementation class returned by an already-actived plugin type
|
52
|
+
# @returns [Array] Possibly empty array of Activators
|
53
|
+
def find_activators(filters = {})
|
54
|
+
plugin_statuses.map(&:activators).flatten.select do |act|
|
55
|
+
[:plugin_name, :plugin_type, :activator_name, :implementation_class].all? do |criteria|
|
56
|
+
!filters.key?(criteria) || act[criteria] == filters[criteria]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def register(name, status)
|
62
|
+
if known_plugin? name
|
63
|
+
Inspec::Log.warn "PluginLoader: refusing to re-register plugin '#{name}': an existing plugin with that name was loaded via #{existing.installation_type}-loading from #{existing.entry_point}"
|
64
|
+
else
|
65
|
+
registry[name.to_sym] = status
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
alias []= register
|
70
|
+
|
71
|
+
# Provided for test support. Purges the registry.
|
72
|
+
def __reset
|
73
|
+
@registry.clear
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Inspec::Plugin::V2
|
2
|
+
# Track loading status of each plugin. These are the elements of the Registry.
|
3
|
+
#
|
4
|
+
# Lifecycle of an installed plugin:
|
5
|
+
# If present in the config file, bundled, or core, it is "known"
|
6
|
+
# All known plugins are loaded. v1 plugins auto-activate. All loaded plugins know their version.
|
7
|
+
# v2 plugins activate when they are used. All activated plugins know their implementation class.
|
8
|
+
Status = Struct.new(
|
9
|
+
:activators, # Array of Activators - where plugin_type info gets stored
|
10
|
+
:api_generation, # 0,1,2 # TODO: convert all bundled (v0) to v2
|
11
|
+
:plugin_class, # Plugin class
|
12
|
+
:entry_point, # a gem name or filesystem path
|
13
|
+
:installation_type, # :gem, :path, :core, bundle # TODO: combine core and bundle
|
14
|
+
:loaded, # true, false False could mean not attempted or failed
|
15
|
+
:load_exception, # Exception class if it failed to load
|
16
|
+
:name, # String name
|
17
|
+
:version, # three-digit version. Core / bundled plugins use InSpec version here.
|
18
|
+
) do
|
19
|
+
def initialize(*)
|
20
|
+
super
|
21
|
+
self[:activators] = []
|
22
|
+
self[:loaded] = false
|
23
|
+
end
|
24
|
+
|
25
|
+
def plugin_types
|
26
|
+
activators.map(&:plugin_type).uniq.sort
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/inspec/reporters.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'inspec/reporters/base'
|
2
2
|
require 'inspec/reporters/cli'
|
3
3
|
require 'inspec/reporters/json'
|
4
|
-
require 'inspec/reporters/
|
4
|
+
require 'inspec/reporters/json_automate'
|
5
5
|
require 'inspec/reporters/json_min'
|
6
6
|
require 'inspec/reporters/junit'
|
7
7
|
require 'inspec/reporters/automate'
|
@@ -17,6 +17,10 @@ module Inspec::Reporters
|
|
17
17
|
reporter = Inspec::Reporters::CLI.new(config)
|
18
18
|
when 'json'
|
19
19
|
reporter = Inspec::Reporters::Json.new(config)
|
20
|
+
# This reporter is only used for Chef internal. We reserve the
|
21
|
+
# right to introduce breaking changes to this reporter at any time.
|
22
|
+
when 'json-automate'
|
23
|
+
reporter = Inspec::Reporters::JsonAutomate.new(config)
|
20
24
|
when 'json-min'
|
21
25
|
reporter = Inspec::Reporters::JsonMin.new(config)
|
22
26
|
when 'junit'
|
data/lib/inspec/resource.rb
CHANGED
data/lib/inspec/rule.rb
CHANGED
@@ -42,7 +42,7 @@ module Inspec
|
|
42
42
|
@__rule_id = id
|
43
43
|
@__profile_id = profile_id
|
44
44
|
@__checks = []
|
45
|
-
@__skip_rule =
|
45
|
+
@__skip_rule = {}
|
46
46
|
@__merge_count = 0
|
47
47
|
@__merge_changes = []
|
48
48
|
@__skip_only_if_eval = opts[:skip_only_if_eval]
|
@@ -118,11 +118,12 @@ module Inspec
|
|
118
118
|
#
|
119
119
|
# @param [Type] &block returns true if tests are added, false otherwise
|
120
120
|
# @return [nil]
|
121
|
-
def only_if
|
121
|
+
def only_if(message = nil)
|
122
122
|
return unless block_given?
|
123
123
|
return if @__skip_only_if_eval == true
|
124
124
|
|
125
|
-
@__skip_rule ||= !yield
|
125
|
+
@__skip_rule[:result] ||= !yield
|
126
|
+
@__skip_rule[:message] = message
|
126
127
|
end
|
127
128
|
|
128
129
|
# Describe will add one or more tests to this control. There is 2 ways
|
@@ -174,8 +175,9 @@ module Inspec
|
|
174
175
|
rule.instance_variable_get(:@__skip_rule)
|
175
176
|
end
|
176
177
|
|
177
|
-
def self.set_skip_rule(rule, value)
|
178
|
-
rule.instance_variable_set(:@__skip_rule,
|
178
|
+
def self.set_skip_rule(rule, value, message = nil)
|
179
|
+
rule.instance_variable_set(:@__skip_rule,
|
180
|
+
{ result: value, message: message })
|
179
181
|
end
|
180
182
|
|
181
183
|
def self.merge_count(rule)
|
@@ -187,9 +189,13 @@ module Inspec
|
|
187
189
|
end
|
188
190
|
|
189
191
|
def self.prepare_checks(rule)
|
190
|
-
|
191
|
-
return checks(rule) unless
|
192
|
-
|
192
|
+
skip_check = skip_status(rule)
|
193
|
+
return checks(rule) unless skip_check[:result].eql?(true)
|
194
|
+
if skip_check[:message]
|
195
|
+
msg = "Skipped control due to only_if condition: #{skip_check[:message]}"
|
196
|
+
else
|
197
|
+
msg = 'Skipped control due to only_if condition.'
|
198
|
+
end
|
193
199
|
|
194
200
|
# TODO: we use os as the carrier here, but should consider
|
195
201
|
# a separate resource to do skipping
|
data/lib/inspec/secrets.rb
CHANGED
data/lib/inspec/source_reader.rb
CHANGED
data/lib/inspec/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.64
|
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-08-
|
11
|
+
date: 2018-08-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: train
|
@@ -313,6 +313,7 @@ files:
|
|
313
313
|
- docs/dev/control-eval.md
|
314
314
|
- docs/dev/filtertable-internals.md
|
315
315
|
- docs/dev/filtertable-usage.md
|
316
|
+
- docs/dev/plugins.md
|
316
317
|
- docs/dsl_inspec.md
|
317
318
|
- docs/dsl_resource.md
|
318
319
|
- docs/glossary.md
|
@@ -619,12 +620,22 @@ files:
|
|
619
620
|
- lib/inspec/objects/tag.rb
|
620
621
|
- lib/inspec/objects/test.rb
|
621
622
|
- lib/inspec/objects/value.rb
|
622
|
-
- lib/inspec/
|
623
|
-
- lib/inspec/
|
624
|
-
- lib/inspec/
|
625
|
-
- lib/inspec/
|
626
|
-
- lib/inspec/
|
627
|
-
- lib/inspec/
|
623
|
+
- lib/inspec/plugin/v1.rb
|
624
|
+
- lib/inspec/plugin/v1/plugin_types/cli.rb
|
625
|
+
- lib/inspec/plugin/v1/plugin_types/fetcher.rb
|
626
|
+
- lib/inspec/plugin/v1/plugin_types/resource.rb
|
627
|
+
- lib/inspec/plugin/v1/plugin_types/secret.rb
|
628
|
+
- lib/inspec/plugin/v1/plugin_types/source_reader.rb
|
629
|
+
- lib/inspec/plugin/v1/plugins.rb
|
630
|
+
- lib/inspec/plugin/v1/registry.rb
|
631
|
+
- lib/inspec/plugin/v2.rb
|
632
|
+
- lib/inspec/plugin/v2/activator.rb
|
633
|
+
- lib/inspec/plugin/v2/loader.rb
|
634
|
+
- lib/inspec/plugin/v2/plugin_base.rb
|
635
|
+
- lib/inspec/plugin/v2/plugin_types/cli.rb
|
636
|
+
- lib/inspec/plugin/v2/plugin_types/mock.rb
|
637
|
+
- lib/inspec/plugin/v2/registry.rb
|
638
|
+
- lib/inspec/plugin/v2/status.rb
|
628
639
|
- lib/inspec/polyfill.rb
|
629
640
|
- lib/inspec/profile.rb
|
630
641
|
- lib/inspec/profile_context.rb
|
@@ -634,7 +645,7 @@ files:
|
|
634
645
|
- lib/inspec/reporters/base.rb
|
635
646
|
- lib/inspec/reporters/cli.rb
|
636
647
|
- lib/inspec/reporters/json.rb
|
637
|
-
- lib/inspec/reporters/
|
648
|
+
- lib/inspec/reporters/json_automate.rb
|
638
649
|
- lib/inspec/reporters/json_min.rb
|
639
650
|
- lib/inspec/reporters/junit.rb
|
640
651
|
- lib/inspec/reporters/yaml.rb
|
@@ -823,7 +834,6 @@ files:
|
|
823
834
|
- lib/utils/object_traversal.rb
|
824
835
|
- lib/utils/parser.rb
|
825
836
|
- lib/utils/pkey_reader.rb
|
826
|
-
- lib/utils/plugin_registry.rb
|
827
837
|
- lib/utils/simpleconfig.rb
|
828
838
|
- lib/utils/spdx.rb
|
829
839
|
- lib/utils/spdx.txt
|