encrypt_env 1.1.6 → 1.2.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 +4 -4
- data/bin/encrypt_env +11 -3
- data/lib/encrypt_env.rb +147 -71
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d696c60bf3a51762a466ccae6de5a7fea2a18b9e5c9ee744708e9541e097f2c
|
4
|
+
data.tar.gz: 36d4248ccbcf1c5121c28248dd045f40f3806c23be0519a3f01624148bb7c172
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebb16a54fda48f54342a9d2987dcdf95d37b2c32b20ee304428e4d435d794d1b6e5a303233e2c26104c3534756d37c1f1dc554025becb72ef55e3a6b9f62fa69
|
7
|
+
data.tar.gz: 3add45fbf64eef00a7f0d131229bb9dab796f99bf43d0529d9f34b8dbd635a5e198d32afaed210cfd3c356dcfa7184215bfda83fca47b145d6cf6d1371fad1a9
|
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,32 +8,96 @@ 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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
@
|
20
|
-
|
21
|
-
|
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
|
22
34
|
else
|
23
|
-
puts '
|
24
|
-
|
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
|
25
44
|
end
|
45
|
+
Rails.env
|
26
46
|
end
|
27
47
|
|
28
|
-
private_class_method def self.
|
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*')
|
63
|
+
end
|
64
|
+
|
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
|
+
|
29
93
|
encrypted = raw_data.slice(0, raw_data.length - 28)
|
30
94
|
iv = raw_data.slice(raw_data.length - 28, 12)
|
31
95
|
tag = raw_data.slice(raw_data.length - 16, 16)
|
32
96
|
{ encrypted: encrypted, iv: iv, tag: tag }
|
33
97
|
end
|
34
98
|
|
35
|
-
private_class_method def self.encrypt(content)
|
36
|
-
|
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"
|
37
101
|
cipher = OpenSSL::Cipher.new('aes-128-gcm')
|
38
102
|
cipher.encrypt
|
39
103
|
cipher.key = @master_key
|
@@ -42,20 +106,15 @@ class EncryptEnv
|
|
42
106
|
encrypted = cipher.update(content) + cipher.final
|
43
107
|
tag = cipher.auth_tag
|
44
108
|
hex_string = (encrypted + iv + tag).unpack('H*')[0]
|
45
|
-
File.open(
|
109
|
+
File.open(file_path, 'w') { |file| file.write(hex_string) }
|
46
110
|
end
|
47
111
|
|
48
|
-
private_class_method def self.decrypt
|
49
|
-
|
50
|
-
|
51
|
-
puts "master key not found in 'config/master.key' file and 'MASTER_KEY' environment variable!"
|
52
|
-
@raw_decrypted = ''
|
53
|
-
return false
|
54
|
-
end
|
112
|
+
private_class_method def self.decrypt(env = nil)
|
113
|
+
load_master_key(env)
|
114
|
+
|
55
115
|
decipher = OpenSSL::Cipher.new('aes-128-gcm')
|
56
116
|
decipher.decrypt
|
57
|
-
|
58
|
-
data = data_decrypt([hex_string].pack('H*'))
|
117
|
+
data = load_encrypted_data(env)
|
59
118
|
encrypted = data[:encrypted]
|
60
119
|
decipher.key = @master_key
|
61
120
|
decipher.iv = data[:iv]
|
@@ -63,69 +122,86 @@ class EncryptEnv
|
|
63
122
|
decipher.auth_data = ''
|
64
123
|
|
65
124
|
@raw_decrypted = decipher.update(encrypted) + decipher.final
|
66
|
-
@decrypted =
|
67
|
-
|
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
|
68
130
|
end
|
69
131
|
|
70
|
-
private_class_method def self.
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
140
|
+
end
|
141
|
+
obj
|
78
142
|
end
|
79
143
|
|
80
|
-
def self.
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
File.open("#{@path_root}/config/master.key", 'w') { |file| file.write(key.unpack('H*')[0]) }
|
86
|
-
encrypt(File.read(@secret_file))
|
87
|
-
File.rename(@secret_file, "#{@path_root}/config/secrets.yml.old")
|
88
|
-
system("echo '/config/master.key' >> #{@path_root}/.gitignore")
|
89
|
-
system("echo '/config/secrets.yml.old' >> #{@path_root}/.gitignore")
|
90
|
-
system("echo 'Set up complete!'")
|
144
|
+
def self.secrets_all
|
145
|
+
return all_decrypted_object if @opt == 2
|
146
|
+
|
147
|
+
decrypt
|
148
|
+
@decrypted
|
91
149
|
end
|
92
150
|
|
93
|
-
def self.
|
94
|
-
|
151
|
+
def self.secrets(env = nil)
|
152
|
+
load_curr_opt unless @opt
|
153
|
+
return secrets_all if env == 'all'
|
95
154
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
@decrypted = nil
|
155
|
+
if @opt == 1
|
156
|
+
decrypt
|
157
|
+
@decrypted[env || current_env]
|
158
|
+
else
|
159
|
+
decrypt(env || current_env)
|
160
|
+
@decrypted
|
103
161
|
end
|
104
162
|
end
|
105
163
|
|
106
|
-
def self.
|
107
|
-
|
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'
|
108
175
|
|
109
|
-
|
176
|
+
load_master_key(env)
|
177
|
+
encrypt(value.to_hash.to_yaml, env)
|
178
|
+
end
|
179
|
+
end
|
110
180
|
|
111
|
-
{}
|
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!'")
|
112
185
|
end
|
113
186
|
|
114
|
-
def self.
|
115
|
-
|
187
|
+
def self.edit(env = nil)
|
188
|
+
load_curr_opt unless @opt
|
189
|
+
env ||= current_env if @opt == 2
|
190
|
+
return unless decrypt(env)
|
116
191
|
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
120
199
|
end
|
121
|
-
@decrypted[Rails.env.to_sym]
|
122
|
-
end
|
123
|
-
|
124
|
-
def self.show
|
125
|
-
jj secrets
|
126
200
|
end
|
127
201
|
|
128
|
-
def self.
|
129
|
-
jj
|
202
|
+
def self.show(env = nil)
|
203
|
+
jj secrets(env)
|
130
204
|
end
|
131
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
|
4
|
+
version: 1.2.1
|
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
|