require 'open-uri' module Uricp class OrbitAuth AuthenticationFailure = Class.new(ArgumentError) def initialize(auth_uri, auth_id, auth_key) @auth_uri = auth_uri @auth_id = auth_id @auth_key = auth_key end def storage_url @storage_url || begin authenticate @storage_url end end def token authenticate @token end def self.validate_options(options) if options['auth-token'] && (options['auth-key'] || options['auth-user']) raise ::OptionParser::NeedlessArgument, 'use either key based or token based authentication' end if options['auth-key'].nil? ^ options['auth-user'].nil? raise ::OptionParser::MissingArgument, "'auth-user' requires 'auth-key'" end if (options['auth-token'] || options['auth-user']) && options['auth_uri'].nil? raise ::OptionParser::NeedlessArgument, 'authentication is for http uris only' end end def self.add_auth_token(options) if options['auth-user'] orbit_credentials = new(options['auth_uri'], options['auth-user'], options['auth-key']) options['authenticator'] = orbit_credentials.method(:token) elsif options['auth-token'] orbit_token = options['auth-token'] options['authenticator'] = -> { orbit_token } end options.delete('auth-key') options.delete('auth-user') options.delete('auth-token') end def self.add_auth_to_optionparser(app) app.on('--auth-token AUTH_TOKEN', 'Use AUTH_TOKEN for non-local requests') app.on('--auth-user AUTH_USER', 'Use AUTH_USER for authentication') app.on('--auth-key AUTH_KEY', 'Use AUTH_KEY for authentication') end private def authenticate @auth_uri.open( 'X-Auth-User' => @auth_id, 'X-Auth-Key' => @auth_key, 'Range' => 'bytes=0-0' ) do |uri| @storage_url = uri.meta['x-storage-url'] @token = uri.meta['x-auth-token'] end rescue OpenURI::HTTPError => e raise AuthenticationFailure, "Cannot authenticate against #{@auth_uri}" end end end