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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/LICENSE.md +20 -0
- data/README.md +46 -35
- data/lib/rapid-vaults/api.rb +4 -5
- data/lib/rapid-vaults/binding.rb +6 -2
- data/lib/rapid-vaults/bindings/chef.rb +33 -29
- data/lib/rapid-vaults/bindings/puppet_gpg_decrypt.rb +1 -1
- data/lib/rapid-vaults/bindings/puppet_gpg_encrypt.rb +1 -1
- data/lib/rapid-vaults/bindings/puppet_ssl_decrypt.rb +7 -6
- data/lib/rapid-vaults/bindings/puppet_ssl_encrypt.rb +10 -8
- data/lib/rapid-vaults/bindings/rapid_vaults_pb.rb +20 -0
- data/lib/rapid-vaults/bindings/rapid_vaults_services_pb.rb +33 -0
- data/lib/rapid-vaults/cli.rb +9 -9
- data/lib/rapid-vaults/decrypt.rb +7 -8
- data/lib/rapid-vaults/encrypt.rb +10 -8
- data/lib/rapid-vaults/generate.rb +6 -5
- data/lib/rapid-vaults/grpc.rb +77 -0
- data/lib/{rapid-vaults.rb → rapid_vaults.rb} +18 -12
- data/lib/rapid_vaults.rbs +40 -0
- data/rapid-vaults.gemspec +23 -0
- data/spec/rapid-vaults/cli_spec.rb +2 -2
- data/spec/rapid-vaults/decrypt_spec.rb +24 -25
- data/spec/rapid-vaults/encrypt_spec.rb +17 -15
- data/spec/rapid-vaults/generate_spec.rb +13 -16
- data/spec/rapid-vaults/grpc_spec.rb +50 -0
- data/spec/rapid_vaults_spec.rb +73 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/system/system_spec.rb +9 -11
- metadata +70 -44
- data/spec/rapid-vaults_spec.rb +0 -39
@@ -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
|
-
#
|
24
|
+
# default to openssl algorithm and `pwd` output directory
|
26
25
|
if settings[:ui] == :cli
|
27
|
-
#
|
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]}"
|
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.
|
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
|
-
|
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:
|
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:
|
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:
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
37
|
+
after(:all) do
|
38
|
+
%w[encrypted.txt decrypted.txt].each { |file| File.delete(file) }
|
39
|
+
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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:
|
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:
|
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:
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
31
|
-
|
32
|
-
it 'generates the key files' do
|
33
|
-
require 'fileutils'
|
30
|
+
it 'generates the key files' do
|
31
|
+
require 'fileutils'
|
34
32
|
|
35
|
-
|
33
|
+
ENV['GNUPGHOME'] = fixtures_dir
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
data/spec/system/system_spec.rb
CHANGED
@@ -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
|
11
|
-
%w[random_seed pubring.kbx trustdb.gpg pubring.kbx~
|
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
|
-
#
|
63
|
-
unless
|
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')
|
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
|
|