inspec 2.2.102 → 2.2.112
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/.rubocop.yml +1 -0
- data/CHANGELOG.md +25 -7
- data/Rakefile +8 -2
- data/docs/profiles.md +9 -0
- data/docs/resources/aws_security_group.md.erb +19 -2
- data/docs/resources/gem.md.erb +24 -5
- data/docs/resources/mssql_session.md.erb +8 -0
- data/lib/inspec/plugin/v2/loader.rb +33 -7
- data/lib/inspec/reporters/json_automate.rb +1 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/README.md +16 -0
- data/lib/plugins/inspec-artifact/lib/inspec-artifact.rb +12 -0
- data/lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb +162 -0
- data/lib/plugins/inspec-artifact/lib/inspec-artifact/cli.rb +114 -0
- data/lib/plugins/inspec-artifact/test/functional/inspec_artifact_test.rb +46 -0
- data/lib/plugins/inspec-habitat/lib/inspec-habitat.rb +11 -0
- data/lib/plugins/inspec-habitat/lib/inspec-habitat/cli.rb +39 -0
- data/lib/plugins/inspec-habitat/lib/inspec-habitat/profile.rb +394 -0
- data/lib/plugins/inspec-habitat/test/unit/profile_test.rb +184 -0
- data/lib/{bundles → plugins}/inspec-init/README.md +0 -0
- data/lib/plugins/inspec-init/lib/inspec-init.rb +12 -0
- data/lib/plugins/inspec-init/lib/inspec-init/cli.rb +28 -0
- data/lib/plugins/inspec-init/lib/inspec-init/renderer.rb +81 -0
- data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/README.md +0 -0
- data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/controls/example.rb +0 -0
- data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/inspec.yml +0 -0
- data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/libraries/.gitkeep +0 -0
- data/lib/plugins/inspec-init/test/functional/inspec_init_test.rb +30 -0
- data/lib/plugins/shared/core_plugin_test_helper.rb +50 -0
- data/lib/resources/aws/aws_security_group.rb +38 -6
- data/lib/resources/gem.rb +7 -1
- data/lib/resources/mssql_session.rb +4 -2
- metadata +21 -17
- data/lib/bundles/inspec-artifact.rb +0 -7
- data/lib/bundles/inspec-artifact/README.md +0 -1
- data/lib/bundles/inspec-artifact/cli.rb +0 -278
- data/lib/bundles/inspec-habitat.rb +0 -12
- data/lib/bundles/inspec-habitat/cli.rb +0 -37
- data/lib/bundles/inspec-habitat/log.rb +0 -10
- data/lib/bundles/inspec-habitat/profile.rb +0 -391
- data/lib/bundles/inspec-init.rb +0 -12
- data/lib/bundles/inspec-init/cli.rb +0 -39
- data/lib/bundles/inspec-init/renderer.rb +0 -79
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'mixlib/log'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'mocha/setup'
|
5
|
+
require_relative '../../lib/inspec-habitat/profile.rb'
|
6
|
+
|
7
|
+
describe InspecPlugins::Habitat::Profile do
|
8
|
+
let(:profile) do
|
9
|
+
OpenStruct.new(
|
10
|
+
name: 'my_profile',
|
11
|
+
version: '1.2.3',
|
12
|
+
files: %w(file1 file2)
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:subject) { InspecPlugins::Habitat::Profile.new('/path/to/profile', { 'log_level' => 'fatal' }) }
|
17
|
+
|
18
|
+
before do
|
19
|
+
Inspec::Log.level(:fatal)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#verify_profile' do
|
23
|
+
it 'exits if the profile is not valid' do
|
24
|
+
profile = mock
|
25
|
+
profile.stubs(:check).returns(summary: { valid: false })
|
26
|
+
subject.expects(:profile).returns(profile)
|
27
|
+
proc { subject.send(:verify_profile) }.must_raise SystemExit
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'does not exist if the profile is valid' do
|
31
|
+
profile = mock
|
32
|
+
profile.stubs(:check).returns(summary: { valid: true })
|
33
|
+
subject.expects(:profile).returns(profile)
|
34
|
+
subject.send(:verify_profile)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#vendor_profile_dependencies' do
|
39
|
+
let(:profile_vendor) do
|
40
|
+
profile_vendor = mock
|
41
|
+
profile_vendor.stubs(:lockfile).returns(lockfile)
|
42
|
+
profile_vendor.stubs(:cache_path).returns(cache_path)
|
43
|
+
profile_vendor
|
44
|
+
end
|
45
|
+
let(:lockfile) { mock }
|
46
|
+
let(:cache_path) { mock }
|
47
|
+
|
48
|
+
before do
|
49
|
+
Inspec::ProfileVendor.expects(:new).returns(profile_vendor)
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'when lockfile exists and cache dir exists' do
|
53
|
+
it 'does not vendor the dependencies' do
|
54
|
+
lockfile.expects(:exist?).returns(true)
|
55
|
+
cache_path.expects(:exist?).returns(true)
|
56
|
+
profile_vendor.expects(:vendor!).never
|
57
|
+
profile_vendor.expects(:make_readable).never
|
58
|
+
subject.send(:vendor_profile_dependencies)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'when the lockfile exists but the cache dir does not' do
|
63
|
+
it 'vendors the dependencies and refreshes the profile object' do
|
64
|
+
lockfile.expects(:exist?).returns(true)
|
65
|
+
cache_path.expects(:exist?).returns(false)
|
66
|
+
profile_vendor.expects(:vendor!)
|
67
|
+
profile_vendor.expects(:make_readable)
|
68
|
+
subject.expects(:create_profile_object)
|
69
|
+
|
70
|
+
subject.send(:vendor_profile_dependencies)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'when the lockfile does not exist' do
|
75
|
+
it 'vendors the dependencies and refreshes the profile object' do
|
76
|
+
lockfile.expects(:exist?).returns(false)
|
77
|
+
profile_vendor.expects(:vendor!)
|
78
|
+
profile_vendor.expects(:make_readable)
|
79
|
+
subject.expects(:create_profile_object)
|
80
|
+
|
81
|
+
subject.send(:vendor_profile_dependencies)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#validate_habitat_installed' do
|
87
|
+
it 'exits if hab --version fails' do
|
88
|
+
cmd = mock
|
89
|
+
cmd.stubs(:error?).returns(true)
|
90
|
+
cmd.stubs(:run_command)
|
91
|
+
cmd.stubs(:stdout)
|
92
|
+
cmd.stubs(:stderr)
|
93
|
+
Mixlib::ShellOut.expects(:new).with('hab --version').returns(cmd)
|
94
|
+
proc { subject.send(:validate_habitat_installed) }.must_raise SystemExit
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#validate_habitat_origin' do
|
99
|
+
it 'does not exit if the origin key exists' do
|
100
|
+
subject.expects(:habitat_origin).returns('12345')
|
101
|
+
subject.send(:validate_habitat_origin)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'exits if no origin key exists' do
|
105
|
+
subject.expects(:habitat_origin).returns(nil)
|
106
|
+
proc { subject.send(:validate_habitat_origin) }.must_raise SystemExit
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#validate_habitat_auth_token' do
|
111
|
+
it 'does not exit if the auth_token exists' do
|
112
|
+
subject.expects(:habitat_auth_token).returns('12345')
|
113
|
+
subject.send(:validate_habitat_auth_token)
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'exits if no auth_token exists' do
|
117
|
+
subject.expects(:habitat_auth_token).returns(nil)
|
118
|
+
proc { subject.send(:validate_habitat_auth_token) }.must_raise SystemExit
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '#build_hart' do
|
123
|
+
before do
|
124
|
+
subject.expects(:work_dir).at_least_once.returns(Dir.tmpdir)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'exits if the build fails' do
|
128
|
+
subject.expects(:system).returns(false)
|
129
|
+
proc { subject.send(:build_hart) }.must_raise SystemExit
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'exits if more than one hart is created' do
|
133
|
+
subject.expects(:system).returns(true)
|
134
|
+
Dir.expects(:glob).returns(%w(hart1 hart2))
|
135
|
+
proc { subject.send(:build_hart) }.must_raise SystemExit
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'exits if more than no hart is created' do
|
139
|
+
subject.expects(:system).returns(true)
|
140
|
+
Dir.expects(:glob).returns([])
|
141
|
+
proc { subject.send(:build_hart) }.must_raise SystemExit
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'returns the hart filename' do
|
145
|
+
subject.expects(:system).returns(true)
|
146
|
+
Dir.expects(:glob).returns(%w(hart1))
|
147
|
+
subject.send(:build_hart).must_equal('hart1')
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#upload_hart' do
|
152
|
+
it 'exits if the upload failed' do
|
153
|
+
env = {
|
154
|
+
'TERM' => 'vt100',
|
155
|
+
'HAB_AUTH_TOKEN' => 'my_token',
|
156
|
+
'HAB_NONINTERACTIVE' => 'true',
|
157
|
+
}
|
158
|
+
|
159
|
+
cmd = mock
|
160
|
+
cmd.stubs(:run_command)
|
161
|
+
cmd.stubs(:error?).returns(true)
|
162
|
+
cmd.stubs(:stdout)
|
163
|
+
cmd.stubs(:stderr)
|
164
|
+
|
165
|
+
subject.expects(:habitat_auth_token).returns('my_token')
|
166
|
+
Mixlib::ShellOut.expects(:new).with("hab pkg upload my_hart", env: env).returns(cmd)
|
167
|
+
proc { subject.send(:upload_hart, 'my_hart') }.must_raise SystemExit
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe '#habitat_cli_config' do
|
172
|
+
it 'returns an empty hash if the CLI config does not exist' do
|
173
|
+
File.expects(:exist?).with(File.join(ENV['HOME'], '.hab', 'etc', 'cli.toml')).returns(false)
|
174
|
+
subject.send(:habitat_cli_config).must_equal({})
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'returns parsed TOML from the hab config file' do
|
178
|
+
config_file = File.join(ENV['HOME'], '.hab', 'etc', 'cli.toml')
|
179
|
+
File.expects(:exist?).with(config_file).returns(true)
|
180
|
+
Tomlrb.expects(:load_file).with(config_file).returns(foo: 1)
|
181
|
+
subject.send(:habitat_cli_config).must_equal(foo: 1)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require_relative 'renderer'
|
5
|
+
|
6
|
+
module InspecPlugins
|
7
|
+
module Init
|
8
|
+
class CLI < Inspec.plugin(2, :cli_command)
|
9
|
+
subcommand_desc 'init SUBCOMMAND', 'Initialize InSpec objects'
|
10
|
+
|
11
|
+
# Look in the 'template' directory, and register a subcommand
|
12
|
+
# for each template directory found there.
|
13
|
+
template_dir = File.join(File.dirname(__FILE__), 'templates')
|
14
|
+
Dir.glob(File.join(template_dir, '*')) do |template|
|
15
|
+
template_name = Pathname.new(template).relative_path_from(Pathname.new(template_dir)).to_s
|
16
|
+
|
17
|
+
# register command for the template
|
18
|
+
desc "#{template_name} NAME", "Create a new #{template_name}"
|
19
|
+
option :overwrite, type: :boolean, default: false,
|
20
|
+
desc: 'Overwrites existing directory'
|
21
|
+
define_method template_name.to_sym do |name_for_new_structure|
|
22
|
+
renderer = InspecPlugins::Init::Renderer.new(self, options)
|
23
|
+
renderer.render_with_values(template_name, name: name_for_new_structure)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module InspecPlugins
|
5
|
+
module Init
|
6
|
+
class Renderer
|
7
|
+
# Creates a renderer able to render the given template type
|
8
|
+
# 1. iterate over all files
|
9
|
+
# 2. read content in erb
|
10
|
+
# 3. write to full_destination_root_path
|
11
|
+
|
12
|
+
attr_reader :overwrite_mode, :ui
|
13
|
+
def initialize(cli_ui, cli_options = {})
|
14
|
+
@ui = cli_ui
|
15
|
+
@overwrite_mode = cli_options['overwrite']
|
16
|
+
end
|
17
|
+
|
18
|
+
# rubocop: disable Metrics/AbcSize
|
19
|
+
def render_with_values(template_type, template_values = {})
|
20
|
+
# look for template directory
|
21
|
+
base_dir = File.join(File.dirname(__FILE__), 'templates', template_type)
|
22
|
+
# prepare glob for all subdirectories and files
|
23
|
+
template_glob = File.join(base_dir, '**', '{*,.*}')
|
24
|
+
# Use the name attribute to define the path to the profile.
|
25
|
+
profile_path = template_values[:name]
|
26
|
+
# Use slashes (\, /) to split up the name into an Array then use the last entry
|
27
|
+
# to reset the name of the profile.
|
28
|
+
template_values[:name] = template_values[:name].split(%r{\\|\/}).last
|
29
|
+
# Generate the full full_destination_root_path path on disk
|
30
|
+
full_destination_root_path = Pathname.new(Dir.pwd).join(profile_path)
|
31
|
+
ui.plain_text "Create new #{template_type} at #{ui.mark_text(full_destination_root_path)}"
|
32
|
+
|
33
|
+
# check that the directory does not exist
|
34
|
+
if File.exist?(full_destination_root_path) && !overwrite_mode
|
35
|
+
ui.plain_text "#{ui.mark_text(full_destination_root_path)} exists already, use --overwrite"
|
36
|
+
ui.exit(1)
|
37
|
+
end
|
38
|
+
|
39
|
+
# ensure that full_destination_root_path directory is available
|
40
|
+
FileUtils.mkdir_p(full_destination_root_path)
|
41
|
+
|
42
|
+
# iterate over files and write to full_destination_root_path
|
43
|
+
Dir.glob(template_glob) do |file|
|
44
|
+
relative_destination_item_path = Pathname.new(file).relative_path_from(Pathname.new(base_dir))
|
45
|
+
full_destination_item_path = Pathname.new(full_destination_root_path).join(relative_destination_item_path)
|
46
|
+
if File.directory?(file)
|
47
|
+
ui.li "Create directory #{ui.mark_text(relative_destination_item_path)}"
|
48
|
+
FileUtils.mkdir_p(full_destination_item_path)
|
49
|
+
elsif File.file?(file)
|
50
|
+
ui.li "Create file #{ui.mark_text(relative_destination_item_path)}"
|
51
|
+
# read & render content
|
52
|
+
content = render(File.read(file), template_values)
|
53
|
+
# write file content
|
54
|
+
File.write(full_destination_item_path, content)
|
55
|
+
else
|
56
|
+
ui.plain_text "Ignore #{file}, because its not an file or directoy"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
# rubocop: enable Metrics/AbcSize
|
61
|
+
|
62
|
+
# This is a render helper to bind hash values to a ERB template
|
63
|
+
# ERB provides result_with_hash in ruby 2.5.0+, which does exactly this
|
64
|
+
def render(template_content, hash)
|
65
|
+
# create a new binding class
|
66
|
+
cls = Class.new do
|
67
|
+
hash.each do |key, value|
|
68
|
+
define_method key.to_sym do
|
69
|
+
value
|
70
|
+
end
|
71
|
+
end
|
72
|
+
# expose binding
|
73
|
+
define_method :bind do
|
74
|
+
binding
|
75
|
+
end
|
76
|
+
end
|
77
|
+
ERB.new(template_content).result(cls.new.bind)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
File without changes
|
data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/controls/example.rb
RENAMED
File without changes
|
File without changes
|
data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/libraries/.gitkeep
RENAMED
File without changes
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative '../../../shared/core_plugin_test_helper.rb'
|
4
|
+
|
5
|
+
class InitCli < MiniTest::Test
|
6
|
+
include CorePluginFunctionalHelper
|
7
|
+
|
8
|
+
def test_generating_inspec_profile
|
9
|
+
Dir.mktmpdir do |dir|
|
10
|
+
profile = File.join(dir, 'test-profile')
|
11
|
+
out = run_inspec_process("init profile test-profile", prefix: "cd #{dir} &&")
|
12
|
+
assert_equal 0, out.exit_status
|
13
|
+
assert_includes out.stdout, 'Create new profile at'
|
14
|
+
assert_includes out.stdout, profile
|
15
|
+
assert_includes Dir.entries(profile).join, 'inspec.yml'
|
16
|
+
assert_includes Dir.entries(profile).join, 'README.md'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_profile_with_slash_name
|
21
|
+
Dir.mktmpdir do |dir|
|
22
|
+
profile = dir + '/test/deeper/profile'
|
23
|
+
out = run_inspec_process("init profile test/deeper/profile", prefix: "cd #{dir} &&")
|
24
|
+
assert_equal 0, out.exit_status
|
25
|
+
assert_equal true, File.exist?(profile)
|
26
|
+
profile = YAML.load_file("#{profile}/inspec.yml")
|
27
|
+
assert_equal 'profile', profile['name']
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
# Load test harness - MiniTest
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'minitest/unit'
|
5
|
+
require 'minitest/pride'
|
6
|
+
require 'minitest/spec'
|
7
|
+
|
8
|
+
# Data formats commonly used in testing
|
9
|
+
require 'json'
|
10
|
+
require 'ostruct'
|
11
|
+
|
12
|
+
# Utilities often needed
|
13
|
+
require 'fileutils'
|
14
|
+
|
15
|
+
# Configure MiniTest to expose things like `let`
|
16
|
+
class Module
|
17
|
+
include Minitest::Spec::DSL
|
18
|
+
end
|
19
|
+
|
20
|
+
module CorePluginBaseHelper
|
21
|
+
let(:repo_path) { File.expand_path(File.join(__FILE__, '..', '..', '..', '..')) }
|
22
|
+
let(:inspec_bin_path) { File.join(repo_path, 'bin', 'inspec') }
|
23
|
+
let(:core_mock_path) { File.join(repo_path, 'test', 'unit', 'mock') }
|
24
|
+
let(:core_fixture_plugins_path) { File.join(core_mock_path, 'plugins') }
|
25
|
+
let(:core_config_dir_path) { File.join(core_mock_path, 'config_dirs') }
|
26
|
+
|
27
|
+
let(:registry) { Inspec::Plugin::V2::Registry.instance }
|
28
|
+
end
|
29
|
+
|
30
|
+
module CorePluginFunctionalHelper
|
31
|
+
include CorePluginBaseHelper
|
32
|
+
|
33
|
+
require 'train'
|
34
|
+
TRAIN_CONNECTION = Train.create('local', command_runner: :generic).connection
|
35
|
+
|
36
|
+
def run_inspec_process(command_line, opts = {})
|
37
|
+
prefix = ''
|
38
|
+
if opts.key?(:prefix)
|
39
|
+
prefix = opts[:prefix]
|
40
|
+
elsif opts.key?(:env)
|
41
|
+
prefix = opts[:env].to_a.map { |assignment| "#{assignment[0]}=#{assignment[1]}" }.join(' ')
|
42
|
+
end
|
43
|
+
TRAIN_CONNECTION.run_command("#{prefix} #{inspec_bin_path} #{command_line}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module CorePluginUnitHelper
|
48
|
+
include CorePluginBaseHelper
|
49
|
+
require 'inspec'
|
50
|
+
end
|
@@ -12,7 +12,7 @@ class AwsSecurityGroup < Inspec.resource(1)
|
|
12
12
|
supports platform: 'aws'
|
13
13
|
|
14
14
|
include AwsSingularResourceMixin
|
15
|
-
attr_reader :description, :group_id, :group_name, :vpc_id, :inbound_rules, :outbound_rules
|
15
|
+
attr_reader :description, :group_id, :group_name, :vpc_id, :inbound_rules, :outbound_rules, :inbound_rules_count, :outbound_rules_count
|
16
16
|
|
17
17
|
def to_s
|
18
18
|
"EC2 Security Group #{@group_id}"
|
@@ -57,6 +57,7 @@ class AwsSecurityGroup < Inspec.resource(1)
|
|
57
57
|
matched &&= allow__match_port(rule, criteria)
|
58
58
|
matched &&= allow__match_protocol(rule, criteria)
|
59
59
|
matched &&= allow__match_ipv4_range(rule, criteria)
|
60
|
+
matched &&= allow__match_ipv6_range(rule, criteria)
|
60
61
|
matched
|
61
62
|
end
|
62
63
|
end
|
@@ -65,6 +66,7 @@ class AwsSecurityGroup < Inspec.resource(1)
|
|
65
66
|
allowed_criteria = [
|
66
67
|
:from_port,
|
67
68
|
:ipv4_range,
|
69
|
+
:ipv6_range,
|
68
70
|
:port,
|
69
71
|
:position,
|
70
72
|
:protocol,
|
@@ -149,11 +151,17 @@ class AwsSecurityGroup < Inspec.resource(1)
|
|
149
151
|
rule[:ip_protocol] == prot
|
150
152
|
end
|
151
153
|
|
152
|
-
def
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
154
|
+
def match_ipv4_or_6_range(rule, criteria)
|
155
|
+
if criteria.key?(:ipv4_range)
|
156
|
+
query = criteria[:ipv4_range]
|
157
|
+
query = [query] unless query.is_a?(Array)
|
158
|
+
ranges = rule[:ip_ranges].map { |rng| rng[:cidr_ip] }
|
159
|
+
else # IPv6
|
160
|
+
query = criteria[:ipv6_range]
|
161
|
+
query = [query] unless query.is_a?(Array)
|
162
|
+
ranges = rule[:ipv_6_ranges].map { |rng| rng[:cidr_ipv_6] }
|
163
|
+
end
|
164
|
+
|
157
165
|
if criteria[:exact]
|
158
166
|
Set.new(query) == Set.new(ranges)
|
159
167
|
else
|
@@ -169,6 +177,16 @@ class AwsSecurityGroup < Inspec.resource(1)
|
|
169
177
|
end
|
170
178
|
end
|
171
179
|
|
180
|
+
def allow__match_ipv4_range(rule, criteria)
|
181
|
+
return true unless criteria.key?(:ipv4_range)
|
182
|
+
match_ipv4_or_6_range(rule, criteria)
|
183
|
+
end
|
184
|
+
|
185
|
+
def allow__match_ipv6_range(rule, criteria)
|
186
|
+
return true unless criteria.key?(:ipv6_range)
|
187
|
+
match_ipv4_or_6_range(rule, criteria)
|
188
|
+
end
|
189
|
+
|
172
190
|
def validate_params(raw_params)
|
173
191
|
recognized_params = check_resource_param_names(
|
174
192
|
raw_params: raw_params,
|
@@ -196,6 +214,18 @@ class AwsSecurityGroup < Inspec.resource(1)
|
|
196
214
|
validated_params
|
197
215
|
end
|
198
216
|
|
217
|
+
def count_sg_rules(ip_permissions)
|
218
|
+
rule_count = 0
|
219
|
+
ip_permissions.each do |ip_permission|
|
220
|
+
[:ip_ranges, :ipv_6_ranges, :user_id_group_pairs].each do |key|
|
221
|
+
if ip_permission.key? key
|
222
|
+
rule_count += ip_permission[key].length
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
rule_count
|
227
|
+
end
|
228
|
+
|
199
229
|
def fetch_from_api # rubocop: disable Metrics/AbcSize
|
200
230
|
backend = BackendFactory.create(inspec_runner)
|
201
231
|
|
@@ -233,7 +263,9 @@ class AwsSecurityGroup < Inspec.resource(1)
|
|
233
263
|
@group_name = dsg_response.security_groups[0].group_name
|
234
264
|
@vpc_id = dsg_response.security_groups[0].vpc_id
|
235
265
|
@inbound_rules = dsg_response.security_groups[0].ip_permissions.map(&:to_h)
|
266
|
+
@inbound_rules_count = count_sg_rules(dsg_response.security_groups[0].ip_permissions.map(&:to_h))
|
236
267
|
@outbound_rules = dsg_response.security_groups[0].ip_permissions_egress.map(&:to_h)
|
268
|
+
@outbound_rules_count = count_sg_rules(dsg_response.security_groups[0].ip_permissions_egress.map(&:to_h))
|
237
269
|
end
|
238
270
|
|
239
271
|
class Backend
|