encrypt_env 1.1.5 → 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 +4 -4
- data/bin/encrypt_env +11 -3
- data/lib/encrypt_env.rb +151 -77
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31ee9ab6595f4b030378dbab20064c2a6fbaf78703ceb8d673b6a937d21c5ab0
|
4
|
+
data.tar.gz: b4e53740a417b02fe1b4920609f11b9fedb9d1913b70ab7c0593f67b3599a994
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de90b6a660b19c26bde561133ac8816c06c3b87bb8d3cda02c3ba8cafaf3063e5b4937b50376de233da2a060339cc92a04e4ff8af811e23794a31daf5d75af4d
|
7
|
+
data.tar.gz: 2515b17576ab29ff0a71414c100e23e974029c7c4dccc04c43def34eb761e06cdbbeb7fdac0bd912950b7f7c4b9c4b8c12b0ea690f3459d294f51b070ba9fa0e
|
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
|
-
|
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.
|
21
|
+
EncryptEnv.show('all')
|
18
22
|
exit 0
|
19
23
|
elsif action == 'edit'
|
20
|
-
|
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,126 +8,200 @@ 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.
|
13
|
-
|
14
|
-
|
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}"
|
27
|
+
end
|
28
|
+
|
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
|
34
|
+
else
|
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
|
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']
|
62
|
+
@master_key = [key].pack('H*')
|
15
63
|
end
|
16
64
|
|
17
|
-
private_class_method def self.
|
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
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
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)
|
91
|
+
raw_data = [hex_string].pack('H*')
|
92
|
+
|
18
93
|
encrypted = raw_data.slice(0, raw_data.length - 28)
|
19
94
|
iv = raw_data.slice(raw_data.length - 28, 12)
|
20
95
|
tag = raw_data.slice(raw_data.length - 16, 16)
|
21
96
|
{ encrypted: encrypted, iv: iv, tag: tag }
|
22
97
|
end
|
23
98
|
|
24
|
-
private_class_method def self.encrypt(content)
|
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"
|
25
101
|
cipher = OpenSSL::Cipher.new('aes-128-gcm')
|
26
102
|
cipher.encrypt
|
27
|
-
cipher.key = master_key
|
103
|
+
cipher.key = @master_key
|
28
104
|
iv = cipher.random_iv
|
29
105
|
cipher.auth_data = ''
|
30
106
|
encrypted = cipher.update(content) + cipher.final
|
31
107
|
tag = cipher.auth_tag
|
32
108
|
hex_string = (encrypted + iv + tag).unpack('H*')[0]
|
33
|
-
File.open(
|
109
|
+
File.open(file_path, 'w') { |file| file.write(hex_string) }
|
34
110
|
end
|
35
111
|
|
36
|
-
private_class_method def self.decrypt
|
112
|
+
private_class_method def self.decrypt(env = nil)
|
113
|
+
load_master_key(env)
|
114
|
+
|
37
115
|
decipher = OpenSSL::Cipher.new('aes-128-gcm')
|
38
116
|
decipher.decrypt
|
39
|
-
|
40
|
-
data = data_decrypt([hex_string].pack('H*'))
|
117
|
+
data = load_encrypted_data(env)
|
41
118
|
encrypted = data[:encrypted]
|
42
|
-
decipher.key = master_key
|
119
|
+
decipher.key = @master_key
|
43
120
|
decipher.iv = data[:iv]
|
44
121
|
decipher.auth_tag = data[:tag]
|
45
122
|
decipher.auth_data = ''
|
46
123
|
|
47
|
-
decipher.update(encrypted) + decipher.final
|
124
|
+
@raw_decrypted = decipher.update(encrypted) + decipher.final
|
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
|
48
130
|
end
|
49
131
|
|
50
|
-
private_class_method def self.
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.setup
|
61
|
-
path_root
|
62
|
-
@secret_file = File.expand_path("#{@path_root}/config/secrets.yml")
|
63
|
-
key = OpenSSL::Random.random_bytes(16)
|
64
|
-
# save key in master.key file
|
65
|
-
File.open("#{@path_root}/config/master.key", 'w') { |file| file.write(key.unpack('H*')[0]) }
|
66
|
-
encrypt(File.read(@secret_file))
|
67
|
-
File.rename(@secret_file, "#{@path_root}/config/secrets.yml.old")
|
68
|
-
system("echo '/config/master.key' >> #{@path_root}/.gitignore")
|
69
|
-
system("echo '/config/secrets.yml.old' >> #{@path_root}/.gitignore")
|
70
|
-
system("echo 'Set up complete!'")
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.edit
|
74
|
-
path_root unless @path_root
|
75
|
-
secrets unless @decrypted
|
76
|
-
Tempfile.create('secrets.yml') do |f|
|
77
|
-
f.write(decrypt)
|
78
|
-
f.flush
|
79
|
-
f.rewind
|
80
|
-
system("vim #{f.path}")
|
81
|
-
encrypt(File.read(f.path))
|
82
|
-
@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
|
83
140
|
end
|
141
|
+
obj
|
84
142
|
end
|
85
143
|
|
86
144
|
def self.secrets_all
|
87
|
-
|
88
|
-
|
145
|
+
return all_decrypted_object if @opt == 2
|
146
|
+
|
147
|
+
decrypt
|
89
148
|
@decrypted
|
90
149
|
end
|
91
150
|
|
92
|
-
def self.secrets
|
93
|
-
@
|
151
|
+
def self.secrets(env = nil)
|
152
|
+
load_curr_opt unless @opt
|
153
|
+
return secrets_all if env == 'all'
|
94
154
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
155
|
+
if @opt == 1
|
156
|
+
decrypt
|
157
|
+
@decrypted[env || current_env]
|
158
|
+
else
|
159
|
+
decrypt(env || current_env)
|
160
|
+
@decrypted
|
100
161
|
end
|
101
|
-
@decrypted[Rails.env.to_sym] || @decrypted[:default] || @decrypted
|
102
162
|
end
|
103
163
|
|
104
|
-
def self.
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
164
|
+
def self.setup
|
165
|
+
define_option
|
166
|
+
load_content_to_encrypt
|
167
|
+
generate_keys
|
168
|
+
|
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
|
179
|
+
end
|
113
180
|
|
114
|
-
|
115
|
-
|
116
|
-
|
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!'")
|
117
185
|
end
|
118
186
|
|
119
|
-
def self.
|
120
|
-
|
121
|
-
@
|
122
|
-
|
187
|
+
def self.edit(env = nil)
|
188
|
+
load_curr_opt unless @opt
|
189
|
+
env ||= current_env if @opt == 2
|
190
|
+
return unless decrypt(env)
|
123
191
|
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|
127
200
|
end
|
128
201
|
|
129
|
-
def self.
|
130
|
-
|
131
|
-
jj secrets_all
|
202
|
+
def self.show(env = nil)
|
203
|
+
jj secrets(env)
|
132
204
|
end
|
133
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.
|
4
|
+
version: 1.2.0
|
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-
|
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
|
@@ -39,7 +39,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
requirements: []
|
42
|
-
rubygems_version: 3.
|
42
|
+
rubygems_version: 3.3.7
|
43
43
|
signing_key:
|
44
44
|
specification_version: 4
|
45
45
|
summary: Ecrypt secrets.yml file
|