lib/secretmgr/secretmgr.rb in secretmgr-0.1.0 vs lib/secretmgr/secretmgr.rb in secretmgr-0.2.0
- old
+ new
@@ -1,200 +1,247 @@
-# frozen_string_literal: true
-
-require "pathname"
-
-module Secretmgr
- # 秘匿情報マネージャ
- class Secretmgr
- attr_reader :decrypted_text, :secret
-
- class << self
- def create(secret_dir_pn, plain_setting_file_pn, plain_secret_file_pn)
- @inst = Secretmgr.new(secret_dir_pn)
- @inst.set_setting_for_data(plain_setting_file_pn, plain_secret_file_pn)
- @inst
- end
- end
-
- def initialize(secret_dir_pn)
- @content = nil
- @secret_dir_pn = secret_dir_pn
- @encrypted_setting_file_pn = "#{@secret_dir_pn}setting.yml"
-
- @format_config = Config.new(@secret_dir_pn, "format.txt")
- home_dir = ENV["HOME"]
- @home_pn = Pathname.new(home_dir)
- # pemフォーマットの公開鍵ファイルの内容を取得
- path = File.join(home_dir, ".ssh", "pem")
- pub_key = File.read(path)
- # 鍵をOpenSSLのオブジェクトにする
- @public_key = OpenSSL::PKey::RSA.new(pub_key)
- path = File.join(home_dir, ".ssh", "id_rsa_no")
- private_key = File.read(path)
- @private_key = OpenSSL::PKey::RSA.new(private_key)
-
- @mode = OpenSSL::PKey::RSA::PKCS1_PADDING
- end
-
- def set_setting_for_data(plain_setting_file_pn, plain_secret_file_pn)
- @plain_setting_file_pn = plain_setting_file_pn
- @plain_secret_file_pn = plain_secret_file_pn
- @plain_dir_pn = @plain_setting_file_pn.parent
- end
-
- def setup
- setup_setting
- setup_secret
- setup_secret_for_json_file
- end
-
- def setup_setting
- content = File.read(@plain_setting_file_pn)
- @setting = Ykxutils.yaml_load_compati(content)
- # content = YAML.dump(@setting)
- encrypted_text = encrypt_with_public_key(content)
- dest_setting_file_pn = make_pair_file_pn(@secret_dir_pn, @plain_setting_file_pn, "yml")
-
- File.write(dest_setting_file_pn, encrypted_text)
- end
-
- def make_pair_file_pn(dest_dir_pn, file_pn, ext)
- basename = file_pn.basename
- extname = basename.extname
- return nil if extname == ext
-
- basename = file_pn.basename(".*")
- dest_dir_pn + %(#{basename}.#{ext})
- end
-
- def setup_secret
- plaintext = File.read(@plain_secret_file_pn)
- encrypted_text = encrypt_with_common_key(plaintext, @setting["key"], @setting["iv"])
- dest_secret_file_pn = make_pair_file_pn(@secret_dir_pn, @plain_secret_file_pn, "yml")
- dest_secret_file_pn.realpath
- # puts "setup_secret dest_secret_file_pn=#{dest_secret_file_pn}"
- # puts "real_pn=#{real_pn}"
- File.write(dest_secret_file_pn, encrypted_text)
- end
-
- def setup_secret_for_json_file
- top_pn = "#{@plain_dir_pn}JSON_FILE"
- top_pn.find do |x|
- # p x if x.file?
- relative_path = x.relative_path_from(@plain_dir_pn)
- # p relative_path
- encrypt_and_copy(x, @secret_dir_pn, relative_path)
- end
- end
-
- def encrypt_and_copy(src_pn, dest_top_dir_pn, relative_path)
- dest_pn = dest_top_dir_pn + relative_path
- return unless src_pn.exist? && src_pn.file?
-
- puts "e_adn_c #{src_pn} -> #{dest_pn}"
- plaintext = File.read(src_pn)
- encrypted_text = encrypt_with_common_key(plaintext, @setting["key"], @setting["iv"])
- File.write(dest_pn, encrypted_text)
- end
-
- def set_setting_for_query(*dirs)
- @valid_dirs = dirs.flatten.reject(&:nil?)
- @target, @sub_target, _tmp = @valid_dirs
- # p "@valid_dirs=#{@valid_dirs}"
- @file_format = @format_config.file_format(@target, @sub_target)
- p "@file_format=#{@file_format}"
- p "dirs=#{dirs}"
- @encrypted_secret_file_pn = @format_config.get_file_path(@secret_dir_pn, dirs)
- end
-
- def load_setting
- encrypted_text = File.read(@encrypted_setting_file_pn)
- # puts "encrypted_text=#{encrypted_text}"
- decrypted_text = decrypt_with_private_key(encrypted_text)
- setting = YAML.safe_load(decrypted_text)
- @key = setting["key"]
- @iv = setting["iv"]
- # p "load_settings @key=#{@key}"
- # p "load_settings @iv=#{@iv}"
- end
-
- def load_secret
- base64_text = File.read(@encrypted_secret_file_pn)
- encrypted_content = Base64.decode64(base64_text)
- begin
- @decrpyted_content = decrypt_with_common_key(encrypted_content, @key, @iv)
- @content = case @file_format
- when "JSON_FILE"
- @decrpyted_content
- when "YAML"
- @secret = YAML.safe_load(@decrpyted_content)
- @sub_target ? @secret[@target][@sub_target] : @secret[@target]
- else
- ""
- end
- rescue StandardError => e
- puts e
- puts e.message
- puts e.backtrace
- puts "Can't dencrypt #{@encrypted_setting_file_pn}"
- end
- @content
- end
-
- def load
- load_setting
- load_secret
- end
-
- def encrypt_with_public_key(data)
- Base64.encode64(
- @public_key.public_encrypt(
- data,
- OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
- )
- ).delete("\n")
- end
-
- def decrypt_with_private_key(base64_text)
- @private_key.private_decrypt(
- Base64.decode64(base64_text),
- OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
- )
- end
-
- # 引数 str を暗号化した結果を返す
- def encrypt_with_common_key(plaintext, key, _ivalue)
- encx = OpenSSL::Cipher.new(CIPHER_NAME)
- encx.encrypt
- encx.key = key
- encx.iv = ivvalue
- # str に与えた文字列を暗号化します。
- encrypted_text = encx.update(plaintext) + encx.final
-
- Base64.encode64(encrypted_text)
- end
-
- def decrypt_with_common_key(encrypted_data, key, ivalue)
- decx = OpenSSL::Cipher.new(CIPHER_NAME)
- decx.decrypt
- decx.key = key
- decx.iv = ivalue
- data = decx.update(encrypted_data)
- final_data = decx.final
- decrypted_data = data + final_data
- decrypted_data.force_encoding("UTF-8")
- end
-
- def make(_template_dir, _target, _sub_target)
- case @file_format
- when "JSON_FILE"
- @content
- when "YAML"
- @content.map do |item|
- %(export #{item[0]}=#{item[1]})
- end.flatten
- else
- ""
- end
- end
- end
-end
+# frozen_string_literal: true
+
+require "pathname"
+require "debug"
+
+module Secretmgr
+ # 秘匿情報マネージャ
+ class Secretmgr
+ attr_reader :decrypted_text, :secret
+
+ @log_level = nil
+ @init_count = 0
+ # @setting_file = "setting.yml"
+ JSON_FILE_DIR = "JSON_FILE"
+ SETTING_KEY = "key"
+ SETTING_IV = "iv"
+ FORMAT_JSON = "JSON_FILE"
+ FORMAT_YAML = "YAML"
+ YML = "yml"
+ # @dot_yml = "yml"
+ # @secret_dir = "secret"
+ DEFAULT_PRIVATE_KEYFILE = ".ssh/id_rsa"
+ DEFAULT_PUBLIC_KEYFILE = ".ssh/id_rsa.pub"
+
+ class << self
+ def log_init(log_level)
+ return unless @log_level.nil?
+
+ @log_level = log_level
+ Loggerxs.init("log_", "log.txt", ".", true, log_level) if @init_count.zero?
+ @init_count += 1
+ end
+
+ def reset_init_count
+ @init_count = 0
+ end
+ end
+
+ def initialize(seting, secret_dir_pn, secret_key_dir_pn, ope,
+ public_keyfile_pn: nil, private_keyfile_pn: nil)
+ log_level = :info
+ # log_level = :debug
+ Secretmgr.log_init(log_level)
+
+ @setting = seting
+ home_pn = Pathname.new(Dir.home)
+ secret_dir_pn = Pathname.new(secret_dir_pn) unless secret_dir_pn.instance_of?(Pathname)
+ secret_key_dir_pn = Pathname.new(secret_key_dir_pn) unless secret_key_dir_pn.instance_of?(Pathname)
+ secret_key_dir_pn.mkdir unless secret_key_dir_pn.exist?
+ default_public_keyfile_pn = secret_key_dir_pn + "id_rsa.pub"
+ default_private_keyfile_pn = secret_key_dir_pn + "id_rsa"
+ public_keyfile_pn = Pathname.new(public_keyfile_pn) if public_keyfile_pn
+ private_keyfile_pn = Pathname.new(private_keyfile_pn) if private_keyfile_pn
+
+ @secret = Secret.new(@setting, home_pn, secret_dir_pn, ope,
+ default_public_keyfile_pn,
+ default_private_keyfile_pn,
+ public_keyfile_pn: public_keyfile_pn,
+ private_keyfile_pn: private_keyfile_pn)
+ end
+
+ def valid?
+ @secret.valid
+ # Loggerxs.debug "1 ret=#{ret}"
+ # p "2 ret=#{ret}"
+ end
+
+ def output_public_key(public_keyfile_pn)
+ @secret.output_public_key(public_keyfile_pn)
+ end
+
+ def create_public_key(public_keyfile_pn)
+ @secret.create_public_key(public_keyfile_pn)
+ end
+
+ def output_private_key(private_keyfile_pn)
+ @secret.output_private_key(private_keyfile_pn)
+ end
+
+ def create_private_key(private_keyfile_pn)
+ @secret.create_private_key(private_keyfile_pn)
+ end
+
+ def set_setting_for_plain(plain_setting_file_pn, plain_secret_file_pn)
+ @plain_setting_file_pn = Pathname.new(@plain_setting_file_pn) if @plain_setting_file_pn
+ @plain_setting_file_pn ||= Pathname.new(plain_setting_file_pn)
+ @plain_secret_file_pn = Pathname.new(@plain_secret_file_pn) if @plain_secret_file_pn
+ @plain_secret_file_pn ||= Pathname.new(plain_secret_file_pn)
+ @plain_dir_pn = @plain_setting_file_pn.parent
+ @encrypted_setting_file_pn = @secret.encrypted_setting_file_pn
+ @encrypted_secret_file_pn = @secret.encrypted_secret_file_pn
+ end
+
+ def set_setting_for_encrypted(encrypted_setting_file_pn, encrypted_secret_file_pn)
+ @encrypted_setting_file_pn = Pathname.new(encrypted_setting_file_pn)
+ @encrypted_secret_file_pn = Pathname.new(encrypted_secret_file_pn)
+ end
+
+ def setup
+ # p "###### setup_setting"
+ setup_setting
+ # p "###### setup_secret"
+ setup_secret
+ # p "###### setup_secret_for_json_file"
+ setup_secret_for_json_file
+ end
+
+ def setup_setting
+ content = File.read(@plain_setting_file_pn)
+ # p "setup_setting content.size=#{content.size}"
+ # p "setup_setting content=#{content}"
+
+ @setting = YAML.safe_load(content)
+ # p "setup_setting @setting=#{@setting}"
+
+ Loggerxs.debug @setting
+ # pp "@setting=#{@setting}"
+ # puts "setup_setting @setting=#{@setting}"
+ encrypted_text = @secret.encrypt_with_public_key(content)
+ # puts "setup_setting encrypted_text.size=#{encrypted_text.size}"
+ # puts "setup_setting encrypted_text=#{encrypted_text}"
+ #
+ @secret.decrypt_with_private_key(encrypted_text)
+ # puts "setup_setting decrypted_text=#{decrypted_text}"
+ # puts "setup_setting decrypted_text.size=#{decrypted_text.size}"
+
+ dest_setting_file_pn = @secret.make_pair_file_pn(@plain_setting_file_pn, YML)
+
+ Loggerxs.debug "setup_setting dest_setting_file_pn=#{dest_setting_file_pn}"
+ File.write(dest_setting_file_pn, encrypted_text)
+ # p "dest_setting_file_pn=#{dest_setting_file_pn}"
+ end
+
+ def setup_secret
+ plaintext = File.read(@plain_secret_file_pn)
+ # puts "setup_secret @setting=#{@setting}"
+ encrypted_text = @secret.encrypt_with_common_key(plaintext,
+ @setting[SETTING_KEY],
+ @setting[SETTING_IV])
+ dest_secret_file_pn = @secret.make_pair_file_pn(@plain_secret_file_pn, YML)
+ Loggerxs.debug "setup_secret dest_secret_file_pn=#{dest_secret_file_pn}"
+ File.write(dest_secret_file_pn, encrypted_text)
+ end
+
+ def remove_last_extension(pathn)
+ parent = pathn.parent
+ basename = pathn.basename
+ ext = basename.extname
+ base = basename.basename(ext)
+ parent + base
+ end
+
+ def setup_secret_for_json_file
+ top_pn = @plain_dir_pn + JSON_FILE_DIR
+ top_pn.find do |x|
+ next if x.directory?
+
+ relative_path = x.relative_path_from(@plain_dir_pn)
+ new_relative_path = remove_last_extension(relative_path)
+ Loggerxs.debug("################ relative_path=#{relative_path}")
+ Loggerxs.debug("################ new_relative_path=#{new_relative_path}")
+ @secret.encrypt_and_copy(x, new_relative_path, @setting[SETTING_KEY], @setting[SETTING_IV])
+ end
+ end
+
+ def set_setting_for_query(*dirs)
+ @valid_dirs = dirs.flatten.compact
+ @target, @sub_target, _tmp = @valid_dirs
+ # p "@valid_dirs=#{@valid_dirs}"
+ @file_format = @secret.file_format(@target, @sub_target)
+ Loggerxs.debug "@secret_dir_pn=#{@secret_dir_pn}"
+ Loggerxs.debug "dirs=#{dirs}"
+ Loggerxs.debug "@encrypted_secret_file_pn=#{@encrypted_secret_file_pn}"
+
+ @encrypted_secret_file_pn = @secret.get_file_path(dirs)
+ end
+
+ def load_setting
+ Loggerxs.debug "load_setting @encrypted_setting_file_pn=#{@encrypted_setting_file_pn}"
+ encrypted_text = File.read(@encrypted_setting_file_pn)
+ Loggerxs.debug "load_setting encrypted_text=#{encrypted_text}"
+ decrypted_text = @secret.decrypt_with_private_key(encrypted_text)
+ setting = YAML.safe_load(decrypted_text)
+ @key = setting[SETTING_KEY]
+ Loggerxs.debug "load_setting @key=#{@key}"
+ @iv = setting[SETTING_IV]
+ Loggerxs.debug "load_setting @iv=#{@iv}"
+ end
+
+ def load_and_decrypt
+ Loggerxs.debug("@encrypted_secret_file_pn=#{@encrypted_secret_file_pn}")
+ base64_text = File.read(@encrypted_secret_file_pn)
+ encrypted_content = Base64.decode64(base64_text)
+ begin
+ @decrpyted_content = @secret.decrypt_with_common_key(encrypted_content, @key, @iv)
+ @content = case @file_format
+ when FORMAT_JSON
+ @decrpyted_content
+ when FORMAT_YAML
+ @secret_content = YAML.safe_load(@decrpyted_content)
+ @sub_target ? @secret_content[@target][@sub_target] : @secret_content[@target]
+ else
+ ""
+ end
+ rescue StandardError => e
+ Loggerxs.error e
+ Loggerxs.error e.message
+ Loggerxs.error e.backtrace
+ Loggerxs.error "Can't dencrypt #{@encrypted_setting_file_pn}"
+ end
+ @content
+ end
+
+ def load
+ load_setting
+ load_and_decrypt
+ end
+
+ def make(_target, _sub_target)
+ case @file_format
+ when FORMAT_JSON
+ @content
+ when FORMAT_YAML
+ @content.map do |item|
+ %(export #{item[0]}=#{item[1]})
+ end.flatten
+ else
+ ""
+ end
+ end
+
+ def valid_private_keyfile(path, default_path = DEFAULT_PRIVATE_KEYFILE)
+ valid_pathname(path, default_path)
+ end
+
+ def valid_public_keyfile(path, default_path = DEFAULT_PUBLIC_KEYFILE)
+ valid_pathname(path, default_path)
+ end
+
+ def valid_pathname(path, default_path)
+ pathn = path
+ pathn = Pathname.new(Dir.home) + default_path if Util.nil_or_dontexist?(path)
+ pathn = nil if Util.nil_or_dontexist?(pathn)
+ pathn
+ end
+ end
+end