inspec-core 2.2.102 → 2.2.112

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -7
  3. data/docs/profiles.md +9 -0
  4. data/docs/resources/gem.md.erb +24 -5
  5. data/docs/resources/mssql_session.md.erb +8 -0
  6. data/lib/inspec/plugin/v2/loader.rb +33 -7
  7. data/lib/inspec/reporters/json_automate.rb +1 -1
  8. data/lib/inspec/version.rb +1 -1
  9. data/lib/plugins/README.md +16 -0
  10. data/lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb +162 -0
  11. data/lib/plugins/inspec-artifact/lib/inspec-artifact/cli.rb +114 -0
  12. data/lib/plugins/inspec-artifact/lib/inspec-artifact.rb +12 -0
  13. data/lib/plugins/inspec-artifact/test/functional/inspec_artifact_test.rb +46 -0
  14. data/lib/plugins/inspec-habitat/lib/inspec-habitat/cli.rb +39 -0
  15. data/lib/plugins/inspec-habitat/lib/inspec-habitat/profile.rb +394 -0
  16. data/lib/plugins/inspec-habitat/lib/inspec-habitat.rb +11 -0
  17. data/lib/plugins/inspec-habitat/test/unit/profile_test.rb +184 -0
  18. data/lib/{bundles → plugins}/inspec-init/README.md +0 -0
  19. data/lib/plugins/inspec-init/lib/inspec-init/cli.rb +28 -0
  20. data/lib/plugins/inspec-init/lib/inspec-init/renderer.rb +81 -0
  21. data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/README.md +0 -0
  22. data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/controls/example.rb +0 -0
  23. data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/inspec.yml +0 -0
  24. data/lib/{bundles → plugins/inspec-init/lib}/inspec-init/templates/profile/libraries/.gitkeep +0 -0
  25. data/lib/plugins/inspec-init/lib/inspec-init.rb +12 -0
  26. data/lib/plugins/inspec-init/test/functional/inspec_init_test.rb +30 -0
  27. data/lib/plugins/shared/core_plugin_test_helper.rb +50 -0
  28. data/lib/resources/gem.rb +7 -1
  29. data/lib/resources/mssql_session.rb +4 -2
  30. metadata +21 -17
  31. data/lib/bundles/inspec-artifact/README.md +0 -1
  32. data/lib/bundles/inspec-artifact/cli.rb +0 -278
  33. data/lib/bundles/inspec-artifact.rb +0 -7
  34. data/lib/bundles/inspec-habitat/cli.rb +0 -37
  35. data/lib/bundles/inspec-habitat/log.rb +0 -10
  36. data/lib/bundles/inspec-habitat/profile.rb +0 -391
  37. data/lib/bundles/inspec-habitat.rb +0 -12
  38. data/lib/bundles/inspec-init/cli.rb +0 -39
  39. data/lib/bundles/inspec-init/renderer.rb +0 -79
  40. data/lib/bundles/inspec-init.rb +0 -12
@@ -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
@@ -0,0 +1,12 @@
1
+ module InspecPlugins
2
+ module Init
3
+ class Plugin < Inspec.plugin(2)
4
+ plugin_name :'inspec-init'
5
+
6
+ cli_command :init do
7
+ require_relative 'inspec-init/cli'
8
+ InspecPlugins::Init::CLI
9
+ end
10
+ end
11
+ end
12
+ end
@@ -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
data/lib/resources/gem.rb CHANGED
@@ -49,9 +49,10 @@ module Inspec::Resources
49
49
  }
50
50
  return @info unless @info[:installed]
51
51
 
52
- versions = params[2].split(',')
52
+ versions = params[2].split(',').map(&:strip)
53
53
  @info[:name] = params[1]
54
54
  @info[:version] = versions[0]
55
+ @info[:versions] = versions
55
56
  @info
56
57
  end
57
58
 
@@ -63,6 +64,11 @@ module Inspec::Resources
63
64
  info[:version]
64
65
  end
65
66
 
67
+ # this returns an array of strings
68
+ def versions
69
+ info[:versions]
70
+ end
71
+
66
72
  def to_s
67
73
  "gem package #{@package_name}"
68
74
  end
@@ -29,7 +29,7 @@ module Inspec::Resources
29
29
  end
30
30
  "
31
31
 
32
- attr_reader :user, :password, :host, :port, :instance, :local_mode
32
+ attr_reader :user, :password, :host, :port, :instance, :local_mode, :db_name
33
33
  def initialize(opts = {})
34
34
  @user = opts[:user]
35
35
  @password = opts[:password] || opts[:pass]
@@ -46,6 +46,7 @@ module Inspec::Resources
46
46
  end
47
47
  end
48
48
  @instance = opts[:instance]
49
+ @db_name = opts[:db_name]
49
50
 
50
51
  # check if sqlcmd is available
51
52
  raise Inspec::Exceptions::ResourceSkipped, 'sqlcmd is missing' unless inspec.command('sqlcmd').exist?
@@ -53,11 +54,12 @@ module Inspec::Resources
53
54
  raise Inspec::Exceptions::ResourceSkipped, "Can't connect to the MS SQL Server." unless test_connection
54
55
  end
55
56
 
56
- def query(q)
57
+ def query(q) # rubocop:disable Metrics/PerceivedComplexity
57
58
  escaped_query = q.gsub(/\\/, '\\\\').gsub(/"/, '\\"').gsub(/\$/, '\\$')
58
59
  # surpress 'x rows affected' in SQLCMD with 'set nocount on;'
59
60
  cmd_string = "sqlcmd -Q \"set nocount on; #{escaped_query}\" -W -w 1024 -s ','"
60
61
  cmd_string += " -U '#{@user}' -P '#{@password}'" unless @user.nil? || @password.nil?
62
+ cmd_string += " -d '#{@db_name}'" unless @db_name.nil?
61
63
  unless local_mode?
62
64
  if @port.nil?
63
65
  cmd_string += " -S '#{@host}"
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.102
4
+ version: 2.2.112
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-17 00:00:00.000000000 Z
11
+ date: 2018-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: train-core
@@ -482,9 +482,6 @@ files:
482
482
  - examples/profile/libraries/gordon_config.rb
483
483
  - inspec-core.gemspec
484
484
  - lib/bundles/README.md
485
- - lib/bundles/inspec-artifact.rb
486
- - lib/bundles/inspec-artifact/README.md
487
- - lib/bundles/inspec-artifact/cli.rb
488
485
  - lib/bundles/inspec-compliance.rb
489
486
  - lib/bundles/inspec-compliance/.kitchen.yml
490
487
  - lib/bundles/inspec-compliance/README.md
@@ -498,18 +495,6 @@ files:
498
495
  - lib/bundles/inspec-compliance/support.rb
499
496
  - lib/bundles/inspec-compliance/target.rb
500
497
  - lib/bundles/inspec-compliance/test/integration/default/cli.rb
501
- - lib/bundles/inspec-habitat.rb
502
- - lib/bundles/inspec-habitat/cli.rb
503
- - lib/bundles/inspec-habitat/log.rb
504
- - lib/bundles/inspec-habitat/profile.rb
505
- - lib/bundles/inspec-init.rb
506
- - lib/bundles/inspec-init/README.md
507
- - lib/bundles/inspec-init/cli.rb
508
- - lib/bundles/inspec-init/renderer.rb
509
- - lib/bundles/inspec-init/templates/profile/README.md
510
- - lib/bundles/inspec-init/templates/profile/controls/example.rb
511
- - lib/bundles/inspec-init/templates/profile/inspec.yml
512
- - lib/bundles/inspec-init/templates/profile/libraries/.gitkeep
513
498
  - lib/bundles/inspec-supermarket.rb
514
499
  - lib/bundles/inspec-supermarket/README.md
515
500
  - lib/bundles/inspec-supermarket/api.rb
@@ -611,6 +596,25 @@ files:
611
596
  - lib/inspec/source_reader.rb
612
597
  - lib/inspec/version.rb
613
598
  - lib/matchers/matchers.rb
599
+ - lib/plugins/README.md
600
+ - lib/plugins/inspec-artifact/lib/inspec-artifact.rb
601
+ - lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb
602
+ - lib/plugins/inspec-artifact/lib/inspec-artifact/cli.rb
603
+ - lib/plugins/inspec-artifact/test/functional/inspec_artifact_test.rb
604
+ - lib/plugins/inspec-habitat/lib/inspec-habitat.rb
605
+ - lib/plugins/inspec-habitat/lib/inspec-habitat/cli.rb
606
+ - lib/plugins/inspec-habitat/lib/inspec-habitat/profile.rb
607
+ - lib/plugins/inspec-habitat/test/unit/profile_test.rb
608
+ - lib/plugins/inspec-init/README.md
609
+ - lib/plugins/inspec-init/lib/inspec-init.rb
610
+ - lib/plugins/inspec-init/lib/inspec-init/cli.rb
611
+ - lib/plugins/inspec-init/lib/inspec-init/renderer.rb
612
+ - lib/plugins/inspec-init/lib/inspec-init/templates/profile/README.md
613
+ - lib/plugins/inspec-init/lib/inspec-init/templates/profile/controls/example.rb
614
+ - lib/plugins/inspec-init/lib/inspec-init/templates/profile/inspec.yml
615
+ - lib/plugins/inspec-init/lib/inspec-init/templates/profile/libraries/.gitkeep
616
+ - lib/plugins/inspec-init/test/functional/inspec_init_test.rb
617
+ - lib/plugins/shared/core_plugin_test_helper.rb
614
618
  - lib/resources/aide_conf.rb
615
619
  - lib/resources/apache.rb
616
620
  - lib/resources/apache_conf.rb
@@ -1 +0,0 @@
1
- # TODO
@@ -1,278 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: true
3
- require 'base64'
4
- require 'openssl'
5
- require 'pathname'
6
- require 'set'
7
- require 'tempfile'
8
- require 'yaml'
9
- require 'inspec/base_cli'
10
-
11
- # Notes:
12
- #
13
- # Generate keys
14
- # The initial implementation uses 2048 bit RSA key pairs (public + private).
15
- # Public keys must be available for a customer to install and verify an artifact.
16
- # Private keys should be stored in a secure location and NOT be distributed.
17
- # (They're only for creating artifacts).
18
- #
19
- #
20
- # .IAF file format
21
- # .iaf = "Inspec Artifact File", easy to rename if you'd like something more appropriate.
22
- # The iaf file wraps a binary artifact with some metadata. The first implementation
23
- # looks like this:
24
- #
25
- # INSPEC-PROFILE-1
26
- # name_of_signing_key
27
- # algorithm
28
- # signature
29
- # <empty line>
30
- # binary-blob
31
- # <eof>
32
- #
33
- # Let's look at each line:
34
- # INSPEC-PROFILE-1:
35
- # This is the artifact version descriptor. It should't change unless the
36
- # format of the archive changes.
37
- #
38
- # name_of_signing_key
39
- # The name of the public key that can be used to verify an artifact
40
- #
41
- # algorithm
42
- # The digest used to sign, I picked SHA512 to start with.
43
- # If we support multiple digests, we'll need to have the verify() method
44
- # support each digest.
45
- #
46
- # signature
47
- # The result of passing the binary artifact through the digest algorithm above.
48
- # Result is base64 encoded.
49
- #
50
- # <empty line>
51
- # We use an empty line to separate artifact header from artifact body (binary blob).
52
- # The artifact body can be anything you like.
53
- #
54
- # binary-blob
55
- # A binary blob, most likely a .tar.gz or tar.xz file. We'll need to pick one and
56
- # stick with it as part of the "INSPEC-PROFILE-1" artifact version. If we change block
57
- # format, the artifact version descriptor must be incremented, and the sign()
58
- # and verify() methods must be updated to support a newer version.
59
- #
60
- #
61
- # Key revocation
62
- # This implementation doesn't support key revocation. However, a customer
63
- # can remove the public cert file before installation, and artifacts will then
64
- # fail verification.
65
- #
66
- # Key locations
67
- # This implementation uses the current working directory to find public and
68
- # private keys. We should establish a common key directory (similar to /hab/cache/keys
69
- # or ~/.hab/cache/keys in Habitat).
70
- #
71
- # Extracting artifacts outside of Inspec
72
- # As in Habitat, the artifact format for Inspec allows the use of common
73
- # Unix tools to read the header and body of an artifact.
74
- # To extract the header from a .iaf:
75
- # sed '/^$/q' foo.iaf
76
- # To extract the raw content from a .iaf:
77
- # sed '1,/^$/d' foo.iaf
78
-
79
- module Artifact
80
- KEY_BITS=2048
81
- KEY_ALG=OpenSSL::PKey::RSA
82
-
83
- INSPEC_PROFILE_VERSION_1='INSPEC-PROFILE-1'
84
- INSPEC_REPORT_VERSION_1='INSPEC-REPORT-1'
85
-
86
- ARTIFACT_DIGEST=OpenSSL::Digest::SHA512
87
- ARTIFACT_DIGEST_NAME='SHA512'
88
-
89
- VALID_PROFILE_VERSIONS=Set.new [INSPEC_PROFILE_VERSION_1]
90
- VALID_PROFILE_DIGESTS=Set.new [ARTIFACT_DIGEST_NAME]
91
-
92
- SIGNED_PROFILE_SUFFIX='iaf'
93
- SIGNED_REPORT_SUFFIX='iar'
94
- class CLI < Inspec::BaseCLI
95
- namespace 'artifact'
96
-
97
- # TODO: find another solution, once https://github.com/erikhuda/thor/issues/261 is fixed
98
- def self.banner(command, _namespace = nil, _subcommand = false)
99
- "#{basename} #{subcommand_prefix} #{command.usage}"
100
- end
101
-
102
- def self.subcommand_prefix
103
- namespace
104
- end
105
-
106
- desc 'generate', 'Generate a RSA key pair for signing and verification'
107
- option :keyname, type: :string, required: true,
108
- desc: 'Desriptive name of key'
109
- option :keydir, type: :string, default: './',
110
- desc: 'Directory to search for keys'
111
- def generate_keys
112
- puts 'Generating keys'
113
- keygen
114
- end
115
-
116
- desc 'sign-profile', 'Create a signed .iaf artifact'
117
- option :profile, type: :string, required: true,
118
- desc: 'Path to profile directory'
119
- option :keyname, type: :string, required: true,
120
- desc: 'Desriptive name of key'
121
- def sign_profile
122
- profile_sign
123
- end
124
-
125
- desc 'verify-profile', 'Verify a signed .iaf artifact'
126
- option :infile, type: :string, required: true,
127
- desc: '.iaf file to verify'
128
- def verify_profile
129
- profile_verify
130
- end
131
-
132
- desc 'install-profile', 'Verify and install a signed .iaf artifact'
133
- option :infile, type: :string, required: true,
134
- desc: '.iaf file to install'
135
- option :destdir, type: :string, required: true,
136
- desc: 'Installation directory'
137
- def install_profile
138
- profile_install
139
- end
140
-
141
- private
142
-
143
- def keygen
144
- key = KEY_ALG.new KEY_BITS
145
- puts 'Generating private key'
146
- open "#{options['keyname']}.pem.key", 'w' do |io| io.write key.to_pem end
147
- puts 'Generating public key'
148
- open "#{options['keyname']}.pem.pub", 'w' do |io| io.write key.public_key.to_pem end
149
- end
150
-
151
- def read_profile_metadata(path_to_profile)
152
- begin
153
- p = Pathname.new(path_to_profile)
154
- p = p.join('inspec.yml')
155
- if not p.exist?
156
- raise "#{path_to_profile} doesn't appear to be a valid Inspec profile"
157
- end
158
- yaml = YAML.load_file(p.to_s)
159
- yaml = yaml.to_hash
160
-
161
- if not yaml.key? 'name'
162
- raise 'Profile is invalid, name is not defined'
163
- end
164
-
165
- if not yaml.key? 'version'
166
- raise 'Profile is invalid, version is not defined'
167
- end
168
- rescue => e
169
- # rewrap it and pass it up to the CLI
170
- raise "Error reading Inspec profile metadata: #{e}"
171
- end
172
-
173
- yaml
174
- end
175
-
176
- def profile_compress(path_to_profile, profile_md, workdir)
177
- profile_name = profile_md['name']
178
- profile_version = profile_md['version']
179
- outfile_name = "#{workdir}/#{profile_name}-#{profile_version}.tar.gz"
180
- `tar czf #{outfile_name} -C #{path_to_profile} .`
181
- outfile_name
182
- end
183
-
184
- def profile_sign
185
- Dir.mktmpdir do |workdir|
186
- puts "Signing #{options['profile']} with key #{options['keyname']}"
187
- path_to_profile = options['profile']
188
- profile_md = read_profile_metadata(path_to_profile)
189
- artifact_filename = "#{profile_md['name']}-#{profile_md['version']}.#{SIGNED_PROFILE_SUFFIX}"
190
- tarfile = profile_compress(path_to_profile, profile_md, workdir)
191
- content = IO.binread(tarfile)
192
- signing_key = KEY_ALG.new File.read "#{options['keyname']}.pem.key"
193
- sha = ARTIFACT_DIGEST.new
194
- signature = signing_key.sign sha, content
195
- # convert the signature to Base64
196
- signature_base64 = Base64.encode64(signature)
197
- tar_content = IO.binread(tarfile)
198
- File.open(artifact_filename, 'wb') do |f|
199
- f.puts(INSPEC_PROFILE_VERSION_1)
200
- f.puts(options['keyname'])
201
- f.puts(ARTIFACT_DIGEST_NAME)
202
- f.puts(signature_base64)
203
- f.puts('') # newline separates artifact header with body
204
- f.write(tar_content)
205
- end
206
- puts "Successfully generated #{artifact_filename}"
207
- end
208
- end
209
-
210
- def valid_header?(file_alg, file_version, file_keyname)
211
- public_keyfile = "#{file_keyname}.pem.pub"
212
- puts "Looking for #{public_keyfile} to verify artifact"
213
- if !File.exist? public_keyfile
214
- raise "Can't find #{public_keyfile}"
215
- end
216
-
217
- raise 'Invalid artifact digest algorithm detected' if !VALID_PROFILE_DIGESTS.member?(file_alg)
218
- raise 'Invalid artifact version detected' if !VALID_PROFILE_VERSIONS.member?(file_version)
219
- end
220
-
221
- def verify(file_to_verifiy, &content_block)
222
- f = File.open(file_to_verifiy, 'r')
223
- file_version = f.readline.strip!
224
- file_keyname = f.readline.strip!
225
- file_alg = f.readline.strip!
226
-
227
- file_sig = ''
228
- # the signature is multi-line
229
- while (line = f.readline) != "\n"
230
- file_sig += line
231
- end
232
- file_sig.strip!
233
- f.close
234
-
235
- valid_header?(file_alg, file_version, file_keyname)
236
-
237
- public_keyfile = "#{file_keyname}.pem.pub"
238
- verification_key = KEY_ALG.new File.read public_keyfile
239
-
240
- f = File.open(file_to_verifiy, 'r')
241
- while f.readline != "\n" do end
242
- content = f.read
243
-
244
- signature = Base64.decode64(file_sig)
245
- digest = ARTIFACT_DIGEST.new
246
- if verification_key.verify digest, signature, content
247
- content_block.yield(content)
248
- else
249
- puts 'Artifact is invalid'
250
- end
251
- end
252
-
253
- def profile_verify
254
- file_to_verifiy = options['infile']
255
- puts "Verifying #{file_to_verifiy}"
256
- verify(file_to_verifiy) do ||
257
- puts 'Artifact is valid'
258
- end
259
- end
260
-
261
- def profile_install
262
- puts 'Installing profile'
263
- file_to_verifiy = options['infile']
264
- dest_dir = options['destdir']
265
- verify(file_to_verifiy) do |content|
266
- Dir.mktmpdir do |workdir|
267
- tmpfile = Pathname.new(workdir).join('artifact_to_install.tar.gz')
268
- File.write(tmpfile, content)
269
- puts "Installing to #{dest_dir}"
270
- `tar xzf #{tmpfile} -C #{dest_dir}`
271
- end
272
- end
273
- end
274
- end
275
-
276
- # register the subcommand to Inspec CLI registry
277
- Inspec::Plugins::CLI.add_subcommand(Artifact::CLI, 'artifact', 'artifact SUBCOMMAND ...', 'Sign, verify and install artifacts', {})
278
- end
@@ -1,7 +0,0 @@
1
- # encoding: utf-8
2
- # author: Dave Parfitt
3
-
4
- libdir = File.dirname(__FILE__)
5
- $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
6
-
7
- require 'inspec-artifact/cli'
@@ -1,37 +0,0 @@
1
- # encoding: utf-8
2
- # author: Adam Leff
3
-
4
- require 'thor'
5
- require 'inspec/base_cli'
6
-
7
- module Habitat
8
- class HabitatProfileCLI < Thor
9
- namespace 'habitat profile'
10
-
11
- desc 'create PATH', 'Create a one-time Habitat artifact for the profile found at PATH'
12
- option :output_dir, type: :string, required: false,
13
- desc: 'Directory in which to save the generated Habitat artifact. Default: current directory'
14
- def create(path)
15
- Habitat::Profile.create(path, options)
16
- end
17
-
18
- desc 'setup PATH', 'Configure the profile at PATH for Habitat, including a plan and hooks'
19
- def setup(path)
20
- Habitat::Profile.setup(path)
21
- end
22
-
23
- desc 'upload PATH', 'Create a one-time Habitat artifact for the profile found at PATH, and upload it to a Habitat Depot'
24
- def upload(path)
25
- Habitat::Profile.upload(path, options)
26
- end
27
- end
28
-
29
- class HabitatCLI < Inspec::BaseCLI
30
- namespace 'habitat'
31
-
32
- desc 'profile', 'Manage InSpec profiles as Habitat artifacts'
33
- subcommand 'profile', HabitatProfileCLI
34
- end
35
-
36
- Inspec::Plugins::CLI.add_subcommand(HabitatCLI, 'habitat', 'habitat SUBCOMMAND ...', 'Commands for InSpec + Habitat Integration', {})
37
- end
@@ -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