secretmgr 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,200 +1,247 @@
1
- # frozen_string_literal: true
2
-
3
- require "pathname"
4
-
5
- module Secretmgr
6
- # 秘匿情報マネージャ
7
- class Secretmgr
8
- attr_reader :decrypted_text, :secret
9
-
10
- class << self
11
- def create(secret_dir_pn, plain_setting_file_pn, plain_secret_file_pn)
12
- @inst = Secretmgr.new(secret_dir_pn)
13
- @inst.set_setting_for_data(plain_setting_file_pn, plain_secret_file_pn)
14
- @inst
15
- end
16
- end
17
-
18
- def initialize(secret_dir_pn)
19
- @content = nil
20
- @secret_dir_pn = secret_dir_pn
21
- @encrypted_setting_file_pn = "#{@secret_dir_pn}setting.yml"
22
-
23
- @format_config = Config.new(@secret_dir_pn, "format.txt")
24
- home_dir = ENV["HOME"]
25
- @home_pn = Pathname.new(home_dir)
26
- # pemフォーマットの公開鍵ファイルの内容を取得
27
- path = File.join(home_dir, ".ssh", "pem")
28
- pub_key = File.read(path)
29
- # 鍵をOpenSSLのオブジェクトにする
30
- @public_key = OpenSSL::PKey::RSA.new(pub_key)
31
- path = File.join(home_dir, ".ssh", "id_rsa_no")
32
- private_key = File.read(path)
33
- @private_key = OpenSSL::PKey::RSA.new(private_key)
34
-
35
- @mode = OpenSSL::PKey::RSA::PKCS1_PADDING
36
- end
37
-
38
- def set_setting_for_data(plain_setting_file_pn, plain_secret_file_pn)
39
- @plain_setting_file_pn = plain_setting_file_pn
40
- @plain_secret_file_pn = plain_secret_file_pn
41
- @plain_dir_pn = @plain_setting_file_pn.parent
42
- end
43
-
44
- def setup
45
- setup_setting
46
- setup_secret
47
- setup_secret_for_json_file
48
- end
49
-
50
- def setup_setting
51
- content = File.read(@plain_setting_file_pn)
52
- @setting = Ykxutils.yaml_load_compati(content)
53
- # content = YAML.dump(@setting)
54
- encrypted_text = encrypt_with_public_key(content)
55
- dest_setting_file_pn = make_pair_file_pn(@secret_dir_pn, @plain_setting_file_pn, "yml")
56
-
57
- File.write(dest_setting_file_pn, encrypted_text)
58
- end
59
-
60
- def make_pair_file_pn(dest_dir_pn, file_pn, ext)
61
- basename = file_pn.basename
62
- extname = basename.extname
63
- return nil if extname == ext
64
-
65
- basename = file_pn.basename(".*")
66
- dest_dir_pn + %(#{basename}.#{ext})
67
- end
68
-
69
- def setup_secret
70
- plaintext = File.read(@plain_secret_file_pn)
71
- encrypted_text = encrypt_with_common_key(plaintext, @setting["key"], @setting["iv"])
72
- dest_secret_file_pn = make_pair_file_pn(@secret_dir_pn, @plain_secret_file_pn, "yml")
73
- dest_secret_file_pn.realpath
74
- # puts "setup_secret dest_secret_file_pn=#{dest_secret_file_pn}"
75
- # puts "real_pn=#{real_pn}"
76
- File.write(dest_secret_file_pn, encrypted_text)
77
- end
78
-
79
- def setup_secret_for_json_file
80
- top_pn = "#{@plain_dir_pn}JSON_FILE"
81
- top_pn.find do |x|
82
- # p x if x.file?
83
- relative_path = x.relative_path_from(@plain_dir_pn)
84
- # p relative_path
85
- encrypt_and_copy(x, @secret_dir_pn, relative_path)
86
- end
87
- end
88
-
89
- def encrypt_and_copy(src_pn, dest_top_dir_pn, relative_path)
90
- dest_pn = dest_top_dir_pn + relative_path
91
- return unless src_pn.exist? && src_pn.file?
92
-
93
- puts "e_adn_c #{src_pn} -> #{dest_pn}"
94
- plaintext = File.read(src_pn)
95
- encrypted_text = encrypt_with_common_key(plaintext, @setting["key"], @setting["iv"])
96
- File.write(dest_pn, encrypted_text)
97
- end
98
-
99
- def set_setting_for_query(*dirs)
100
- @valid_dirs = dirs.flatten.reject(&:nil?)
101
- @target, @sub_target, _tmp = @valid_dirs
102
- # p "@valid_dirs=#{@valid_dirs}"
103
- @file_format = @format_config.file_format(@target, @sub_target)
104
- p "@file_format=#{@file_format}"
105
- p "dirs=#{dirs}"
106
- @encrypted_secret_file_pn = @format_config.get_file_path(@secret_dir_pn, dirs)
107
- end
108
-
109
- def load_setting
110
- encrypted_text = File.read(@encrypted_setting_file_pn)
111
- # puts "encrypted_text=#{encrypted_text}"
112
- decrypted_text = decrypt_with_private_key(encrypted_text)
113
- setting = YAML.safe_load(decrypted_text)
114
- @key = setting["key"]
115
- @iv = setting["iv"]
116
- # p "load_settings @key=#{@key}"
117
- # p "load_settings @iv=#{@iv}"
118
- end
119
-
120
- def load_secret
121
- base64_text = File.read(@encrypted_secret_file_pn)
122
- encrypted_content = Base64.decode64(base64_text)
123
- begin
124
- @decrpyted_content = decrypt_with_common_key(encrypted_content, @key, @iv)
125
- @content = case @file_format
126
- when "JSON_FILE"
127
- @decrpyted_content
128
- when "YAML"
129
- @secret = YAML.safe_load(@decrpyted_content)
130
- @sub_target ? @secret[@target][@sub_target] : @secret[@target]
131
- else
132
- ""
133
- end
134
- rescue StandardError => e
135
- puts e
136
- puts e.message
137
- puts e.backtrace
138
- puts "Can't dencrypt #{@encrypted_setting_file_pn}"
139
- end
140
- @content
141
- end
142
-
143
- def load
144
- load_setting
145
- load_secret
146
- end
147
-
148
- def encrypt_with_public_key(data)
149
- Base64.encode64(
150
- @public_key.public_encrypt(
151
- data,
152
- OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
153
- )
154
- ).delete("\n")
155
- end
156
-
157
- def decrypt_with_private_key(base64_text)
158
- @private_key.private_decrypt(
159
- Base64.decode64(base64_text),
160
- OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
161
- )
162
- end
163
-
164
- # 引数 str を暗号化した結果を返す
165
- def encrypt_with_common_key(plaintext, key, _ivalue)
166
- encx = OpenSSL::Cipher.new(CIPHER_NAME)
167
- encx.encrypt
168
- encx.key = key
169
- encx.iv = ivvalue
170
- # str に与えた文字列を暗号化します。
171
- encrypted_text = encx.update(plaintext) + encx.final
172
-
173
- Base64.encode64(encrypted_text)
174
- end
175
-
176
- def decrypt_with_common_key(encrypted_data, key, ivalue)
177
- decx = OpenSSL::Cipher.new(CIPHER_NAME)
178
- decx.decrypt
179
- decx.key = key
180
- decx.iv = ivalue
181
- data = decx.update(encrypted_data)
182
- final_data = decx.final
183
- decrypted_data = data + final_data
184
- decrypted_data.force_encoding("UTF-8")
185
- end
186
-
187
- def make(_template_dir, _target, _sub_target)
188
- case @file_format
189
- when "JSON_FILE"
190
- @content
191
- when "YAML"
192
- @content.map do |item|
193
- %(export #{item[0]}=#{item[1]})
194
- end.flatten
195
- else
196
- ""
197
- end
198
- end
199
- end
200
- end
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "debug"
5
+
6
+ module Secretmgr
7
+ # 秘匿情報マネージャ
8
+ class Secretmgr
9
+ attr_reader :decrypted_text, :secret
10
+
11
+ @log_level = nil
12
+ @init_count = 0
13
+ # @setting_file = "setting.yml"
14
+ JSON_FILE_DIR = "JSON_FILE"
15
+ SETTING_KEY = "key"
16
+ SETTING_IV = "iv"
17
+ FORMAT_JSON = "JSON_FILE"
18
+ FORMAT_YAML = "YAML"
19
+ YML = "yml"
20
+ # @dot_yml = "yml"
21
+ # @secret_dir = "secret"
22
+ DEFAULT_PRIVATE_KEYFILE = ".ssh/id_rsa"
23
+ DEFAULT_PUBLIC_KEYFILE = ".ssh/id_rsa.pub"
24
+
25
+ class << self
26
+ def log_init(log_level)
27
+ return unless @log_level.nil?
28
+
29
+ @log_level = log_level
30
+ Loggerxs.init("log_", "log.txt", ".", true, log_level) if @init_count.zero?
31
+ @init_count += 1
32
+ end
33
+
34
+ def reset_init_count
35
+ @init_count = 0
36
+ end
37
+ end
38
+
39
+ def initialize(seting, secret_dir_pn, secret_key_dir_pn, ope,
40
+ public_keyfile_pn: nil, private_keyfile_pn: nil)
41
+ log_level = :info
42
+ # log_level = :debug
43
+ Secretmgr.log_init(log_level)
44
+
45
+ @setting = seting
46
+ home_pn = Pathname.new(Dir.home)
47
+ secret_dir_pn = Pathname.new(secret_dir_pn) unless secret_dir_pn.instance_of?(Pathname)
48
+ secret_key_dir_pn = Pathname.new(secret_key_dir_pn) unless secret_key_dir_pn.instance_of?(Pathname)
49
+ secret_key_dir_pn.mkdir unless secret_key_dir_pn.exist?
50
+ default_public_keyfile_pn = secret_key_dir_pn + "id_rsa.pub"
51
+ default_private_keyfile_pn = secret_key_dir_pn + "id_rsa"
52
+ public_keyfile_pn = Pathname.new(public_keyfile_pn) if public_keyfile_pn
53
+ private_keyfile_pn = Pathname.new(private_keyfile_pn) if private_keyfile_pn
54
+
55
+ @secret = Secret.new(@setting, home_pn, secret_dir_pn, ope,
56
+ default_public_keyfile_pn,
57
+ default_private_keyfile_pn,
58
+ public_keyfile_pn: public_keyfile_pn,
59
+ private_keyfile_pn: private_keyfile_pn)
60
+ end
61
+
62
+ def valid?
63
+ @secret.valid
64
+ # Loggerxs.debug "1 ret=#{ret}"
65
+ # p "2 ret=#{ret}"
66
+ end
67
+
68
+ def output_public_key(public_keyfile_pn)
69
+ @secret.output_public_key(public_keyfile_pn)
70
+ end
71
+
72
+ def create_public_key(public_keyfile_pn)
73
+ @secret.create_public_key(public_keyfile_pn)
74
+ end
75
+
76
+ def output_private_key(private_keyfile_pn)
77
+ @secret.output_private_key(private_keyfile_pn)
78
+ end
79
+
80
+ def create_private_key(private_keyfile_pn)
81
+ @secret.create_private_key(private_keyfile_pn)
82
+ end
83
+
84
+ def set_setting_for_plain(plain_setting_file_pn, plain_secret_file_pn)
85
+ @plain_setting_file_pn = Pathname.new(@plain_setting_file_pn) if @plain_setting_file_pn
86
+ @plain_setting_file_pn ||= Pathname.new(plain_setting_file_pn)
87
+ @plain_secret_file_pn = Pathname.new(@plain_secret_file_pn) if @plain_secret_file_pn
88
+ @plain_secret_file_pn ||= Pathname.new(plain_secret_file_pn)
89
+ @plain_dir_pn = @plain_setting_file_pn.parent
90
+ @encrypted_setting_file_pn = @secret.encrypted_setting_file_pn
91
+ @encrypted_secret_file_pn = @secret.encrypted_secret_file_pn
92
+ end
93
+
94
+ def set_setting_for_encrypted(encrypted_setting_file_pn, encrypted_secret_file_pn)
95
+ @encrypted_setting_file_pn = Pathname.new(encrypted_setting_file_pn)
96
+ @encrypted_secret_file_pn = Pathname.new(encrypted_secret_file_pn)
97
+ end
98
+
99
+ def setup
100
+ # p "###### setup_setting"
101
+ setup_setting
102
+ # p "###### setup_secret"
103
+ setup_secret
104
+ # p "###### setup_secret_for_json_file"
105
+ setup_secret_for_json_file
106
+ end
107
+
108
+ def setup_setting
109
+ content = File.read(@plain_setting_file_pn)
110
+ # p "setup_setting content.size=#{content.size}"
111
+ # p "setup_setting content=#{content}"
112
+
113
+ @setting = YAML.safe_load(content)
114
+ # p "setup_setting @setting=#{@setting}"
115
+
116
+ Loggerxs.debug @setting
117
+ # pp "@setting=#{@setting}"
118
+ # puts "setup_setting @setting=#{@setting}"
119
+ encrypted_text = @secret.encrypt_with_public_key(content)
120
+ # puts "setup_setting encrypted_text.size=#{encrypted_text.size}"
121
+ # puts "setup_setting encrypted_text=#{encrypted_text}"
122
+ #
123
+ @secret.decrypt_with_private_key(encrypted_text)
124
+ # puts "setup_setting decrypted_text=#{decrypted_text}"
125
+ # puts "setup_setting decrypted_text.size=#{decrypted_text.size}"
126
+
127
+ dest_setting_file_pn = @secret.make_pair_file_pn(@plain_setting_file_pn, YML)
128
+
129
+ Loggerxs.debug "setup_setting dest_setting_file_pn=#{dest_setting_file_pn}"
130
+ File.write(dest_setting_file_pn, encrypted_text)
131
+ # p "dest_setting_file_pn=#{dest_setting_file_pn}"
132
+ end
133
+
134
+ def setup_secret
135
+ plaintext = File.read(@plain_secret_file_pn)
136
+ # puts "setup_secret @setting=#{@setting}"
137
+ encrypted_text = @secret.encrypt_with_common_key(plaintext,
138
+ @setting[SETTING_KEY],
139
+ @setting[SETTING_IV])
140
+ dest_secret_file_pn = @secret.make_pair_file_pn(@plain_secret_file_pn, YML)
141
+ Loggerxs.debug "setup_secret dest_secret_file_pn=#{dest_secret_file_pn}"
142
+ File.write(dest_secret_file_pn, encrypted_text)
143
+ end
144
+
145
+ def remove_last_extension(pathn)
146
+ parent = pathn.parent
147
+ basename = pathn.basename
148
+ ext = basename.extname
149
+ base = basename.basename(ext)
150
+ parent + base
151
+ end
152
+
153
+ def setup_secret_for_json_file
154
+ top_pn = @plain_dir_pn + JSON_FILE_DIR
155
+ top_pn.find do |x|
156
+ next if x.directory?
157
+
158
+ relative_path = x.relative_path_from(@plain_dir_pn)
159
+ new_relative_path = remove_last_extension(relative_path)
160
+ Loggerxs.debug("################ relative_path=#{relative_path}")
161
+ Loggerxs.debug("################ new_relative_path=#{new_relative_path}")
162
+ @secret.encrypt_and_copy(x, new_relative_path, @setting[SETTING_KEY], @setting[SETTING_IV])
163
+ end
164
+ end
165
+
166
+ def set_setting_for_query(*dirs)
167
+ @valid_dirs = dirs.flatten.compact
168
+ @target, @sub_target, _tmp = @valid_dirs
169
+ # p "@valid_dirs=#{@valid_dirs}"
170
+ @file_format = @secret.file_format(@target, @sub_target)
171
+ Loggerxs.debug "@secret_dir_pn=#{@secret_dir_pn}"
172
+ Loggerxs.debug "dirs=#{dirs}"
173
+ Loggerxs.debug "@encrypted_secret_file_pn=#{@encrypted_secret_file_pn}"
174
+
175
+ @encrypted_secret_file_pn = @secret.get_file_path(dirs)
176
+ end
177
+
178
+ def load_setting
179
+ Loggerxs.debug "load_setting @encrypted_setting_file_pn=#{@encrypted_setting_file_pn}"
180
+ encrypted_text = File.read(@encrypted_setting_file_pn)
181
+ Loggerxs.debug "load_setting encrypted_text=#{encrypted_text}"
182
+ decrypted_text = @secret.decrypt_with_private_key(encrypted_text)
183
+ setting = YAML.safe_load(decrypted_text)
184
+ @key = setting[SETTING_KEY]
185
+ Loggerxs.debug "load_setting @key=#{@key}"
186
+ @iv = setting[SETTING_IV]
187
+ Loggerxs.debug "load_setting @iv=#{@iv}"
188
+ end
189
+
190
+ def load_and_decrypt
191
+ Loggerxs.debug("@encrypted_secret_file_pn=#{@encrypted_secret_file_pn}")
192
+ base64_text = File.read(@encrypted_secret_file_pn)
193
+ encrypted_content = Base64.decode64(base64_text)
194
+ begin
195
+ @decrpyted_content = @secret.decrypt_with_common_key(encrypted_content, @key, @iv)
196
+ @content = case @file_format
197
+ when FORMAT_JSON
198
+ @decrpyted_content
199
+ when FORMAT_YAML
200
+ @secret_content = YAML.safe_load(@decrpyted_content)
201
+ @sub_target ? @secret_content[@target][@sub_target] : @secret_content[@target]
202
+ else
203
+ ""
204
+ end
205
+ rescue StandardError => e
206
+ Loggerxs.error e
207
+ Loggerxs.error e.message
208
+ Loggerxs.error e.backtrace
209
+ Loggerxs.error "Can't dencrypt #{@encrypted_setting_file_pn}"
210
+ end
211
+ @content
212
+ end
213
+
214
+ def load
215
+ load_setting
216
+ load_and_decrypt
217
+ end
218
+
219
+ def make(_target, _sub_target)
220
+ case @file_format
221
+ when FORMAT_JSON
222
+ @content
223
+ when FORMAT_YAML
224
+ @content.map do |item|
225
+ %(export #{item[0]}=#{item[1]})
226
+ end.flatten
227
+ else
228
+ ""
229
+ end
230
+ end
231
+
232
+ def valid_private_keyfile(path, default_path = DEFAULT_PRIVATE_KEYFILE)
233
+ valid_pathname(path, default_path)
234
+ end
235
+
236
+ def valid_public_keyfile(path, default_path = DEFAULT_PUBLIC_KEYFILE)
237
+ valid_pathname(path, default_path)
238
+ end
239
+
240
+ def valid_pathname(path, default_path)
241
+ pathn = path
242
+ pathn = Pathname.new(Dir.home) + default_path if Util.nil_or_dontexist?(path)
243
+ pathn = nil if Util.nil_or_dontexist?(pathn)
244
+ pathn
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Secretmgr
4
+ class Util
5
+ class << self
6
+ def nil_or_dontexist?(pathn)
7
+ pathn.nil? || !pathn.exist?
8
+ end
9
+
10
+ def nil_or_zero?(str)
11
+ str.nil? || str.empty?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Secretmgr
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/secretmgr.rb CHANGED
@@ -1,22 +1,28 @@
1
- # frozen_string_literal: true
2
-
3
- require "openssl"
4
- require "base64"
5
- require "multi_json"
6
- require "ykxutils"
7
- require "ykutils"
8
-
9
- require_relative "secretmgr/version"
10
- require_relative "secretmgr/secretmgr"
11
- require_relative "secretmgr/config"
12
-
13
- module Secretmgr
14
- INSTALLED_APP = "installed"
15
- WEB_APP = "web"
16
- CLIENT_ID = "client_id"
17
- CLIENT_SECRET = "client_secret"
18
- CIPHER_NAME = "AES-256-CBC"
19
-
20
- class Error < StandardError; end
21
- # Your code goes here...
22
- end
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+ require "base64"
5
+ require "multi_json"
6
+
7
+ require "loggerx"
8
+ require_relative "secretmgr/version"
9
+ require_relative "secretmgr/util"
10
+ require_relative "secretmgr/globalsetting"
11
+ require_relative "secretmgr/cli"
12
+ require_relative "secretmgr/secretmgr"
13
+ require_relative "secretmgr/config"
14
+ require_relative "secretmgr/secret"
15
+ require_relative "secretmgr/loggerxs"
16
+ # require_relative "secretmgr/loggerxs"
17
+
18
+ module Secretmgr
19
+ INSTALLED_APP = "installed"
20
+ WEB_APP = "web"
21
+ CLIENT_ID = "client_id"
22
+ CLIENT_SECRET = "client_secret"
23
+ CIPHER_NAME = "AES-256-CBC"
24
+
25
+ class Error < StandardError; end
26
+
27
+ # Your code goes here...
28
+ end
data/rubocoprefine.bat CHANGED
@@ -1,30 +1,30 @@
1
- REMM メソッド定義やメソッド呼び出しの()をいい感じに
2
- rubocop -a --only Style/DefWithParentheses,\
3
- Style/MethodCallParentheses,\
4
- Style/MethodDefParentheses
5
-
6
- REM インデント崩れを修正
7
- rubocop -a --only Style/IndentationConsistency,\
8
- Style/IndentationWidth,\
9
- Style/MultilineOperationIndentation
10
-
11
- REM 空行をいい感じに
12
- rubocop -a --only Style/EmptyLineBetweenDefs,\
13
- Style/EmptyLines,\
14
- Style/EmptyLinesAroundAccessModifier,\
15
- Style/EmptyLinesAroundBlockBody,\
16
- Style/EmptyLinesAroundClassBody,\
17
- Style/EmptyLinesAroundMethodBody,\
18
- Style/EmptyLinesAroundModuleBody,\
19
- Style/TrailingBlankLines
20
-
21
- REM コロンやカンマの前後のスペースをいい感じにする
22
- rubocop -a --only Style/SpaceAfterColon,\
23
- Style/SpaceAfterComma,\
24
- Style/SpaceAfterNot,\
25
- Style/SpaceAfterSemicolon,\
26
- Style/SpaceAroundEqualsInParameterDefault,\
27
- Style/SpaceBeforeSemicolon
28
-
29
- REM 行末のスペース削除
1
+ REMM メソッド定義やメソッド呼び出しの()をいい感じに
2
+ rubocop -a --only Style/DefWithParentheses,\
3
+ Style/MethodCallParentheses,\
4
+ Style/MethodDefParentheses
5
+
6
+ REM インデント崩れを修正
7
+ rubocop -a --only Style/IndentationConsistency,\
8
+ Style/IndentationWidth,\
9
+ Style/MultilineOperationIndentation
10
+
11
+ REM 空行をいい感じに
12
+ rubocop -a --only Style/EmptyLineBetweenDefs,\
13
+ Style/EmptyLines,\
14
+ Style/EmptyLinesAroundAccessModifier,\
15
+ Style/EmptyLinesAroundBlockBody,\
16
+ Style/EmptyLinesAroundClassBody,\
17
+ Style/EmptyLinesAroundMethodBody,\
18
+ Style/EmptyLinesAroundModuleBody,\
19
+ Style/TrailingBlankLines
20
+
21
+ REM コロンやカンマの前後のスペースをいい感じにする
22
+ rubocop -a --only Style/SpaceAfterColon,\
23
+ Style/SpaceAfterComma,\
24
+ Style/SpaceAfterNot,\
25
+ Style/SpaceAfterSemicolon,\
26
+ Style/SpaceAroundEqualsInParameterDefault,\
27
+ Style/SpaceBeforeSemicolon
28
+
29
+ REM 行末のスペース削除
30
30
  rubocop -a --only Style/TrailingWhitespace