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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/CHANGELOG.md +25 -7
  4. data/Rakefile +8 -2
  5. data/docs/profiles.md +9 -0
  6. data/docs/resources/aws_security_group.md.erb +19 -2
  7. data/docs/resources/gem.md.erb +24 -5
  8. data/docs/resources/mssql_session.md.erb +8 -0
  9. data/lib/inspec/plugin/v2/loader.rb +33 -7
  10. data/lib/inspec/reporters/json_automate.rb +1 -1
  11. data/lib/inspec/version.rb +1 -1
  12. data/lib/plugins/README.md +16 -0
  13. data/lib/plugins/inspec-artifact/lib/inspec-artifact.rb +12 -0
  14. data/lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb +162 -0
  15. data/lib/plugins/inspec-artifact/lib/inspec-artifact/cli.rb +114 -0
  16. data/lib/plugins/inspec-artifact/test/functional/inspec_artifact_test.rb +46 -0
  17. data/lib/plugins/inspec-habitat/lib/inspec-habitat.rb +11 -0
  18. data/lib/plugins/inspec-habitat/lib/inspec-habitat/cli.rb +39 -0
  19. data/lib/plugins/inspec-habitat/lib/inspec-habitat/profile.rb +394 -0
  20. data/lib/plugins/inspec-habitat/test/unit/profile_test.rb +184 -0
  21. data/lib/{bundles → plugins}/inspec-init/README.md +0 -0
  22. data/lib/plugins/inspec-init/lib/inspec-init.rb +12 -0
  23. data/lib/plugins/inspec-init/lib/inspec-init/cli.rb +28 -0
  24. data/lib/plugins/inspec-init/lib/inspec-init/renderer.rb +81 -0
  25. data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/README.md +0 -0
  26. data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/controls/example.rb +0 -0
  27. data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/inspec.yml +0 -0
  28. data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/libraries/.gitkeep +0 -0
  29. data/lib/plugins/inspec-init/test/functional/inspec_init_test.rb +30 -0
  30. data/lib/plugins/shared/core_plugin_test_helper.rb +50 -0
  31. data/lib/resources/aws/aws_security_group.rb +38 -6
  32. data/lib/resources/gem.rb +7 -1
  33. data/lib/resources/mssql_session.rb +4 -2
  34. metadata +21 -17
  35. data/lib/bundles/inspec-artifact.rb +0 -7
  36. data/lib/bundles/inspec-artifact/README.md +0 -1
  37. data/lib/bundles/inspec-artifact/cli.rb +0 -278
  38. data/lib/bundles/inspec-habitat.rb +0 -12
  39. data/lib/bundles/inspec-habitat/cli.rb +0 -37
  40. data/lib/bundles/inspec-habitat/log.rb +0 -10
  41. data/lib/bundles/inspec-habitat/profile.rb +0 -391
  42. data/lib/bundles/inspec-init.rb +0 -12
  43. data/lib/bundles/inspec-init/cli.rb +0 -39
  44. data/lib/bundles/inspec-init/renderer.rb +0 -79
@@ -1,10 +0,0 @@
1
- # encoding: utf-8
2
- # author: Adam Leff
3
-
4
- require 'mixlib/log'
5
-
6
- module Habitat
7
- class Log
8
- extend Mixlib::Log
9
- end
10
- end
@@ -1,391 +0,0 @@
1
- # encoding: utf-8
2
- # author: Adam Leff
3
-
4
- require 'inspec/profile_vendor'
5
- require 'mixlib/shellout'
6
- require 'tomlrb'
7
-
8
- module Habitat
9
- class Profile
10
- attr_reader :options, :path, :profile
11
-
12
- def self.create(path, options = {})
13
- creator = new(path, options)
14
- hart_file = creator.create
15
- creator.copy(hart_file)
16
- ensure
17
- creator.delete_work_dir
18
- end
19
-
20
- def self.setup(path)
21
- new(path).setup
22
- end
23
-
24
- def self.upload(path, options = {})
25
- uploader = new(path, options)
26
- uploader.upload
27
- ensure
28
- uploader.delete_work_dir
29
- end
30
-
31
- def initialize(path, options = {})
32
- @path = path
33
- @options = options
34
- @cli_config = nil
35
-
36
- log_level = options.fetch('log_level', 'info')
37
- Habitat::Log.level(log_level.to_sym)
38
- end
39
-
40
- def create
41
- Habitat::Log.info("Creating a Habitat artifact for profile: #{path}")
42
-
43
- validate_habitat_installed
44
- validate_habitat_origin
45
- create_profile_object
46
- verify_profile
47
- vendor_profile_dependencies
48
- copy_profile_to_work_dir
49
- create_habitat_directories(work_dir)
50
- create_plan(work_dir)
51
- create_run_hook(work_dir)
52
- create_settings_file(work_dir)
53
- create_default_config(work_dir)
54
-
55
- # returns the path to the .hart file in the work directory
56
- build_hart
57
- rescue => e
58
- Habitat::Log.debug(e.backtrace.join("\n"))
59
- exit_with_error(
60
- 'Unable to generate Habitat artifact.',
61
- "#{e.class} -- #{e.message}",
62
- )
63
- end
64
-
65
- def copy(hart_file)
66
- validate_output_dir
67
-
68
- Habitat::Log.info("Copying artifact to #{output_dir}...")
69
- copy_hart(hart_file)
70
- end
71
-
72
- def upload
73
- validate_habitat_auth_token
74
- hart_file = create
75
- upload_hart(hart_file)
76
- rescue => e
77
- Habitat::Log.debug(e.backtrace.join("\n"))
78
- exit_with_error(
79
- 'Unable to upload Habitat artifact.',
80
- "#{e.class} -- #{e.message}",
81
- )
82
- end
83
-
84
- def delete_work_dir
85
- Habitat::Log.debug("Deleting work directory #{work_dir}")
86
- FileUtils.rm_rf(work_dir) if Dir.exist?(work_dir)
87
- end
88
-
89
- def setup
90
- Habitat::Log.info("Setting up profile at #{path} for Habitat...")
91
- create_profile_object
92
- verify_profile
93
- vendor_profile_dependencies
94
- create_habitat_directories(path)
95
- create_plan(path)
96
- create_run_hook(path)
97
- create_settings_file(path)
98
- create_default_config(path)
99
- end
100
-
101
- private
102
-
103
- def create_profile_object
104
- @profile = Inspec::Profile.for_target(
105
- path,
106
- backend: Inspec::Backend.create(target: 'mock://'),
107
- )
108
- end
109
-
110
- def verify_profile
111
- Habitat::Log.info('Checking to see if the profile is valid...')
112
-
113
- unless profile.check[:summary][:valid]
114
- exit_with_error('Profile check failed. Please fix the profile before creating a Habitat artifact.')
115
- end
116
-
117
- Habitat::Log.info('Profile is valid.')
118
- end
119
-
120
- def vendor_profile_dependencies
121
- profile_vendor = Inspec::ProfileVendor.new(path)
122
- if profile_vendor.lockfile.exist? && profile_vendor.cache_path.exist?
123
- Habitat::Log.info("Profile's dependencies are already vendored, skipping vendor process.")
124
- else
125
- Habitat::Log.info("Vendoring the profile's dependencies...")
126
- profile_vendor.vendor!
127
-
128
- Habitat::Log.info('Ensuring all vendored content has read permissions...')
129
- profile_vendor.make_readable
130
-
131
- # refresh the profile object since the profile now has new files
132
- create_profile_object
133
- end
134
- end
135
-
136
- def validate_habitat_installed
137
- Habitat::Log.info('Checking to see if Habitat is installed...')
138
- cmd = Mixlib::ShellOut.new('hab --version')
139
- cmd.run_command
140
- exit_with_error('Unable to run Habitat commands.', cmd.stderr) if cmd.error?
141
- end
142
-
143
- def validate_habitat_origin
144
- exit_with_error(
145
- 'Unable to determine Habitat origin name.',
146
- 'Run `hab setup` or set the HAB_ORIGIN environment variable.',
147
- ) if habitat_origin.nil?
148
- end
149
-
150
- def validate_habitat_auth_token
151
- exit_with_error(
152
- 'Unable to determine Habitat auth token for publishing.',
153
- 'Run `hab setup` or set the HAB_AUTH_TOKEN environment variable.',
154
- ) if habitat_auth_token.nil?
155
- end
156
-
157
- def validate_output_dir
158
- exit_with_error("Output directory #{output_dir} is not a directory or does not exist.") unless
159
- File.directory?(output_dir)
160
- end
161
-
162
- def work_dir
163
- return @work_dir if @work_dir
164
-
165
- @work_dir ||= Dir.mktmpdir('inspec-habitat-exporter')
166
- Habitat::Log.debug("Generated work directory #{@work_dir}")
167
-
168
- @work_dir
169
- end
170
-
171
- def create_habitat_directories(parent_directory)
172
- [
173
- File.join(parent_directory, 'habitat'),
174
- File.join(parent_directory, 'habitat', 'config'),
175
- File.join(parent_directory, 'habitat', 'hooks'),
176
- ].each do |dir|
177
- Dir.mkdir(dir) unless Dir.exist?(dir)
178
- end
179
- end
180
-
181
- def copy_profile_to_work_dir
182
- Habitat::Log.info('Copying profile contents to the work directory...')
183
- profile.files.each do |f|
184
- src = File.join(profile.root_path, f)
185
- dst = File.join(work_dir, f)
186
- if File.directory?(f)
187
- Habitat::Log.debug("Creating directory #{dst}")
188
- FileUtils.mkdir_p(dst)
189
- else
190
- Habitat::Log.debug("Copying file #{src} to #{dst}")
191
- FileUtils.cp_r(src, dst)
192
- end
193
- end
194
- end
195
-
196
- def create_plan(directory)
197
- plan_file = File.join(directory, 'habitat', 'plan.sh')
198
- Habitat::Log.info("Generating Habitat plan at #{plan_file}...")
199
- File.write(plan_file, plan_contents)
200
- end
201
-
202
- def create_run_hook(directory)
203
- run_hook_file = File.join(directory, 'habitat', 'hooks', 'run')
204
- Habitat::Log.info("Generating a Habitat run hook at #{run_hook_file}...")
205
- File.write(run_hook_file, run_hook_contents)
206
- end
207
-
208
- def create_settings_file(directory)
209
- settings_file = File.join(directory, 'habitat', 'config', 'settings.sh')
210
- Habitat::Log.info("Generating a settings file at #{settings_file}...")
211
- File.write(settings_file, "SLEEP_TIME={{cfg.sleep_time}}\n")
212
- end
213
-
214
- def create_default_config(directory)
215
- default_toml = File.join(directory, 'habitat', 'default.toml')
216
- Habitat::Log.info("Generating Habitat's default.toml configuration...")
217
- File.write(default_toml, 'sleep_time = 300')
218
- end
219
-
220
- def build_hart
221
- Habitat::Log.info('Building our Habitat artifact...')
222
-
223
- env = {
224
- 'TERM' => 'vt100',
225
- 'HAB_ORIGIN' => habitat_origin,
226
- 'HAB_NONINTERACTIVE' => 'true',
227
- }
228
-
229
- env['RUST_LOG'] = 'debug' if Habitat::Log.level == :debug
230
-
231
- # TODO: Would love to use Mixlib::ShellOut here, but it doesn't
232
- # seem to preserve the STDIN tty, and docker gets angry.
233
- Dir.chdir(work_dir) do
234
- unless system(env, 'hab pkg build .')
235
- exit_with_error('Unable to build the Habitat artifact.')
236
- end
237
- end
238
-
239
- hart_files = Dir.glob(File.join(work_dir, 'results', '*.hart'))
240
-
241
- if hart_files.length > 1
242
- exit_with_error('More than one Habitat artifact was created which was not expected.')
243
- elsif hart_files.empty?
244
- exit_with_error('No Habitat artifact was created.')
245
- end
246
-
247
- hart_files.first
248
- end
249
-
250
- def copy_hart(working_dir_hart)
251
- hart_basename = File.basename(working_dir_hart)
252
- dst = File.join(output_dir, hart_basename)
253
- FileUtils.cp(working_dir_hart, dst)
254
-
255
- dst
256
- end
257
-
258
- def upload_hart(hart_file)
259
- Habitat::Log.info('Uploading the Habitat artifact to our Depot...')
260
-
261
- env = {
262
- 'TERM' => 'vt100',
263
- 'HAB_AUTH_TOKEN' => habitat_auth_token,
264
- 'HAB_NONINTERACTIVE' => 'true',
265
- }
266
-
267
- env['HAB_DEPOT_URL'] = ENV['HAB_DEPOT_URL'] if ENV['HAB_DEPOT_URL']
268
-
269
- cmd = Mixlib::ShellOut.new("hab pkg upload #{hart_file}", env: env)
270
- cmd.run_command
271
- if cmd.error?
272
- exit_with_error(
273
- 'Unable to upload Habitat artifact to the Depot.',
274
- cmd.stdout,
275
- cmd.stderr,
276
- )
277
- end
278
-
279
- Habitat::Log.info('Upload complete!')
280
- end
281
-
282
- def habitat_origin
283
- ENV['HAB_ORIGIN'] || habitat_cli_config['origin']
284
- end
285
-
286
- def habitat_auth_token
287
- ENV['HAB_AUTH_TOKEN'] || habitat_cli_config['auth_token']
288
- end
289
-
290
- def habitat_cli_config
291
- return @cli_config if @cli_config
292
-
293
- config_file = File.join(ENV['HOME'], '.hab', 'etc', 'cli.toml')
294
- return {} unless File.exist?(config_file)
295
-
296
- @cli_config = Tomlrb.load_file(config_file)
297
- end
298
-
299
- def output_dir
300
- options[:output_dir] || Dir.pwd
301
- end
302
-
303
- def exit_with_error(*errors)
304
- errors.each do |error_msg|
305
- Habitat::Log.error(error_msg)
306
- end
307
-
308
- exit 1
309
- end
310
-
311
- def package_name
312
- "inspec-profile-#{profile.name}"
313
- end
314
-
315
- def plan_contents
316
- plan = <<~EOL
317
- pkg_name=#{package_name}
318
- pkg_version=#{profile.version}
319
- pkg_origin=#{habitat_origin}
320
- pkg_deps=(chef/inspec core/ruby core/hab)
321
- pkg_svc_user=root
322
- EOL
323
-
324
- plan += "pkg_license='#{profile.metadata.params[:license]}'\n\n" if profile.metadata.params[:license]
325
-
326
- plan += <<~EOL
327
-
328
- do_build() {
329
- cp -vr $PLAN_CONTEXT/../* $HAB_CACHE_SRC_PATH/$pkg_dirname
330
- }
331
-
332
- do_install() {
333
- local profile_contents
334
- local excludes
335
- profile_contents=($(ls))
336
- excludes=(habitat results *.hart)
337
-
338
- for item in ${excludes[@]}; do
339
- profile_contents=(${profile_contents[@]/$item/})
340
- done
341
-
342
- mkdir ${pkg_prefix}/dist
343
- cp -r ${profile_contents[@]} ${pkg_prefix}/dist/
344
- }
345
- EOL
346
-
347
- plan
348
- end
349
-
350
- def run_hook_contents
351
- <<~EOL
352
- #!/bin/sh
353
-
354
- # redirect stderr to stdout
355
- # ultimately, we'd like to log this somewhere useful, but due to
356
- # https://github.com/habitat-sh/habitat/issues/2395, we need to
357
- # avoid doing that for now.
358
- exec 2>&1
359
-
360
- # InSpec will try to create a .cache directory in the user's home directory
361
- # so this needs to be someplace writeable by the hab user
362
- export HOME={{pkg.svc_var_path}}
363
-
364
- PROFILE_IDENT="{{pkg.origin}}/{{pkg.name}}"
365
- RESULTS_DIR="{{pkg.svc_var_path}}/inspec_results"
366
- RESULTS_FILE="${RESULTS_DIR}/{{pkg.name}}.json"
367
-
368
- # Create a directory for inspec formatter output
369
- mkdir -p {{pkg.svc_var_path}}/inspec_results
370
-
371
- while true; do
372
- echo "Executing InSpec for ${PROFILE_IDENT}"
373
- inspec exec {{pkg.path}}/dist --format=json > ${RESULTS_FILE}
374
-
375
- if [ $? -eq 0 ]; then
376
- echo "InSpec run completed successfully."
377
- else
378
- echo "InSpec run did not complete successfully. If you do not see any errors above,"
379
- echo "control failures were detected. Check the InSpec results here for details:"
380
- echo ${RESULTS_FILE}
381
- echo "Otherwise, troubleshoot any errors shown above."
382
- fi
383
-
384
- source {{pkg.svc_config_path}}/settings.sh
385
- echo "sleeping for ${SLEEP_TIME} seconds"
386
- sleep ${SLEEP_TIME}
387
- done
388
- EOL
389
- end
390
- end
391
- end
@@ -1,12 +0,0 @@
1
- # encoding: utf-8
2
- # author: Christoph Hartmann
3
- # author: Dominik Richter
4
-
5
- libdir = File.dirname(__FILE__)
6
- $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
7
-
8
- module Init
9
- autoload :Profile, 'inspec-init/profile'
10
- end
11
-
12
- require 'inspec-init/cli'
@@ -1,39 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'pathname'
4
- require_relative 'renderer'
5
- require 'inspec/base_cli'
6
-
7
- module Init
8
- class CLI < Inspec::BaseCLI
9
- namespace 'init'
10
-
11
- # TODO: find another solution, once https://github.com/erikhuda/thor/issues/261 is fixed
12
- def self.banner(command, _namespace = nil, _subcommand = false)
13
- "#{basename} #{subcommand_prefix} #{command.usage}"
14
- end
15
-
16
- def self.subcommand_prefix
17
- namespace
18
- end
19
-
20
- # Look in the 'template' directory, and register a subcommand
21
- # for each template directory found there.
22
- template_dir = File.join(File.dirname(__FILE__), 'templates')
23
- Dir.glob(File.join(template_dir, '*')) do |template|
24
- template_name = Pathname.new(template).relative_path_from(Pathname.new(template_dir)).to_s
25
-
26
- # register command for the template
27
- desc "#{template_name} NAME", "Create a new #{template_name}"
28
- option :overwrite, type: :boolean, default: false,
29
- desc: 'Overwrites existing directory'
30
- define_method template_name.to_sym do |name_for_new_structure|
31
- renderer = Init::Renderer.new(self, options)
32
- renderer.render_with_values(template_name, name: name_for_new_structure)
33
- end
34
- end
35
- end
36
-
37
- # register the subcommand to Inspec CLI registry
38
- Inspec::Plugins::CLI.add_subcommand(Init::CLI, 'init', 'init TEMPLATE ...', 'Scaffolds a new project', {})
39
- end