From ac5b935b89eab854e0c593e366b3dc73d3abede1 Mon Sep 17 00:00:00 2001 From: Norm MacLennan Date: Tue, 17 May 2016 21:21:59 -0400 Subject: [PATCH] rubocoppy refactor --- lib/zanzibar.rb | 191 +++++++++++++------------------------- lib/zanzibar/client.rb | 79 ++++++++++++++++ spec/lib/zanzibar_spec.rb | 8 +- 3 files changed, 150 insertions(+), 128 deletions(-) create mode 100644 lib/zanzibar/client.rb diff --git a/lib/zanzibar.rb b/lib/zanzibar.rb index c859ff1..2ecccd2 100644 --- a/lib/zanzibar.rb +++ b/lib/zanzibar.rb @@ -3,6 +3,7 @@ require 'savon' require 'io/console' require 'fileutils' require 'yaml' +require 'zanzibar/client' module Zanzibar ## @@ -10,62 +11,19 @@ module Zanzibar class Zanzibar ## # @param args{:domain, :wsdl, :pwd, :username, :globals{}} - def initialize(args = {}) - @@username = if args[:username] - args[:username] - elsif ENV['ZANZIBAR_USER'] - ENV['ZANZIBAR_USER'] - else - ENV['USER'] - end - - @@wsdl = if args[:wsdl] - args[:wsdl] - else - get_wsdl_location - end - - @@password = if args[:pwd] - args[:pwd] - elsif ENV['ZANZIBAR_PASSWORD'] - ENV['ZANZIBAR_PASSWORD'] - else - prompt_for_password - end - - @@domain = if args[:domain] - args[:domain] - else - prompt_for_domain - end + @username = resolve_username(args) + @wsdl = resolve_wsdl(args) + @password = resolve_password(args) + @domain = resolve_domain(args) args[:globals] = {} unless args[:globals] - init_client(args[:globals]) - end - - def get_client_username - @@username - end - - def get_client_password - @@password - end - - ## Initializes the Savon client class variable with the wdsl document location and optional global variables - # @param globals{}, optional - - def init_client(globals = {}) - globals = {} if globals.nil? - @@client = Savon.client(globals) do - wsdl @@wsdl - end + @client = Client.new(@username, @password, @domain, @wsdl, args[:globals]) end ## Gets the user's password if none is provided in the constructor. # @return [String] the password for the current user - def prompt_for_password - puts "Please enter password for #{@@username}:" + puts "Please enter password for #{@username}:" STDIN.noecho(&:gets).chomp.tap do puts 'Using password to login...' end @@ -73,7 +31,6 @@ module Zanzibar ## Gets the wsdl document location if none is provided in the constructor # @return [String] the location of the WDSL document - def prompt_for_wsdl_location puts 'Enter the URL of the Secret Server WSDL:' STDIN.gets.chomp @@ -81,47 +38,20 @@ module Zanzibar ## Gets the domain of the Secret Server installation if none is provided in the constructor # @return [String] the domain of the secret server installation - def prompt_for_domain puts 'Enter the domain of your Secret Server:' STDIN.gets.chomp end - ## Get an authentication token for interacting with Secret Server. These are only good for about 10 minutes so just get a new one each time. - # Will raise an error if there is an issue with the authentication. - # @return the authentication token for the current user. - - def get_token - response = @@client.call(:authenticate, message: { username: @@username, password: @@password, organization: '', domain: @@domain }) - .hash[:envelope][:body][:authenticate_response][:authenticate_result] - raise "Error generating the authentication token for user #{@@username}: #{response[:errors][:string]}" if response[:errors] - response[:token] - rescue Savon::Error => err - raise "There was an error generating the authentiaton token for user #{@@username}: #{err}" - end - - ## Get a secret returned as a hash - # Will raise an error if there was an issue getting the secret - # @param [Integer] the secret id - # @return [Hash] the secret hash retrieved from the wsdl - - def get_secret(scrt_id, token = nil) - secret = @@client.call(:get_secret, message: { token: token || get_token, secretId: scrt_id }).hash[:envelope][:body][:get_secret_response][:get_secret_result] - raise "There was an error getting secret #{scrt_id}: #{secret[:errors][:string]}" if secret[:errors] - return secret - rescue Savon::Error => err - raise "There was an error getting the secret with id #{scrt_id}: #{err}" - end - ## Retrieve the value from a field label of a secret # Will raise an error if there are any issues # @param [Integer] the secret id # @param [String] the field label to get, defaults to Password # @return [String] the value for the given field label def get_fieldlabel_value(scrt_id, fieldlabel = 'Password') - secret = get_secret(scrt_id) + secret = @client.get_secret(scrt_id) secret_items = secret[:secret][:items][:secret_item] - return get_secret_item_by_field_name(secret_items, fieldlabel)[:value] + return @client.get_secret_item_by_field_name(secret_items, fieldlabel)[:value] rescue Savon::Error => err raise "There was an error getting '#{fieldlabel}' for secret #{scrt_id}: #{err}" end @@ -136,19 +66,13 @@ module Zanzibar ## Get the password, save it to a file, and return the path to the file. def get_username_and_password_and_save(scrt_id, path, name) - secret_items = get_secret(scrt_id)[:secret][:items][:secret_item] - password = get_secret_item_by_field_name(secret_items, 'Password')[:value] - username = get_secret_item_by_field_name(secret_items, 'Username')[:value] + secret_items = @client.get_secret(scrt_id)[:secret][:items][:secret_item] + password = @client.get_secret_item_by_field_name(secret_items, 'Password')[:value] + username = @client.get_secret_item_by_field_name(secret_items, 'Username')[:value] save_username_and_password_to_file(password, username, path, name) File.join(path, name) end - def write_secret_to_file(path, secret_response) - File.open(File.join(path, secret_response[:file_name]), 'wb') do |file| - file.puts Base64.decode64(secret_response[:file_attachment]) - end - end - ## Write the password to a file. Intended for use with a Zanzifile def save_username_and_password_to_file(password, username, path, name) user_pass = { 'username' => username.to_s, 'password' => password.to_s }.to_yaml @@ -157,46 +81,15 @@ module Zanzibar end end - def get_secret_item_by_field_name(secret_items, field_name) - secret_items.each do |item| - return item if item[:field_name] == field_name - end - end - - ## Get the secret item id that relates to a key file or attachment. - # Will raise on error - # @param [Integer] the secret id - # @param [String] the type of secret item to get, one of privatekey, publickey, attachment - # @return [Integer] the secret item id - - def get_scrt_item_id(scrt_id, type, token) - secret = get_secret(scrt_id, token) - secret_items = secret[:secret][:items][:secret_item] - begin - return get_secret_item_by_field_name(secret_items, type)[:id] - rescue - raise "Unknown type, #{type}." - end - end - ## Downloads a file for a secret and places it where Zanzibar is running, or :path if specified # Raise on error # @param [Hash] args, :scrt_id, :type (one of "Private Key", "Public Key", "Attachment"), :scrt_item_id - optional, :path - optional - def download_secret_file(args = {}) - token = get_token - FileUtils.mkdir_p(args[:path]) if args[:path] - path = args[:path] ? args[:path] : '.' ## The File.join below doesn't handle nils well, so let's take that possibility away. - begin - response = @@client.call(:download_file_attachment_by_item_id, message: - { token: token, secretId: args[:scrt_id], secretItemId: args[:scrt_item_id] || get_scrt_item_id(args[:scrt_id], args[:type], token) }) - .hash[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result] - raise "There was an error getting the #{args[:type]} for secret #{args[:scrt_id]}: #{response[:errors][:string]}" if response[:errors] - write_secret_to_file(path, response) - return File.join(path, response[:file_name]) - rescue Savon::Error => err - raise "There was an error getting the #{args[:type]} for secret #{args[:scrt_id]}: #{err}" - end + response = @client.download_file_attachment_by_item_id(args[:scrt_id], args[:scrt_item_id], args[:type]) + raise "There was an error getting the #{args[:type]} for secret #{args[:scrt_id]}: #{response[:errors][:string]}" if response[:errors] + return write_secret_to_file(args[:path], response) + rescue Savon::Error => err + raise "There was an error getting the #{args[:type]} for secret #{args[:scrt_id]}: #{err}" end ## Methods to maintain backwards compatibility @@ -214,5 +107,55 @@ module Zanzibar args[:type] = 'Attachment' download_secret_file(args) end + + private + + def make_or_find_path(path = nil) + FileUtils.mkdir_p(path) if path + path || '.' + end + + def resolve_username(args = {}) + if args[:username] + args[:username] + elsif ENV['ZANZIBAR_USER'] + ENV['ZANZIBAR_USER'] + else + ENV['USER'] + end + end + + def resolve_wsdl(args = {}) + args[:wsdl] + end + + def resolve_password(args = {}) + if args[:pwd] + args[:pwd] + elsif ENV['ZANZIBAR_PASSWORD'] + ENV['ZANZIBAR_PASSWORD'] + else + prompt_for_password + end + end + + def resolve_domain(args = {}) + if args[:domain] + args[:domain] + else + prompt_for_domain + end + end + + def write_secret_to_file(path, secret_response) + path = make_or_find_path(path) + filepath = File.join(path, secret_response[:file_name]) + + File.open(filepath, 'wb') do |file| + file.puts Base64.decode64(secret_response[:file_attachment]) + end + + filepath + end end end diff --git a/lib/zanzibar/client.rb b/lib/zanzibar/client.rb new file mode 100644 index 0000000..e91eb4b --- /dev/null +++ b/lib/zanzibar/client.rb @@ -0,0 +1,79 @@ +require 'zanzibar/version' +require 'savon' +require 'io/console' +require 'fileutils' +require 'yaml' + +module Zanzibar + ## + # Class for interacting with Secret Server + class Client + ## Initializes the Savon client class variable with the wdsl document location and optional global variables + # @param globals{}, optional + def initialize(username, password, domain, wsdl, globals = {}) + @username = username + @password = password + @domain = domain + + globals = {} if globals.nil? + + wsdl_loc = wsdl + @client = Savon.client(globals) do + wsdl wsdl_loc + end + end + + ## Get an authentication token for interacting with Secret Server. These are only good for about 10 minutes so just get a new one each time. + # Will raise an error if there is an issue with the authentication. + # @return the authentication token for the current user. + def generate_token + response = @client.call(:authenticate, message: { username: @username, password: @password, organization: '', domain: @domain }) + .hash[:envelope][:body][:authenticate_response][:authenticate_result] + raise "Error generating the authentication token for user #{@username}: #{response[:errors][:string]}" if response[:errors] + response[:token] + rescue Savon::Error => err + raise "There was an error generating the authentiaton token for user #{@username}: #{err}" + end + + ## Get a secret returned as a hash + # Will raise an error if there was an issue getting the secret + # @param [Integer] the secret id + # @return [Hash] the secret hash retrieved from the wsdl + def get_secret(scrt_id, token = nil) + secret = @client.call(:get_secret, message: { token: token || generate_token, secretId: scrt_id }).hash[:envelope][:body][:get_secret_response][:get_secret_result] + raise "There was an error getting secret #{scrt_id}: #{secret[:errors][:string]}" if secret[:errors] + return secret + rescue Savon::Error => err + raise "There was an error getting the secret with id #{scrt_id}: #{err}" + end + + ## Get the secret item id that relates to a key file or attachment. + # Will raise on error + # @param [Integer] the secret id + # @param [String] the type of secret item to get, one of privatekey, publickey, attachment + # @return [Integer] the secret item id + def get_scrt_item_id(scrt_id, type, token) + secret = get_secret(scrt_id, token) + secret_items = secret[:secret][:items][:secret_item] + begin + return get_secret_item_by_field_name(secret_items, type)[:id] + rescue => e + + raise "Unknown type, #{type}. #{e}" + end + end + + def download_file_attachment_by_item_id(scrt_id, secret_item_id, item_type, token = nil) + token = generate_token unless token + @client.call(:download_file_attachment_by_item_id, message: + { token: token, secretId: scrt_id, secretItemId: secret_item_id || get_scrt_item_id(scrt_id, item_type, token) }) + .hash[:envelope][:body][:download_file_attachment_by_item_id_response][:download_file_attachment_by_item_id_result] + end + + def get_secret_item_by_field_name(secret_items, field_name) + secret_items.each do |item| + return item if item[:field_name] == field_name + end + end + end +end diff --git a/spec/lib/zanzibar_spec.rb b/spec/lib/zanzibar_spec.rb index cbafca9..6b4609b 100644 --- a/spec/lib/zanzibar_spec.rb +++ b/spec/lib/zanzibar_spec.rb @@ -13,7 +13,7 @@ describe 'Zanzibar Test' do stub_request(:any, 'https://www.zanzitest.net/webservices/sswebservice.asmx') .to_return(body: AUTH_XML, status: 200) - expect(client.get_token).to eq('imatoken') + expect(client.instance_variable_get(:@client).generate_token).to eq('imatoken') end it 'should get a secret' do @@ -21,7 +21,7 @@ describe 'Zanzibar Test' do .to_return(body: AUTH_XML, status: 200).then .to_return(body: SECRET_XML, status: 200) - expect(client.get_secret(1234)[:secret][:name]).to eq('Zanzi Test Secret') + expect(client.instance_variable_get(:@client).get_secret(1234)[:secret][:name]).to eq('Zanzi Test Secret') end it 'should get a password' do @@ -119,8 +119,8 @@ describe 'Zanzibar Test' do ENV['ZANZIBAR_USER'] = 'environment_user' ENV['ZANZIBAR_PASSWORD'] = 'environment_password' client = Zanzibar::Zanzibar.new(domain: 'zanzitest.net', wsdl: 'spec/scrt.wsdl') - expect(client.get_client_username).to eq(ENV['ZANZIBAR_USER']) - expect(client.get_client_password).to eq(ENV['ZANZIBAR_PASSWORD']) + expect(client.instance_variable_get(:@username)).to eq(ENV['ZANZIBAR_USER']) + expect(client.instance_variable_get(:@password)).to eq(ENV['ZANZIBAR_PASSWORD']) ENV.delete 'ZANZIBAR_PASSWORD' ENV.delete 'ZANZIBAR_USER' end