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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -19
  3. data/README.md +1 -1
  4. data/docs/dev/integration-testing.md +31 -0
  5. data/docs/dev/plugins.md +4 -2
  6. data/docs/dsl_inspec.md +104 -4
  7. data/docs/plugins.md +57 -0
  8. data/docs/style.md +178 -0
  9. data/examples/plugins/inspec-resource-lister/Gemfile +12 -0
  10. data/examples/plugins/inspec-resource-lister/LICENSE +13 -0
  11. data/examples/plugins/inspec-resource-lister/README.md +62 -0
  12. data/examples/plugins/inspec-resource-lister/Rakefile +40 -0
  13. data/examples/plugins/inspec-resource-lister/inspec-resource-lister.gemspec +45 -0
  14. data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister.rb +16 -0
  15. data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/cli_command.rb +70 -0
  16. data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/plugin.rb +55 -0
  17. data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/version.rb +10 -0
  18. data/examples/plugins/inspec-resource-lister/test/fixtures/README.md +24 -0
  19. data/examples/plugins/inspec-resource-lister/test/functional/README.md +18 -0
  20. data/examples/plugins/inspec-resource-lister/test/functional/inspec_resource_lister_test.rb +110 -0
  21. data/examples/plugins/inspec-resource-lister/test/helper.rb +26 -0
  22. data/examples/plugins/inspec-resource-lister/test/unit/README.md +17 -0
  23. data/examples/plugins/inspec-resource-lister/test/unit/cli_args_test.rb +64 -0
  24. data/examples/plugins/inspec-resource-lister/test/unit/plugin_def_test.rb +51 -0
  25. data/examples/profile/controls/example.rb +9 -8
  26. data/inspec-core.gemspec +1 -1
  27. data/lib/inspec/attribute_registry.rb +1 -1
  28. data/lib/inspec/globals.rb +4 -0
  29. data/lib/inspec/objects/control.rb +18 -3
  30. data/lib/inspec/plugin/v2.rb +14 -3
  31. data/lib/inspec/plugin/v2/activator.rb +7 -2
  32. data/lib/inspec/plugin/v2/installer.rb +426 -0
  33. data/lib/inspec/plugin/v2/loader.rb +137 -30
  34. data/lib/inspec/plugin/v2/registry.rb +13 -4
  35. data/lib/inspec/profile.rb +2 -1
  36. data/lib/inspec/reporters/json.rb +11 -1
  37. data/lib/inspec/resource.rb +6 -15
  38. data/lib/inspec/rule.rb +18 -9
  39. data/lib/inspec/runner_rspec.rb +1 -1
  40. data/lib/inspec/schema.rb +1 -0
  41. data/lib/inspec/version.rb +1 -1
  42. data/lib/plugins/inspec-plugin-manager-cli/README.md +6 -0
  43. data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli.rb +18 -0
  44. data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +420 -0
  45. data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/plugin.rb +12 -0
  46. data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/config_dirs/empty/.gitkeep +0 -0
  47. data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/inspec-egg-white-omelette/lib/inspec-egg-white-omelette.rb +2 -0
  48. data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/inspec-egg-white-omelette/lib/inspec-egg-white-omelette/.gitkeep +0 -0
  49. data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/inspec-wrong-structure/.gitkeep +0 -0
  50. data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/wrong-name/lib/wrong-name.rb +1 -0
  51. data/lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/wrong-name/lib/wrong-name/.gitkeep +0 -0
  52. data/lib/plugins/inspec-plugin-manager-cli/test/functional/inspec-plugin_test.rb +651 -0
  53. data/lib/plugins/inspec-plugin-manager-cli/test/unit/cli_args_test.rb +71 -0
  54. data/lib/plugins/inspec-plugin-manager-cli/test/unit/plugin_def_test.rb +20 -0
  55. data/lib/plugins/shared/core_plugin_test_helper.rb +101 -2
  56. data/lib/plugins/things-for-train-integration.rb +14 -0
  57. data/lib/resources/port.rb +10 -6
  58. metadata +38 -11
  59. 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
@@ -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 - Inode, 8 - PID/Program name
477
- parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)?\s+(\S+)\s+(\S+)\s+(\S+)/.match(line)
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[1].downcase
485
+ protocol = parsed[:proto].downcase
482
486
 
483
487
  # detect protocol if not provided
484
- protocol += '6' if parsed[4].count(':') > 1 && %w{tcp udp}.include?(protocol)
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[4], protocol)
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[9].split('/')
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.2.112
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-19 00:00:00.000000000 Z
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.4'
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.4'
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
@@ -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
- ```