inspec-core 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 (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