rapid-vaults 1.1.2 → 1.3.0

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.
@@ -0,0 +1,77 @@
1
+ require_relative '../rapid_vaults'
2
+ require_relative 'bindings/rapid_vaults_services_pb'
3
+
4
+ # provides a grpc server
5
+ class RapidVaults::GRPC < Rapidvaults::RapidVaults::Service
6
+ # start the server
7
+ def server(addr = '0.0.0.0:8080')
8
+ server = GRPC::RpcServer.new
9
+ server.add_http2_port(addr, :this_port_is_insecure)
10
+ server.handle(RapidVaults.new)
11
+ server.run_till_terminated
12
+ end
13
+
14
+ # grpc api for generate openssl
15
+ def ssl_generate(geninputs, _call)
16
+ settings = geninputs.to_hash
17
+ settings_process(settings)
18
+ Generate.openssl(settings)
19
+ end
20
+
21
+ # grpc api for generate gpg
22
+ def gpg_generate(geninputs, _call)
23
+ settings = geninputs.to_hash
24
+ settings_process(settings)
25
+ Generate.gpgme(settings)
26
+ end
27
+
28
+ # grpc api for encrypt ssl
29
+ def ssl_encrypt(unencrypted, _call)
30
+ settings = {}
31
+ settings[:file] = unencrypted.text
32
+ settings[:key] = unencrypted.key
33
+ settings[:nonce] = unencrypted.nonce
34
+ settings[:pw] = unencrypted.password
35
+ settings_process(settings)
36
+ Encrypt.openssl(settings)
37
+ end
38
+
39
+ # grpc api for encrypt gpg
40
+ def gpg_encrypt(unencrypted, _call)
41
+ settings = {}
42
+ settings[:file] = unencrypted.text
43
+ settings[:pw] = unencrypted.password
44
+ settings_process(settings)
45
+ Encrypt.gpgme(settings)
46
+ end
47
+
48
+ # grpc api for ssl decrypt
49
+ def ssl_decrypt(undecrypted, _call)
50
+ settings = {}
51
+ settings[:file] = undecrypted.text
52
+ settings[:key] = undecrypted.key
53
+ settings[:nonce] = undecrypted.nonce
54
+ settings[:tag] = undecrypted.tag
55
+ settings[:pw] = undecrypted.password
56
+ settings_process(settings)
57
+ Decrypt.openssl(settings)
58
+ end
59
+
60
+ # grpc api for gpg decrypt
61
+ def gpg_decrypt(undecrypted, _call)
62
+ settings = {}
63
+ settings[:file] = undecrypted.text
64
+ settings[:pw] = undecrypted.password
65
+ settings_process(settings)
66
+ Decrypt.gpgme(settings)
67
+ end
68
+
69
+ private
70
+
71
+ # helper method
72
+ def settings_process(settings)
73
+ settings[:ui] = :api
74
+ RapidVaults.process(settings)
75
+ settings
76
+ end
77
+ end
@@ -7,11 +7,10 @@ require_relative 'rapid-vaults/binding'
7
7
  class RapidVaults
8
8
  # main runner for software
9
9
  def main(settings)
10
- # process settings
10
+ # process settings via pass-by-reference
11
11
  self.class.process(settings)
12
12
 
13
13
  # execute desired action and algorithm via dynamic call
14
- # public_send("#{settings[:action].capitalize}.#{settings[:algorithm]}".to_sym, settings)
15
14
  case settings[:action]
16
15
  when :generate then Generate.public_send(settings[:algorithm], settings)
17
16
  when :encrypt then Encrypt.public_send(settings[:algorithm], settings)
@@ -22,9 +21,9 @@ class RapidVaults
22
21
 
23
22
  # method for processing the settings and inputs
24
23
  def self.process(settings)
25
- # :outdir only relevant for :cli
24
+ # default to openssl algorithm and `pwd` output directory
26
25
  if settings[:ui] == :cli
27
- # default to openssl algorithm and `pwd` output directory
26
+ # :outdir only relevant for :cli
28
27
  settings[:outdir] ||= Dir.pwd
29
28
  settings[:outdir] += '/' unless settings[:outdir][-1] == '/'
30
29
  end
@@ -33,7 +32,7 @@ class RapidVaults
33
32
  settings[:algorithm] ||= :openssl
34
33
 
35
34
  # check for problems with arguments and inputs
36
- public_send("process_#{settings[:algorithm]}".to_sym, settings)
35
+ public_send(:"process_#{settings[:algorithm]}", settings)
37
36
  end
38
37
 
39
38
  # processing openssl
@@ -50,13 +49,22 @@ class RapidVaults
50
49
  end
51
50
 
52
51
  # lambda for input processing
53
- process_input = ->(input) { File.file?(settings[input]) ? settings[input] = File.read(settings[input]) : (raise "Input #{input} is not an existing file.") }
52
+ process_input = ->(input) { File.readable?(settings[input]) ? settings[input] = File.read(settings[input]) : (raise "Input file '#{settings[input]}' for argument '#{input}' is not an existing readable file.") }
54
53
 
55
54
  # check inputs and read in files
56
55
  raise 'Password must be a string.' if settings.key?(:pw) && !settings[:pw].is_a?(String)
57
56
  %i[file key nonce].each(&process_input)
58
- # only decrypt needs a tag input
57
+
58
+ # validate key and nonce
59
+ raise 'The key is not a valid 32 byte key.' unless settings[:key].bytesize == 32
60
+ raise 'The nonce is not a valid 12 byte nonce.' unless settings[:nonce].bytesize == 12
61
+
62
+ # decrypt: check inputs and read in files, and validate encrypted and tag
63
+ return unless settings[:action] == :decrypt
59
64
  process_input.call(:tag) if settings[:action] == :decrypt
65
+
66
+ raise 'The encrypted data is not a valid multiple of 9 bytes.' unless (settings[:file].bytesize % 9).zero?
67
+ raise 'Tag is not 16 bytes.' unless settings[:tag].bytesize == 16
60
68
  end
61
69
 
62
70
  # processing gpgme
@@ -66,14 +74,12 @@ class RapidVaults
66
74
  case settings[:action]
67
75
  when :generate
68
76
  raise 'GPG params file argument required for generation.' unless settings.key?(:gpgparams)
69
- return
70
77
  when :decrypt, :encrypt
78
+ # check inputs and read in files
71
79
  raise 'File and password arguments required for encryption or decryption.' unless settings.key?(:file) && settings.key?(:pw)
80
+ raise 'Password must be a string.' unless settings[:pw].is_a?(String)
81
+ settings[:file] = File.readable?(settings[:file]) ? File.read(settings[:file]) : (raise "Input file '#{settings[:file]}' for argument 'file' is not an existing readable file.")
72
82
  else raise 'Action must be one of generate, encrypt, or decrypt.'
73
83
  end
74
-
75
- # check inputs and read in files
76
- raise 'Password must be a string.' unless settings[:pw].is_a?(String)
77
- File.file?(settings[:file]) ? settings[:file] = File.read(settings[:file]) : (raise 'Input file is not an existing file.')
78
84
  end
79
85
  end
@@ -0,0 +1,40 @@
1
+ # Classes
2
+ class Binding
3
+ CRYPT: [String, String]
4
+ ACTION: [String, String]
5
+
6
+ def self.puppet: (Hash[Symbol, untyped]) -> nil
7
+ def self.chef: (Hash[Symbol, untyped]) -> nil
8
+ end
9
+
10
+ class Decrypt
11
+ def self.openssl: (Hash[Symbol, untyped]) -> String?
12
+ def self.gpgme: (Hash[Symbol, untyped]) -> String?
13
+ end
14
+
15
+ class Encrypt
16
+ def self.openssl: (Hash[Symbol, untyped]) -> [String, String]?
17
+ def self.gpgme: (Hash[Symbol, untyped]) -> String?
18
+ end
19
+
20
+ class Generate
21
+ def self.openssl: (Hash[Symbol, untyped]) -> [String, String]?
22
+ def self.gpgme: (Hash[Symbol, untyped]) -> nil
23
+ end
24
+
25
+ class RapidVaults
26
+ def main: (Hash[Symbol, untyped]) -> nil
27
+ def self.process: (Hash[Symbol, untyped]) -> nil
28
+ def self.process_openssl: (Hash[Symbol, untyped]) -> nil
29
+ def self.process_gpgme: (Hash[Symbol, untyped]) -> nil
30
+
31
+ class API
32
+ def self.main: (Hash[Symbol, untyped]) -> nil
33
+ def self.parse: (Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
34
+ end
35
+
36
+ class CLI
37
+ def self.main: ([String]) -> Integer
38
+ def self.parse: ([String]) -> Hash[Symbol, untyped]
39
+ end
40
+ end
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'rapid-vaults'
3
+ spec.version = '1.3.0'
4
+ spec.authors = ['Matt Schuchard']
5
+ spec.description = 'Ad-hoc encrypt and decrypt data behind multiple layers of protection via OpenSSL or GPG.'
6
+ spec.summary = 'Ad-hoc encrypt and decrypt data.'
7
+ spec.homepage = 'https://www.github.com/mschuchard/rapid-vaults'
8
+ spec.license = 'MIT'
9
+
10
+ spec.files = Dir['bin/**/*', 'lib/**/*', 'spec/**/*', 'CHANGELOG.md', 'LICENSE.md', 'README.md', 'rapid-vaults.gemspec']
11
+ spec.executables = spec.files.grep(%r{^bin/}) { |file| File.basename(file) }
12
+ spec.require_paths = Dir['lib']
13
+
14
+ spec.required_ruby_version = '>= 2.6.0'
15
+ spec.add_dependency 'gpgme', '~> 2.0'
16
+ spec.add_development_dependency 'grpc', '~> 1.0'
17
+ spec.add_development_dependency 'grpc-tools', '~> 1.0'
18
+ spec.add_development_dependency 'rake', '~> 13.0'
19
+ spec.add_development_dependency 'reek', '~> 6.0'
20
+ spec.add_development_dependency 'rspec', '~> 3.0'
21
+ spec.add_development_dependency 'rubocop', '~> 1.0'
22
+ spec.add_development_dependency 'rubocop-performance', '~> 1.0'
23
+ end
@@ -22,10 +22,10 @@ describe RapidVaults::CLI do
22
22
  expect(RapidVaults::CLI.parse(%w[-b puppet -o .])).to eq(ui: :cli, action: :binding, binding: :puppet, outdir: '.')
23
23
  end
24
24
  it 'raises an error for a nonexistent password file' do
25
- expect { RapidVaults::CLI.parse(%w[-f /nopasswordhere]) }.to raise_error('Password file /nopasswordhere is not an existing file!')
25
+ expect { RapidVaults::CLI.parse(%w[-f /nopasswordhere]) }.to raise_error('Password file /nopasswordhere is not an existing readable file!')
26
26
  end
27
27
  it 'raises an error for a nonexistent gpg parameters file' do
28
- expect { RapidVaults::CLI.parse(%w[--gpgparams /foo/bar]) }.to raise_error('GPG Parameters file /foo/bar is not an existing file!')
28
+ expect { RapidVaults::CLI.parse(%w[--gpgparams /foo/bar]) }.to raise_error('GPG Parameters file /foo/bar is not an existing readable file!')
29
29
  end
30
30
  it 'raises an error for a nonexistent output directory' do
31
31
  expect { RapidVaults::CLI.parse(%w[-o /foo/bar/baz]) }.to raise_error('The output directory /foo/bar/baz does not exist or is not a directory!')
@@ -4,8 +4,13 @@ require_relative '../../lib/rapid-vaults/decrypt'
4
4
 
5
5
  describe Decrypt do
6
6
  context '.openssl' do
7
+ require 'openssl'
8
+ cipher = OpenSSL::Cipher.new('aes-256-gcm').encrypt
9
+ key = cipher.random_key
10
+ nonce = cipher.random_iv
11
+
7
12
  before(:all) do
8
- Encrypt.openssl(ui: :cli, file: "foo: bar\n", key: '���b+����R�v�Í%("����=8o/���', nonce: 'Ëá!í^Uë^EÜ<83>oã^M')
13
+ Encrypt.openssl(ui: :cli, file: "foo: bar\n", key: key, nonce: nonce)
9
14
  end
10
15
 
11
16
  after(:all) do
@@ -13,41 +18,35 @@ describe Decrypt do
13
18
  end
14
19
 
15
20
  it 'outputs a decrypted file with the key, nonce, and tag from the cli' do
16
- Decrypt.openssl(ui: :cli, file: File.read('encrypted.txt'), key: '���b+����R�v�Í%("����=8o/���', nonce: 'Ëá!í^Uë^EÜ<83>oã^M', tag: File.read('tag.txt'))
21
+ Decrypt.openssl(ui: :cli, file: File.read('encrypted.txt'), key: key, nonce: nonce, tag: File.read('tag.txt'))
17
22
  expect(File.file?('decrypted.txt')).to be true
18
23
  expect(File.read('decrypted.txt')).to eq("foo: bar\n")
19
24
  end
20
25
  it 'outputs decrypted content with the key, nonce, and tag from the api' do
21
- decrypt = Decrypt.openssl(ui: :api, file: File.read('encrypted.txt'), key: '���b+����R�v�Í%("����=8o/���', nonce: 'Ëá!í^Uë^EÜ<83>oã^M', tag: File.read('tag.txt'))
26
+ decrypt = Decrypt.openssl(ui: :api, file: File.read('encrypted.txt'), key: key, nonce: nonce, tag: File.read('tag.txt'))
22
27
  expect(decrypt).to be_a(String)
23
28
  expect(decrypt).to eq("foo: bar\n")
24
29
  end
25
- it 'raises an error for an invalid tag size' do
26
- expect { Decrypt.openssl(file: File.read('encrypted.txt'), key: '���b+����R�v�Í%("����=8o/���', nonce: 'Ëá!í^Uë^EÜ<83>oã^M', tag: "�a����e�O_H|�\n") }.to raise_error('Tag is not 16 bytes.')
27
- end
28
30
  end
29
31
 
30
- # travis ci cannot support non-interactive gpg encryption
31
- unless File.directory?('/home/travis')
32
- context '.gpgme' do
33
- before(:all) do
34
- Encrypt.gpgme(ui: :cli, file: "foo: bar\n", key: '', pw: 'foo')
35
- end
32
+ context '.gpgme' do
33
+ before(:all) do
34
+ Encrypt.gpgme(ui: :cli, file: "foo: bar\n", key: '', pw: 'foo')
35
+ end
36
36
 
37
- after(:all) do
38
- %w[encrypted.txt decrypted.txt].each { |file| File.delete(file) }
39
- end
37
+ after(:all) do
38
+ %w[encrypted.txt decrypted.txt].each { |file| File.delete(file) }
39
+ end
40
40
 
41
- it 'outputs a decrypted file with the key from the cli' do
42
- Decrypt.gpgme(ui: :cli, file: File.read('encrypted.txt'), key: '', pw: 'foo')
43
- expect(File.file?('decrypted.txt')).to be true
44
- expect(File.read('decrypted.txt')).to eq("foo: bar\n")
45
- end
46
- it 'outputs decrypted content with the key from the api' do
47
- decrypt = Decrypt.gpgme(ui: :api, file: File.read('encrypted.txt'), key: '', pw: 'foo')
48
- expect(decrypt).to be_a(String)
49
- expect(decrypt).to eq("foo: bar\n")
50
- end
41
+ it 'outputs a decrypted file with the key from the cli' do
42
+ Decrypt.gpgme(ui: :cli, file: File.read('encrypted.txt'), key: '', pw: 'foo')
43
+ expect(File.file?('decrypted.txt')).to be true
44
+ expect(File.read('decrypted.txt')).to eq("foo: bar\n")
45
+ end
46
+ it 'outputs decrypted content with the key from the api' do
47
+ decrypt = Decrypt.gpgme(ui: :api, file: File.read('encrypted.txt'), key: '', pw: 'foo')
48
+ expect(decrypt).to be_a(String)
49
+ expect(decrypt).to eq("foo: bar\n")
51
50
  end
52
51
  end
53
52
  end
@@ -3,40 +3,42 @@ require_relative '../../lib/rapid-vaults/encrypt'
3
3
 
4
4
  describe Encrypt do
5
5
  context '.openssl' do
6
+ require 'openssl'
7
+ cipher = OpenSSL::Cipher.new('aes-256-gcm').encrypt
8
+ key = cipher.random_key
9
+ nonce = cipher.random_iv
10
+
6
11
  after(:all) do
7
12
  %w[tag.txt encrypted.txt].each { |file| File.delete(file) }
8
13
  end
9
14
 
10
15
  it 'outputs an encrypted file with the key and nonce from the cli' do
11
- Encrypt.openssl(ui: :cli, file: "foo: bar\n", key: '���b+����R�v�Í%("����=8o/���', nonce: 'Ëá!í^Uë^EÜ<83>oã^M')
16
+ Encrypt.openssl(ui: :cli, file: "foo: bar\n", key: key, nonce: nonce)
12
17
  expect(File.file?('tag.txt')).to be true
13
18
  expect(File.file?('encrypted.txt')).to be true
14
19
  end
15
20
  it 'outputs an encrypted file with the key, nonce, and password from the cli' do
16
- Encrypt.openssl(ui: :cli, file: "foo: bar\n", key: '���b+����R�v�Í%("����=8o/���', nonce: 'Ëá!í^Uë^EÜ<83>oã^M', pw: 'password')
21
+ Encrypt.openssl(ui: :cli, file: "foo: bar\n", key: key, nonce: nonce, pw: 'password')
17
22
  expect(File.file?('tag.txt')).to be true
18
23
  expect(File.file?('encrypted.txt')).to be true
19
24
  end
20
25
  it 'outputs an array of encrypted content and tag with the key and nonce from the api' do
21
- encrypt = Encrypt.openssl(ui: :api, file: "foo: bar\n", key: '���b+����R�v�Í%("����=8o/���', nonce: 'Ëá!í^Uë^EÜ<83>oã^M')
26
+ encrypt = Encrypt.openssl(ui: :api, file: "foo: bar\n", key: key, nonce: nonce)
22
27
  expect(encrypt).to be_a(Array)
28
+ expect(encrypt.length).to eq(2)
23
29
  expect(encrypt[0]).to be_a(String)
24
30
  expect(encrypt[1]).to be_a(String)
25
- expect(encrypt.length).to eq(2)
26
31
  end
27
32
  end
28
33
 
29
- # travis ci cannot support non-interactive gpg encryption
30
- unless File.directory?('/home/travis')
31
- context '.gpgme' do
32
- it 'outputs an encrypted file with the key from the cli' do
33
- Encrypt.gpgme(ui: :cli, file: "foo: bar\n", key: '', pw: 'foo')
34
- expect(File.file?('encrypted.txt')).to be true
35
- end
36
- it 'outputs a string of encrypted content with the key from the api' do
37
- encrypt = Encrypt.gpgme(ui: :api, file: "foo: bar\n", key: '', pw: 'foo')
38
- expect(encrypt).to be_a(String)
39
- end
34
+ context '.gpgme' do
35
+ it 'outputs an encrypted file with the key from the cli' do
36
+ Encrypt.gpgme(ui: :cli, file: "foo: bar\n", key: '', pw: 'foo')
37
+ expect(File.file?('encrypted.txt')).to be true
38
+ end
39
+ it 'outputs a string of encrypted content with the key from the api' do
40
+ encrypt = Encrypt.gpgme(ui: :api, file: "foo: bar\n", key: '', pw: 'foo')
41
+ expect(encrypt).to be_a(String)
40
42
  end
41
43
  end
42
44
  end
@@ -17,9 +17,9 @@ describe Generate do
17
17
  it 'outputs an array with the key and nonce from the api' do
18
18
  generate = Generate.openssl(ui: :api)
19
19
  expect(generate).to be_a(Array)
20
+ expect(generate.length).to eq(2)
20
21
  expect(generate[0]).to be_a(String)
21
22
  expect(generate[1]).to be_a(String)
22
- expect(generate.length).to eq(2)
23
23
  end
24
24
  end
25
25
 
@@ -27,24 +27,21 @@ describe Generate do
27
27
  it 'raises an error for a missing GNUPGHOME variable' do
28
28
  expect { Generate.gpgme(gpgparams: File.read("#{fixtures_dir}/gpgparams.txt")) }.to raise_error('Environment variable "GNUPGHOME" was not set.')
29
29
  end
30
- # travis ci cannot support non-interactive gpg
31
- unless File.directory?('/home/travis')
32
- it 'generates the key files' do
33
- require 'fileutils'
30
+ it 'generates the key files' do
31
+ require 'fileutils'
34
32
 
35
- ENV['GNUPGHOME'] = fixtures_dir
33
+ ENV['GNUPGHOME'] = fixtures_dir
36
34
 
37
- Generate.gpgme(gpgparams: File.read("#{fixtures_dir}/gpgparams.txt"))
38
- %w[trustdb.gpg pubring.kbx pubring.kbx~].each do |file|
39
- expect(File.file?("#{fixtures_dir}/#{file}")).to be true
40
- File.delete("#{fixtures_dir}/#{file}")
41
- end
42
- %w[openpgp-revocs.d private-keys-v1.d].each do |dir|
43
- expect(File.directory?("#{fixtures_dir}/#{dir}")).to be true
44
- FileUtils.rm_r("#{fixtures_dir}/#{dir}")
45
- end
46
- %w[S.gpg-agent random_seed].each { |file| File.delete("#{fixtures_dir}/#{file}") if File.exist?(file) }
35
+ Generate.gpgme(gpgparams: File.read("#{fixtures_dir}/gpgparams.txt"))
36
+ %w[trustdb.gpg pubring.kbx pubring.kbx~].each do |file|
37
+ expect(File.file?("#{fixtures_dir}/#{file}")).to be true
38
+ File.delete("#{fixtures_dir}/#{file}")
39
+ end
40
+ %w[openpgp-revocs.d private-keys-v1.d].each do |dir|
41
+ expect(File.directory?("#{fixtures_dir}/#{dir}")).to be true
42
+ FileUtils.rm_r("#{fixtures_dir}/#{dir}")
47
43
  end
44
+ %w[S.gpg-agent random_seed].each { |file| File.delete("#{fixtures_dir}/#{file}") if File.file?(file) }
48
45
  end
49
46
  end
50
47
  end
@@ -0,0 +1,50 @@
1
+ require_relative '../../lib/rapid-vaults/grpc'
2
+
3
+ # TODO: use RapidVaults::GRPC.server instead?
4
+
5
+ # stub = Rapidvaults::RapidVaults::Stub.new('localhost:0.0.0.0:8080', :this_channel_is_insecure)
6
+ describe GRPC do
7
+ context '.Stub' do
8
+ it 'starts a rapaid-vaults api local server' do
9
+ expect { Rapidvaults::RapidVaults::Stub.new('localhost:0.0.0.0:8080', :this_channel_is_insecure) }.not_to raise_error
10
+ end
11
+ end
12
+ end
13
+
14
+ # need to create class with encode member method to pass in as dummy
15
+ # ssl generate
16
+ # outputs = stub.ssl_generate('string')
17
+ =begin
18
+ puts outputs.key
19
+ puts outputs.nonce
20
+
21
+ # gpg generate
22
+ stub.gpg_generate
23
+
24
+ # ssl encrypt
25
+ # TODO: unencrypted should be an object
26
+ unencrypted.text = ''
27
+ unencrypted.key = ''
28
+ unencrypted.nonce = ''
29
+ outputs = stub.ssl_encrypt(unencrypted)
30
+ puts outputs.text
31
+ puts outputs.tag
32
+
33
+ # gpg encrypt
34
+ unencrypted.text = ''
35
+ unencrypted.password = ''
36
+ puts stub.gpg_encrypt(unencrypted).text
37
+
38
+ # ssl decrypt
39
+ # TODO: undecrypted should be an object
40
+ undecrypted.text = ''
41
+ undecrypted.key = ''
42
+ undecrypted.nonce = ''
43
+ undecrypted.tag = ''
44
+ puts stub.ssl_decrypt(undecrypted).text
45
+
46
+ # gpg decrypt
47
+ undecrypted.text = ''
48
+ undecrypted.password = ''
49
+ puts stub.gpg_decrypt(undecrypted).text
50
+ =end
@@ -0,0 +1,73 @@
1
+ require_relative 'spec_helper'
2
+ require_relative '../lib/rapid_vaults'
3
+
4
+ describe RapidVaults do
5
+ context '.process' do
6
+ # prepare for support file validation tests
7
+ require 'securerandom'
8
+ before(:all) do
9
+ File.write('key_bad.txt', SecureRandom.random_bytes(64).strip)
10
+ File.write('key_good.txt', SecureRandom.random_bytes(32).strip)
11
+ File.write('nonce_bad.txt', SecureRandom.random_bytes(24).strip)
12
+ File.write('nonce_good.txt', SecureRandom.random_bytes(12).strip)
13
+ File.write('tag_bad.txt', SecureRandom.random_bytes(24).strip)
14
+ File.write('tag_good.txt', SecureRandom.random_bytes(16).strip)
15
+ File.write('encrypted_bad.txt', SecureRandom.random_bytes(16).strip)
16
+ File.write('encrypted_good.txt', '')
17
+ end
18
+
19
+ after(:all) do
20
+ %w[key nonce tag encrypted].each { |file| File.delete("#{file}_bad.txt", "#{file}_good.txt") }
21
+ end
22
+
23
+ it 'raises an error for a non-string password with openssl' do
24
+ expect { RapidVaults.process(action: :encrypt, file: 'a', key: 'b', nonce: 'c', pw: 1) }.to raise_error('Password must be a string.')
25
+ end
26
+ it 'raises an error for a non-string password with gpgme' do
27
+ expect { RapidVaults.process(action: :encrypt, file: 'a', key: 'b', nonce: 'c', pw: 1) }.to raise_error('Password must be a string.')
28
+ end
29
+ it 'raises an error for a missing argument to generate with gpgme' do
30
+ expect { RapidVaults.process(algorithm: :gpgme, action: :generate) }.to raise_error('GPG params file argument required for generation.')
31
+ end
32
+ it 'raises an error for a missing argument to encrypt with openssl' do
33
+ expect { RapidVaults.process(action: :encrypt, file: 'a', key: 'b') }.to raise_error('File, key, and nonce arguments are required for encryption.')
34
+ end
35
+ it 'raises an error for a missing argument to decrypt with openssl' do
36
+ expect { RapidVaults.process(action: :decrypt, file: 'a', key: 'b', nonce: 'c') }.to raise_error('File, key, nonce, and tag arguments are required for decryption.')
37
+ end
38
+ it 'raises an error for a missing argument to decrypt with gpgme' do
39
+ expect { RapidVaults.process(algorithm: :gpgme, action: :decrypt, file: 'a') }.to raise_error('File and password arguments required for encryption or decryption.')
40
+ end
41
+ it 'raises an error for a missing action with openssl' do
42
+ expect { RapidVaults.process(file: 'a', key: 'b', nonce: 'c', tag: 'd') }.to raise_error('Action must be one of generate, encrypt, or decrypt.')
43
+ end
44
+ it 'raises an error for a missing action with gpgme' do
45
+ expect { RapidVaults.process(algorithm: :gpgme, file: 'a', key: 'b') }.to raise_error('Action must be one of generate, encrypt, or decrypt.')
46
+ end
47
+ it 'raises an error for a nonexistent input file with openssl' do
48
+ expect { RapidVaults.process(action: :encrypt, file: 'a', key: 'b', nonce: 'c', tag: 'd') }.to raise_error('Input file \'a\' for argument \'file\' is not an existing readable file.')
49
+ end
50
+ it 'raises an error for a nonexistent input file with gpgme' do
51
+ expect { RapidVaults.process(algorithm: :gpgme, action: :encrypt, file: 'a', pw: 'password') }.to raise_error('Input file \'a\' for argument \'file\' is not an existing readable file.')
52
+ end
53
+ it 'raises an error for an invalid key size' do
54
+ expect { RapidVaults.process(action: :encrypt, file: "#{fixtures_dir}file.yaml", key: 'key_bad.txt', nonce: 'nonce_good.txt') }.to raise_error('The key is not a valid 32 byte key.')
55
+ end
56
+ it 'raises an error for an invalid nonce size' do
57
+ expect { RapidVaults.process(action: :encrypt, file: "#{fixtures_dir}file.yaml", key: 'key_good.txt', nonce: 'nonce_bad.txt') }.to raise_error('The nonce is not a valid 12 byte nonce.')
58
+ end
59
+ it 'raises an error for an invalid tag size' do
60
+ expect { RapidVaults.process(action: :decrypt, file: 'encrypted_good.txt', key: 'key_good.txt', nonce: 'nonce_good.txt', tag: 'tag_bad.txt') }.to raise_error('Tag is not 16 bytes.')
61
+ end
62
+ it 'raises an error for corrupted encrypted file content' do
63
+ expect { RapidVaults.process(action: :decrypt, file: 'encrypted_bad.txt', key: 'key_good.txt', nonce: 'nonce_good.txt', tag: 'tag_good.txt') }.to raise_error('The encrypted data is not a valid multiple of 9 bytes.')
64
+ end
65
+ it 'reads in all input files correctly for openssl encryption' do
66
+ expect { RapidVaults.process(action: :decrypt, file: 'encrypted_good.txt', key: 'key_good.txt', nonce: 'nonce_good.txt', tag: 'tag_good.txt', pw: 'password') }.not_to raise_exception
67
+ end
68
+ it 'reads in all input files correctly for gpgme decryption' do
69
+ dummy = "#{fixtures_dir}file.yaml"
70
+ expect { RapidVaults.process(algorithm: :gpgme, action: :decrypt, file: dummy, pw: 'password') }.not_to raise_exception
71
+ end
72
+ end
73
+ end
data/spec/spec_helper.rb CHANGED
@@ -4,7 +4,7 @@ require 'rspec'
4
4
  module Variables
5
5
  extend RSpec::SharedContext
6
6
 
7
- let(:fixtures_dir) { File.dirname(__FILE__) + '/fixtures/' }
7
+ let(:fixtures_dir) { "#{File.dirname(__FILE__)}/fixtures/" }
8
8
  end
9
9
 
10
10
  RSpec.configure do |config|
@@ -7,13 +7,13 @@ describe RapidVaults do
7
7
  require 'fileutils'
8
8
 
9
9
  %w[key.txt nonce.txt tag.txt encrypted.txt decrypted.txt chef.rb puppet_gpg_decrypt.rb puppet_gpg_encrypt.rb puppet_ssl_decrypt.rb puppet_ssl_encrypt.rb].each { |file| File.delete(file) }
10
- unless File.directory?('/home/travis')
11
- %w[random_seed pubring.kbx trustdb.gpg pubring.kbx~ S.gpg-agent].each { |file| File.delete(file) }
10
+ unless ENV['CIRCLECI'] == 'true' || ENV['GITHUB_ACTIONS'] == 'true'
11
+ %w[random_seed pubring.kbx trustdb.gpg pubring.kbx~].each { |file| File.delete(file) }
12
12
  %w[openpgp-revocs.d private-keys-v1.d].each { |dir| FileUtils.rm_r(dir) }
13
13
  end
14
14
  end
15
15
 
16
- context 'executed as a system from the CLI with settings and a file to be processed' do
16
+ context 'executed with openssl algorithm as a system from the CLI with settings and a file to be processed' do
17
17
  it 'generates key and nonce, encrypts a file, and then decrypts a file in order' do
18
18
  # generate and utilize files inside suitable directory
19
19
  Dir.chdir(fixtures_dir)
@@ -35,7 +35,7 @@ describe RapidVaults do
35
35
  end
36
36
  end
37
37
 
38
- context 'executed as a system from the API with settings and a file to be processed' do
38
+ context 'executed with openssl algorithm as a system from the API with settings and a file to be processed' do
39
39
  it 'generates key and nonce, encrypts a file, and then decrypts a file in order' do
40
40
  # generate and utilize files inside suitable directory
41
41
  Dir.chdir(fixtures_dir)
@@ -59,17 +59,15 @@ describe RapidVaults do
59
59
  end
60
60
  end
61
61
 
62
- # travis ci cannot support non-interactive gpg encryption
63
- unless File.directory?('/home/travis')
64
- context 'executed wtih gpg as a system from the CLI with settings and a file to be processed' do
62
+ # ci platforms cannot support end-to-end gpg generate/encrypt/decrypt
63
+ unless ENV['CIRCLECI'] == 'true' || ENV['GITHUB_ACTIONS'] == 'true'
64
+ context 'executed wtih gpg algorithm as a system from the CLI with settings and a file to be processed' do
65
65
  it 'encrypts a file and then decrypts a file in order' do
66
66
  ENV['GNUPGHOME'] = fixtures_dir
67
67
 
68
68
  # generate and utilize files inside suitable directory
69
69
  Dir.chdir(fixtures_dir)
70
70
 
71
- puts fixtures_dir
72
-
73
71
  # generate keys
74
72
  RapidVaults::CLI.main(%w[-g --gpg --gpgparams gpgparams.txt])
75
73
  %w[trustdb.gpg pubring.kbx pubring.kbx~].each { |file| expect(File.file?("#{fixtures_dir}/#{file}")).to be true }
@@ -86,7 +84,7 @@ describe RapidVaults do
86
84
  end
87
85
  end
88
86
 
89
- context 'executed with gpg as a system from the API with settings and a file to be processed' do
87
+ context 'executed with gpg algorithm as a system from the API with settings and a file to be processed' do
90
88
  it 'encrypts a file and then decrypts a file in order' do
91
89
  ENV['GNUPGHOME'] = fixtures_dir
92
90
 
@@ -94,7 +92,7 @@ describe RapidVaults do
94
92
  Dir.chdir(fixtures_dir)
95
93
 
96
94
  # generate keys
97
- RapidVaults::API.main(action: :generate, algorithm: :gpgme, gpgparams: File.read('gpgparams.txt'), ui: :cli)
95
+ RapidVaults::API.main(action: :generate, algorithm: :gpgme, gpgparams: File.read('gpgparams.txt'))
98
96
  %w[trustdb.gpg pubring.kbx pubring.kbx~].each { |file| expect(File.file?("#{fixtures_dir}/#{file}")).to be true }
99
97
  %w[openpgp-revocs.d private-keys-v1.d].each { |dir| expect(File.directory?("#{fixtures_dir}/#{dir}")).to be true }
100
98