secret-keeper 1.0.0 → 2.0.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/README.md +25 -9
- data/lib/secret-keeper.rb +31 -21
- data/spec/secret-keeper_spec.rb +72 -2
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 993613940fe2fd54b0db8ea676aeaeb82a1de574b6d986a904f14e166d9826a2
|
4
|
+
data.tar.gz: 92c2b76672090397d60871cf438fc597877351ae74c09cd4f43d927d2c3de0b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3c9d114ab4bcd7b0958ff3fa999e2b2ffb3c4bda4eeab15e54841daa9596d24ec6c7323893d07995e8fe6f4c7fb47ccc082e88b5c89513fe12010a350ba1b84
|
7
|
+
data.tar.gz: 9a6e63acc12ef13e56237e8dde65e28b45a47423a700b71c6d79486fabcf89dbd3f13426f26e23ab08f54a9ca09fb186b00bcdefab19f6a3c1bc1e27c8682719
|
data/README.md
CHANGED
@@ -12,6 +12,16 @@ with bundler, write follwing line in your Gemfile
|
|
12
12
|
|
13
13
|
gem 'secret-keeper', require: false
|
14
14
|
|
15
|
+
## Upgrade from v1 to v2
|
16
|
+
|
17
|
+
The *remove_production* parameter of *decrypt_files* has been removed after version 2.0.0.
|
18
|
+
If you wants to remove *production* settings after decrypt files, you can set *remove_production* option to *true* in *secret-keeper.yml*:
|
19
|
+
|
20
|
+
```
|
21
|
+
options:
|
22
|
+
remove_production: false
|
23
|
+
```
|
24
|
+
|
15
25
|
## Usage
|
16
26
|
setup files need to be encrypted in config/secret-keeper.yml
|
17
27
|
|
@@ -19,6 +29,10 @@ setup files need to be encrypted in config/secret-keeper.yml
|
|
19
29
|
development:
|
20
30
|
ev_name: SECRET_KEEPER
|
21
31
|
cipher: AES-256-CBC
|
32
|
+
options:
|
33
|
+
slience: false
|
34
|
+
remove_production: false
|
35
|
+
remove_source: false
|
22
36
|
tasks:
|
23
37
|
-
|
24
38
|
encrypt_from: example/database.yml
|
@@ -55,16 +69,18 @@ decrypt files based on your tasks defined in config/secret-keeper.yml
|
|
55
69
|
# * example/secrets.yml.enc --> example/secrets.yml, ok
|
56
70
|
# Done!
|
57
71
|
|
58
|
-
decrypt files and remove production configs
|
59
|
-
|
60
|
-
irb> production? = true
|
61
|
-
irb> SecretKeeper.decrypt_files(production?)
|
62
|
-
# Decrypting... (production config removed)
|
63
|
-
# * example/database.yml.enc --> example/database.yml, ok
|
64
|
-
# * example/secrets.yml.enc --> example/secrets.yml, ok
|
65
|
-
# Done!
|
66
|
-
|
67
72
|
## Available Ciphers
|
68
73
|
|
69
74
|
irb> require 'openssl'
|
70
75
|
irb> OpenSSL::Cipher.ciphers
|
76
|
+
|
77
|
+
## Options
|
78
|
+
|
79
|
+
* slience
|
80
|
+
When this option set to *true*, the tasks will run in slience mode. Messages will not show no screen. Default is *false*.
|
81
|
+
|
82
|
+
* remove_production
|
83
|
+
When this option set to *true*, the *production* settings in the decrypted files will be removed after the decryption task. Default is *false*.
|
84
|
+
|
85
|
+
* remove_source
|
86
|
+
When this option set to *true*, the source file will be removed after either encrypt or decrypt tasks. Default is *false*.
|
data/lib/secret-keeper.rb
CHANGED
@@ -2,27 +2,37 @@ require 'openssl'
|
|
2
2
|
require 'yaml'
|
3
3
|
|
4
4
|
class SecretKeeper
|
5
|
+
attr_reader :tasks, :options
|
6
|
+
|
5
7
|
def self.encrypt_files
|
8
|
+
printer = ['Encrypting...']
|
6
9
|
sk = SecretKeeper.new
|
7
|
-
|
10
|
+
printer << '(production config removed)' if sk.options['remove_production']
|
11
|
+
printer << '(source files removed)' if sk.options['remove_source']
|
8
12
|
ok_queue = []
|
9
13
|
sk.tasks.each do |task|
|
10
|
-
from = task['encrypt_from']
|
14
|
+
from = File.exists?(task['encrypt_from']) ? task['encrypt_from'] : task['decrypt_to']
|
11
15
|
to = task['encrypt_to']
|
12
16
|
|
13
17
|
result = sk.encrypt_file(from, to)
|
18
|
+
if result == :ok
|
19
|
+
result = sk.remove_file(from) if sk.options['remove_source']
|
20
|
+
end
|
21
|
+
|
14
22
|
ok_queue << result if result == :ok
|
15
|
-
|
23
|
+
printer << " * #{from} --> #{to}, #{result}"
|
16
24
|
end
|
17
25
|
success = ok_queue.count == sk.tasks.count
|
18
|
-
|
26
|
+
printer << (success ? 'Done!' : 'Failed!')
|
27
|
+
printer.each{ |row| puts row } unless sk.options['slience']
|
19
28
|
success
|
20
29
|
end
|
21
30
|
|
22
|
-
def self.decrypt_files
|
31
|
+
def self.decrypt_files
|
32
|
+
printer = ['Decrypting...']
|
23
33
|
sk = SecretKeeper.new
|
24
|
-
|
25
|
-
|
34
|
+
printer << '(production config removed)' if sk.options['remove_production']
|
35
|
+
printer << '(source files removed)' if sk.options['remove_source']
|
26
36
|
|
27
37
|
ok_queue = []
|
28
38
|
sk.tasks.each do |task|
|
@@ -30,16 +40,17 @@ class SecretKeeper
|
|
30
40
|
to = task['decrypt_to'] || task['encrypt_from']
|
31
41
|
|
32
42
|
result = sk.decrypt_file(from, to)
|
33
|
-
|
34
|
-
|
35
|
-
result = sk.
|
43
|
+
if result == :ok
|
44
|
+
result = sk.remove_production_config(to) if sk.options['remove_production']
|
45
|
+
result = sk.remove_file(from) if sk.options['remove_source']
|
36
46
|
end
|
37
47
|
|
38
48
|
ok_queue << result if result == :ok
|
39
|
-
|
49
|
+
printer << " * #{from} --> #{to}, #{result}"
|
40
50
|
end
|
41
51
|
success = ok_queue.count == sk.tasks.count
|
42
|
-
|
52
|
+
printer << (success ? 'Done!' : 'Failed!')
|
53
|
+
printer.each{ |row| puts row } unless sk.options['slience']
|
43
54
|
success
|
44
55
|
end
|
45
56
|
|
@@ -56,15 +67,7 @@ class SecretKeeper
|
|
56
67
|
@using_cipher = OpenSSL::Cipher.new(config['cipher'] || 'AES-256-CBC')
|
57
68
|
@cipher_key = Digest::SHA2.hexdigest(ENV[ev_name])[0...@using_cipher.key_len]
|
58
69
|
|
59
|
-
@
|
60
|
-
end
|
61
|
-
|
62
|
-
def tasks
|
63
|
-
@tasks
|
64
|
-
end
|
65
|
-
|
66
|
-
def slience
|
67
|
-
@slience
|
70
|
+
@options = config['options']
|
68
71
|
end
|
69
72
|
|
70
73
|
def encrypt_file(from_file, to_file)
|
@@ -93,6 +96,13 @@ class SecretKeeper
|
|
93
96
|
e
|
94
97
|
end
|
95
98
|
|
99
|
+
def remove_file(file_path)
|
100
|
+
File.delete(file_path)
|
101
|
+
:ok
|
102
|
+
rescue => e
|
103
|
+
e
|
104
|
+
end
|
105
|
+
|
96
106
|
private
|
97
107
|
|
98
108
|
def encrypt(data)
|
data/spec/secret-keeper_spec.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
describe SecretKeeper do
|
2
2
|
before(:each) do
|
3
3
|
ENV['SECRET_KEEPER'] = 'PASSWORD_HERE'
|
4
|
+
FileUtils.copy_entry('./example', './example_backup')
|
5
|
+
end
|
6
|
+
|
7
|
+
after(:each) do
|
8
|
+
FileUtils.rm_r('./example')
|
9
|
+
FileUtils.mv('./example_backup', './example')
|
4
10
|
end
|
5
11
|
|
6
12
|
describe '.encrypt_files' do
|
@@ -8,6 +14,24 @@ describe SecretKeeper do
|
|
8
14
|
result = SecretKeeper.encrypt_files
|
9
15
|
expect(result).to eq(true)
|
10
16
|
end
|
17
|
+
|
18
|
+
it 'should return true on remove_source true' do
|
19
|
+
options = {
|
20
|
+
'slience' => true,
|
21
|
+
'remove_production' => false,
|
22
|
+
'remove_source' => true
|
23
|
+
}
|
24
|
+
allow_any_instance_of(SecretKeeper).to receive(:options).and_return(options)
|
25
|
+
|
26
|
+
result = SecretKeeper.encrypt_files
|
27
|
+
expect(result).to eq(true)
|
28
|
+
SecretKeeper.new.tasks.each do |task|
|
29
|
+
source_file = task['encrypt_from']
|
30
|
+
target_file = task['encrypt_to']
|
31
|
+
expect(File.exists?(source_file)).to eq(false)
|
32
|
+
expect(File.exists?(target_file)).to eq(true)
|
33
|
+
end
|
34
|
+
end
|
11
35
|
end
|
12
36
|
|
13
37
|
describe '.decrypt_files' do
|
@@ -19,12 +43,58 @@ describe SecretKeeper do
|
|
19
43
|
expect(hash['production']['secret_key_base']).to eq('339f639f4fe35c5ffaa47ace973260b12e51b0b4fe1f65effd283a5f054f47594b24bd565779e351a20dfd4ada4f777958f0417b305c06cdedbde392b8e1fd07')
|
20
44
|
end
|
21
45
|
|
22
|
-
it 'should return true on remove_production true' do
|
23
|
-
|
46
|
+
it 'should return true on remove_production true and remove_source false' do
|
47
|
+
options = {
|
48
|
+
'slience' => true,
|
49
|
+
'remove_production' => true,
|
50
|
+
'remove_source' => false
|
51
|
+
}
|
52
|
+
allow_any_instance_of(SecretKeeper).to receive(:options).and_return(options)
|
53
|
+
|
54
|
+
result = SecretKeeper.decrypt_files
|
55
|
+
expect(result).to eq(true)
|
56
|
+
hash = YAML.load_file('example/secrets.yml')
|
57
|
+
expect(hash['development']['secret_key_base']).to eq('e8310af93d52f174f475940c41fbfb90417b300ebc19e1b24bd5639f4fe35c5ffaa5775a347ace9732958f656a47f6bb8e1fd0760b12e51b0b4fe1f65ef0a1d6')
|
58
|
+
expect(hash['production']).to be_nil
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should return true on remove_production false and remove_source true' do
|
62
|
+
options = {
|
63
|
+
'slience' => true,
|
64
|
+
'remove_production' => false,
|
65
|
+
'remove_source' => true
|
66
|
+
}
|
67
|
+
allow_any_instance_of(SecretKeeper).to receive(:options).and_return(options)
|
68
|
+
|
69
|
+
result = SecretKeeper.decrypt_files
|
70
|
+
expect(result).to eq(true)
|
71
|
+
SecretKeeper.new.tasks.each do |task|
|
72
|
+
source_file = task['decrypt_from'] || task['encrypt_to']
|
73
|
+
target_file = task['decrypt_to'] || task['encrypt_from']
|
74
|
+
expect(File.exists?(source_file)).to eq(false)
|
75
|
+
expect(File.exists?(target_file)).to eq(true)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should return true on remove_production true and remove_source true' do
|
80
|
+
options = {
|
81
|
+
'slience' => true,
|
82
|
+
'remove_production' => true,
|
83
|
+
'remove_source' => true
|
84
|
+
}
|
85
|
+
allow_any_instance_of(SecretKeeper).to receive(:options).and_return(options)
|
86
|
+
|
87
|
+
result = SecretKeeper.decrypt_files
|
24
88
|
expect(result).to eq(true)
|
25
89
|
hash = YAML.load_file('example/secrets.yml')
|
26
90
|
expect(hash['development']['secret_key_base']).to eq('e8310af93d52f174f475940c41fbfb90417b300ebc19e1b24bd5639f4fe35c5ffaa5775a347ace9732958f656a47f6bb8e1fd0760b12e51b0b4fe1f65ef0a1d6')
|
27
91
|
expect(hash['production']).to be_nil
|
92
|
+
SecretKeeper.new.tasks.each do |task|
|
93
|
+
source_file = task['decrypt_from'] || task['encrypt_to']
|
94
|
+
target_file = task['decrypt_to'] || task['encrypt_from']
|
95
|
+
expect(File.exists?(source_file)).to eq(false)
|
96
|
+
expect(File.exists?(target_file)).to eq(true)
|
97
|
+
end
|
28
98
|
end
|
29
99
|
|
30
100
|
it 'should be false, if SECRET_KEEPER incorrect' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: secret-keeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ray Lee
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-05-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '3.
|
19
|
+
version: '3.9'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '3.
|
26
|
+
version: '3.9'
|
27
27
|
description: A Secret keeper
|
28
28
|
email: ray-lee@kdanmobile.com
|
29
29
|
executables: []
|
@@ -47,14 +47,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
47
47
|
requirements:
|
48
48
|
- - ">="
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version: 2.
|
50
|
+
version: 2.7.0
|
51
51
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0'
|
56
56
|
requirements: []
|
57
|
-
rubygems_version: 3.
|
57
|
+
rubygems_version: 3.2.32
|
58
58
|
signing_key:
|
59
59
|
specification_version: 4
|
60
60
|
summary: Keep all your secret files within openssl
|