From f44eca1c7653f5f4dc1691c54d8e80699784ba89 Mon Sep 17 00:00:00 2001 From: Peter Souter Date: Wed, 24 Feb 2016 22:45:00 +0000 Subject: [PATCH] Move Utils methods into specific helper classes --- lib/hiera/backend/eyaml/CLI.rb | 1 + lib/hiera/backend/eyaml/edithelper.rb | 39 +++++++++ lib/hiera/backend/eyaml/encrypthelper.rb | 40 +++++++++ lib/hiera/backend/eyaml/encryptor.rb | 10 +-- lib/hiera/backend/eyaml/encryptors/pkcs7.rb | 13 +-- lib/hiera/backend/eyaml/highlinehelper.rb | 24 ++++++ lib/hiera/backend/eyaml/logginghelper.rb | 4 + lib/hiera/backend/eyaml/options.rb | 10 +-- lib/hiera/backend/eyaml/subcommand.rb | 2 +- lib/hiera/backend/eyaml/subcommands/edit.rb | 8 +- .../backend/eyaml/subcommands/encrypt.rb | 3 +- lib/hiera/backend/eyaml/utils.rb | 81 +------------------ 12 files changed, 134 insertions(+), 101 deletions(-) create mode 100644 lib/hiera/backend/eyaml/encrypthelper.rb create mode 100644 lib/hiera/backend/eyaml/highlinehelper.rb diff --git a/lib/hiera/backend/eyaml/CLI.rb b/lib/hiera/backend/eyaml/CLI.rb index 3723a57c..ea06bc33 100644 --- a/lib/hiera/backend/eyaml/CLI.rb +++ b/lib/hiera/backend/eyaml/CLI.rb @@ -1,5 +1,6 @@ require 'trollop' require 'hiera/backend/eyaml' +require 'hiera/backend/eyaml/logginghelper' require 'hiera/backend/eyaml/utils' require 'hiera/backend/eyaml/plugins' require 'hiera/backend/eyaml/options' diff --git a/lib/hiera/backend/eyaml/edithelper.rb b/lib/hiera/backend/eyaml/edithelper.rb index 2a734c9a..5e58c0eb 100644 --- a/lib/hiera/backend/eyaml/edithelper.rb +++ b/lib/hiera/backend/eyaml/edithelper.rb @@ -1,3 +1,5 @@ +require 'hiera/backend/eyaml/logginghelper' + class Hiera module Backend module Eyaml @@ -27,6 +29,43 @@ def self.find_editor editor end + def self.secure_file_delete args + file = File.open(args[:file], 'r+') + num_bytes = args[:num_bytes] + [0xff, 0x55, 0xaa, 0x00].each do |byte| + file.seek(0, IO::SEEK_SET) + num_bytes.times { file.print(byte.chr) } + file.fsync + end + file.close + File.delete args[:file] + end + + def self.write_tempfile data_to_write + file = Tempfile.open(['eyaml_edit', '.yaml']) + path = file.path + file.close! + + file = File.open(path, "w") + file.chmod(0600) + if ENV['OS'] == 'Windows_NT' + # Windows doesn't support chmod + icacls = 'C:\Windows\system32\icacls.exe' + if File.executable? icacls + current_user = `C:\\Windows\\system32\\whoami.exe`.chomp + # Use ACLs to restrict access to the current user only + command = %Q{#{icacls} "#{file.path}" /grant:r "#{current_user}":f /inheritance:r} + system "#{command} >NUL 2>&1" + end + end + file.puts data_to_write + file.close + + LoggingHelper::debug "Wrote temporary file: #{path}" + + path + end + end end end diff --git a/lib/hiera/backend/eyaml/encrypthelper.rb b/lib/hiera/backend/eyaml/encrypthelper.rb new file mode 100644 index 00000000..3bf7e7f9 --- /dev/null +++ b/lib/hiera/backend/eyaml/encrypthelper.rb @@ -0,0 +1,40 @@ +require 'tempfile' +require 'fileutils' + +class Hiera + module Backend + module Eyaml + class EncryptHelper + + def self.write_important_file args + require 'hiera/backend/eyaml/highlinehelper' + filename = args[ :filename ] + content = args[ :content ] + mode = args[ :mode ] + if File.file? "#{filename}" + raise StandardError, "User aborted" unless HighlineHelper::confirm? "Are you sure you want to overwrite \"#{filename}\"?" + end + open( "#{filename}", "w" ) do |io| + io.write(content) + end + File.chmod( mode, filename ) unless mode.nil? + end + + def self.ensure_key_dir_exists key_file + key_dir = File.dirname key_file + + unless File.directory? key_dir + begin + FileUtils.mkdir_p key_dir + LoggingHelper::info "Created key directory: #{key_dir}" + rescue + raise StandardError, "Cannot create key directory: #{key_dir}" + end + end + + end + + end + end + end +end diff --git a/lib/hiera/backend/eyaml/encryptor.rb b/lib/hiera/backend/eyaml/encryptor.rb index b559d4ec..843254b8 100644 --- a/lib/hiera/backend/eyaml/encryptor.rb +++ b/lib/hiera/backend/eyaml/encryptor.rb @@ -1,5 +1,5 @@ require 'base64' -require 'hiera/backend/eyaml/utils' +require 'hiera/backend/eyaml/encrypthelper' class Hiera module Backend @@ -60,19 +60,19 @@ def self.format_message msg end def self.trace msg - Utils::trace :from => plugin_classname, :msg => msg + LoggingHelper::trace :from => plugin_classname, :msg => msg end def self.debug msg - Utils::debug :from => plugin_classname, :msg => msg + LoggingHelper::debug :from => plugin_classname, :msg => msg end def self.info msg - Utils::info :from => plugin_classname, :msg => msg + LoggingHelper::info :from => plugin_classname, :msg => msg end def self.warn msg - Utils::warn :from => plugin_classname, :msg => msg + LoggingHelper::warn :from => plugin_classname, :msg => msg end end diff --git a/lib/hiera/backend/eyaml/encryptors/pkcs7.rb b/lib/hiera/backend/eyaml/encryptors/pkcs7.rb index 3f986200..106afb28 100644 --- a/lib/hiera/backend/eyaml/encryptors/pkcs7.rb +++ b/lib/hiera/backend/eyaml/encryptors/pkcs7.rb @@ -1,6 +1,7 @@ require 'openssl' require 'hiera/backend/eyaml/encryptor' -require 'hiera/backend/eyaml/utils' +require 'hiera/backend/eyaml/encrypthelper' +require 'hiera/backend/eyaml/logginghelper' require 'hiera/backend/eyaml/options' class Hiera @@ -65,8 +66,8 @@ def self.create_keys subject = self.option :subject key = OpenSSL::PKey::RSA.new(2048) - Utils.ensure_key_dir_exists private_key - Utils.write_important_file :filename => private_key, :content => key.to_pem, :mode => 0600 + EncryptHelper.ensure_key_dir_exists private_key + EncryptHelper.write_important_file :filename => private_key, :content => key.to_pem, :mode => 0600 cert = OpenSSL::X509::Certificate.new() cert.subject = OpenSSL::X509::Name.parse(subject) @@ -92,9 +93,9 @@ def self.create_keys cert.sign key, OpenSSL::Digest::SHA1.new - Utils.ensure_key_dir_exists public_key - Utils.write_important_file :filename => public_key, :content => cert.to_pem - Utils.info "Keys created OK" + EncryptHelper.ensure_key_dir_exists public_key + EncryptHelper.write_important_file :filename => public_key, :content => cert.to_pem + LoggingHelper.info "Keys created OK" end diff --git a/lib/hiera/backend/eyaml/highlinehelper.rb b/lib/hiera/backend/eyaml/highlinehelper.rb new file mode 100644 index 00000000..8349aab0 --- /dev/null +++ b/lib/hiera/backend/eyaml/highlinehelper.rb @@ -0,0 +1,24 @@ +require 'highline/import' + +class Hiera + module Backend + module Eyaml + class HighlineHelper + + def self.read_password + ask("Enter password: ") {|q| q.echo = "*" } + end + + def self.confirm? message + result = ask("#{message} (y/N): ") + if result.downcase == "y" or result.downcase == "yes" + true + else + false + end + end + + end + end + end +end diff --git a/lib/hiera/backend/eyaml/logginghelper.rb b/lib/hiera/backend/eyaml/logginghelper.rb index 48e1e1e8..ebba05bf 100644 --- a/lib/hiera/backend/eyaml/logginghelper.rb +++ b/lib/hiera/backend/eyaml/logginghelper.rb @@ -70,6 +70,10 @@ def self.colorize message, color "#{prefix}#{message}#{suffix}" end + def self.hiera? + "hiera".eql? Eyaml::Options[:source] + end + end end end diff --git a/lib/hiera/backend/eyaml/options.rb b/lib/hiera/backend/eyaml/options.rb index dd40b204..6622a191 100644 --- a/lib/hiera/backend/eyaml/options.rb +++ b/lib/hiera/backend/eyaml/options.rb @@ -21,16 +21,16 @@ def self.set hash end def self.trace - Utils::trace "Dump of eyaml tool options dict:" - Utils::trace "--------------------------------" + LoggingHelper::trace "Dump of eyaml tool options dict:" + LoggingHelper::trace "--------------------------------" @@options.each do |k, v| begin - Utils::trace sprintf "%18s %-18s = %18s %-18s", "(#{k.class.name})", k.to_s, "(#{v.class.name})", v.to_s + LoggingHelper::trace sprintf "%18s %-18s = %18s %-18s", "(#{k.class.name})", k.to_s, "(#{v.class.name})", v.to_s rescue - Utils::trace sprintf "%18s %-18s = %18s %-18s", "(#{k.class.name})", k.to_s, "(#{v.class.name})", "" # case where v is binary + LoggingHelper::trace sprintf "%18s %-18s = %18s %-18s", "(#{k.class.name})", k.to_s, "(#{v.class.name})", "" # case where v is binary end end - Utils::trace "--------------------------------" + LoggingHelper::trace "--------------------------------" end end diff --git a/lib/hiera/backend/eyaml/subcommand.rb b/lib/hiera/backend/eyaml/subcommand.rb index 02736c37..75f19cf8 100644 --- a/lib/hiera/backend/eyaml/subcommand.rb +++ b/lib/hiera/backend/eyaml/subcommand.rb @@ -38,7 +38,7 @@ def self.load_config_file [ "/etc/eyaml/config.yaml", "#{ENV['HOME']}/.eyaml/config.yaml", "#{ENV['EYAML_CONFIG']}" ].each do |config_file| begin yaml_contents = YAML.load_file(config_file) - Utils::info "Loaded config from #{config_file}" + LoggingHelper::info "Loaded config from #{config_file}" config.merge! yaml_contents rescue raise StandardError, "Could not open config file \"#{config_file}\" for reading" diff --git a/lib/hiera/backend/eyaml/subcommands/edit.rb b/lib/hiera/backend/eyaml/subcommands/edit.rb index 8edb195a..8efe5d31 100644 --- a/lib/hiera/backend/eyaml/subcommands/edit.rb +++ b/lib/hiera/backend/eyaml/subcommands/edit.rb @@ -1,8 +1,8 @@ -require 'hiera/backend/eyaml/utils' +require 'hiera/backend/eyaml/edithelper' +require 'hiera/backend/eyaml/highlinehelper' require 'hiera/backend/eyaml/options' require 'hiera/backend/eyaml/parser/parser' require 'hiera/backend/eyaml/subcommand' -require 'highline/import' class Hiera module Backend @@ -76,7 +76,7 @@ def self.execute decrypted_file_content = Eyaml::Options[:no_preamble] ? decrypted_input : (self.preamble + decrypted_input) begin - decrypted_file = Utils.write_tempfile decrypted_file_content unless decrypted_file + decrypted_file = EditHelper.write_tempfile decrypted_file_content unless decrypted_file system "#{editor} \"#{decrypted_file}\"" status = $? @@ -130,7 +130,7 @@ def self.execute raise e end ensure - Utils.secure_file_delete :file => decrypted_file, :num_bytes => [edited_file.length, decrypted_input.length].max + EditHelper.secure_file_delete :file => decrypted_file, :num_bytes => [edited_file.length, decrypted_input.length].max end nil diff --git a/lib/hiera/backend/eyaml/subcommands/encrypt.rb b/lib/hiera/backend/eyaml/subcommands/encrypt.rb index 71a0ef55..f9dcbb11 100644 --- a/lib/hiera/backend/eyaml/subcommands/encrypt.rb +++ b/lib/hiera/backend/eyaml/subcommands/encrypt.rb @@ -53,7 +53,8 @@ def self.validate options options[:input_data] = case options[:source] when :password - Utils.read_password + require 'hiera/backend/eyaml/highlinehelper' + HighlineHelper.read_password when :string options[:string] when :file diff --git a/lib/hiera/backend/eyaml/utils.rb b/lib/hiera/backend/eyaml/utils.rb index 3e62180d..8c93bcf0 100644 --- a/lib/hiera/backend/eyaml/utils.rb +++ b/lib/hiera/backend/eyaml/utils.rb @@ -1,25 +1,12 @@ -require 'highline/import' require 'tempfile' require 'fileutils' +require 'hiera/backend/eyaml/logginghelper' class Hiera module Backend module Eyaml class Utils - def self.read_password - ask("Enter password: ") {|q| q.echo = "*" } - end - - def self.confirm? message - result = ask("#{message} (y/N): ") - if result.downcase == "y" or result.downcase == "yes" - true - else - false - end - end - def self.camelcase string return string if string !~ /_/ && string =~ /[A-Z]+.*/ string.split('_').map{|e| e.capitalize}.join @@ -30,70 +17,6 @@ def self.snakecase string string.split(/(?=[A-Z])/).collect {|x| x.downcase}.join("_") end - def self.secure_file_delete args - file = File.open(args[:file], 'r+') - num_bytes = args[:num_bytes] - [0xff, 0x55, 0xaa, 0x00].each do |byte| - file.seek(0, IO::SEEK_SET) - num_bytes.times { file.print(byte.chr) } - file.fsync - end - file.close - File.delete args[:file] - end - - def self.write_tempfile data_to_write - file = Tempfile.open(['eyaml_edit', '.yaml']) - path = file.path - file.close! - - file = File.open(path, "w") - file.chmod(0600) - if ENV['OS'] == 'Windows_NT' - # Windows doesn't support chmod - icacls = 'C:\Windows\system32\icacls.exe' - if File.executable? icacls - current_user = `C:\\Windows\\system32\\whoami.exe`.chomp - # Use ACLs to restrict access to the current user only - command = %Q{#{icacls} "#{file.path}" /grant:r "#{current_user}":f /inheritance:r} - system "#{command} >NUL 2>&1" - end - end - file.puts data_to_write - file.close - - Utils::debug "Wrote temporary file: #{path}" - - path - end - - def self.write_important_file args - filename = args[ :filename ] - content = args[ :content ] - mode = args[ :mode ] - if File.file? "#{filename}" - raise StandardError, "User aborted" unless Utils::confirm? "Are you sure you want to overwrite \"#{filename}\"?" - end - open( "#{filename}", "w" ) do |io| - io.write(content) - end - File.chmod( mode, filename ) unless mode.nil? - end - - def self.ensure_key_dir_exists key_file - key_dir = File.dirname key_file - - unless File.directory? key_dir - begin - FileUtils.mkdir_p key_dir - Utils::info "Created key directory: #{key_dir}" - rescue - raise StandardError, "Cannot create key directory: #{key_dir}" - end - end - - end - def self.find_closest_class args parent_class = args[ :parent_class ] class_name = args[ :class_name ] @@ -114,7 +37,7 @@ def self.require_dir classdir root_folder = File.dirname(__FILE__) + "/" + Array.new(num_class_hierarchy_levels).fill("..").join("/") class_folder = root_folder + "/" + classdir Dir[File.expand_path("#{class_folder}/*.rb")].uniq.each do |file| - self.trace "Requiring file: #{file}" + LoggingHelper.trace "Requiring file: #{file}" require file end end