encrypt_env 1.1.7 → 1.2.2

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/bin/encrypt_env +11 -3
  3. data/lib/encrypt_env.rb +140 -62
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e450fae62c0ff654e9034c4b09d4f7775285c7f446bf6af24d8c99f124841e3
4
- data.tar.gz: e83e7f84b9821f7a1790f4320ae12f3296312f3716daa57b90646f904afd787c
3
+ metadata.gz: 39d324cf43ef142486ae13f849ef25d421c4b84a889bfb620ba02febe43734ac
4
+ data.tar.gz: 3744f4b529dfe535d98dd94392b0aa527e102c8cbfb57696e53469794dbb0203
5
5
  SHA512:
6
- metadata.gz: 7fdbcb0834f9f34edcbbd547fa28cafe680a655e69d4320428c3bba80bf2187989cc9a0b2d58ecee61bcbee762828a27bb4754638066cc1eac174ec3fa4aea99
7
- data.tar.gz: cca971c37af42ece717519c0b6d795c8f577ccc12e5dcff29a7bb21b1edecc3a3b7ffa95e4b15781dcf35cca67b85ba60c8db072e16c08dc82c4c9f439ec0b50
6
+ metadata.gz: 9e660e1d3390110ddbdfae62a8e4d0c331e6703c696af4202f158fedd5227a165b59bcf3d43449fa6d96f21658cf260db7d607f46faf070aefdc206cfa9a92b0
7
+ data.tar.gz: 07ed2e14def1acebde149fdba0f9e22d2c85ddfdf9fc1d08c9d0ee0fdbe0cc85f19f9b762361a7e2d97ff99efc7cbd1c49fde82057b755d98bde20556c8e7030
data/bin/encrypt_env CHANGED
@@ -11,13 +11,21 @@ if action == 'setup'
11
11
  EncryptEnv.setup
12
12
  exit 0
13
13
  elsif action == 'show'
14
- EncryptEnv.show
14
+ if argv[0]
15
+ EncryptEnv.show(argv[0])
16
+ else
17
+ EncryptEnv.show
18
+ end
15
19
  exit 0
16
20
  elsif action == 'all'
17
- EncryptEnv.show_all
21
+ EncryptEnv.show('all')
18
22
  exit 0
19
23
  elsif action == 'edit'
20
- EncryptEnv.edit
24
+ if argv[0]
25
+ EncryptEnv.edit(argv[0])
26
+ else
27
+ EncryptEnv.edit
28
+ end
21
29
  exit 0
22
30
  elsif ['help', '--help', '-h'].include?(action)
23
31
  puts <<~HELP
data/lib/encrypt_env.rb CHANGED
@@ -8,34 +8,86 @@ require 'tempfile'
8
8
  require 'json'
9
9
 
10
10
  # gem 'encrypt_env'
11
+ # rubocop:disable Metrics/ClassLength
12
+ # rubocop:disable Metrics/MethodLength
11
13
  class EncryptEnv
12
- private_class_method def self.path_root
13
- @path_root = (defined?(Rails) && Rails.root.to_s) || (defined?(Bundler) && Bundler.root.to_s) || Dir.pwd
14
+ private_class_method def self.define_option
15
+ puts "Options to 'encrypt secrets.yml' file"
16
+ puts '1. Generate only one master.key and one encrypted file for all environment'
17
+ puts '2. Generate master.key and encrypted file for each environment'
18
+
19
+ loop do
20
+ @opt = gets.chomp.to_i
21
+ break if @opt == 1 || @opt == 2
22
+
23
+ puts "Please enter '1' or '2'!"
24
+ end
25
+
26
+ puts "Your option is #{@opt}"
14
27
  end
15
28
 
16
- private_class_method def self.master_key
17
- if File.file?("#{@path_root}/config/master.key")
18
- key = File.read("#{@path_root}/config/master.key").strip
19
- elsif ENV.key?('MASTER_KEY')
20
- key = ENV['MASTER_KEY']
29
+ private_class_method def self.load_curr_opt
30
+ if File.file?("#{Dir.pwd}/config/secrets.yml.enc")
31
+ @opt = 1
32
+ elsif Dir["#{Dir.pwd}/config/secrets_*.yml.enc"].length.positive?
33
+ @opt = 2
21
34
  else
22
- false
35
+ puts 'You must setup first to encrypt file!'
36
+ exit
37
+ end
38
+ end
39
+
40
+ private_class_method def self.current_env
41
+ unless defined?(Rails)
42
+ env = `rails r "print Rails.env"`
43
+ return env
23
44
  end
45
+ Rails.env
46
+ end
47
+
48
+ private_class_method def self.check_key_existence(env = nil)
49
+ file_name = env.nil? ? 'master.key' : "master_#{env}.key"
50
+ return if File.file?("#{Dir.pwd}/config/#{file_name}")
51
+ # return if Dir["#{Dir.pwd}/config/master_*.key"].length.positive? && @opt == 2
52
+ return if ENV.key?('MASTER_KEY')
53
+
54
+ puts 'Please provide master key!'
55
+ exit
56
+ end
57
+
58
+ private_class_method def self.load_master_key(env = nil)
59
+ check_key_existence(env)
60
+ file_path = env ? "#{Dir.pwd}/config/master_#{env}.key" : "#{Dir.pwd}/config/master.key"
61
+ key = File.file?(file_path) ? File.read(file_path).strip : ENV['MASTER_KEY']
24
62
  @master_key = [key].pack('H*')
25
- true
26
63
  end
27
64
 
28
- private_class_method def self.master_key?
29
- if @master_key.nil? && !master_key
30
- puts "master key not found in 'config/master.key' file and 'MASTER_KEY' environment variable!"
31
- @raw_decrypted = ''
32
- return false
65
+ private_class_method def self.generate_keys
66
+ if @opt == 1
67
+ key = OpenSSL::Random.random_bytes(16)
68
+ File.open("#{Dir.pwd}/config/master.key", 'w') { |file| file.write(key.unpack('H*')[0]) }
69
+ else
70
+ to_hash_type(@content_to_encrypt).each_key do |env|
71
+ next if env == 'default'
72
+
73
+ key = OpenSSL::Random.random_bytes(16)
74
+ File.open("#{Dir.pwd}/config/master_#{env}.key", 'w') { |file| file.write(key.unpack('H*')[0]) }
75
+ end
33
76
  end
34
- true
35
77
  end
36
78
 
37
- private_class_method def self.data_to_decrypt
38
- hex_string = File.read("#{@path_root}/config/secrets.yml.enc")
79
+ private_class_method def self.load_content_to_encrypt
80
+ secret_file = File.expand_path("#{Dir.pwd}/config/secrets.yml")
81
+ @content_to_encrypt = File.read(secret_file)
82
+ end
83
+
84
+ private_class_method def self.to_hash_type(raw_data)
85
+ HashWithIndifferentAccess.new(YAML.load(raw_data, aliases: true))
86
+ end
87
+
88
+ private_class_method def self.load_encrypted_data(env = nil)
89
+ file_path = env ? "#{Dir.pwd}/config/secrets_#{env}.yml.enc" : "#{Dir.pwd}/config/secrets.yml.enc"
90
+ hex_string = File.read(file_path)
39
91
  raw_data = [hex_string].pack('H*')
40
92
 
41
93
  encrypted = raw_data.slice(0, raw_data.length - 28)
@@ -44,8 +96,8 @@ class EncryptEnv
44
96
  { encrypted: encrypted, iv: iv, tag: tag }
45
97
  end
46
98
 
47
- private_class_method def self.encrypt(content)
48
- master_key unless @master_key
99
+ private_class_method def self.encrypt(content, typ = nil)
100
+ file_path = typ ? "#{Dir.pwd}/config/secrets_#{typ}.yml.enc" : "#{Dir.pwd}/config/secrets.yml.enc"
49
101
  cipher = OpenSSL::Cipher.new('aes-128-gcm')
50
102
  cipher.encrypt
51
103
  cipher.key = @master_key
@@ -54,16 +106,15 @@ class EncryptEnv
54
106
  encrypted = cipher.update(content) + cipher.final
55
107
  tag = cipher.auth_tag
56
108
  hex_string = (encrypted + iv + tag).unpack('H*')[0]
57
- File.open("#{@path_root}/config/secrets.yml.enc", 'w') { |file| file.write(hex_string) }
109
+ File.open(file_path, 'w') { |file| file.write(hex_string) }
58
110
  end
59
111
 
60
- private_class_method def self.decrypt
61
- path_root unless @path_root
62
- return unless master_key?
112
+ private_class_method def self.decrypt(env = nil)
113
+ load_master_key(env)
63
114
 
64
115
  decipher = OpenSSL::Cipher.new('aes-128-gcm')
65
116
  decipher.decrypt
66
- data = data_to_decrypt
117
+ data = load_encrypted_data(env)
67
118
  encrypted = data[:encrypted]
68
119
  decipher.key = @master_key
69
120
  decipher.iv = data[:iv]
@@ -71,59 +122,86 @@ class EncryptEnv
71
122
  decipher.auth_data = ''
72
123
 
73
124
  @raw_decrypted = decipher.update(encrypted) + decipher.final
74
- @decrypted = HashWithIndifferentAccess.new(YAML.load(@raw_decrypted, aliases: true))
75
- true
76
- end
77
-
78
- def self.setup
79
- path_root
80
- secret_file = File.expand_path("#{@path_root}/config/secrets.yml")
81
- key = OpenSSL::Random.random_bytes(16)
82
- # save key in master.key file
83
- File.open("#{@path_root}/config/master.key", 'w') { |file| file.write(key.unpack('H*')[0]) }
84
- encrypt(File.read(secret_file))
85
- File.rename(secret_file, "#{@path_root}/config/secrets.yml.old")
86
- system("echo '/config/master.key' >> #{@path_root}/.gitignore")
87
- system("echo '/config/secrets.yml.old' >> #{@path_root}/.gitignore")
88
- system("echo 'Set up complete!'")
125
+ @decrypted = to_hash_type(@raw_decrypted)
126
+ # Catch error if master key is wrong
127
+ rescue OpenSSL::Cipher::CipherError
128
+ puts 'Master key is wrong!'
129
+ exit
89
130
  end
90
131
 
91
- def self.edit
92
- return unless decrypt
93
-
94
- Tempfile.create('secrets.yml') do |f|
95
- f.write(@raw_decrypted)
96
- f.flush
97
- f.rewind
98
- system("vim #{f.path}")
99
- encrypt(File.read(f.path))
100
- @decrypted = nil
132
+ private_class_method def self.all_decrypted_object
133
+ obj = {}
134
+ env_lst = Dir["#{Dir.pwd}/config/secrets_*.yml.enc"].map do |path|
135
+ path.scan(/secrets_(.*)\.yml\.enc/).flatten.first
136
+ end
137
+ env_lst.each do |e|
138
+ decrypt(e)
139
+ obj[e] = @decrypted
101
140
  end
141
+ obj
102
142
  end
103
143
 
104
144
  def self.secrets_all
105
- return @decrypted if @decrypted
145
+ return all_decrypted_object if @opt == 2
106
146
 
107
- return @decrypted if decrypt
147
+ decrypt
148
+ @decrypted
149
+ end
150
+
151
+ def self.secrets(env = nil)
152
+ load_curr_opt unless @opt
153
+ return secrets_all if env == 'all'
108
154
 
109
- {}
155
+ if @opt == 1
156
+ decrypt
157
+ @decrypted[env || current_env]
158
+ else
159
+ decrypt(env || current_env)
160
+ @decrypted
161
+ end
110
162
  end
111
163
 
112
- def self.secrets
113
- return {} if !@decrypted && !decrypt
164
+ def self.setup
165
+ define_option
166
+ load_content_to_encrypt
167
+ generate_keys
114
168
 
115
- unless defined?(Rails)
116
- env = `rails r "print Rails.env"`.to_sym
117
- return @decrypted[env]
169
+ if @opt == 1
170
+ load_master_key
171
+ encrypt(@content_to_encrypt)
172
+ else
173
+ to_hash_type(@content_to_encrypt).each do |env, value|
174
+ next if env == 'default'
175
+
176
+ load_master_key(env)
177
+ encrypt(value.to_hash.to_yaml, env)
178
+ end
118
179
  end
119
- @decrypted[Rails.env.to_sym]
180
+
181
+ File.rename("#{Dir.pwd}/config/secrets.yml", "#{Dir.pwd}/config/secrets.yml.old")
182
+ system("echo '/config/master*.key' >> #{Dir.pwd}/.gitignore")
183
+ system("echo '/config/secrets.yml.old' >> #{Dir.pwd}/.gitignore")
184
+ system("echo 'Set up complete!'")
120
185
  end
121
186
 
122
- def self.show
123
- jj secrets
187
+ def self.edit(env = nil)
188
+ load_curr_opt unless @opt
189
+ env ||= current_env if @opt == 2
190
+ return unless decrypt(env)
191
+
192
+ Tempfile.create("secrets_#{env}.yml") do |f|
193
+ f.write(@raw_decrypted)
194
+ f.flush
195
+ f.rewind
196
+ system("vim #{f.path}")
197
+ encrypt(File.read(f.path), env)
198
+ @decrypted = nil
199
+ end
124
200
  end
125
201
 
126
- def self.show_all
127
- jj secrets_all
202
+ def self.show(env = nil)
203
+ jj secrets(env)
128
204
  end
129
205
  end
206
+ # rubocop:enable Metrics/ClassLength
207
+ # rubocop:enable Metrics/MethodLength
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: encrypt_env
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.7
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nhu Tan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-09 00:00:00.000000000 Z
11
+ date: 2022-08-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Encrypts and decrypts environment variables
14
14
  email: nhutan2001@gmail.com