diff --git a/lib/fog/hp.rb b/lib/fog/hp.rb index 6859fd541..7e48a10cf 100644 --- a/lib/fog/hp.rb +++ b/lib/fog/hp.rb @@ -8,7 +8,8 @@ module Fog service(:compute, 'hp/compute', 'Compute') service(:storage, 'hp/storage', 'Storage') - def self.authenticate(options, connection_options = {}) + # legacy swauth 1.0/1.1 style authentication + def self.authenticate_v1(options, connection_options = {}) hp_auth_uri = options[:hp_auth_uri] || "https://region-a.geo-1.objects.hpcloudsvc.com/auth/v1.0/" endpoint = URI.parse(hp_auth_uri) @scheme = endpoint.scheme || "http" @@ -37,6 +38,95 @@ module Fog response.headers.reject do |key, value| !['X-Server-Management-Url', 'X-Storage-Url', 'X-CDN-Management-Url', 'X-Auth-Token'].include?(key) end + + return { + :auth_token => response.headers['X-Auth-Token'], + :endpoint_url => response.headers['X-Server-Management-Url'], + :cdn_storage_url => response.headers['X-Storage-Url'] + } + end + + # keystone based control services style authentication + def self.authenticate_v2(options, connection_options = {}) + hp_auth_uri = options[:hp_auth_uri] || "https://region-a.geo-1.identity.hpcloudsvc.com/v2.0/" + endpoint = URI.parse(hp_auth_uri) + @scheme = endpoint.scheme || "http" + @host = endpoint.host || "region-a.geo-1.identity.hpcloudsvc.com" + @port = endpoint.port.to_s || "80" + if (endpoint.path) + @auth_path = endpoint.path.slice(1, endpoint.path.length) # remove the leading slash + else + @auth_path = "v2.0/" + end + service_url = "#{@scheme}://#{@host}:#{@port}" + connection = Fog::Connection.new(service_url, false, connection_options) + + ### Implement HP Control Services Authentication services ### + # Get the style of auth credentials passed, defaults to access/secret key style + @hp_use_upass_auth_style = options[:hp_use_upass_auth_style] || false + @hp_account_id = options[:hp_account_id] + @hp_secret_key = options[:hp_secret_key] + @hp_tenant_id = options[:hp_tenant_id] + @hp_service_type = options[:hp_service_type] || "object-store" + + ### Decide which auth style to use + unless (@hp_use_upass_auth_style) + # If Access Key style credentials are provided, use that + request_body = { + 'auth' => { + 'apiAccessKeyCredentials' => { + 'accessKey' => "#{@hp_account_id}", + 'secretKey' => "#{@hp_secret_key}" + } + } + } + else + # Otherwise use the Username/Password style + request_body = { + 'auth' => { + 'passwordCredentials' => { + 'username' => "#{@hp_account_id}", + 'password' => "#{@hp_secret_key}" + } + } + } + end + # add tenant_id if specified + request_body['auth']['tenantId'] = "#{@hp_tenant_id}" if @hp_tenant_id + + ### Make the call to CS to get auth token and service catalog + response = connection.request( + { + :expects => 200, + :headers => { + 'Content-Type' => 'application/json' + }, + :host => @host, + :port => @port, + :method => 'POST', + :body => MultiJson.encode(request_body), + :path => @auth_path + } + ) + + body = MultiJson.decode(response.body) + ### fish out auth_token and endpoint for the service + if body['access']['serviceCatalog'] + service_item = body['access']['serviceCatalog'].select {|s| s["type"] == @hp_service_type}.first + if service_item and service_item['endpoints'] and service_item['endpoints'][0] + endpoint_url = service_item['endpoints'][0]['publicURL'] + auth_token = body['access']['token']['id'] + return { + :auth_token => auth_token, + :endpoint_url => endpoint_url + } + else + raise "No endpoints found for the service type: #{@hp_service_type}" + end + else + raise "Unable to parse service catalog." + end + end class Mock diff --git a/lib/fog/hp/storage.rb b/lib/fog/hp/storage.rb index b6bce31dd..61648cdf2 100644 --- a/lib/fog/hp/storage.rb +++ b/lib/fog/hp/storage.rb @@ -6,7 +6,7 @@ module Fog class HP < Fog::Service requires :hp_secret_key, :hp_account_id - recognizes :hp_auth_uri, :hp_servicenet, :hp_cdn_ssl, :hp_cdn_uri, :persistent, :connection_options + recognizes :hp_auth_uri, :hp_servicenet, :hp_cdn_ssl, :hp_cdn_uri, :persistent, :connection_options, :hp_use_upass_auth_style, :hp_tenant_id, :hp_service_type model_path 'fog/hp/models/storage' model :directory @@ -144,10 +144,14 @@ module Fog @hp_cdn_ssl = options[:hp_cdn_ssl] @hp_cdn_uri = options[:hp_cdn_uri] @connection_options = options[:connection_options] || {} - credentials = Fog::HP.authenticate(options, @connection_options) - @auth_token = credentials['X-Auth-Token'] + ### Pass the service type for object storage via the options hash + options[:hp_service_type] ||= "object-store" - uri = URI.parse(credentials['X-Storage-Url']) + ### Call the control services authentication + credentials = Fog::HP.authenticate_v2(options, @connection_options) + @auth_token = credentials[:auth_token] + + uri = URI.parse(credentials[:endpoint_url]) @host = options[:hp_servicenet] == true ? "snet-#{uri.host}" : uri.host @path = uri.path @persistent = options[:persistent] || false