class Keystok::Client

Keystok client class

Constants

API_HOST
AUTH_HOST
DEFAULT_CONFIG
REQUEST_TRY_COUNT

Public Class Methods

new(config = {}) click to toggle source
# File lib/keystok/client.rb, line 24
def initialize(config = {})
  @config = DEFAULT_CONFIG.merge(decode_config(config))
  @keys_store = {}
end

Public Instance Methods

access_token() click to toggle source
# File lib/keystok/client.rb, line 29
def access_token
  @access_token ||= begin
    fail Error::ConfigError, 'SDK not configured' if @config[:rt].nil?
    refresh_token = OAuth2::AccessToken.new(oauth_client, nil,
                                            refresh_token:
                                              @config[:rt])
    access_token = nil
    REQUEST_TRY_COUNT.times do |try_count|
      begin
        access_token = refresh_token.refresh!
        break
      rescue Faraday::Error::ClientError => exception
        Keystok.logger.warn(
          "Exception during token refresh: #{exception.message}")
        raise if try_count == (REQUEST_TRY_COUNT - 1)
      end
    end
    access_token
  end
end
configured?() click to toggle source
# File lib/keystok/client.rb, line 50
def configured?
  check_config
  true
rescue Error::ConfigError
  false
end
get(key_name_or_symbol, force_reload = false) click to toggle source
# File lib/keystok/client.rb, line 57
def get(key_name_or_symbol, force_reload = false)
  key_name = key_name_or_symbol.to_s
  if force_reload || @config[:volatile] || @keys_store[key_name].nil?
    load_keys(key_name_or_symbol)
  end
  @keys_store[key_name]
end
keys(force_reload = false) click to toggle source
# File lib/keystok/client.rb, line 65
def keys(force_reload = false)
  load_keys if force_reload || @config[:volatile] || @keys_store.empty?
  @keys_store
end

Private Instance Methods

check_config() click to toggle source
# File lib/keystok/client.rb, line 72
def check_config
  %w(rt dk id).map(&:to_sym).each do |key|
    if @config[key].nil?
      fail Error::ConfigError, "Config key: #{key} is missing!"
    end
  end
end
connection() click to toggle source
# File lib/keystok/client.rb, line 80
def connection
  @connection ||= Faraday.new(url: @config[:api_host] || API_HOST,
                              ssl: { verify: true })
end
decode_config(access_token) click to toggle source
# File lib/keystok/client.rb, line 85
def decode_config(access_token)
  config_hash = access_token
  case
  when access_token.kind_of?(Hash)
  when access_token.kind_of?(String)
    config_hash = decode_string_config(access_token)
  else
    fail Error::ConfigError, 'Unknown config format'
  end
  config_hash = keys_to_symbols(config_hash)
  config_hash = merge_access_token(config_hash, :connection_string)
  config_hash = merge_access_token(config_hash)
  config_hash
end
decode_json_string_config(access_token) click to toggle source
# File lib/keystok/client.rb, line 100
def decode_json_string_config(access_token)
  parsed_config = nil
  begin
    parsed_config = JSON.parse(access_token)
  # rubocop:disable HandleExceptions
  rescue JSON::ParserError
  # rubocop:enable HandleExceptions
    # Whatever may fail, we don't want to raise it.
  end
  parsed_config ? keys_to_symbols(parsed_config) : parsed_config
end
decode_string_config(access_token) click to toggle source
# File lib/keystok/client.rb, line 112
def decode_string_config(access_token)
  return {} if access_token == ''
  parsed_config = decode_json_string_config(access_token)
  unless parsed_config
    decoded_string = Base64.decode64(access_token)
    parsed_config = decode_json_string_config(decoded_string)
  end
  fail Error::ConfigError, 'Unknown config format' unless parsed_config
  keys_to_symbols(parsed_config)
end
fetch_data(key = nil) click to toggle source
# File lib/keystok/client.rb, line 123
def fetch_data(key = nil)
  response = nil
  if key.nil? || @config[:eager_fetching]
    key_path_part = ''
  else
    key_path_part = "/#{key}"
  end
  REQUEST_TRY_COUNT.times do |try_count|
    begin
      response = connection.get do |request|
        request.url ['/apps/', @config[:id],
                     '/deploy', key_path_part,
                     '?access_token=', access_token.token].join
        request.options[:open_timeout] = 5
        request.options[:timeout] = 5
      end
      if response.status == 200
        break
      else
        Keystok.logger.warn(
          "Keystok API response status: #{response.status}")
        @access_token = nil
      end
    rescue Faraday::Error::ClientError => exception
      Keystok.logger.warn(
        "Exception during Keystok API data fetch: #{exception.message}")
      raise if try_count == (REQUEST_TRY_COUNT - 1)
    end
  end
  response
end
keys_to_symbols(input_hash) click to toggle source
# File lib/keystok/client.rb, line 155
def keys_to_symbols(input_hash)
  Hash[input_hash.map do |key, val|
    [key.kind_of?(String) ? key.to_s.to_sym : key, val]
  end]
end
load_keys(key = nil) click to toggle source
# File lib/keystok/client.rb, line 161
def load_keys(key = nil)
  begin
    response = fetch_data(key)
    if response.status == 200
      response_data = response.body
    elsif cache_file_exist?
      response_data = load_cache
    else
      fail Keystok::Error::ConnectionError,
           "No cache data and response code:\n" \
             "#{response.status} with body: #{response.body}"
    end
  rescue Faraday::Error::ClientError => exception
    if cache_file_exist?
      response_data = load_cache
    else
      raise Keystok::Error::ConnectionError,
            "No cache data and connection error:\n" \
              "#{exception.class} with message: #{exception.message}"
    end
  end
  @keys_store = {}
  JSON.parse(response_data).each do |key_id, key_info|
    @keys_store[key_id] = decrypt_key(key_info['key'])
  end
  write_cache(response_data) unless @config[:no_cache]
  @keys_store
end
merge_access_token(config_hash, field = :access_token) click to toggle source
# File lib/keystok/client.rb, line 190
def merge_access_token(config_hash, field = :access_token)
  if config_hash[field]
    decoded_hash = decode_string_config(config_hash[field])
    config_hash.delete(field)
    config_hash = decoded_hash.merge(config_hash)
  end
  config_hash
end
oauth_client() click to toggle source
# File lib/keystok/client.rb, line 199
def oauth_client
  @oauth_client ||= begin
    OAuth2::Client.new(nil, nil, site: @config[:auth_host] || AUTH_HOST)
  end
end