inspec-core 2.2.112 → 2.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -19
- data/README.md +1 -1
- data/docs/dev/integration-testing.md +31 -0
- data/docs/dev/plugins.md +4 -2
- data/docs/dsl_inspec.md +104 -4
- data/docs/plugins.md +57 -0
- data/docs/style.md +178 -0
- data/examples/plugins/inspec-resource-lister/Gemfile +12 -0
- data/examples/plugins/inspec-resource-lister/LICENSE +13 -0
- data/examples/plugins/inspec-resource-lister/README.md +62 -0
- data/examples/plugins/inspec-resource-lister/Rakefile +40 -0
- data/examples/plugins/inspec-resource-lister/inspec-resource-lister.gemspec +45 -0
- data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister.rb +16 -0
- data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/cli_command.rb +70 -0
- data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/plugin.rb +55 -0
- data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/version.rb +10 -0
- data/examples/plugins/inspec-resource-lister/test/fixtures/README.md +24 -0
- data/examples/plugins/inspec-resource-lister/test/functional/README.md +18 -0
- data/examples/plugins/inspec-resource-lister/test/functional/inspec_resource_lister_test.rb +110 -0
- data/examples/plugins/inspec-resource-lister/test/helper.rb +26 -0
- data/examples/plugins/inspec-resource-lister/test/unit/README.md +17 -0
- data/examples/plugins/inspec-resource-lister/test/unit/cli_args_test.rb +64 -0
- data/examples/plugins/inspec-resource-lister/test/unit/plugin_def_test.rb +51 -0
- data/examples/profile/controls/example.rb +9 -8
- data/inspec-core.gemspec +1 -1
- data/lib/inspec/attribute_registry.rb +1 -1
- data/lib/inspec/globals.rb +4 -0
- data/lib/inspec/objects/control.rb +18 -3
- data/lib/inspec/plugin/v2.rb +14 -3
- data/lib/inspec/plugin/v2/activator.rb +7 -2
- data/lib/inspec/plugin/v2/installer.rb +426 -0
- data/lib/inspec/plugin/v2/loader.rb +137 -30
- data/lib/inspec/plugin/v2/registry.rb +13 -4
- data/lib/inspec/profile.rb +2 -1
- data/lib/inspec/reporters/json.rb +11 -1
- data/lib/inspec/resource.rb +6 -15
- data/lib/inspec/rule.rb +18 -9
- data/lib/inspec/runner_rspec.rb +1 -1
- data/lib/inspec/schema.rb +1 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/inspec-plugin-manager-cli/README.md +6 -0
- data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli.rb +18 -0
- data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +420 -0
- data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/plugin.rb +12 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/config_dirs/empty/.gitkeep +0 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/inspec-egg-white-omelette/lib/inspec-egg-white-omelette.rb +2 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/inspec-egg-white-omelette/lib/inspec-egg-white-omelette/.gitkeep +0 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/inspec-wrong-structure/.gitkeep +0 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/wrong-name/lib/wrong-name.rb +1 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/wrong-name/lib/wrong-name/.gitkeep +0 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/functional/inspec-plugin_test.rb +651 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/unit/cli_args_test.rb +71 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/unit/plugin_def_test.rb +20 -0
- data/lib/plugins/shared/core_plugin_test_helper.rb +101 -2
- data/lib/plugins/things-for-train-integration.rb +14 -0
- data/lib/resources/port.rb +10 -6
- metadata +38 -11
- data/docs/ruby_usage.md +0 -204
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative '../../../shared/core_plugin_test_helper.rb'
|
2
|
+
|
3
|
+
#-----------------------------------------------------------------------#
|
4
|
+
# Thor option defs
|
5
|
+
#-----------------------------------------------------------------------#
|
6
|
+
class PluginManagerCliOptions < MiniTest::Test
|
7
|
+
include CorePluginUnitHelper
|
8
|
+
let(:cli_class) { InspecPlugins::PluginManager::CliCommand }
|
9
|
+
|
10
|
+
def setup
|
11
|
+
require_relative '../../lib/inspec-plugin-manager-cli/cli_command'
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_list_args
|
15
|
+
arg_config = cli_class.all_commands['list'].options
|
16
|
+
assert_equal 1, arg_config.count, 'The list command should have 1 option'
|
17
|
+
|
18
|
+
assert_includes arg_config.keys, :all, 'The list command should have an --all option'
|
19
|
+
assert_equal :boolean, arg_config[:all].type, 'The --all option should be boolean'
|
20
|
+
assert_equal :a, arg_config[:all].aliases.first, 'The --all option should be aliased as -a'
|
21
|
+
refute_nil arg_config[:all].description, 'The --all option should have a description'
|
22
|
+
refute arg_config[:all].required, 'The --all option should not be required'
|
23
|
+
|
24
|
+
assert_equal 0, cli_class.instance_method(:list).arity, 'The list command should take no arguments'
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_search_args
|
28
|
+
arg_config = cli_class.all_commands['search'].options
|
29
|
+
assert_equal 2, arg_config.count, 'The search command should have 2 options'
|
30
|
+
|
31
|
+
assert_includes arg_config.keys, :all, 'The search command should have an --all option'
|
32
|
+
assert_equal :boolean, arg_config[:all].type, 'The --all option should be boolean'
|
33
|
+
assert_equal :a, arg_config[:all].aliases.first, 'The --all option should be aliased as -a'
|
34
|
+
refute_nil arg_config[:all].description, 'The --all option should have a description'
|
35
|
+
refute arg_config[:all].required, 'The --all option should not be required'
|
36
|
+
|
37
|
+
assert_includes arg_config.keys, :exact, 'The search command should have an --exact option'
|
38
|
+
assert_equal :boolean, arg_config[:exact].type, 'The --exact option should be boolean'
|
39
|
+
assert_equal :e, arg_config[:exact].aliases.first, 'The --exact option should be aliased as -e'
|
40
|
+
refute_nil arg_config[:exact].description, 'The --exact option should have a description'
|
41
|
+
refute arg_config[:exact].required, 'The --exact option should not be required'
|
42
|
+
|
43
|
+
assert_equal 1, cli_class.instance_method(:search).arity, 'The search command should take one argument'
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_install_args
|
47
|
+
arg_config = cli_class.all_commands['install'].options
|
48
|
+
assert_equal 1, arg_config.count, 'The install command should have 1 option'
|
49
|
+
|
50
|
+
assert_includes arg_config.keys, :version, 'The install command should have a --version option'
|
51
|
+
assert_equal :string, arg_config[:version].type, 'The --version option should be a string'
|
52
|
+
assert_equal :v, arg_config[:version].aliases.first, 'The --version option should be aliased as -v'
|
53
|
+
refute_nil arg_config[:version].description, 'The --version option should have a description'
|
54
|
+
refute arg_config[:version].required, 'The --version option should not be required'
|
55
|
+
|
56
|
+
assert_equal 1, cli_class.instance_method(:install).arity, 'The install command should take one argument'
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_update_args
|
60
|
+
# TODO: allow specifying version
|
61
|
+
arg_config = cli_class.all_commands['update'].options
|
62
|
+
assert_equal 0, arg_config.count, 'The update command should have no options'
|
63
|
+
assert_equal 1, cli_class.instance_method(:update).arity, 'The update command should take one argument'
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_uninstall_args
|
67
|
+
arg_config = cli_class.all_commands['uninstall'].options
|
68
|
+
assert_equal 0, arg_config.count, 'The uninstall command should have no options'
|
69
|
+
assert_equal 1, cli_class.instance_method(:uninstall).arity, 'The uninstall command should take one argument'
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative '../../../shared/core_plugin_test_helper.rb'
|
2
|
+
|
3
|
+
#-----------------------------------------------------------------------#
|
4
|
+
# Plugin Definition
|
5
|
+
#-----------------------------------------------------------------------#
|
6
|
+
class PluginManagerCliDefinitionTests < MiniTest::Test
|
7
|
+
include CorePluginUnitHelper
|
8
|
+
|
9
|
+
def test_plugin_registered
|
10
|
+
loader = Inspec::Plugin::V2::Loader.new
|
11
|
+
loader.load_all # We want to ensure it is auto-loaded
|
12
|
+
|
13
|
+
assert registry.known_plugin?(:'inspec-plugin-manager-cli'), 'inspec-plugin-manager-cli should be registered'
|
14
|
+
assert registry.loaded_plugin?(:'inspec-plugin-manager-cli'), 'inspec-plugin-manager-cli should be loaded'
|
15
|
+
|
16
|
+
status = registry[:'inspec-plugin-manager-cli']
|
17
|
+
assert_equal 2, status.api_generation, 'inspec-plugin-manager-cli should be v2'
|
18
|
+
assert_includes status.plugin_types, :cli_command, 'inspec-plugin-manager-cli should have cli_command activators'
|
19
|
+
end
|
20
|
+
end
|
@@ -11,12 +11,32 @@ require 'ostruct'
|
|
11
11
|
|
12
12
|
# Utilities often needed
|
13
13
|
require 'fileutils'
|
14
|
+
require 'tmpdir'
|
15
|
+
require 'pathname'
|
16
|
+
require 'forwardable'
|
14
17
|
|
15
18
|
# Configure MiniTest to expose things like `let`
|
16
19
|
class Module
|
17
20
|
include Minitest::Spec::DSL
|
18
21
|
end
|
19
22
|
|
23
|
+
module Inspec
|
24
|
+
class FuncTestRunResult
|
25
|
+
attr_reader :train_result
|
26
|
+
attr_reader :payload
|
27
|
+
|
28
|
+
extend Forwardable
|
29
|
+
def_delegator :train_result, :stdout
|
30
|
+
def_delegator :train_result, :stderr
|
31
|
+
def_delegator :train_result, :exit_status
|
32
|
+
|
33
|
+
def initialize(train_result)
|
34
|
+
@train_result = train_result
|
35
|
+
@payload = OpenStruct.new
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
20
40
|
module CorePluginBaseHelper
|
21
41
|
let(:repo_path) { File.expand_path(File.join(__FILE__, '..', '..', '..', '..')) }
|
22
42
|
let(:inspec_bin_path) { File.join(repo_path, 'bin', 'inspec') }
|
@@ -40,11 +60,90 @@ module CorePluginFunctionalHelper
|
|
40
60
|
elsif opts.key?(:env)
|
41
61
|
prefix = opts[:env].to_a.map { |assignment| "#{assignment[0]}=#{assignment[1]}" }.join(' ')
|
42
62
|
end
|
43
|
-
TRAIN_CONNECTION.run_command("#{prefix} #{inspec_bin_path} #{command_line}")
|
63
|
+
Inspec::FuncTestRunResult.new(TRAIN_CONNECTION.run_command("#{prefix} #{inspec_bin_path} #{command_line}"))
|
64
|
+
end
|
65
|
+
|
66
|
+
# This helper does some fancy footwork to make InSpec think a plugin
|
67
|
+
# under development is temporarily installed.
|
68
|
+
# @param String command_line Invocation, without the word 'inspec'
|
69
|
+
# @param Hash opts options as for run_inspec_process, with more options:
|
70
|
+
# :pre_run: Proc(plugin_statefile_data, tmp_dir_path) - optional setup block.
|
71
|
+
# Modify plugin_statefile_data as needed; it will be written to a plugins.json
|
72
|
+
# in tmp_dir_path. You may also copy in other things to the tmp_dir_path. Your PWD
|
73
|
+
# will be in the tmp_dir, and it will exist and be empty.
|
74
|
+
# :post_run: Proc(FuncTestRunResult, tmp_dir_path) - optional result capture block.
|
75
|
+
# run_result will be populated, but you can add more to the ostruct .payload
|
76
|
+
# Your PWD will be the tmp_dir, and it will still exist (for a moment!)
|
77
|
+
def run_inspec_process_with_this_plugin(command_line, opts = {})
|
78
|
+
plugin_path = __find_plugin_path_from_caller
|
79
|
+
|
80
|
+
# If it looks like it is a core plugin under test, don't add it to the plugin file
|
81
|
+
# since the loader will auto-load it anyway
|
82
|
+
if plugin_path.include?('lib/plugins/inspec-')
|
83
|
+
plugin_file_data = __make_empty_plugin_file_data_structure
|
84
|
+
else
|
85
|
+
plugin_file_data = __make_plugin_file_data_structure_with_path(plugin_path)
|
86
|
+
end
|
87
|
+
|
88
|
+
Dir.mktmpdir do |tmp_dir|
|
89
|
+
opts[:pre_run]&.call(plugin_file_data, tmp_dir)
|
90
|
+
plugin_file_path = File.join(tmp_dir, 'plugins.json')
|
91
|
+
# HACK: If the block cleared the hash, take that to mean it will provide a plugins.json file of its own.
|
92
|
+
File.write(plugin_file_path, JSON.generate(plugin_file_data)) unless plugin_file_data.empty?
|
93
|
+
opts[:env] ||= {}
|
94
|
+
opts[:env]['INSPEC_CONFIG_DIR'] = tmp_dir
|
95
|
+
run_result = run_inspec_process(command_line, opts)
|
96
|
+
|
97
|
+
# Read the resulting plugins.json into memory, if any
|
98
|
+
if File.exist?(plugin_file_path)
|
99
|
+
run_result.payload.plugin_data = JSON.parse(File.read(plugin_file_path))
|
100
|
+
end
|
101
|
+
|
102
|
+
opts[:post_run]&.call(run_result, tmp_dir)
|
103
|
+
run_result
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def __find_plugin_path_from_caller(frames_back = 2)
|
108
|
+
caller_path = Pathname.new(caller_locations(frames_back, 1).first.absolute_path)
|
109
|
+
# Typical caller path:
|
110
|
+
# /Users/cwolfe/sandbox/inspec-resource-lister/test/functional/inspec_resource_lister_test.rb
|
111
|
+
# We want:
|
112
|
+
# /Users/cwolfe/sandbox/inspec-resource-lister/lib/inspec-resource-lister.rb
|
113
|
+
cursor = caller_path
|
114
|
+
until cursor.basename.to_s == 'test' && cursor.parent.basename.to_s =~ /^(inspec|train)-/
|
115
|
+
cursor = cursor.parent
|
116
|
+
break if cursor.nil?
|
117
|
+
end
|
118
|
+
raise 'Could not comprehend plugin project directory structure' if cursor.nil?
|
119
|
+
|
120
|
+
project_dir = cursor.parent
|
121
|
+
plugin_name = project_dir.basename
|
122
|
+
entry_point = File.join(project_dir.to_s, 'lib', plugin_name.to_s + '.rb')
|
123
|
+
raise 'Could not find plugin entry point' unless File.exist?(entry_point)
|
124
|
+
entry_point
|
125
|
+
end
|
126
|
+
|
127
|
+
def __make_plugin_file_data_structure_with_path(path)
|
128
|
+
# TODO: dry this up, refs #3350
|
129
|
+
plugin_name = File.basename(path, '.rb')
|
130
|
+
data = __make_empty_plugin_file_data_structure
|
131
|
+
data['plugins'] << {
|
132
|
+
'name' => plugin_name,
|
133
|
+
'installation_type' => 'path',
|
134
|
+
'installation_path' => path,
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
def __make_empty_plugin_file_data_structure
|
139
|
+
# TODO: dry this up, refs #3350
|
140
|
+
{
|
141
|
+
'plugins_config_version' => '1.0.0',
|
142
|
+
'plugins' => [],
|
143
|
+
}
|
44
144
|
end
|
45
145
|
end
|
46
146
|
|
47
147
|
module CorePluginUnitHelper
|
48
148
|
include CorePluginBaseHelper
|
49
|
-
require 'inspec'
|
50
149
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# docs/plugins
|
2
|
+
# Update that train plugins are now possible
|
3
|
+
|
4
|
+
# test/unit/plugin/v2/loader_test.rb
|
5
|
+
# TODO: loading all plugins does not activate Train plugins
|
6
|
+
|
7
|
+
# lib/plugins/inspec-plugin-manager-cli/test/functional/inspec-plugin_test.rb
|
8
|
+
# ~ Should be able to install a train plugin - in place, will fail until plugin published
|
9
|
+
# ~ Should be able to search for a train plugin - in place, will fail until plugin published
|
10
|
+
|
11
|
+
# test/functional/plugins_test.rb
|
12
|
+
# % Should be able to suggest a train transport plugin when an unsupported --target schema is used and a gem search is successful
|
13
|
+
# % Should be able to suggest a train transport plugin when an unrecognized profile platform declaration is used and a gem search is successful
|
14
|
+
# - Should be able to run inspec detect targeting a test target
|
data/lib/resources/port.rb
CHANGED
@@ -473,22 +473,26 @@ module Inspec::Resources
|
|
473
473
|
|
474
474
|
def parse_netstat_line(line)
|
475
475
|
# parse each line
|
476
|
-
# 1 - Proto, 2 - Recv-Q, 3 - Send-Q, 4 - Local Address, 5 - Foreign Address, 6 - State, 7 -
|
477
|
-
|
476
|
+
# 1 - Proto, 2 - Recv-Q, 3 - Send-Q, 4 - Local Address, 5 - Foreign Address, 6 - State, 7 - User, 8 - Inode, 9 - PID/Program name
|
477
|
+
# * UDP lines have an empty State column and the Busybox variant lacks
|
478
|
+
# the User and Inode columns.
|
479
|
+
reg = /^(?<proto>\S+)\s+(\S+)\s+(\S+)\s+(?<local_addr>\S+)\s+(?<foreign_addr>\S+)\s+(\S+)?\s+((\S+)\s+(\S+)\s+)?(?<pid_prog>\S+)/
|
480
|
+
parsed = reg.match(line)
|
481
|
+
|
478
482
|
return {} if parsed.nil? || line.match(/^proto/i)
|
479
483
|
|
480
484
|
# parse ip4 and ip6 addresses
|
481
|
-
protocol = parsed[
|
485
|
+
protocol = parsed[:proto].downcase
|
482
486
|
|
483
487
|
# detect protocol if not provided
|
484
|
-
protocol += '6' if parsed[
|
488
|
+
protocol += '6' if parsed[:local_addr].count(':') > 1 && %w{tcp udp}.include?(protocol)
|
485
489
|
|
486
490
|
# extract host and port information
|
487
|
-
host, port = parse_net_address(parsed[
|
491
|
+
host, port = parse_net_address(parsed[:local_addr], protocol)
|
488
492
|
return {} if host.nil?
|
489
493
|
|
490
494
|
# extract PID
|
491
|
-
process = parsed[
|
495
|
+
process = parsed[:pid_prog].split('/')
|
492
496
|
pid = process[0]
|
493
497
|
pid = pid.to_i if pid =~ /^\d+$/
|
494
498
|
process = process[1]
|
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: 2.
|
4
|
+
version: 2.3.4
|
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-09-
|
11
|
+
date: 2018-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: train-core
|
@@ -16,20 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 1.4.37
|
19
|
+
version: '1.5'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: '1.
|
30
|
-
- - ">="
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 1.4.37
|
26
|
+
version: '1.5'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: thor
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -308,6 +302,7 @@ files:
|
|
308
302
|
- docs/dev/control-eval.md
|
309
303
|
- docs/dev/filtertable-internals.md
|
310
304
|
- docs/dev/filtertable-usage.md
|
305
|
+
- docs/dev/integration-testing.md
|
311
306
|
- docs/dev/plugins.md
|
312
307
|
- docs/dsl_inspec.md
|
313
308
|
- docs/dsl_resource.md
|
@@ -318,6 +313,7 @@ files:
|
|
318
313
|
- docs/migration.md
|
319
314
|
- docs/platforms.md
|
320
315
|
- docs/plugin_kitchen_inspec.md
|
316
|
+
- docs/plugins.md
|
321
317
|
- docs/profiles.md
|
322
318
|
- docs/reporters.md
|
323
319
|
- docs/resources/aide_conf.md.erb
|
@@ -424,13 +420,13 @@ files:
|
|
424
420
|
- docs/resources/yum.md.erb
|
425
421
|
- docs/resources/zfs_dataset.md.erb
|
426
422
|
- docs/resources/zfs_pool.md.erb
|
427
|
-
- docs/ruby_usage.md
|
428
423
|
- docs/shared/matcher_be.md.erb
|
429
424
|
- docs/shared/matcher_cmp.md.erb
|
430
425
|
- docs/shared/matcher_eq.md.erb
|
431
426
|
- docs/shared/matcher_include.md.erb
|
432
427
|
- docs/shared/matcher_match.md.erb
|
433
428
|
- docs/shell.md
|
429
|
+
- docs/style.md
|
434
430
|
- examples/README.md
|
435
431
|
- examples/custom-resource/README.md
|
436
432
|
- examples/custom-resource/controls/example.rb
|
@@ -466,6 +462,22 @@ files:
|
|
466
462
|
- examples/meta-profile/README.md
|
467
463
|
- examples/meta-profile/controls/example.rb
|
468
464
|
- examples/meta-profile/inspec.yml
|
465
|
+
- examples/plugins/inspec-resource-lister/Gemfile
|
466
|
+
- examples/plugins/inspec-resource-lister/LICENSE
|
467
|
+
- examples/plugins/inspec-resource-lister/README.md
|
468
|
+
- examples/plugins/inspec-resource-lister/Rakefile
|
469
|
+
- examples/plugins/inspec-resource-lister/inspec-resource-lister.gemspec
|
470
|
+
- examples/plugins/inspec-resource-lister/lib/inspec-resource-lister.rb
|
471
|
+
- examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/cli_command.rb
|
472
|
+
- examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/plugin.rb
|
473
|
+
- examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/version.rb
|
474
|
+
- examples/plugins/inspec-resource-lister/test/fixtures/README.md
|
475
|
+
- examples/plugins/inspec-resource-lister/test/functional/README.md
|
476
|
+
- examples/plugins/inspec-resource-lister/test/functional/inspec_resource_lister_test.rb
|
477
|
+
- examples/plugins/inspec-resource-lister/test/helper.rb
|
478
|
+
- examples/plugins/inspec-resource-lister/test/unit/README.md
|
479
|
+
- examples/plugins/inspec-resource-lister/test/unit/cli_args_test.rb
|
480
|
+
- examples/plugins/inspec-resource-lister/test/unit/plugin_def_test.rb
|
469
481
|
- examples/profile-attribute.yml
|
470
482
|
- examples/profile-attribute/README.md
|
471
483
|
- examples/profile-attribute/controls/example.rb
|
@@ -561,6 +573,7 @@ files:
|
|
561
573
|
- lib/inspec/plugin/v1/registry.rb
|
562
574
|
- lib/inspec/plugin/v2.rb
|
563
575
|
- lib/inspec/plugin/v2/activator.rb
|
576
|
+
- lib/inspec/plugin/v2/installer.rb
|
564
577
|
- lib/inspec/plugin/v2/loader.rb
|
565
578
|
- lib/inspec/plugin/v2/plugin_base.rb
|
566
579
|
- lib/inspec/plugin/v2/plugin_types/cli.rb
|
@@ -614,7 +627,21 @@ files:
|
|
614
627
|
- lib/plugins/inspec-init/lib/inspec-init/templates/profile/inspec.yml
|
615
628
|
- lib/plugins/inspec-init/lib/inspec-init/templates/profile/libraries/.gitkeep
|
616
629
|
- lib/plugins/inspec-init/test/functional/inspec_init_test.rb
|
630
|
+
- lib/plugins/inspec-plugin-manager-cli/README.md
|
631
|
+
- lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli.rb
|
632
|
+
- lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb
|
633
|
+
- lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/plugin.rb
|
634
|
+
- lib/plugins/inspec-plugin-manager-cli/test/fixtures/config_dirs/empty/.gitkeep
|
635
|
+
- lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/inspec-egg-white-omelette/lib/inspec-egg-white-omelette.rb
|
636
|
+
- lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/inspec-egg-white-omelette/lib/inspec-egg-white-omelette/.gitkeep
|
637
|
+
- lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/inspec-wrong-structure/.gitkeep
|
638
|
+
- lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/wrong-name/lib/wrong-name.rb
|
639
|
+
- lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/wrong-name/lib/wrong-name/.gitkeep
|
640
|
+
- lib/plugins/inspec-plugin-manager-cli/test/functional/inspec-plugin_test.rb
|
641
|
+
- lib/plugins/inspec-plugin-manager-cli/test/unit/cli_args_test.rb
|
642
|
+
- lib/plugins/inspec-plugin-manager-cli/test/unit/plugin_def_test.rb
|
617
643
|
- lib/plugins/shared/core_plugin_test_helper.rb
|
644
|
+
- lib/plugins/things-for-train-integration.rb
|
618
645
|
- lib/resources/aide_conf.rb
|
619
646
|
- lib/resources/apache.rb
|
620
647
|
- lib/resources/apache_conf.rb
|
data/docs/ruby_usage.md
DELETED
@@ -1,204 +0,0 @@
|
|
1
|
-
# Using Ruby in InSpec
|
2
|
-
|
3
|
-
The InSpec DSL is a Ruby based DSL for writing audit controls, which
|
4
|
-
includes audit resources that you can invoke. Core and custom resources
|
5
|
-
are written as regular Ruby classes which inherit from
|
6
|
-
`Inspec.resource`.
|
7
|
-
|
8
|
-
Assuming we have a JSON file like this on the node to be tested:
|
9
|
-
|
10
|
-
```json
|
11
|
-
{
|
12
|
-
"keys":[
|
13
|
-
{"username":"john", "key":"/opt/keys/johnd.key"},
|
14
|
-
{"username":"jane", "key":"/opt/keys/janed.key"},
|
15
|
-
{"username":"sunny ", "key":"/opt/keys/sunnym.key"}
|
16
|
-
]
|
17
|
-
}
|
18
|
-
```
|
19
|
-
|
20
|
-
The following example shows how you can use pure Ruby code(variables,
|
21
|
-
loops, conditionals, regular expressions, etc) to run a few tests
|
22
|
-
against the above JSON file:
|
23
|
-
|
24
|
-
```ruby
|
25
|
-
control 'check-interns' do
|
26
|
-
# use the json InSpec resource to get the file
|
27
|
-
json_obj = json('/opt/keys/interns.json')
|
28
|
-
describe json_obj do
|
29
|
-
its('keys') { should_not eq nil }
|
30
|
-
end
|
31
|
-
if json_obj['keys']
|
32
|
-
# loop over the keys array
|
33
|
-
json_obj['keys'].each do |intern|
|
34
|
-
username = intern['username'].strip
|
35
|
-
# check for white spaces chars in usernames
|
36
|
-
describe username do
|
37
|
-
it { should_not match(/\s/) }
|
38
|
-
end
|
39
|
-
# check key file owners and permissions
|
40
|
-
describe file(intern['key']) do
|
41
|
-
it { should be_owned_by username }
|
42
|
-
its('mode') { should cmp '0600' }
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
```
|
48
|
-
|
49
|
-
## Execution
|
50
|
-
|
51
|
-
It's important to understand that Ruby code used in custom resources and
|
52
|
-
controls DSL is executed on the system that runs InSpec. This allows
|
53
|
-
InSpec to work without Ruby and rubygems being required on remote
|
54
|
-
targets(servers or containers).
|
55
|
-
|
56
|
-
For example, using `` `ls ``\` or `system('ls')` will result in the `ls`
|
57
|
-
command being run locally and not on the target(remote) system. In order
|
58
|
-
to process the output of `ls` executed on the target system, use
|
59
|
-
`inspec.command('ls')` or `inspec.powershell('ls')`
|
60
|
-
|
61
|
-
Similarly, use `inspec.file(PATH)` to access files or directories from
|
62
|
-
remote systems in your tests or custom resources.
|
63
|
-
|
64
|
-
## Using rubygems
|
65
|
-
|
66
|
-
Ruby gems are self-contained programs and libraries. If you create a custom
|
67
|
-
resource please vendor gems into the library. This ensures that all resources
|
68
|
-
are self-contained and complete and don't need any resolution at runtime. We
|
69
|
-
vendor resources and requirements through dependency resolution, which is
|
70
|
-
independent of programming languages and their resolver mechanisms.
|
71
|
-
|
72
|
-
## Interactive Debugging with Pry
|
73
|
-
|
74
|
-
Here's a sample InSpec control that users Ruby variables to instantiate
|
75
|
-
an InSpec resource once and use the content in multiple tests.
|
76
|
-
|
77
|
-
```ruby
|
78
|
-
control 'check-perl' do
|
79
|
-
impact 0.3
|
80
|
-
title 'Check perl compiled options and permissions'
|
81
|
-
perl_out = command('perl -V')
|
82
|
-
#require 'pry'; binding.pry;
|
83
|
-
describe perl_out do
|
84
|
-
its('exit_status') { should eq 0 }
|
85
|
-
its('stdout') { should match (/USE_64_BIT_ALL/) }
|
86
|
-
its('stdout') { should match (/useposix=true/) }
|
87
|
-
its('stdout') { should match (/-fstack-protector/) }
|
88
|
-
end
|
89
|
-
|
90
|
-
# extract an array of include directories
|
91
|
-
perl_inc = perl_out.stdout.partition('@INC:').last.strip.split("\n")
|
92
|
-
# ensure include directories are only writable by 'owner'
|
93
|
-
perl_inc.each do |path|
|
94
|
-
describe directory(path.strip) do
|
95
|
-
it { should_not be_writable.by('group') }
|
96
|
-
it { should_not be_writable.by('other') }
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
```
|
101
|
-
|
102
|
-
An **advanced** but very useful Ruby tip. In the previous example, I
|
103
|
-
commented out the `require 'pry'; binding.pry;` line. If you remove the
|
104
|
-
`#` prefix and run the control, the execution will stop at that line and
|
105
|
-
give you a `pry` shell. Use that to troubleshoot, print variables, see
|
106
|
-
methods available, etc. For the above example:
|
107
|
-
|
108
|
-
```ruby
|
109
|
-
[1] pry> perl_out.exit_status
|
110
|
-
=> 0
|
111
|
-
[2] pry> perl_out.stderr
|
112
|
-
=> ""
|
113
|
-
[3] pry> ls perl_out
|
114
|
-
Inspec::Plugins::Resource#methods: inspect
|
115
|
-
Inspec::Resources::Cmd#methods: command exist? exit_status result stderr stdout to_s
|
116
|
-
Inspec::Resource::Registry::Command#methods: inspec
|
117
|
-
instance variables: @__backend_runner__ @__resource_name__ @command @result
|
118
|
-
[4] pry> perl_out.stdout.partition('@INC:').last.strip.split("\n")
|
119
|
-
=> ["/Library/Perl/5.18/darwin-thread-multi-2level",
|
120
|
-
" /Library/Perl/5.18",
|
121
|
-
...REDACTED...
|
122
|
-
[5] pry> exit # or abort
|
123
|
-
```
|
124
|
-
|
125
|
-
You can use `pry` inside both the controls DSL and resources. Similarly,
|
126
|
-
for dev and test, you can use `inspec shell` which is based on `pry`,
|
127
|
-
for example:
|
128
|
-
|
129
|
-
```ruby
|
130
|
-
$ inspec shell
|
131
|
-
Welcome to the interactive InSpec Shell
|
132
|
-
To find out how to use it, type: help
|
133
|
-
|
134
|
-
inspec> command('ls /home/gordon/git/inspec/docs').stdout
|
135
|
-
=> "ctl_inspec.rst\ndsl_inspec.rst\ndsl_resource.rst\n"
|
136
|
-
inspec> command('ls').stdout.split("\n")
|
137
|
-
=> ["ctl_inspec.rst", "dsl_inspec.rst", "dsl_resource.rst"]
|
138
|
-
|
139
|
-
inspec> help command
|
140
|
-
Name: command
|
141
|
-
|
142
|
-
Description:
|
143
|
-
Use the command InSpec audit resource to test an arbitrary command that is run on the system.
|
144
|
-
|
145
|
-
Example:
|
146
|
-
describe command('ls -al /') do
|
147
|
-
it { should exist }
|
148
|
-
its('stdout') { should match /bin/ }
|
149
|
-
its('stderr') { should eq '' }
|
150
|
-
its('exit_status') { should eq 0 }
|
151
|
-
end
|
152
|
-
```
|
153
|
-
|
154
|
-
## Shelling out in tests
|
155
|
-
|
156
|
-
When writing tests you can not use standard ruby methods to shellout as it tries to execute those commands locally.
|
157
|
-
However, the `command` resource has a `.stdout` method that will allow you to manipulate the results.
|
158
|
-
Using the above example, you could check the writes on several subdirectories.
|
159
|
-
|
160
|
-
### Example 1
|
161
|
-
|
162
|
-
```ruby
|
163
|
-
$ inspec shell
|
164
|
-
Welcome to the interactive InSpec Shell
|
165
|
-
To find out how to use it, type: help
|
166
|
-
|
167
|
-
inspec> output=command('echo test').stdout
|
168
|
-
=> "test\n"
|
169
|
-
inspec> describe command('echo test') do
|
170
|
-
inspec> its('stdout') { should eq output }
|
171
|
-
inspec> end
|
172
|
-
|
173
|
-
Profile: inspec-shell
|
174
|
-
Version: (not specified)
|
175
|
-
|
176
|
-
Command echo
|
177
|
-
✔ test stdout should eq "test\n"
|
178
|
-
|
179
|
-
Test Summary: 1 successful, 0 failures, 0 skipped
|
180
|
-
```
|
181
|
-
|
182
|
-
### Example 2
|
183
|
-
|
184
|
-
```ruby
|
185
|
-
$ inspec shell
|
186
|
-
Welcome to the interactive InSpec Shell
|
187
|
-
To find out how to use it, type: help
|
188
|
-
|
189
|
-
inspec> dirs = command('ls -d /home/gordon/git/inspec/docs').stdout.split("\n")
|
190
|
-
=> ["/home/gordon/git/inspec/docs"]
|
191
|
-
inspec> dirs.each do |dir|
|
192
|
-
inspec> describe directory(dir) do
|
193
|
-
inspec> its('mode') { should cmp '0775' }
|
194
|
-
inspec> end
|
195
|
-
inspec> end
|
196
|
-
|
197
|
-
Profile: inspec-shell
|
198
|
-
Version: (not specified)
|
199
|
-
|
200
|
-
File /home/gordon/git/inspec/docs/
|
201
|
-
✔ mode should cmp == "0775"
|
202
|
-
|
203
|
-
Test Summary: 1 successful, 0 failures, 0 skipped
|
204
|
-
```
|