secret-keeper 1.0.0 → 2.0.1

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: 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