rapid-vaults 1.1.2 → 1.2.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 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