inspec 3.0.52 → 3.0.61
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -12
- data/lib/inspec/control_eval_context.rb +26 -1
- data/lib/inspec/dsl.rb +23 -0
- data/lib/inspec/plugin/v1/plugin_types/resource.rb +28 -0
- data/lib/inspec/plugin/v2.rb +1 -0
- data/lib/inspec/plugin/v2/config_file.rb +148 -0
- data/lib/inspec/plugin/v2/installer.rb +17 -37
- data/lib/inspec/plugin/v2/loader.rb +11 -85
- data/lib/inspec/plugin/v2/plugin_types/dsl.rb +11 -0
- data/lib/inspec/plugin/v2/registry.rb +15 -0
- data/lib/inspec/rspec_extensions.rb +71 -7
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/inspec-init/lib/inspec-init/templates/profiles/aws/README.md +54 -0
- data/lib/plugins/inspec-init/lib/inspec-init/templates/profiles/aws/attributes.yml +2 -0
- data/lib/plugins/inspec-init/lib/inspec-init/templates/profiles/aws/controls/example.rb +26 -0
- data/lib/plugins/inspec-init/lib/inspec-init/templates/profiles/aws/inspec.yml +16 -0
- data/lib/plugins/inspec-init/lib/inspec-init/templates/profiles/aws/libraries/.gitkeep +0 -0
- data/lib/plugins/inspec-init/test/functional/inspec_init_test.rb +13 -1
- data/lib/resource_support/aws.rb +1 -0
- data/lib/resources/aws/aws_eks_cluster.rb +101 -0
- data/lib/resources/filesystem.rb +81 -8
- data/lib/resources/package.rb +1 -1
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86ef35666565e8d57ca2acb1cfe50db549911f47e24353c9cedbec221263d7b9
|
4
|
+
data.tar.gz: d7be319f163e120f5b707b6d06bf2f81bf973c34b6372e411f8856f4191e6419
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19b0706c8586860e8c6d05fb692389339f073ae77976ddb44eae8e3f0b3e5907a1eaccec8467fcae6fb1d3303df0b9ed0e655b4277dc999e6646a3e459052533
|
7
|
+
data.tar.gz: 3e32a292b04daebdd2ac1bc167fd575e2924a6be93f9e136cb021ce026a2a2219ce16c69ff29f31b38a4a6529035b4df91d603e8a264f9decfc3eed11d001d4a
|
data/CHANGELOG.md
CHANGED
@@ -1,27 +1,47 @@
|
|
1
1
|
# Change Log
|
2
2
|
<!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
|
3
|
-
<!-- latest_release 3.0.
|
4
|
-
## [v3.0.
|
3
|
+
<!-- latest_release 3.0.61 -->
|
4
|
+
## [v3.0.61](https://github.com/inspec/inspec/tree/v3.0.61) (2018-11-29)
|
5
5
|
|
6
|
-
####
|
7
|
-
-
|
6
|
+
#### New Features
|
7
|
+
- Plugin Type: DSLs [#3557](https://github.com/inspec/inspec/pull/3557) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
8
8
|
<!-- latest_release -->
|
9
9
|
|
10
|
-
<!-- release_rollup since=3.0.
|
11
|
-
### Changes since 3.0.
|
10
|
+
<!-- release_rollup since=3.0.52 -->
|
11
|
+
### Changes since 3.0.52 release
|
12
12
|
|
13
|
-
####
|
14
|
-
-
|
13
|
+
#### New Features
|
14
|
+
- Plugin Type: DSLs [#3557](https://github.com/inspec/inspec/pull/3557) ([clintoncwolfe](https://github.com/clintoncwolfe)) <!-- 3.0.61 -->
|
15
15
|
|
16
16
|
#### Bug Fixes
|
17
|
-
-
|
17
|
+
- package: fix package detection on windows [#3607](https://github.com/inspec/inspec/pull/3607) ([mhackethal](https://github.com/mhackethal)) <!-- 3.0.58 -->
|
18
|
+
- www: remove jquery sticky on the sidebar [#3623](https://github.com/inspec/inspec/pull/3623) ([arlimus](https://github.com/arlimus)) <!-- 3.0.57 -->
|
18
19
|
|
19
20
|
#### Enhancements
|
20
|
-
-
|
21
|
-
|
21
|
+
- filesystem: improve Windows support [#3606](https://github.com/inspec/inspec/pull/3606) ([mhackethal](https://github.com/mhackethal)) <!-- 3.0.56 -->
|
22
|
+
|
23
|
+
#### Merged Pull Requests
|
24
|
+
- Add SQLcl to Oracledb_session Doc [#3632](https://github.com/inspec/inspec/pull/3632) ([ibsavage](https://github.com/ibsavage)) <!-- 3.0.60 -->
|
25
|
+
- lc/add-aws-platform-template [#3622](https://github.com/inspec/inspec/pull/3622) ([Caprowni](https://github.com/Caprowni)) <!-- 3.0.59 -->
|
26
|
+
- Revert setting RSpec expectation syntax to 'should' mode [#3620](https://github.com/inspec/inspec/pull/3620) ([clintoncwolfe](https://github.com/clintoncwolfe)) <!-- 3.0.55 -->
|
27
|
+
- Improvements to the functional helper run_inspec_process [#3603](https://github.com/inspec/inspec/pull/3603) ([clintoncwolfe](https://github.com/clintoncwolfe)) <!-- 3.0.54 -->
|
28
|
+
- Create a class to handle the plugins.json file [#3575](https://github.com/inspec/inspec/pull/3575) ([clintoncwolfe](https://github.com/clintoncwolfe)) <!-- 3.0.53 -->
|
22
29
|
<!-- release_rollup -->
|
23
30
|
|
24
31
|
<!-- latest_stable_release -->
|
32
|
+
## [v3.0.52](https://github.com/inspec/inspec/tree/v3.0.52) (2018-11-15)
|
33
|
+
|
34
|
+
#### Enhancements
|
35
|
+
- aws_security_group: Query against other security group ids in allow_* matchers [#3576](https://github.com/inspec/inspec/pull/3576) ([j00p34](https://github.com/j00p34))
|
36
|
+
- Adding --no-pager to service checks [#3592](https://github.com/inspec/inspec/pull/3592) ([fernandoalex](https://github.com/fernandoalex))
|
37
|
+
|
38
|
+
#### Bug Fixes
|
39
|
+
- Adds protection against zipslip vulnerability [#3604](https://github.com/inspec/inspec/pull/3604) ([hdost](https://github.com/hdost))
|
40
|
+
|
41
|
+
#### Merged Pull Requests
|
42
|
+
- Load the compliance plugin when the fetcher is needed [#3609](https://github.com/inspec/inspec/pull/3609) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
|
43
|
+
<!-- latest_stable_release -->
|
44
|
+
|
25
45
|
## [v3.0.46](https://github.com/inspec/inspec/tree/v3.0.46) (2018-11-08)
|
26
46
|
|
27
47
|
#### New Features
|
@@ -42,7 +62,6 @@
|
|
42
62
|
- Fix functional tests issues with vendoring [#3572](https://github.com/inspec/inspec/pull/3572) ([jquick](https://github.com/jquick))
|
43
63
|
- Fixes (some) ruby warnings related to functional tests [#3561](https://github.com/inspec/inspec/pull/3561) ([TheLonelyGhost](https://github.com/TheLonelyGhost))
|
44
64
|
- Fixes broken link in documentation [#3588](https://github.com/inspec/inspec/pull/3588) ([dmccown](https://github.com/dmccown))
|
45
|
-
<!-- latest_stable_release -->
|
46
65
|
|
47
66
|
## [v3.0.25](https://github.com/inspec/inspec/tree/v3.0.25) (2018-11-01)
|
48
67
|
|
@@ -29,6 +29,32 @@ module Inspec
|
|
29
29
|
define_method :attribute do |name|
|
30
30
|
Inspec::AttributeRegistry.find_attribute(name, profile_id).value
|
31
31
|
end
|
32
|
+
|
33
|
+
# Support for Control DSL plugins.
|
34
|
+
# This is called when an unknown method is encountered
|
35
|
+
# within a control block.
|
36
|
+
def method_missing(method_name, *arguments, &block)
|
37
|
+
# Check to see if there is a control_dsl plugin activator hook with the method name
|
38
|
+
registry = Inspec::Plugin::V2::Registry.instance
|
39
|
+
hook = registry.find_activators(plugin_type: :control_dsl, activator_name: method_name).first
|
40
|
+
if hook
|
41
|
+
# OK, load the hook if it hasn't been already. We'll then know a module,
|
42
|
+
# which we can then inject into the context
|
43
|
+
registry.activate(:control_dsl, method_name) unless hook.activated?
|
44
|
+
# Inject the module's methods into the context.
|
45
|
+
# implementation_class is the field name, but this is actually a module.
|
46
|
+
self.class.include(hook.implementation_class)
|
47
|
+
# Now that the module is loaded, it defined one or more methods
|
48
|
+
# (presumably the one we were looking for.)
|
49
|
+
# We still haven't called it, so do so now.
|
50
|
+
send(method_name, *arguments, &block)
|
51
|
+
else
|
52
|
+
# If we couldn't find a plugin to match, maybe something up above has it,
|
53
|
+
# or maybe it is just a unknown method error.
|
54
|
+
super
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
32
58
|
end
|
33
59
|
end
|
34
60
|
|
@@ -44,7 +70,6 @@ module Inspec
|
|
44
70
|
profile_context_owner = profile_context
|
45
71
|
profile_id = profile_context.profile_id
|
46
72
|
rule_class = rule_context(resources_dsl, profile_id)
|
47
|
-
|
48
73
|
Class.new do # rubocop:disable Metrics/BlockLength
|
49
74
|
include Inspec::DSL
|
50
75
|
include Inspec::DSL::RequireOverride
|
data/lib/inspec/dsl.rb
CHANGED
@@ -27,6 +27,29 @@ module Inspec::DSL
|
|
27
27
|
add_resource(target_name, res)
|
28
28
|
end
|
29
29
|
|
30
|
+
# Support for Outer Profile DSL plugins
|
31
|
+
# This is called when an unknown method is encountered
|
32
|
+
# "bare" in a control file - outside of a control or describe block.
|
33
|
+
def method_missing(method_name, *arguments, &block)
|
34
|
+
# Check to see if there is a outer_profile_dsl plugin activator hook with the method name
|
35
|
+
registry = Inspec::Plugin::V2::Registry.instance
|
36
|
+
hook = registry.find_activators(plugin_type: :outer_profile_dsl, activator_name: method_name).first
|
37
|
+
if hook
|
38
|
+
# OK, load the hook if it hasn't been already. We'll then know a module,
|
39
|
+
# which we can then inject into the context
|
40
|
+
registry.activate(:outer_profile_dsl, method_name) unless hook.activated?
|
41
|
+
# Inject the module's methods into the context
|
42
|
+
# implementation_class is the field name, but this is actually a module.
|
43
|
+
self.class.include(hook.implementation_class)
|
44
|
+
# Now that the module is loaded, it defined one or more methods
|
45
|
+
# (presumably the one we were looking for.)
|
46
|
+
# We still haven't called it, so do so now.
|
47
|
+
send(method_name, *arguments, &block)
|
48
|
+
else
|
49
|
+
super
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
30
53
|
def self.load_spec_files_for_profile(bind_context, opts, &block)
|
31
54
|
dependencies = opts[:dependencies]
|
32
55
|
profile_id = opts[:profile_id]
|
@@ -39,6 +39,34 @@ module Inspec
|
|
39
39
|
__resource_registry[@name].example(example)
|
40
40
|
end
|
41
41
|
|
42
|
+
# Support for Resource DSL plugins.
|
43
|
+
# This is called when an unknown method is encountered
|
44
|
+
# within a resource class definition.
|
45
|
+
# Even tho this is defined as an instance method, it gets added to
|
46
|
+
# Inspec::Plugins::Resource via `extend`, so this is actually a class defintion.
|
47
|
+
def method_missing(method_name, *arguments, &block)
|
48
|
+
require 'inspec/plugin/v2'
|
49
|
+
# Check to see if there is a resource_dsl plugin activator hook with the method name
|
50
|
+
registry = Inspec::Plugin::V2::Registry.instance
|
51
|
+
hook = registry.find_activators(plugin_type: :resource_dsl, activator_name: method_name).first
|
52
|
+
if hook
|
53
|
+
# OK, load the hook if it hasn't been already. We'll then know a module,
|
54
|
+
# which we can then inject into the resource
|
55
|
+
registry.activate(:resource_dsl, method_name) unless hook.activated?
|
56
|
+
# Inject the module's methods into the resource as class methods.
|
57
|
+
# implementation_class is the field name, but this is actually a module.
|
58
|
+
extend(hook.implementation_class)
|
59
|
+
# Now that the module is loaded, it defined one or more methods
|
60
|
+
# (presumably the one we were looking for.)
|
61
|
+
# We still haven't called it, so do so now.
|
62
|
+
send(method_name, *arguments, &block)
|
63
|
+
else
|
64
|
+
# If we couldn't find a plugin to match, maybe something up above has it,
|
65
|
+
# or maybe it is just a unknown method error.
|
66
|
+
super
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
42
70
|
def __resource_registry
|
43
71
|
Inspec::Resource.registry
|
44
72
|
end
|
data/lib/inspec/plugin/v2.rb
CHANGED
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Inspec::Plugin::V2
|
4
|
+
# Represents the plugin config file on disk.
|
5
|
+
class ConfigFile
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
attr_reader :path
|
9
|
+
|
10
|
+
def initialize(path = nil)
|
11
|
+
@path = path || self.class.default_path
|
12
|
+
@data = blank_structure
|
13
|
+
|
14
|
+
read_and_validate_file if File.exist?(@path)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the defaut path for a config file.
|
18
|
+
# This respects ENV['INSPEC_CONFIG_DIR'].
|
19
|
+
def self.default_path
|
20
|
+
File.join(Inspec.config_dir, 'plugins.json')
|
21
|
+
end
|
22
|
+
|
23
|
+
# Implement Enumerable. All Enumerable methds act
|
24
|
+
# on the plugins list, and yield Hashes that represent
|
25
|
+
# an entry.
|
26
|
+
def each(&block)
|
27
|
+
@data[:plugins].each(&block)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Look for a plugin by name.
|
31
|
+
def plugin_by_name(name)
|
32
|
+
detect { |entry| entry[:name] == name.to_sym }
|
33
|
+
end
|
34
|
+
|
35
|
+
# Check for a plugin
|
36
|
+
def existing_entry?(name)
|
37
|
+
!plugin_by_name(name).nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
# Add an entry with full validation.
|
41
|
+
def add_entry(proposed_entry)
|
42
|
+
unless proposed_entry.keys.all? { |field| field.is_a? Symbol }
|
43
|
+
raise Inspec::Plugin::V2::ConfigError, 'All keys to ConfigFile#add_entry must be symbols'
|
44
|
+
end
|
45
|
+
|
46
|
+
validate_entry(proposed_entry)
|
47
|
+
|
48
|
+
if existing_entry?(proposed_entry[:name])
|
49
|
+
raise Inspec::Plugin::V2::ConfigError, "Duplicate plugin name in call to ConfigFile#add_entry: '#{proposed_entry[:name]}'"
|
50
|
+
end
|
51
|
+
|
52
|
+
@data[:plugins] << proposed_entry
|
53
|
+
end
|
54
|
+
|
55
|
+
# Removes an entry specified by plugin name.
|
56
|
+
def remove_entry(name)
|
57
|
+
unless existing_entry?(name)
|
58
|
+
raise Inspec::Plugin::V2::ConfigError, "No such entry with plugin name '#{name}'"
|
59
|
+
end
|
60
|
+
@data[:plugins].delete_if { |entry| entry[:name] == name.to_sym }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Save the file to disk as a JSON structure at the path.
|
64
|
+
def save
|
65
|
+
dir = File.dirname(path)
|
66
|
+
FileUtils.mkdir_p(dir)
|
67
|
+
File.write(path, JSON.pretty_generate(@data))
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def blank_structure
|
73
|
+
{
|
74
|
+
plugins_config_version: '1.0.0',
|
75
|
+
plugins: [],
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def read_and_validate_file
|
80
|
+
@data = JSON.parse(File.read(path), symbolize_names: true)
|
81
|
+
validate_file
|
82
|
+
rescue JSON::ParserError => e
|
83
|
+
raise Inspec::Plugin::V2::ConfigError, "Failed to load plugins JSON configuration from #{path}:\n#{e}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def validate_file # rubocop: disable Metrics/AbcSize
|
87
|
+
unless @data[:plugins_config_version]
|
88
|
+
raise Inspec::Plugin::V2::ConfigError, "Missing 'plugins_config_version' entry at #{path} - currently support versions: 1.0.0"
|
89
|
+
end
|
90
|
+
|
91
|
+
unless @data[:plugins_config_version] == '1.0.0'
|
92
|
+
raise Inspec::Plugin::V2::ConfigError, "Unsupported plugins.json file version #{@data[:plugins_config_version]} at #{path} - currently support versions: 1.0.0"
|
93
|
+
end
|
94
|
+
|
95
|
+
plugin_entries = @data[:plugins]
|
96
|
+
if plugin_entries.nil?
|
97
|
+
raise Inspec::Plugin::V2::ConfigError, "Malformed plugins.json file at #{path} - missing top-level key named 'plugins', whose value should be an array"
|
98
|
+
end
|
99
|
+
|
100
|
+
unless plugin_entries.is_a?(Array)
|
101
|
+
raise Inspec::Plugin::V2::ConfigError, "Malformed plugins.json file at #{path} - top-level key named 'plugins' should be an array"
|
102
|
+
end
|
103
|
+
|
104
|
+
plugin_entries.each_with_index do |plugin_entry, idx|
|
105
|
+
begin
|
106
|
+
validate_entry(plugin_entry)
|
107
|
+
rescue Inspec::Plugin::V2::ConfigError => ex
|
108
|
+
# append some context to the message
|
109
|
+
raise Inspec::Plugin::V2::ConfigError, 'Malformed plugins.json file - ' + ex.message + " at index #{idx}"
|
110
|
+
end
|
111
|
+
|
112
|
+
# Check for duplicates
|
113
|
+
plugin_entries.each_with_index do |other_entry, other_idx|
|
114
|
+
next if idx == other_idx
|
115
|
+
next unless other_entry.is_a? Hash # We'll catch that invalid entry later
|
116
|
+
next if plugin_entry[:name] != other_entry[:name]
|
117
|
+
indices = [idx, other_idx].sort
|
118
|
+
raise Inspec::Plugin::V2::ConfigError, "Malformed plugins.json file - duplicate plugin entry '#{plugin_entry[:name]}' detected at index #{indices[0]} and #{indices[1]}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def validate_entry(plugin_entry)
|
124
|
+
unless plugin_entry.is_a? Hash
|
125
|
+
raise Inspec::Plugin::V2::ConfigError, "each 'plugins' entry should be a Hash / JSON object"
|
126
|
+
end
|
127
|
+
|
128
|
+
unless plugin_entry.key? :name
|
129
|
+
raise Inspec::Plugin::V2::ConfigError, "'plugins' entry missing 'name' field"
|
130
|
+
end
|
131
|
+
|
132
|
+
# Symbolize the name.
|
133
|
+
plugin_entry[:name] = plugin_entry[:name].to_sym
|
134
|
+
|
135
|
+
if plugin_entry.key? :installation_type
|
136
|
+
seen_type = plugin_entry[:installation_type]
|
137
|
+
unless [:gem, :path].include? seen_type.to_sym
|
138
|
+
raise Inspec::Plugin::V2::ConfigError, "'plugins' entry with unrecognized installation_type (must be one of 'gem' or 'path')"
|
139
|
+
end
|
140
|
+
plugin_entry[:installation_type] = seen_type.to_sym
|
141
|
+
|
142
|
+
if plugin_entry[:installation_type] == :path && !plugin_entry.key?(:installation_path)
|
143
|
+
raise Inspec::Plugin::V2::ConfigError, "'plugins' entry with a 'path' installation_type missing installation path"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -24,7 +24,7 @@ module Inspec::Plugin::V2
|
|
24
24
|
|
25
25
|
Gem.configuration['verbose'] = false
|
26
26
|
|
27
|
-
attr_reader :loader, :registry
|
27
|
+
attr_reader :conf_file, :loader, :registry
|
28
28
|
def_delegator :loader, :plugin_gem_path, :gem_path
|
29
29
|
def_delegator :loader, :plugin_conf_file_path
|
30
30
|
def_delegator :loader, :list_managed_gems
|
@@ -459,45 +459,25 @@ module Inspec::Plugin::V2
|
|
459
459
|
#===================================================================#
|
460
460
|
# plugins.json Maintenance Methods #
|
461
461
|
#===================================================================#
|
462
|
-
|
463
|
-
# TODO: refactor the plugin.json file to have its own class, which Installer consumes
|
464
462
|
def update_plugin_config_file(plugin_name, opts)
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
if opts.key?(:path)
|
482
|
-
entry['installation_type'] = 'path'
|
483
|
-
entry['installation_path'] = opts[:path]
|
463
|
+
# Be careful no to initialize this until just before we write.
|
464
|
+
# Under testing, ENV['INSPEC_CONFIG_DIR'] may have changed.
|
465
|
+
@conf_file = Inspec::Plugin::V2::ConfigFile.new
|
466
|
+
|
467
|
+
# Remove, then optionally rebuild, the entry for the plugin being modified.
|
468
|
+
conf_file.remove_entry(plugin_name) if conf_file.existing_entry?(plugin_name)
|
469
|
+
unless opts[:action] == :uninstall
|
470
|
+
entry = { name: plugin_name }
|
471
|
+
# Parsing by Requirement handles lot of awkward formattoes
|
472
|
+
entry[:version] = Gem::Requirement.new(opts[:version]).to_s if opts.key?(:version)
|
473
|
+
if opts.key?(:path)
|
474
|
+
entry[:installation_type] = :path
|
475
|
+
entry[:installation_path] = opts[:path]
|
476
|
+
end
|
477
|
+
conf_file.add_entry(entry)
|
484
478
|
end
|
485
479
|
|
486
|
-
|
487
|
-
config
|
488
|
-
end
|
489
|
-
|
490
|
-
# TODO: check for validity
|
491
|
-
# TODO: refactor the plugin.json file to have its own class, which Installer consumes
|
492
|
-
def read_or_init_config_data
|
493
|
-
if File.exist?(plugin_conf_file_path)
|
494
|
-
JSON.parse(File.read(plugin_conf_file_path))
|
495
|
-
else
|
496
|
-
{
|
497
|
-
'plugins_config_version' => '1.0.0',
|
498
|
-
'plugins' => [],
|
499
|
-
}
|
500
|
-
end
|
480
|
+
conf_file.save
|
501
481
|
end
|
502
482
|
end
|
503
483
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'json'
|
2
1
|
require 'inspec/log'
|
2
|
+
require 'inspec/plugin/v2/config_file'
|
3
3
|
|
4
4
|
# Add the current directory of the process to the load path
|
5
5
|
$LOAD_PATH.unshift('.') unless $LOAD_PATH.include?('.')
|
@@ -9,13 +9,13 @@ $LOAD_PATH.unshift(folder) unless $LOAD_PATH.include?('folder')
|
|
9
9
|
|
10
10
|
module Inspec::Plugin::V2
|
11
11
|
class Loader
|
12
|
-
attr_reader :registry, :options
|
12
|
+
attr_reader :conf_file, :registry, :options
|
13
13
|
|
14
14
|
def initialize(options = {})
|
15
15
|
@options = options
|
16
16
|
@registry = Inspec::Plugin::V2::Registry.instance
|
17
|
-
|
18
|
-
|
17
|
+
@conf_file = Inspec::Plugin::V2::ConfigFile.new
|
18
|
+
read_conf_file_into_registry
|
19
19
|
|
20
20
|
# Old-style (v0, v1) co-distributed plugins were called 'bundles'
|
21
21
|
# and were located in lib/bundles
|
@@ -104,27 +104,12 @@ module Inspec::Plugin::V2
|
|
104
104
|
|
105
105
|
# OK, activate.
|
106
106
|
if activate_me
|
107
|
-
activate(:cli_command, act.activator_name)
|
107
|
+
registry.activate(:cli_command, act.activator_name)
|
108
108
|
act.implementation_class.register_with_thor
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
-
def activate(plugin_type, hook_name)
|
114
|
-
activator = registry.find_activators(plugin_type: plugin_type, activator_name: hook_name).first
|
115
|
-
# We want to capture literally any possible exception here, since we are storing them.
|
116
|
-
# rubocop: disable Lint/RescueException
|
117
|
-
begin
|
118
|
-
impl_class = activator.activation_proc.call
|
119
|
-
activator.activated?(true)
|
120
|
-
activator.implementation_class = impl_class
|
121
|
-
rescue Exception => ex
|
122
|
-
activator.exception = ex
|
123
|
-
Inspec::Log.error "Could not activate #{activator.plugin_type} hook named '#{activator.activator_name}' for plugin #{plugin_name}"
|
124
|
-
end
|
125
|
-
# rubocop: enable Lint/RescueException
|
126
|
-
end
|
127
|
-
|
128
113
|
def plugin_gem_path
|
129
114
|
self.class.plugin_gem_path
|
130
115
|
end
|
@@ -157,16 +142,6 @@ module Inspec::Plugin::V2
|
|
157
142
|
self.class.list_managed_gems
|
158
143
|
end
|
159
144
|
|
160
|
-
# TODO: refactor the plugin.json file to have its own class, which Loader consumes
|
161
|
-
def plugin_conf_file_path
|
162
|
-
self.class.plugin_conf_file_path
|
163
|
-
end
|
164
|
-
|
165
|
-
# TODO: refactor the plugin.json file to have its own class, which Loader consumes
|
166
|
-
def self.plugin_conf_file_path
|
167
|
-
File.join(Inspec.config_dir, 'plugins.json')
|
168
|
-
end
|
169
|
-
|
170
145
|
private
|
171
146
|
|
172
147
|
# 'Activating' a gem adds it to the load path, so 'require "gemname"' will work.
|
@@ -271,71 +246,22 @@ module Inspec::Plugin::V2
|
|
271
246
|
end
|
272
247
|
end
|
273
248
|
|
274
|
-
|
275
|
-
|
276
|
-
def read_conf_file
|
277
|
-
if File.exist?(plugin_conf_file_path)
|
278
|
-
@plugin_file_contents = JSON.parse(File.read(plugin_conf_file_path))
|
279
|
-
else
|
280
|
-
@plugin_file_contents = {
|
281
|
-
'plugins_config_version' => '1.0.0',
|
282
|
-
'plugins' => [],
|
283
|
-
}
|
284
|
-
end
|
285
|
-
rescue JSON::ParserError => e
|
286
|
-
raise Inspec::Plugin::V2::ConfigError, "Failed to load plugins JSON configuration from #{plugin_conf_file_path}:\n#{e}"
|
287
|
-
end
|
288
|
-
|
289
|
-
# TODO: refactor the plugin.json file to have its own class, which Loader consumes
|
290
|
-
def unpack_conf_file
|
291
|
-
validate_conf_file
|
292
|
-
@plugin_file_contents['plugins'].each do |plugin_json|
|
249
|
+
def read_conf_file_into_registry
|
250
|
+
conf_file.each do |plugin_entry|
|
293
251
|
status = Inspec::Plugin::V2::Status.new
|
294
|
-
status.name =
|
252
|
+
status.name = plugin_entry[:name]
|
295
253
|
status.loaded = false
|
296
|
-
status.installation_type = (
|
254
|
+
status.installation_type = (plugin_entry[:installation_type] || :gem)
|
297
255
|
case status.installation_type
|
298
256
|
when :gem
|
299
257
|
status.entry_point = status.name.to_s
|
300
|
-
status.version =
|
258
|
+
status.version = plugin_entry[:version]
|
301
259
|
when :path
|
302
|
-
status.entry_point =
|
260
|
+
status.entry_point = plugin_entry[:installation_path]
|
303
261
|
end
|
304
262
|
|
305
263
|
registry[status.name] = status
|
306
264
|
end
|
307
265
|
end
|
308
|
-
|
309
|
-
# TODO: refactor the plugin.json file to have its own class, which Loader consumes
|
310
|
-
def validate_conf_file
|
311
|
-
unless @plugin_file_contents['plugins_config_version'] == '1.0.0'
|
312
|
-
raise Inspec::Plugin::V2::ConfigError, "Unsupported plugins.json file version #{@plugin_file_contents['plugins_config_version']} at #{plugin_conf_file_path} - currently support versions: 1.0.0"
|
313
|
-
end
|
314
|
-
|
315
|
-
plugin_entries = @plugin_file_contents['plugins']
|
316
|
-
unless plugin_entries.is_a?(Array)
|
317
|
-
raise Inspec::Plugin::V2::ConfigError, "Malformed plugins.json file - should have a top-level key named 'plugins', whose value is an array"
|
318
|
-
end
|
319
|
-
|
320
|
-
plugin_entries.each do |plugin_entry|
|
321
|
-
unless plugin_entry.is_a? Hash
|
322
|
-
raise Inspec::Plugin::V2::ConfigError, "Malformed plugins.json file - each 'plugins' entry should be a Hash / JSON object"
|
323
|
-
end
|
324
|
-
|
325
|
-
unless plugin_entry.key? 'name'
|
326
|
-
raise Inspec::Plugin::V2::ConfigError, "Malformed plugins.json file - each 'plugins' entry must have a 'name' field"
|
327
|
-
end
|
328
|
-
|
329
|
-
next unless plugin_entry.key?('installation_type')
|
330
|
-
unless %w{gem path}.include? plugin_entry['installation_type']
|
331
|
-
raise Inspec::Plugin::V2::ConfigError, "Malformed plugins.json file - each 'installation_type' must be one of 'gem' or 'path'"
|
332
|
-
end
|
333
|
-
|
334
|
-
next unless plugin_entry['installation_type'] == 'path'
|
335
|
-
unless plugin_entry.key?('installation_path')
|
336
|
-
raise Inspec::Plugin::V2::ConfigError, "Malformed plugins.json file - each 'plugins' entry with a 'path' installation_type must provide an 'installation_path' field"
|
337
|
-
end
|
338
|
-
end
|
339
|
-
end
|
340
266
|
end
|
341
267
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# All DSL plugin types are defined here.
|
2
|
+
|
3
|
+
module Inspec::Plugin::V2::PluginType
|
4
|
+
class Dsl < Inspec::Plugin::V2::PluginBase
|
5
|
+
register_plugin_type(:outer_profile_dsl)
|
6
|
+
register_plugin_type(:control_dsl)
|
7
|
+
register_plugin_type(:describe_dsl)
|
8
|
+
register_plugin_type(:test_dsl)
|
9
|
+
register_plugin_type(:resource_dsl)
|
10
|
+
end
|
11
|
+
end
|
@@ -67,6 +67,21 @@ module Inspec::Plugin::V2
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
+
def activate(plugin_type, hook_name)
|
71
|
+
activator = find_activators(plugin_type: plugin_type, activator_name: hook_name).first
|
72
|
+
# We want to capture literally any possible exception here, since we are storing them.
|
73
|
+
# rubocop: disable Lint/RescueException
|
74
|
+
begin
|
75
|
+
impl_class = activator.activation_proc.call
|
76
|
+
activator.activated?(true)
|
77
|
+
activator.implementation_class = impl_class
|
78
|
+
rescue Exception => ex
|
79
|
+
activator.exception = ex
|
80
|
+
Inspec::Log.error "Could not activate #{activator.plugin_type} hook named '#{activator.activator_name}' for plugin #{plugin_name}"
|
81
|
+
end
|
82
|
+
# rubocop: enable Lint/RescueException
|
83
|
+
end
|
84
|
+
|
70
85
|
def register(name, status)
|
71
86
|
if known_plugin? name
|
72
87
|
Inspec::Log.debug "PluginLoader: refusing to re-register plugin '#{name}': an existing plugin with that name was loaded via #{registry[name].installation_type}-loading from #{registry[name].entry_point}"
|
@@ -1,20 +1,84 @@
|
|
1
1
|
require 'inspec/attribute_registry'
|
2
|
-
require '
|
2
|
+
require 'inspec/plugin/v2'
|
3
3
|
require 'rspec/core/example_group'
|
4
4
|
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
# Any additions to RSpec::Core::ExampleGroup (the RSpec class behind describe blocks) should go here.
|
6
|
+
|
7
|
+
module Inspec
|
8
|
+
# This module exists to intercept the method_missing *class* method on RSpec::Core::ExampleGroup
|
9
|
+
# and is part of support for DSL plugintypes
|
10
|
+
module DescribeDslLazyLoader
|
11
|
+
# Support for Describe DSL plugins
|
12
|
+
def method_missing(method_name, *arguments, &block)
|
13
|
+
# Check to see if there is a describe_dsl plugin activator hook with the method name
|
14
|
+
registry = Inspec::Plugin::V2::Registry.instance
|
15
|
+
hook = registry.find_activators(plugin_type: :describe_dsl, activator_name: method_name).first
|
16
|
+
|
17
|
+
if hook
|
18
|
+
# OK, load the hook if it hasn't been already. We'll then know a module,
|
19
|
+
# which we can then inject into the context
|
20
|
+
registry.activate(:describe_dsl, method_name) unless hook.activated?
|
21
|
+
|
22
|
+
# Inject the module's methods into the example group contexts.
|
23
|
+
# implementation_class is the field name, but this is actually a module.
|
24
|
+
# RSpec works by having these helper methods defined as class methods
|
25
|
+
# (see the definition of `let` as an example)
|
26
|
+
# So, we use extend to inject the new DSL methods.
|
27
|
+
RSpec::Core::ExampleGroup.extend(hook.implementation_class)
|
28
|
+
|
29
|
+
# We still haven't called the method we were looking for, so do so now.
|
30
|
+
send(method_name, *arguments, &block)
|
31
|
+
else
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# This module exists to intercept the method_missing *instance* method on RSpec::Core::ExampleGroup
|
38
|
+
# and is part of support for DSL plugintypes
|
39
|
+
module TestDslLazyLoader
|
40
|
+
# Support for test DSL plugins
|
41
|
+
def method_missing(method_name, *arguments, &block)
|
42
|
+
# Check to see if there is a test_dsl plugin activator hook with the method name
|
43
|
+
registry = Inspec::Plugin::V2::Registry.instance
|
44
|
+
hook = registry.find_activators(plugin_type: :test_dsl, activator_name: method_name).first
|
45
|
+
|
46
|
+
if hook
|
47
|
+
# OK, load the hook if it hasn't been already. We'll then know a module,
|
48
|
+
# which we can then inject into the context
|
49
|
+
registry.activate(:test_dsl, method_name) unless hook.activated?
|
50
|
+
|
51
|
+
# Inject the module's methods into the example group contexts.
|
52
|
+
# implementation_class is the field name, but this is actually a module.
|
53
|
+
# RSpec works by having these helper methods defined as instance methods.
|
54
|
+
# So, we use include to inject the new DSL methods.
|
55
|
+
RSpec::Core::ExampleGroup.include(hook.implementation_class)
|
56
|
+
|
57
|
+
# We still haven't called the method we were looking for, so do so now.
|
58
|
+
send(method_name, *arguments, &block)
|
59
|
+
else
|
60
|
+
super
|
61
|
+
end
|
62
|
+
end
|
9
63
|
end
|
10
64
|
end
|
11
65
|
|
12
|
-
# This file allows you to add ExampleGroups to be used in rspec tests
|
13
|
-
#
|
14
66
|
class RSpec::Core::ExampleGroup
|
15
67
|
# This DSL method allows us to access the values of attributes within InSpec tests
|
16
68
|
def attribute(name)
|
17
69
|
Inspec::AttributeRegistry.find_attribute(name, self.class.metadata[:profile_id]).value
|
18
70
|
end
|
19
71
|
define_example_method :attribute
|
72
|
+
|
73
|
+
# Here, we have to ensure our method_missing gets called prior
|
74
|
+
# to RSpec::Core::ExampleGroup.method_missing (the class method).
|
75
|
+
# So, we use prepend.
|
76
|
+
# Because it is a class method we're attempting to prepend, we must
|
77
|
+
# prepend against the singleton class.
|
78
|
+
singleton_class.prepend Inspec::DescribeDslLazyLoader
|
79
|
+
|
80
|
+
# Here, we have to ensure our method_missing gets called prior
|
81
|
+
# to RSpec::Core::ExampleGroup#method_missing (the instance method).
|
82
|
+
# So, we use prepend.
|
83
|
+
prepend Inspec::TestDslLazyLoader
|
20
84
|
end
|
data/lib/inspec/version.rb
CHANGED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Example InSpec Profile For AWS
|
2
|
+
|
3
|
+
This example shows the implementation of an InSpec profile for AWS.
|
4
|
+
|
5
|
+
## Create a profile
|
6
|
+
|
7
|
+
```
|
8
|
+
$ inspec init profile --platform aws aws-security
|
9
|
+
Create new profile at /Users/liamcaproni/aws-security
|
10
|
+
* Create directory libraries
|
11
|
+
* Create file README.md
|
12
|
+
* Create directory controls
|
13
|
+
* Create file controls/example.rb
|
14
|
+
* Create file inspec.yml
|
15
|
+
* Create file attributes.yml
|
16
|
+
* Create file libraries/.gitkeep
|
17
|
+
|
18
|
+
```
|
19
|
+
|
20
|
+
## Update `attributes.yml` to point to your custom VPC
|
21
|
+
|
22
|
+
```
|
23
|
+
aws_vpc_id: 'custom-vpc-id'
|
24
|
+
```
|
25
|
+
|
26
|
+
## Run the tests
|
27
|
+
|
28
|
+
```
|
29
|
+
$ cd aws-profile/
|
30
|
+
$ inspec exec -t aws://eu-west-1/test-iam-profile --attrs attributes.yml aws-security
|
31
|
+
|
32
|
+
Profile: InSpec Profile (aws-security)
|
33
|
+
Version: 0.1.0
|
34
|
+
Target: aws://eu-west-2
|
35
|
+
|
36
|
+
✔ aws-vpc-check: Check to see if custom VPC exists.
|
37
|
+
✔ VPC vpc-0014dad216b7664e3 should exist
|
38
|
+
✔ aws-vpcs-check: Check in all the VPCs for default sg not allowing 22 inwards
|
39
|
+
✔ EC2 Security Group sg-05cd285a7499ee2bf should allow in {:port=>22}
|
40
|
+
✔ EC2 Security Group sg-0f0faf6d01eafc65d should allow in {:port=>22}
|
41
|
+
✔ EC2 Security Group sg-0cb134808cb42f188 should allow in {:port=>22}
|
42
|
+
✔ EC2 Security Group sg-06b2ae6dea43e32b6 should allow in {:port=>22}
|
43
|
+
✔ EC2 Security Group sg-0fc81264868480768 should allow in {:port=>22}
|
44
|
+
✔ EC2 Security Group sg-0cc3c94d414fdcd1b should allow in {:port=>22}
|
45
|
+
✔ EC2 Security Group sg-0abe7f61 should allow in {:port=>22}
|
46
|
+
✔ EC2 Security Group sg-0f346bed179f1e6ad should allow in {:port=>22}
|
47
|
+
✔ EC2 Security Group sg-0ff737c3be7a370ab should allow in {:port=>22}
|
48
|
+
✔ EC2 Security Group sg-0f37838285d37d035 should allow in {:port=>22}
|
49
|
+
✔ EC2 Security Group sg-001651d64991000f7 should allow in {:port=>22}
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
```
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# copyright: 2018, The Authors
|
3
|
+
|
4
|
+
title 'Sample Section'
|
5
|
+
|
6
|
+
aws_vpc_id = attribute('aws_vpc_id')
|
7
|
+
|
8
|
+
# you add controls here
|
9
|
+
control 'aws-vpc-check' do # A unique ID for this control.
|
10
|
+
impact 1.0 # The criticality, if this control fails.
|
11
|
+
title 'Check to see if custom VPC exists.' # A human-readable title
|
12
|
+
describe aws_vpc(aws_vpc_id) do # The test itself.
|
13
|
+
it { should exist }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Plural resources can be inspected to check for specific resource details.
|
18
|
+
control 'aws-vpcs-check' do
|
19
|
+
impact 1.0
|
20
|
+
title 'Check in all the VPCs for default sg not allowing 22 inwards'
|
21
|
+
aws_vpcs.vpc_ids.each do |vpc_id|
|
22
|
+
describe aws_security_group(vpc_id: vpc_id, group_name: 'default') do
|
23
|
+
it { should allow_in(port: 22) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
name: <%= name %>
|
2
|
+
title: AWS InSpec Profile
|
3
|
+
maintainer: The Authors
|
4
|
+
copyright: The Authors
|
5
|
+
copyright_email: you@example.com
|
6
|
+
license: Apache-2.0
|
7
|
+
summary: An InSpec Compliance Profile For AWS
|
8
|
+
version: 0.1.0
|
9
|
+
inspec_version: '>= 2.3.5'
|
10
|
+
attributes:
|
11
|
+
- name: aws_vpc_id
|
12
|
+
required: true
|
13
|
+
description: 'The Custom AWS VPC Id'
|
14
|
+
type: string
|
15
|
+
supports:
|
16
|
+
- platform: aws
|
File without changes
|
@@ -61,4 +61,16 @@ class InitCli < MiniTest::Test
|
|
61
61
|
assert_includes Dir.entries(profile).join, 'README.md'
|
62
62
|
end
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
|
+
def test_generating_inspec_profile_aws
|
66
|
+
Dir.mktmpdir do |dir|
|
67
|
+
profile = File.join(dir,'test-aws-profile')
|
68
|
+
out = run_inspec_process("init profile --platform aws test-aws-profile", prefix: "cd #{dir} &&")
|
69
|
+
assert_equal 0, out.exit_status
|
70
|
+
assert_includes out.stdout, 'Create new profile at'
|
71
|
+
assert_includes out.stdout, profile
|
72
|
+
assert_includes Dir.entries(profile).join, 'inspec.yml'
|
73
|
+
assert_includes Dir.entries(profile).join, 'README.md'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/resource_support/aws.rb
CHANGED
@@ -24,6 +24,7 @@ require 'resources/aws/aws_ebs_volumes'
|
|
24
24
|
require 'resources/aws/aws_flow_log'
|
25
25
|
require 'resources/aws/aws_ec2_instances'
|
26
26
|
require 'resources/aws/aws_ecs_cluster'
|
27
|
+
require 'resources/aws/aws_eks_cluster'
|
27
28
|
require 'resources/aws/aws_elb'
|
28
29
|
require 'resources/aws/aws_elbs'
|
29
30
|
require 'resources/aws/aws_iam_access_key'
|
@@ -0,0 +1,101 @@
|
|
1
|
+
class AwsEksCluster < Inspec.resource(1)
|
2
|
+
name 'aws_eks_cluster'
|
3
|
+
desc 'Verifies settings for an EKS cluster'
|
4
|
+
|
5
|
+
example <<-EOX
|
6
|
+
describe aws_eks_cluster('default') do
|
7
|
+
it { should exist }
|
8
|
+
end
|
9
|
+
EOX
|
10
|
+
supports platform: 'aws'
|
11
|
+
|
12
|
+
include AwsSingularResourceMixin
|
13
|
+
attr_reader :version, :arn, :cluster_name, :certificate_authority, :name,
|
14
|
+
:status, :endpoint, :subnets_count, :subnet_ids, :security_group_ids,
|
15
|
+
:created_at, :role_arn, :vpc_id, :security_groups_count, :creating,
|
16
|
+
:active, :failed, :deleting
|
17
|
+
# Use aliases for matchers
|
18
|
+
alias active? active
|
19
|
+
alias failed? failed
|
20
|
+
alias creating? creating
|
21
|
+
alias deleting? deleting
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
"AWS EKS cluster #{cluster_name}"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def validate_params(raw_params)
|
30
|
+
validated_params = check_resource_param_names(
|
31
|
+
raw_params: raw_params,
|
32
|
+
allowed_params: [:cluster_name],
|
33
|
+
allowed_scalar_name: :cluster_name,
|
34
|
+
allowed_scalar_type: String,
|
35
|
+
)
|
36
|
+
|
37
|
+
if validated_params.empty?
|
38
|
+
raise ArgumentError, 'You must provide a cluster_name to aws_eks_cluster.'
|
39
|
+
end
|
40
|
+
|
41
|
+
validated_params
|
42
|
+
end
|
43
|
+
|
44
|
+
def fetch_from_api # rubocop:disable Metrics/AbcSize
|
45
|
+
backend = BackendFactory.create(inspec_runner)
|
46
|
+
begin
|
47
|
+
params = { name: cluster_name }
|
48
|
+
resp = backend.describe_cluster(params)
|
49
|
+
rescue Aws::EKS::Errors::ResourceNotFoundException
|
50
|
+
@exists = false
|
51
|
+
populate_as_missing
|
52
|
+
return
|
53
|
+
end
|
54
|
+
@exists = true
|
55
|
+
cluster = resp.to_h[:cluster]
|
56
|
+
@version = cluster[:version]
|
57
|
+
@name = cluster[:name]
|
58
|
+
@arn = cluster[:arn]
|
59
|
+
@certificate_authority = cluster[:certificate_authority][:data]
|
60
|
+
@created_at = cluster[:created_at]
|
61
|
+
@endpoint = cluster[:endpoint]
|
62
|
+
@security_group_ids = cluster[:resources_vpc_config][:security_group_ids]
|
63
|
+
@subnet_ids = cluster[:resources_vpc_config][:subnet_ids]
|
64
|
+
@subnets_count = cluster[:resources_vpc_config][:subnet_ids].length
|
65
|
+
@security_groups_count = cluster[:resources_vpc_config][:security_group_ids].length
|
66
|
+
@vpc_id = cluster[:resources_vpc_config][:vpc_id]
|
67
|
+
@role_arn = cluster[:role_arn]
|
68
|
+
@status = cluster[:status]
|
69
|
+
@active = cluster[:status] == 'ACTIVE'
|
70
|
+
@failed = cluster[:status] == 'FAILED'
|
71
|
+
@creating = cluster[:status] == 'CREATING'
|
72
|
+
@deleting = cluster[:status] == 'DELETING'
|
73
|
+
end
|
74
|
+
|
75
|
+
def populate_as_missing
|
76
|
+
@version = nil
|
77
|
+
@name = cluster_name # name is an alias for cluster_name, and it is retained on a miss
|
78
|
+
@arn = nil
|
79
|
+
@certificate_authority = nil
|
80
|
+
@created_at = nil
|
81
|
+
@endpoint = nil
|
82
|
+
@security_group_ids = []
|
83
|
+
@subnet_ids = []
|
84
|
+
@subnets_count = nil
|
85
|
+
@security_groups_count = nil
|
86
|
+
@vpc_id = nil
|
87
|
+
@role_arn = nil
|
88
|
+
@status = nil
|
89
|
+
end
|
90
|
+
|
91
|
+
class Backend
|
92
|
+
class AwsClientApi < AwsBackendBase
|
93
|
+
BackendFactory.set_default_backend(self)
|
94
|
+
self.aws_client_class = Aws::EKS::Client
|
95
|
+
|
96
|
+
def describe_cluster(query = {})
|
97
|
+
aws_service_client.describe_cluster(query)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/resources/filesystem.rb
CHANGED
@@ -2,30 +2,103 @@ module Inspec::Resources
|
|
2
2
|
class FileSystemResource < Inspec.resource(1)
|
3
3
|
name 'filesystem'
|
4
4
|
supports platform: 'linux'
|
5
|
+
supports platform: 'windows'
|
5
6
|
desc 'Use the filesystem InSpec resource to test file system'
|
6
7
|
example "
|
7
8
|
describe filesystem('/') do
|
8
9
|
its('size') { should be >= 32000 }
|
10
|
+
its('type') { should eq false }
|
11
|
+
end
|
12
|
+
describe filesystem('c:') do
|
13
|
+
its('size') { should be >= 90 }
|
14
|
+
its('type') { should eq 'NTFS' }
|
9
15
|
end
|
10
16
|
"
|
11
17
|
attr_reader :partition
|
12
18
|
|
13
19
|
def initialize(partition)
|
14
20
|
@partition = partition
|
21
|
+
@cache = nil
|
22
|
+
# select file system manager
|
23
|
+
@fsman = nil
|
24
|
+
|
25
|
+
os = inspec.os
|
26
|
+
if os.linux?
|
27
|
+
@fsman = LinuxFileSystemResource.new(inspec)
|
28
|
+
elsif os.windows?
|
29
|
+
@fsman = WindowsFileSystemResource.new(inspec)
|
30
|
+
else
|
31
|
+
raise Inspec::Exceptions::ResourceSkipped, 'The `filesystem` resource is not supported on your OS yet.'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def info
|
36
|
+
return @cache if !@cache.nil?
|
37
|
+
return {} if @fsman.nil?
|
38
|
+
@cache = @fsman.info(@partition)
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
"FileSystem #{@partition}"
|
15
43
|
end
|
16
44
|
|
17
45
|
def size
|
18
|
-
|
19
|
-
|
20
|
-
|
46
|
+
info = @fsman.info(@partition)
|
47
|
+
info[:size]
|
48
|
+
end
|
21
49
|
|
22
|
-
|
23
|
-
|
24
|
-
|
50
|
+
def type
|
51
|
+
info = @fsman.info(@partition)
|
52
|
+
info[:type]
|
25
53
|
end
|
26
54
|
|
27
|
-
def
|
28
|
-
|
55
|
+
def name
|
56
|
+
info = @fsman.info(@partition)
|
57
|
+
info[:name]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class FsManagement
|
62
|
+
attr_reader :inspec
|
63
|
+
def initialize(inspec)
|
64
|
+
@inspec = inspec
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class LinuxFileSystemResource < FsManagement
|
69
|
+
def info(partition)
|
70
|
+
cmd = inspec.command("df #{partition} --output=size")
|
71
|
+
raise Inspec::Exceptions::ResourceFailed, "Unable to get available space for partition #{partition}" if cmd.stdout.nil? || cmd.stdout.empty? || !cmd.exit_status.zero?
|
72
|
+
value = cmd.stdout.gsub(/\dK-blocks[\r\n]/, '').strip
|
73
|
+
{
|
74
|
+
name: partition,
|
75
|
+
size: value.to_i,
|
76
|
+
type: false,
|
77
|
+
}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class WindowsFileSystemResource < FsManagement
|
82
|
+
def info(partition)
|
83
|
+
cmd = inspec.command <<-EOF.gsub(/^\s*/, '')
|
84
|
+
$disk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='#{partition}'"
|
85
|
+
$disk.Size = $disk.Size / 1GB
|
86
|
+
$disk | select -property DeviceID,Size,FileSystem | ConvertTo-Json
|
87
|
+
EOF
|
88
|
+
|
89
|
+
raise Inspec::Exceptions::ResourceSkipped, "Unable to get available space for partition #{partition}" if cmd.stdout == '' || cmd.exit_status.to_i != 0
|
90
|
+
begin
|
91
|
+
fs = JSON.parse(cmd.stdout)
|
92
|
+
rescue JSON::ParserError => e
|
93
|
+
raise Inspec::Exceptions::ResourceFailed,
|
94
|
+
'Failed to parse JSON from Powershell. ' \
|
95
|
+
"Error: #{e}"
|
96
|
+
end
|
97
|
+
{
|
98
|
+
name: fs['DeviceID'],
|
99
|
+
size: fs['Size'].to_i,
|
100
|
+
type: fs['FileSystem'],
|
101
|
+
}
|
29
102
|
end
|
30
103
|
end
|
31
104
|
end
|
data/lib/resources/package.rb
CHANGED
@@ -288,7 +288,7 @@ module Inspec::Resources
|
|
288
288
|
# Find the package
|
289
289
|
cmd = inspec.command <<-EOF.gsub(/^\s*/, '')
|
290
290
|
Get-ItemProperty (@("#{search_paths.join('", "')}") | Where-Object { Test-Path $_ }) |
|
291
|
-
Where-Object { $_.DisplayName -match "
|
291
|
+
Where-Object { $_.DisplayName -match "^\s*#{package_name.shellescape}\.*" -or $_.PSChildName -match "^\s*#{package_name.shellescape}\.*" } |
|
292
292
|
Select-Object -Property DisplayName,DisplayVersion | ConvertTo-Json
|
293
293
|
EOF
|
294
294
|
|
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: 3.0.
|
4
|
+
version: 3.0.61
|
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-11-
|
11
|
+
date: 2018-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: train
|
@@ -415,11 +415,13 @@ files:
|
|
415
415
|
- lib/inspec/plugin/v1/registry.rb
|
416
416
|
- lib/inspec/plugin/v2.rb
|
417
417
|
- lib/inspec/plugin/v2/activator.rb
|
418
|
+
- lib/inspec/plugin/v2/config_file.rb
|
418
419
|
- lib/inspec/plugin/v2/filter.rb
|
419
420
|
- lib/inspec/plugin/v2/installer.rb
|
420
421
|
- lib/inspec/plugin/v2/loader.rb
|
421
422
|
- lib/inspec/plugin/v2/plugin_base.rb
|
422
423
|
- lib/inspec/plugin/v2/plugin_types/cli.rb
|
424
|
+
- lib/inspec/plugin/v2/plugin_types/dsl.rb
|
423
425
|
- lib/inspec/plugin/v2/plugin_types/mock.rb
|
424
426
|
- lib/inspec/plugin/v2/registry.rb
|
425
427
|
- lib/inspec/plugin/v2/status.rb
|
@@ -480,6 +482,11 @@ files:
|
|
480
482
|
- lib/plugins/inspec-init/lib/inspec-init.rb
|
481
483
|
- lib/plugins/inspec-init/lib/inspec-init/cli.rb
|
482
484
|
- lib/plugins/inspec-init/lib/inspec-init/renderer.rb
|
485
|
+
- lib/plugins/inspec-init/lib/inspec-init/templates/profiles/aws/README.md
|
486
|
+
- lib/plugins/inspec-init/lib/inspec-init/templates/profiles/aws/attributes.yml
|
487
|
+
- lib/plugins/inspec-init/lib/inspec-init/templates/profiles/aws/controls/example.rb
|
488
|
+
- lib/plugins/inspec-init/lib/inspec-init/templates/profiles/aws/inspec.yml
|
489
|
+
- lib/plugins/inspec-init/lib/inspec-init/templates/profiles/aws/libraries/.gitkeep
|
483
490
|
- lib/plugins/inspec-init/lib/inspec-init/templates/profiles/gcp/README.md
|
484
491
|
- lib/plugins/inspec-init/lib/inspec-init/templates/profiles/gcp/attributes.yml
|
485
492
|
- lib/plugins/inspec-init/lib/inspec-init/templates/profiles/gcp/controls/example.rb
|
@@ -529,6 +536,7 @@ files:
|
|
529
536
|
- lib/resources/aws/aws_ec2_instance.rb
|
530
537
|
- lib/resources/aws/aws_ec2_instances.rb
|
531
538
|
- lib/resources/aws/aws_ecs_cluster.rb
|
539
|
+
- lib/resources/aws/aws_eks_cluster.rb
|
532
540
|
- lib/resources/aws/aws_elb.rb
|
533
541
|
- lib/resources/aws/aws_elbs.rb
|
534
542
|
- lib/resources/aws/aws_flow_log.rb
|