secret-keeper 1.0.0 → 2.0.1

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: a4af085b4a020f82a80ec5e4f2995fc676c6d24497b424ccfe5788d8fa83085b
4
- data.tar.gz: 4f3c88876416d7dadf20f903338827b52c03ecb1799b5b31b823d5cd484e5513
3
+ metadata.gz: 1a314a84c5cdc4c6ef06e417d3c638186eafdaeb522936e97c87a54f7050940a
4
+ data.tar.gz: 2e40a932f8d0c92aa78fea56401f4c115862c302e0c584cc8cf5f95d06faf09a
5
5
  SHA512:
6
- metadata.gz: 40512c3536a8f2b8824f3d6fbf97df57e8381fb7d5f135ef3ac05771a6ca9b472e52aa1818e35d7699400b688f918b6f534895eef04ff359d4706f99bd24da37
7
- data.tar.gz: 5aecafc7b60fb43bc34b46744b63761db551b44d428e7fcfdb8afd8ee74e157a51f43903f45e3f8bf925150975d5c80e999344cef824e81e01c3603591f2190e
6
+ metadata.gz: 877c488a822ec78ca1ef89b2f58c1461de62a866bf5625954a8cb0772af3d1ba6fb789f05802c885eb6841857d4a6e5599af18e0abe129987f13777b86de9e22
7
+ data.tar.gz: 3d580b41a2585c1c2977affbad1ef8ac443b20b59074ce715265b57fc2879da1a6f848702fff8dea3fbf7ca443e70a2cf21ac5d65bf71a3edf99db2267d7f8f5
data/README.md CHANGED
@@ -6,65 +6,97 @@ Keep all your secret files within openssl
6
6
 
7
7
  from console
8
8
 
9
- gem install secret-keeper
9
+ ```bash
10
+ gem install secret-keeper
11
+ ```
10
12
 
11
13
  with bundler, write follwing line in your Gemfile
12
14
 
13
- gem 'secret-keeper', require: false
15
+ ```bash
16
+ gem 'secret-keeper', require: false
17
+ ```
18
+
19
+ ## Upgrade from v1 to v2
20
+
21
+ The *remove_production* parameter of *decrypt_files* has been removed after version 2.0.0.
22
+ If you wants to remove *production* settings after decrypt files, you can set *remove_production* option to *true* in *secret-keeper.yml*:
23
+
24
+ ```yaml
25
+ options:
26
+ remove_production: false
27
+ ```
14
28
 
15
29
  ## Usage
16
30
  setup files need to be encrypted in config/secret-keeper.yml
17
31
 
18
- # config/secret-keeper.yml example
19
- development:
20
- ev_name: SECRET_KEEPER
21
- cipher: AES-256-CBC
22
- tasks:
23
- -
24
- encrypt_from: example/database.yml
25
- encrypt_to: example/database.yml.enc
26
- # decrypt_from: example/database.yml.enc
27
- # decrypt_to: example/database.yml
28
- -
29
- encrypt_from: example/secrets_from_other_source.yml
30
- encrypt_to: example/secrets.yml.enc
31
- # decrypt_from: example/secrets.yml.enc
32
- decrypt_to: example/secrets.yml
32
+ ```yaml
33
+ # config/secret-keeper.yml example
34
+ development:
35
+ ev_name: SECRET_KEEPER
36
+ cipher: AES-256-CBC
37
+ options:
38
+ slience: false
39
+ remove_production: false
40
+ remove_source: false
41
+ tasks:
42
+ -
43
+ encrypt_from: example/database.yml
44
+ encrypt_to: example/database.yml.enc
45
+ # decrypt_from: example/database.yml.enc
46
+ # decrypt_to: example/database.yml
47
+ -
48
+ encrypt_from: example/secrets_from_other_source.yml
49
+ encrypt_to: example/secrets.yml.enc
50
+ # decrypt_from: example/secrets.yml.enc
51
+ decrypt_to: example/secrets.yml
52
+ ```
33
53
 
34
54
  using environment variable SECRET_KEEPER to be your key of cipher
35
55
 
36
- $> SECRET_KEEPER=[YOUR-CIPHER-KEY-HERE] irb
56
+ ```bash
57
+ $> SECRET_KEEPER=[YOUR-CIPHER-KEY-HERE] irb
58
+ ```
37
59
 
38
60
  require on demand
39
61
 
40
- irb> require 'secret-keeper'
62
+ ```bash
63
+ irb> require 'secret-keeper'
64
+ ```
41
65
 
42
66
  encrypt files based on your tasks defined in config/secret-keeper.yml
43
67
 
44
- irb> SecretKeeper.encrypt_files
45
- # Encrypting...
46
- # * example/database.yml --> example/database.yml.enc, ok
47
- # * example/secrets.yml --> example/secrets.yml.enc, ok
48
- # Done!
68
+ ```bash
69
+ irb> SecretKeeper.encrypt_files
70
+ # Encrypting...
71
+ # * example/database.yml --> example/database.yml.enc, ok
72
+ # * example/secrets.yml --> example/secrets.yml.enc, ok
73
+ # Done!
74
+ ```
49
75
 
50
76
  decrypt files based on your tasks defined in config/secret-keeper.yml
51
77
 
52
- irb> SecretKeeper.decrypt_files
53
- # Decrypting...
54
- # * example/database.yml.enc --> example/database.yml, ok
55
- # * example/secrets.yml.enc --> example/secrets.yml, ok
56
- # Done!
78
+ ```bash
79
+ irb> SecretKeeper.decrypt_files
80
+ # Decrypting...
81
+ # * example/database.yml.enc --> example/database.yml, ok
82
+ # * example/secrets.yml.enc --> example/secrets.yml, ok
83
+ # Done!
84
+ ```
57
85
 
58
- decrypt files and remove production configs
86
+ ## Available Ciphers
59
87
 
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!
88
+ ```bash
89
+ irb> require 'openssl'
90
+ irb> OpenSSL::Cipher.ciphers
91
+ ```
66
92
 
67
- ## Available Ciphers
93
+ ## Options
94
+
95
+ * slience
96
+ When this option set to *true*, the tasks will run in slience mode. Messages will not show no screen. Default is *false*.
97
+
98
+ * remove_production
99
+ When this option set to *true*, the *production* settings in the decrypted files will be removed after the decryption task. Default is *false*.
68
100
 
69
- irb> require 'openssl'
70
- irb> OpenSSL::Cipher.ciphers
101
+ * remove_source
102
+ 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
- puts 'Encrypting...' unless sk.slience
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.exist?(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
- puts " * #{from} --> #{to}, #{result}" unless sk.slience
23
+ printer << " * #{from} --> #{to}, #{result}"
16
24
  end
17
25
  success = ok_queue.count == sk.tasks.count
18
- puts success ? 'Done!' : 'Failed!' unless sk.slience
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(remove_production=false)
31
+ def self.decrypt_files
32
+ printer = ['Decrypting...']
23
33
  sk = SecretKeeper.new
24
- print 'Decrypting...' unless sk.slience
25
- puts remove_production ? '(production config removed)' : nil unless sk.slience
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
- if result == :ok && remove_production
35
- result = sk.remove_production_config(to)
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
- puts " * #{from} --> #{to}, #{result}" unless sk.slience
49
+ printer << " * #{from} --> #{to}, #{result}"
40
50
  end
41
51
  success = ok_queue.count == sk.tasks.count
42
- puts success ? 'Done!' : 'Failed!' unless sk.slience
52
+ printer << (success ? 'Done!' : 'Failed!')
53
+ printer.each{ |row| puts row } unless sk.options['slience']
43
54
  success
44
55
  end
45
56
 
@@ -47,8 +58,12 @@ class SecretKeeper
47
58
  env = ENV['RAILS_ENV'] || 'development'
48
59
  string = File.open('config/secret-keeper.yml', 'rb') { |f| f.read }
49
60
  fail 'config/secret-keeper.yml not existed nor not readable' if string.nil?
50
- config = YAML.load(string)[env]
51
- fail 'config/secret-keeper.yml incorrect or environment not exist' if config.nil?
61
+ begin
62
+ config = YAML.load(string, aliases: true)[env] || {}
63
+ rescue ArgumentError
64
+ config = YAML.load(string)[env] || {}
65
+ end
66
+ fail 'config/secret-keeper.yml incorrect or environment not exist' if config.nil? || config.empty?
52
67
  ev_name = config['ev_name'] || 'SECRET_KEEPER'
53
68
  fail "environment variable #{ev_name} not exist" if ENV[ev_name].nil?
54
69
 
@@ -56,15 +71,7 @@ class SecretKeeper
56
71
  @using_cipher = OpenSSL::Cipher.new(config['cipher'] || 'AES-256-CBC')
57
72
  @cipher_key = Digest::SHA2.hexdigest(ENV[ev_name])[0...@using_cipher.key_len]
58
73
 
59
- @slience = config['slience'] || false
60
- end
61
-
62
- def tasks
63
- @tasks
64
- end
65
-
66
- def slience
67
- @slience
74
+ @options = config['options']
68
75
  end
69
76
 
70
77
  def encrypt_file(from_file, to_file)
@@ -85,7 +92,11 @@ class SecretKeeper
85
92
 
86
93
  def remove_production_config(file_path)
87
94
  return :ok unless file_path =~ /\.yml/
88
- hash = YAML.load_file(file_path)
95
+ begin
96
+ hash = YAML.load_file(file_path, aliases: true)
97
+ rescue ArgumentError
98
+ hash = YAML.load_file(file_path)
99
+ end
89
100
  hash.delete('production')
90
101
  File.write(file_path, YAML.dump(hash))
91
102
  :ok
@@ -93,6 +104,13 @@ class SecretKeeper
93
104
  e
94
105
  end
95
106
 
107
+ def remove_file(file_path)
108
+ File.delete(file_path)
109
+ :ok
110
+ rescue => e
111
+ e
112
+ end
113
+
96
114
  private
97
115
 
98
116
  def encrypt(data)
@@ -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,23 +14,91 @@ 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.exist?(source_file)).to eq(false)
32
+ expect(File.exist?(target_file)).to eq(true)
33
+ end
34
+ end
11
35
  end
12
36
 
13
37
  describe '.decrypt_files' do
14
38
  it 'should return true' do
15
39
  result = SecretKeeper.decrypt_files
16
40
  expect(result).to eq(true)
17
- hash = YAML.load_file('example/secrets.yml')
41
+ begin
42
+ hash = YAML.load_file('example/secrets.yml', aliases: true)
43
+ rescue ArgumentError
44
+ hash = YAML.load_file('example/secrets.yml')
45
+ end
18
46
  expect(hash['development']['secret_key_base']).to eq('e8310af93d52f174f475940c41fbfb90417b300ebc19e1b24bd5639f4fe35c5ffaa5775a347ace9732958f656a47f6bb8e1fd0760b12e51b0b4fe1f65ef0a1d6')
19
47
  expect(hash['production']['secret_key_base']).to eq('339f639f4fe35c5ffaa47ace973260b12e51b0b4fe1f65effd283a5f054f47594b24bd565779e351a20dfd4ada4f777958f0417b305c06cdedbde392b8e1fd07')
20
48
  end
21
49
 
22
- it 'should return true on remove_production true' do
23
- result = SecretKeeper.decrypt_files(ENV['RAILS_ENV'] != 'production')
50
+ it 'should return true on remove_production true and remove_source false' do
51
+ options = {
52
+ 'slience' => true,
53
+ 'remove_production' => true,
54
+ 'remove_source' => false
55
+ }
56
+ allow_any_instance_of(SecretKeeper).to receive(:options).and_return(options)
57
+
58
+ result = SecretKeeper.decrypt_files
59
+ expect(result).to eq(true)
60
+ hash = YAML.load_file('example/secrets.yml')
61
+ expect(hash['development']['secret_key_base']).to eq('e8310af93d52f174f475940c41fbfb90417b300ebc19e1b24bd5639f4fe35c5ffaa5775a347ace9732958f656a47f6bb8e1fd0760b12e51b0b4fe1f65ef0a1d6')
62
+ expect(hash['production']).to be_nil
63
+ end
64
+
65
+ it 'should return true on remove_production false and remove_source true' do
66
+ options = {
67
+ 'slience' => true,
68
+ 'remove_production' => false,
69
+ 'remove_source' => true
70
+ }
71
+ allow_any_instance_of(SecretKeeper).to receive(:options).and_return(options)
72
+
73
+ result = SecretKeeper.decrypt_files
74
+ expect(result).to eq(true)
75
+ SecretKeeper.new.tasks.each do |task|
76
+ source_file = task['decrypt_from'] || task['encrypt_to']
77
+ target_file = task['decrypt_to'] || task['encrypt_from']
78
+ expect(File.exist?(source_file)).to eq(false)
79
+ expect(File.exist?(target_file)).to eq(true)
80
+ end
81
+ end
82
+
83
+ it 'should return true on remove_production true and remove_source true' do
84
+ options = {
85
+ 'slience' => true,
86
+ 'remove_production' => true,
87
+ 'remove_source' => true
88
+ }
89
+ allow_any_instance_of(SecretKeeper).to receive(:options).and_return(options)
90
+
91
+ result = SecretKeeper.decrypt_files
24
92
  expect(result).to eq(true)
25
93
  hash = YAML.load_file('example/secrets.yml')
26
94
  expect(hash['development']['secret_key_base']).to eq('e8310af93d52f174f475940c41fbfb90417b300ebc19e1b24bd5639f4fe35c5ffaa5775a347ace9732958f656a47f6bb8e1fd0760b12e51b0b4fe1f65ef0a1d6')
27
95
  expect(hash['production']).to be_nil
96
+ SecretKeeper.new.tasks.each do |task|
97
+ source_file = task['decrypt_from'] || task['encrypt_to']
98
+ target_file = task['decrypt_to'] || task['encrypt_from']
99
+ expect(File.exist?(source_file)).to eq(false)
100
+ expect(File.exist?(target_file)).to eq(true)
101
+ end
28
102
  end
29
103
 
30
104
  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: 1.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ray Lee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-04 00:00:00.000000000 Z
11
+ date: 2023-05-11 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.0'
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.0'
26
+ version: '3.9'
27
27
  description: A Secret keeper
28
28
  email: ray-lee@kdanmobile.com
29
29
  executables: []
@@ -37,7 +37,9 @@ files:
37
37
  homepage: https://github.com/kdan-mobile-software-ltd/secret-keeper
38
38
  licenses:
39
39
  - MIT
40
- metadata: {}
40
+ metadata:
41
+ source_code_uri: https://github.com/kdan-mobile-software-ltd/secret-keeper
42
+ changelog_uri: https://github.com/kdan-mobile-software-ltd/secret-keeper/blob/master/CHANGELOG.md
41
43
  post_install_message:
42
44
  rdoc_options:
43
45
  - "--charset=UTF-8"
@@ -47,14 +49,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
47
49
  requirements:
48
50
  - - ">="
49
51
  - !ruby/object:Gem::Version
50
- version: 2.3.1
52
+ version: 2.7.0
51
53
  required_rubygems_version: !ruby/object:Gem::Requirement
52
54
  requirements:
53
55
  - - ">="
54
56
  - !ruby/object:Gem::Version
55
57
  version: '0'
56
58
  requirements: []
57
- rubygems_version: 3.1.4
59
+ rubygems_version: 3.4.10
58
60
  signing_key:
59
61
  specification_version: 4
60
62
  summary: Keep all your secret files within openssl