rapid-vaults 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 928d90da27078d0b09c9a933e3054d8a3b26183dc5f0dc88e70fe84d2726c6cb
4
- data.tar.gz: 1a4c48a2dbcba14708170f0209105a5523d6fd1286e7ee6ef5d6509c728fe96a
3
+ metadata.gz: eab7b432d2da9ded261c422b220051585469fdd3c93dad84b2e4b9c8b272f20a
4
+ data.tar.gz: ce1aa65551bea26216d87c1137cb076b75b501bac785380ae78dd3161b5b0d7a
5
5
  SHA512:
6
- metadata.gz: 248e094660ee327365c43feebd24361ef99038b83b8b52ad8efde76fa1f6727b2f275c1ca0e5a5caae39cefa5fc4423c1aeee6616e4798e3fb461e9507af3047
7
- data.tar.gz: 4b56a0496557448fb94d6e4c4ba5277448972a0c1518bac0a0c21e2cdfb5f6aecbefb9e9dc4289b3575c20c63874cb3dc227e300a643e406eab71e0563cc7130
6
+ metadata.gz: 59f7a29f22852e58074bd85823028b178f23117c7adb3ce491a18271263f4cf92cc8e201e8bd31949a3d0b106879802755d4bd393909a57b21f295b6123585b6
7
+ data.tar.gz: 6048157efbe27b351b50b102fc2dcc19604de178d6282b45098beb3d51669ff4b833ae06051a727c5768a7b933b04c3cb6850bb9644e5d6b236df95117a081ad
data/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # Rapid Vaults
2
2
  [![Build Status](https://travis-ci.org/mschuchard/rapid-vaults.svg?branch=master)](https://travis-ci.org/mschuchard/rapid-vaults)
3
+ [![CircleCI](https://circleci.com/gh/mschuchard/rapid-vaults.svg?style=svg)](https://circleci.com/gh/mschuchard/rapid-vaults)
3
4
 
4
5
  - [Description](#description)
5
6
  - [Usage](#usage)
6
7
  - [CLI](#cli)
7
8
  - [API](#api)
9
+ - [gRPC](#grpc)
10
+ - [Docker](#docker)
8
11
  - [Ansible](#ansible)
9
12
  - [Puppet](#puppet)
10
- - [Hiera](#hiera)
11
13
  - [Chef](#chef)
12
14
  - [Contributing](#contributing)
13
15
 
@@ -21,7 +23,7 @@ Ansible-Vault is very similar to Rapid Vaults. Both are streamlined and easy to
21
23
 
22
24
  ### Non-Comparative Software
23
25
 
24
- Rapid Vaults is not similar to tools like RbNaCl or Hashicorp's Vault. RbNaCl offers advanced encryption techniques by providing bindings to libsodium. Rapid Vaults relies upon AES-256-GCM (OpenSSL) or GPG's algorithms (RSA, SHA-512, etc.). Hashicorp's Vault is Enterprise level software with many powerful features and conveniences. Rapid Vaults is a lightweight and narrowly focused tool.
26
+ Rapid Vaults is not similar to tools like RbNaCl or Hashicorp's Vault. RbNaCl offers advanced encryption techniques by providing bindings to libsodium. Rapid Vaults relies upon AES-256-GCM (OpenSSL) or GPG's algorithms (RSA, SHA-512, etc.). Hashicorp's Vault is Enterprise level software with many powerful features and conveniences. Rapid Vaults is a lightweight and narrowly focused tool. However, Rapid Vaults can be considered algorithmically very similar to Vault's Transit secret engine.
25
27
 
26
28
  ## Usage
27
29
 
@@ -50,11 +52,11 @@ usage: rapid-vaults [options] file
50
52
 
51
53
  #### Encrypt File with SSL
52
54
 
53
- `rapid-vaults -e -k cert.key -n nonce.txt -p secret -o /output/dir unencrypted.txt`
55
+ `rapid-vaults -e -k key.txt -n nonce.txt -p secret -o /output/dir unencrypted.txt`
54
56
 
55
57
  #### Decrypt a File with SSL
56
58
 
57
- `rapid-vaults -d -k cert.key -n nonce.txt -t tag.txt -p secret -o /output/dir encrypted.txt`
59
+ `rapid-vaults -d -k key.txt -n nonce.txt -t tag.txt -p secret -o /output/dir encrypted.txt`
58
60
 
59
61
  #### Generate Keys with GPG
60
62
  This is the only situation where a `--gpgparams` flag and argument is required or utilized. The file provided as the argument should look like the following:
@@ -112,7 +114,7 @@ require 'rapid-vaults'
112
114
  options = {}
113
115
  options[:action] = :encrypt
114
116
  options[:file] = '/path/to/data.txt'
115
- options[:key] = '/path/to/cert.key'
117
+ options[:key] = '/path/to/key.txt'
116
118
  options[:nonce] = '/path/to/nonce.txt'
117
119
  options[:pw] = File.read('/path/to/password.txt') # optional
118
120
  encrypted_contents, tag = RapidVaults::API.main(options)
@@ -126,7 +128,7 @@ require 'rapid-vaults'
126
128
  options = {}
127
129
  options[:action] = :decrypt
128
130
  options[:file] = '/path/to/encrypted_data.txt'
129
- options[:key] = '/path/to/cert.key'
131
+ options[:key] = '/path/to/key.txt'
130
132
  options[:nonce] = '/path/to/nonce.txt'
131
133
  options[:tag] = '/path/to/tag.txt'
132
134
  options[:pw] = File.read('/path/to/password.txt') # optional
@@ -192,6 +194,14 @@ options[:pw] = File.read('/path/to/password.txt')
192
194
  decrypted_contents = RapidVaults::API.main(options)
193
195
  ```
194
196
 
197
+ ### Docker
198
+
199
+ A supported [Docker image](https://hub.docker.com/r/matthewschuchard/rapid-vaults) of Rapid-Vaults is now available from the public Docker Hub registry. Please consult the repository documentation for further usage information.
200
+
201
+ ### gRPC
202
+
203
+ forthcoming
204
+
195
205
  ### Ansible
196
206
 
197
207
  forthcoming
@@ -1,17 +1,16 @@
1
- require_relative '../rapid-vaults'
1
+ require_relative '../rapid_vaults'
2
2
 
3
3
  # provides an application programming interface to interact with rapid vaults
4
4
  class RapidVaults::API
5
5
  # lightweight api
6
6
  def self.main(settings)
7
- # parse settings for api and run RapidVaults with specified settings
7
+ # parse pass-by-value settings for api and run RapidVaults with specified settings
8
8
  RapidVaults.new.main(parse(settings))
9
9
  end
10
10
 
11
- # parse api options
11
+ # parse api options; this is mostly here for unit testing
12
12
  def self.parse(settings)
13
13
  # establish settings for api and denote using api
14
- settings[:ui] = :api
15
- settings
14
+ settings.merge({ ui: :api })
16
15
  end
17
16
  end
@@ -1,5 +1,5 @@
1
1
  # mymodule/lib/puppet/functions/gpg_decrypt.rb
2
- Puppet::Functions.create_function(:'gpg_decrypt') do
2
+ Puppet::Functions.create_function(:gpg_decrypt) do
3
3
  # Decrypts a file with GnuPG.
4
4
  # @param [String] file The file to decrypt.
5
5
  # @param [String] gpghome The path to the GnuPG home directory containing the credentials.
@@ -1,5 +1,5 @@
1
1
  # mymodule/lib/puppet/functions/gpg_encrypt.rb
2
- Puppet::Functions.create_function(:'gpg_encrypt') do
2
+ Puppet::Functions.create_function(:gpg_encrypt) do
3
3
  # Encrypts a file with GnuPG.
4
4
  # @param [String] file The file to encrypt.
5
5
  # @param [String] gpghome The path to the GnuPG home directory containing the credentials.
@@ -1,5 +1,5 @@
1
1
  # mymodule/lib/puppet/functions/ssl_decrypt.rb
2
- Puppet::Functions.create_function(:'ssl_decrypt') do
2
+ Puppet::Functions.create_function(:ssl_decrypt) do
3
3
  # Decrypts a file with OpenSSL.
4
4
  # @param [String] file The file to decrypt.
5
5
  # @param [String] key The key file to use for decryption.
@@ -25,10 +25,11 @@ Puppet::Functions.create_function(:'ssl_decrypt') do
25
25
  raise 'Rapid Vaults is required to be installed on the puppet master to use this custom function!'
26
26
  end
27
27
 
28
- if password_file.nil?
29
- RapidVaults::API.main(action: :decrypt, file: file, key: key, nonce: nonce, tag: tag)
30
- else
31
- RapidVaults::API.main(action: :encrypt, file: file, key: key, nonce: nonce, tag: tag, pw: File.read(password_file))
32
- end
28
+ # initialize settings
29
+ settings = { action: :decrypt, file: file, key: key, nonce: nonce, tag: tag }
30
+ # update settings with password if input
31
+ settings[pw: File.read(password_file)] unless password_file.nil?
32
+
33
+ RapidVaults::API.main(settings)
33
34
  end
34
35
  end
@@ -1,5 +1,5 @@
1
1
  # mymodule/lib/puppet/functions/ssl_encrypt.rb
2
- Puppet::Functions.create_function(:'ssl_encrypt') do
2
+ Puppet::Functions.create_function(:ssl_encrypt) do
3
3
  # Encrypts a file with OpenSSL.
4
4
  # @param [String] file The file to encrypt.
5
5
  # @param [String] key The key file to use for encryption.
@@ -23,12 +23,14 @@ Puppet::Functions.create_function(:'ssl_encrypt') do
23
23
  raise 'Rapid Vaults is required to be installed on the puppet master to use this custom function!'
24
24
  end
25
25
 
26
- hash = {}
27
- if password_file.nil?
28
- hash[:encrypted_contents], hash[:tag] = RapidVaults::API.main(action: :encrypt, file: file, key: key, nonce: nonce)
29
- else
30
- hash[:encrypted_contents], hash[:tag] = RapidVaults::API.main(action: :encrypt, file: file, key: key, nonce: nonce, pw: File.read(password_file))
31
- end
32
- hash
26
+ # initialize settings and return
27
+ settings = { action: :encrypt, file: file, key: key, nonce: nonce }
28
+ return_hash = {}
29
+ # update settings with password if input
30
+ settings[pw: File.read(password_file)] unless password_file.nil?
31
+
32
+ return_hash[:encrypted_contents], return_hash[:tag] = RapidVaults::API.main(settings)
33
+
34
+ return_hash
33
35
  end
34
36
  end
@@ -1,4 +1,4 @@
1
- require_relative '../rapid-vaults'
1
+ require_relative '../rapid_vaults'
2
2
 
3
3
  # provides a command line interface to interact with rapid vaults
4
4
  class RapidVaults::CLI
@@ -22,10 +22,8 @@ class RapidVaults::CLI
22
22
  # show help message if no args specified
23
23
  args = %w[-h] if args.empty?
24
24
 
25
- # init settings
26
- settings = {}
27
- # specify cli being used
28
- settings[:ui] = :cli
25
+ # init settings with cli setting
26
+ settings = { ui: :cli }
29
27
 
30
28
  opt_parser = OptionParser.new do |opts|
31
29
  # usage
@@ -33,7 +31,7 @@ class RapidVaults::CLI
33
31
 
34
32
  # base options
35
33
  opts.on('--version', 'Display the current version.') do
36
- puts 'rapid-vaults 1.1.2'
34
+ puts 'rapid-vaults 1.2.0'
37
35
  exit 0
38
36
  end
39
37
 
@@ -4,7 +4,10 @@ class Decrypt
4
4
  def self.openssl(settings)
5
5
  require 'openssl'
6
6
 
7
- # check tag size
7
+ # validate key, nonce, encrypted, and tag
8
+ raise 'The key is not a valid 32 byte key.' unless settings[:key].bytesize == 32
9
+ raise 'The nonce is not a valid 12 byte nonce.' unless settings[:nonce].bytesize == 12
10
+ raise 'The encrypted data is not a valid multiple of 9 bytes.' unless (settings[:file].bytesize % 9).zero?
8
11
  raise 'Tag is not 16 bytes.' unless settings[:tag].bytesize == 16
9
12
 
10
13
  # setup the decryption parameters
@@ -15,11 +18,12 @@ class Decrypt
15
18
  decipher.auth_data = settings.key?(:pw) ? settings[:pw] : ''
16
19
 
17
20
  # output the decryption
18
- if settings[:ui] == :cli
21
+ case settings[:ui]
22
+ when :cli
19
23
  # output to file
20
24
  File.write("#{settings[:outdir]}decrypted.txt", decipher.update(settings[:file]) + decipher.final)
21
25
  puts "Your decrypted.txt has been written out to #{settings[:outdir]}."
22
- elsif settings[:ui] == :api
26
+ when :api
23
27
  # output to string
24
28
  decipher.update(settings[:file]) + decipher.final
25
29
  end
@@ -37,11 +41,12 @@ class Decrypt
37
41
  crypto = GPGME::Crypto.new(armor: true, pinentry_mode: GPGME::PINENTRY_MODE_LOOPBACK)
38
42
 
39
43
  # output the decryption
40
- if settings[:ui] == :cli
44
+ case settings[:ui]
45
+ when :cli
41
46
  # output to file
42
47
  File.write("#{settings[:outdir]}decrypted.txt", crypto.decrypt(encrypted, password: settings[:pw]).read)
43
48
  puts "Your decrypted.txt has been written out to #{settings[:outdir]}."
44
- elsif settings[:ui] == :api
49
+ when :api
45
50
  # output to string
46
51
  crypto.decrypt(encrypted, password: settings[:pw]).read
47
52
  end
@@ -4,6 +4,10 @@ class Encrypt
4
4
  def self.openssl(settings)
5
5
  require 'openssl'
6
6
 
7
+ # validate key and nonce
8
+ raise 'The key is not a valid 32 byte key.' unless settings[:key].bytesize == 32
9
+ raise 'The nonce is not a valid 12 byte nonce.' unless settings[:nonce].bytesize == 12
10
+
7
11
  # setup the encryption parameters
8
12
  cipher = OpenSSL::Cipher.new('aes-256-gcm').encrypt
9
13
  cipher.key = settings[:key]
@@ -11,13 +15,14 @@ class Encrypt
11
15
  cipher.auth_data = settings.key?(:pw) ? settings[:pw] : ''
12
16
 
13
17
  # output the encryption and associated tag
14
- if settings[:ui] == :cli
18
+ case settings[:ui]
19
+ when :cli
15
20
  # output to file
16
21
  File.write("#{settings[:outdir]}encrypted.txt", cipher.update(settings[:file]) + cipher.final)
17
22
  File.write("#{settings[:outdir]}tag.txt", cipher.auth_tag)
18
23
  puts "Your encrypted.txt and associated tag.txt for this encryption have been generated in #{settings[:outdir]}."
19
- elsif settings[:ui] == :api
20
- # output to array
24
+ when :api
25
+ # return as array
21
26
  [cipher.update(settings[:file]) + cipher.final, cipher.auth_tag]
22
27
  end
23
28
  end
@@ -33,12 +38,13 @@ class Encrypt
33
38
  crypto = GPGME::Crypto.new(armor: true, pinentry_mode: GPGME::PINENTRY_MODE_LOOPBACK)
34
39
 
35
40
  # output the encryption and associated tag
36
- if settings[:ui] == :cli
41
+ case settings[:ui]
42
+ when :cli
37
43
  # output to file
38
44
  File.write("#{settings[:outdir]}encrypted.txt", crypto.encrypt(settings[:file], symmetric: true, password: settings[:pw]).read)
39
- puts "Your encrypted.txt for this encryption have been generated in #{settings[:outdir]}."
40
- elsif settings[:ui] == :api
41
- # output to string
45
+ puts "Your encrypted.txt for this encryption has been generated in #{settings[:outdir]}."
46
+ when :api
47
+ # return as string
42
48
  crypto.encrypt(settings[:file], symmetric: true, password: settings[:pw]).read
43
49
  end
44
50
  end
@@ -7,13 +7,14 @@ class Generate
7
7
  # setup parameters
8
8
  cipher = OpenSSL::Cipher.new('aes-256-gcm').encrypt
9
9
 
10
- if settings[:ui] == :cli
10
+ case settings[:ui]
11
+ when :cli
11
12
  # output to file
12
13
  File.write("#{settings[:outdir]}key.txt", cipher.random_key)
13
14
  File.write("#{settings[:outdir]}nonce.txt", cipher.random_iv)
14
15
  puts "Your key.txt and nonce.txt have been generated in #{settings[:outdir]}."
15
- elsif settings[:ui] == :api
16
- # output to string
16
+ when :api
17
+ # return as array
17
18
  [cipher.random_key, cipher.random_iv]
18
19
  end
19
20
  end
@@ -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,7 +7,7 @@ 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
@@ -50,7 +50,7 @@ class RapidVaults
50
50
  end
51
51
 
52
52
  # 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.") }
53
+ 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
54
 
55
55
  # check inputs and read in files
56
56
  raise 'Password must be a string.' if settings.key?(:pw) && !settings[:pw].is_a?(String)
@@ -66,14 +66,12 @@ class RapidVaults
66
66
  case settings[:action]
67
67
  when :generate
68
68
  raise 'GPG params file argument required for generation.' unless settings.key?(:gpgparams)
69
- return
70
69
  when :decrypt, :encrypt
70
+ # check inputs and read in files
71
71
  raise 'File and password arguments required for encryption or decryption.' unless settings.key?(:file) && settings.key?(:pw)
72
+ raise 'Password must be a string.' unless settings[:pw].is_a?(String)
73
+ 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
74
  else raise 'Action must be one of generate, encrypt, or decrypt.'
73
75
  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
76
  end
79
77
  end
@@ -4,8 +4,14 @@ require_relative '../../lib/rapid-vaults/decrypt'
4
4
 
5
5
  describe Decrypt do
6
6
  context '.openssl' do
7
+ require 'openssl'
8
+ require 'securerandom'
9
+ cipher = OpenSSL::Cipher.new('aes-256-gcm').encrypt
10
+ key = cipher.random_key
11
+ nonce = cipher.random_iv
12
+
7
13
  before(:all) do
8
- Encrypt.openssl(ui: :cli, file: "foo: bar\n", key: '���b+����R�v�Í%("����=8o/���', nonce: 'Ëá!í^Uë^EÜ<83>oã^M')
14
+ Encrypt.openssl(ui: :cli, file: "foo: bar\n", key: key, nonce: nonce)
9
15
  end
10
16
 
11
17
  after(:all) do
@@ -13,22 +19,31 @@ describe Decrypt do
13
19
  end
14
20
 
15
21
  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'))
22
+ Decrypt.openssl(ui: :cli, file: File.read('encrypted.txt'), key: key, nonce: nonce, tag: File.read('tag.txt'))
17
23
  expect(File.file?('decrypted.txt')).to be true
18
24
  expect(File.read('decrypted.txt')).to eq("foo: bar\n")
19
25
  end
20
26
  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'))
27
+ decrypt = Decrypt.openssl(ui: :api, file: File.read('encrypted.txt'), key: key, nonce: nonce, tag: File.read('tag.txt'))
22
28
  expect(decrypt).to be_a(String)
23
29
  expect(decrypt).to eq("foo: bar\n")
24
30
  end
25
31
  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.')
32
+ expect { Decrypt.openssl(file: File.read('encrypted.txt'), key: key, nonce: nonce, tag: SecureRandom.random_bytes(24).strip) }.to raise_error('Tag is not 16 bytes.')
33
+ end
34
+ it 'raises an error for an invalid key size' do
35
+ expect { Decrypt.openssl(key: SecureRandom.random_bytes(64).strip) }.to raise_error('The key is not a valid 32 byte key.')
36
+ end
37
+ it 'raises an error for an invalid nonce size' do
38
+ expect { Decrypt.openssl(key: key, nonce: SecureRandom.random_bytes(24).strip) }.to raise_error('The nonce is not a valid 12 byte nonce.')
39
+ end
40
+ it 'raises an error for corrupted encrypted file content' do
41
+ expect { Decrypt.openssl(file: SecureRandom.random_bytes(16).strip, key: key, nonce: nonce) }.to raise_error('The encrypted data is not a valid multiple of 9 bytes.')
27
42
  end
28
43
  end
29
44
 
30
45
  # travis ci cannot support non-interactive gpg encryption
31
- unless File.directory?('/home/travis')
46
+ unless ENV['TRAVIS'] == 'true'
32
47
  context '.gpgme' do
33
48
  before(:all) do
34
49
  Encrypt.gpgme(ui: :cli, file: "foo: bar\n", key: '', pw: 'foo')
@@ -3,31 +3,43 @@ require_relative '../../lib/rapid-vaults/encrypt'
3
3
 
4
4
  describe Encrypt do
5
5
  context '.openssl' do
6
+ require 'openssl'
7
+ require 'securerandom'
8
+ cipher = OpenSSL::Cipher.new('aes-256-gcm').encrypt
9
+ key = cipher.random_key
10
+ nonce = cipher.random_iv
11
+
6
12
  after(:all) do
7
13
  %w[tag.txt encrypted.txt].each { |file| File.delete(file) }
8
14
  end
9
15
 
10
16
  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')
17
+ Encrypt.openssl(ui: :cli, file: "foo: bar\n", key: key, nonce: nonce)
12
18
  expect(File.file?('tag.txt')).to be true
13
19
  expect(File.file?('encrypted.txt')).to be true
14
20
  end
15
21
  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')
22
+ Encrypt.openssl(ui: :cli, file: "foo: bar\n", key: key, nonce: nonce, pw: 'password')
17
23
  expect(File.file?('tag.txt')).to be true
18
24
  expect(File.file?('encrypted.txt')).to be true
19
25
  end
20
26
  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')
27
+ encrypt = Encrypt.openssl(ui: :api, file: "foo: bar\n", key: key, nonce: nonce)
22
28
  expect(encrypt).to be_a(Array)
23
29
  expect(encrypt[0]).to be_a(String)
24
30
  expect(encrypt[1]).to be_a(String)
25
31
  expect(encrypt.length).to eq(2)
26
32
  end
33
+ it 'raises an error for an invalid key size' do
34
+ expect { Encrypt.openssl(key: SecureRandom.random_bytes(64).strip) }.to raise_error('The key is not a valid 32 byte key.')
35
+ end
36
+ it 'raises an error for an invalid nonce size' do
37
+ expect { Encrypt.openssl(key: key, nonce: SecureRandom.random_bytes(24).strip) }.to raise_error('The nonce is not a valid 12 byte nonce.')
38
+ end
27
39
  end
28
40
 
29
41
  # travis ci cannot support non-interactive gpg encryption
30
- unless File.directory?('/home/travis')
42
+ unless ENV['TRAVIS'] == 'true'
31
43
  context '.gpgme' do
32
44
  it 'outputs an encrypted file with the key from the cli' do
33
45
  Encrypt.gpgme(ui: :cli, file: "foo: bar\n", key: '', pw: 'foo')
@@ -28,7 +28,7 @@ describe Generate 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
30
  # travis ci cannot support non-interactive gpg
31
- unless File.directory?('/home/travis')
31
+ unless ENV['TRAVIS'] == 'true'
32
32
  it 'generates the key files' do
33
33
  require 'fileutils'
34
34
 
@@ -0,0 +1,42 @@
1
+ require_relative '../../lib/rapid-vaults/grpc'
2
+
3
+ # TODO: use RapidVaults::GRPC.server instead?
4
+ stub = Rapidvaults::RapidVaults::Stub.new('localhost:0.0.0.0:8080', :this_channel_is_insecure)
5
+
6
+ # need to create class with encode member method to pass in as dummy
7
+ # ssl generate
8
+ # outputs = stub.ssl_generate('string')
9
+ =begin
10
+ puts outputs.key
11
+ puts outputs.nonce
12
+
13
+ # gpg generate
14
+ stub.gpg_generate
15
+
16
+ # ssl encrypt
17
+ # TODO: unencrypted should be an object
18
+ unencrypted.text = ''
19
+ unencrypted.key = ''
20
+ unencrypted.nonce = ''
21
+ outputs = stub.ssl_encrypt(unencrypted)
22
+ puts outputs.text
23
+ puts outputs.tag
24
+
25
+ # gpg encrypt
26
+ unencrypted.text = ''
27
+ unencrypted.password = ''
28
+ puts stub.gpg_encrypt(unencrypted).text
29
+
30
+ # ssl decrypt
31
+ # TODO: undecrypted should be an object
32
+ undecrypted.text = ''
33
+ undecrypted.key = ''
34
+ undecrypted.nonce = ''
35
+ undecrypted.tag = ''
36
+ puts stub.ssl_decrypt(undecrypted).text
37
+
38
+ # gpg decrypt
39
+ undecrypted.text = ''
40
+ undecrypted.password = ''
41
+ puts stub.gpg_decrypt(undecrypted).text
42
+ =end
@@ -1,11 +1,17 @@
1
1
  require_relative 'spec_helper'
2
- require_relative '../lib/rapid-vaults'
2
+ require_relative '../lib/rapid_vaults'
3
3
 
4
4
  describe RapidVaults do
5
5
  context '.process' do
6
6
  it 'raises an error for a non-string password with openssl' do
7
7
  expect { RapidVaults.process(action: :encrypt, file: 'a', key: 'b', nonce: 'c', pw: 1) }.to raise_error('Password must be a string.')
8
8
  end
9
+ it 'raises an error for a non-string password with gpgme' do
10
+ expect { RapidVaults.process(action: :encrypt, file: 'a', key: 'b', nonce: 'c', pw: 1) }.to raise_error('Password must be a string.')
11
+ end
12
+ it 'raises an error for a missing argument to generate with gpgme' do
13
+ expect { RapidVaults.process(algorithm: :gpgme, action: :generate) }.to raise_error('GPG params file argument required for generation.')
14
+ end
9
15
  it 'raises an error for a missing argument to encrypt with openssl' do
10
16
  expect { RapidVaults.process(action: :encrypt, file: 'a', key: 'b') }.to raise_error('File, key, and nonce arguments are required for encryption.')
11
17
  end
@@ -21,18 +27,18 @@ describe RapidVaults do
21
27
  it 'raises an error for a missing action with gpgme' do
22
28
  expect { RapidVaults.process(algorithm: :gpgme, file: 'a', key: 'b') }.to raise_error('Action must be one of generate, encrypt, or decrypt.')
23
29
  end
24
- it 'raises an error for a missing argument to generate with gpgme' do
25
- expect { RapidVaults.process(algorithm: :gpgme, action: :generate) }.to raise_error('GPG params file argument required for generation.')
30
+ it 'raises an error for a nonexistent input file with openssl' do
31
+ 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.')
26
32
  end
27
- it 'raises an error for a nonexistent input file' do
28
- expect { RapidVaults.process(action: :encrypt, file: 'a', key: 'b', nonce: 'c', tag: 'd') }.to raise_error('Input file is not an existing file.')
33
+ it 'raises an error for a nonexistent input file with gpgme' do
34
+ 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.')
29
35
  end
30
36
  it 'reads in all input files correctly for openssl encryption' do
31
- dummy = fixtures_dir + 'file.yaml'
37
+ dummy = "#{fixtures_dir}file.yaml"
32
38
  expect { RapidVaults.process(action: :encrypt, file: dummy, key: dummy, nonce: dummy, pw: 'password') }.not_to raise_exception
33
39
  end
34
40
  it 'reads in all input files correctly for gpgme decryption' do
35
- dummy = fixtures_dir + 'file.yaml'
41
+ dummy = "#{fixtures_dir}file.yaml"
36
42
  expect { RapidVaults.process(algorithm: :gpgme, action: :decrypt, file: dummy, pw: 'password') }.not_to raise_exception
37
43
  end
38
44
  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['TRAVIS'] == 'true' || 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,9 +59,9 @@ 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
+ # all three ci cannot support end-to-end gpg generate/encrypt/decrypt
63
+ unless ENV['TRAVIS'] == 'true' || 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
 
@@ -86,7 +86,7 @@ describe RapidVaults do
86
86
  end
87
87
  end
88
88
 
89
- context 'executed with gpg as a system from the API with settings and a file to be processed' do
89
+ context 'executed with gpg algorithm as a system from the API with settings and a file to be processed' do
90
90
  it 'encrypts a file and then decrypts a file in order' do
91
91
  ENV['GNUPGHOME'] = fixtures_dir
92
92
 
@@ -94,7 +94,7 @@ describe RapidVaults do
94
94
  Dir.chdir(fixtures_dir)
95
95
 
96
96
  # generate keys
97
- RapidVaults::API.main(action: :generate, algorithm: :gpgme, gpgparams: File.read('gpgparams.txt'), ui: :cli)
97
+ RapidVaults::API.main(action: :generate, algorithm: :gpgme, gpgparams: File.read('gpgparams.txt'))
98
98
  %w[trustdb.gpg pubring.kbx pubring.kbx~].each { |file| expect(File.file?("#{fixtures_dir}/#{file}")).to be true }
99
99
  %w[openpgp-revocs.d private-keys-v1.d].each { |dir| expect(File.directory?("#{fixtures_dir}/#{dir}")).to be true }
100
100
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rapid-vaults
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Schuchard
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-15 00:00:00.000000000 Z
11
+ date: 2022-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gpgme
@@ -25,45 +25,61 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: grpc
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '9'
34
- - - "<"
33
+ version: '1.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
35
39
  - !ruby/object:Gem::Version
36
- version: '13'
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: grpc-tools
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
37
48
  type: :development
38
49
  prerelease: false
39
50
  version_requirements: !ruby/object:Gem::Requirement
40
51
  requirements:
41
- - - ">="
52
+ - - "~>"
42
53
  - !ruby/object:Gem::Version
43
- version: '9'
44
- - - "<"
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
45
60
  - !ruby/object:Gem::Version
46
- version: '13'
61
+ version: '12.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '12.0'
47
69
  - !ruby/object:Gem::Dependency
48
70
  name: reek
49
71
  requirement: !ruby/object:Gem::Requirement
50
72
  requirements:
51
- - - ">"
52
- - !ruby/object:Gem::Version
53
- version: '4.0'
54
- - - "<"
73
+ - - "~>"
55
74
  - !ruby/object:Gem::Version
56
- version: '6'
75
+ version: '6.0'
57
76
  type: :development
58
77
  prerelease: false
59
78
  version_requirements: !ruby/object:Gem::Requirement
60
79
  requirements:
61
- - - ">"
62
- - !ruby/object:Gem::Version
63
- version: '4.0'
64
- - - "<"
80
+ - - "~>"
65
81
  - !ruby/object:Gem::Version
66
- version: '6'
82
+ version: '6.0'
67
83
  - !ruby/object:Gem::Dependency
68
84
  name: rspec
69
85
  requirement: !ruby/object:Gem::Requirement
@@ -80,21 +96,41 @@ dependencies:
80
96
  version: '3.0'
81
97
  - !ruby/object:Gem::Dependency
82
98
  name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0.58'
104
+ - - "<"
105
+ - !ruby/object:Gem::Version
106
+ version: '2'
107
+ type: :development
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0.58'
114
+ - - "<"
115
+ - !ruby/object:Gem::Version
116
+ version: '2'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rubocop-performance
83
119
  requirement: !ruby/object:Gem::Requirement
84
120
  requirements:
85
121
  - - "~>"
86
122
  - !ruby/object:Gem::Version
87
- version: '0.51'
123
+ version: '1.0'
88
124
  type: :development
89
125
  prerelease: false
90
126
  version_requirements: !ruby/object:Gem::Requirement
91
127
  requirements:
92
128
  - - "~>"
93
129
  - !ruby/object:Gem::Version
94
- version: '0.51'
130
+ version: '1.0'
95
131
  description: Ad-hoc encrypt and decrypt data behind multiple layers of protection
96
132
  via OpenSSL or GPG.
97
- email:
133
+ email:
98
134
  executables:
99
135
  - rapid-vaults
100
136
  extensions: []
@@ -102,7 +138,6 @@ extra_rdoc_files: []
102
138
  files:
103
139
  - README.md
104
140
  - bin/rapid-vaults
105
- - lib/rapid-vaults.rb
106
141
  - lib/rapid-vaults/api.rb
107
142
  - lib/rapid-vaults/binding.rb
108
143
  - lib/rapid-vaults/bindings/chef.rb
@@ -114,6 +149,8 @@ files:
114
149
  - lib/rapid-vaults/decrypt.rb
115
150
  - lib/rapid-vaults/encrypt.rb
116
151
  - lib/rapid-vaults/generate.rb
152
+ - lib/rapid-vaults/grpc.rb
153
+ - lib/rapid_vaults.rb
117
154
  - spec/fixtures/file.yaml
118
155
  - spec/fixtures/gpgparams.txt
119
156
  - spec/rapid-vaults/api_spec.rb
@@ -122,14 +159,15 @@ files:
122
159
  - spec/rapid-vaults/decrypt_spec.rb
123
160
  - spec/rapid-vaults/encrypt_spec.rb
124
161
  - spec/rapid-vaults/generate_spec.rb
125
- - spec/rapid-vaults_spec.rb
162
+ - spec/rapid-vaults/grpc_spec.rb
163
+ - spec/rapid_vaults_spec.rb
126
164
  - spec/spec_helper.rb
127
165
  - spec/system/system_spec.rb
128
166
  homepage: https://www.github.com/mschuchard/rapid-vaults
129
167
  licenses:
130
168
  - MIT
131
169
  metadata: {}
132
- post_install_message:
170
+ post_install_message:
133
171
  rdoc_options: []
134
172
  require_paths:
135
173
  - lib
@@ -137,16 +175,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
137
175
  requirements:
138
176
  - - ">="
139
177
  - !ruby/object:Gem::Version
140
- version: 2.1.0
178
+ version: 2.5.0
141
179
  required_rubygems_version: !ruby/object:Gem::Requirement
142
180
  requirements:
143
181
  - - ">="
144
182
  - !ruby/object:Gem::Version
145
183
  version: '0'
146
184
  requirements: []
147
- rubyforge_project:
148
- rubygems_version: 2.7.6
149
- signing_key:
185
+ rubygems_version: 3.3.5
186
+ signing_key:
150
187
  specification_version: 4
151
188
  summary: Ad-hoc encrypt and decrypt data.
152
189
  test_files:
@@ -158,6 +195,7 @@ test_files:
158
195
  - spec/rapid-vaults/decrypt_spec.rb
159
196
  - spec/rapid-vaults/encrypt_spec.rb
160
197
  - spec/rapid-vaults/generate_spec.rb
161
- - spec/rapid-vaults_spec.rb
198
+ - spec/rapid-vaults/grpc_spec.rb
199
+ - spec/rapid_vaults_spec.rb
162
200
  - spec/spec_helper.rb
163
201
  - spec/system/system_spec.rb