mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
Merge pull request #1320 from brightbox/refresh_tokens
[Brightbox] Refresh tokens
This commit is contained in:
commit
c6518ee3b1
4 changed files with 555 additions and 104 deletions
|
@ -1,5 +1,6 @@
|
|||
require 'fog/brightbox'
|
||||
require 'fog/compute'
|
||||
require 'fog/brightbox/oauth2'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
|
@ -16,6 +17,12 @@ module Fog
|
|||
# User credentials (still requires client details)
|
||||
recognizes :brightbox_username, :brightbox_password, :brightbox_account
|
||||
|
||||
# Cached tokens
|
||||
recognizes :brightbox_access_token, :brightbox_refresh_token
|
||||
|
||||
# Automatic token management
|
||||
recognizes :brightbox_token_management
|
||||
|
||||
# Excon connection settings
|
||||
recognizes :persistent
|
||||
|
||||
|
@ -127,6 +134,139 @@ module Fog
|
|||
request :update_user
|
||||
|
||||
module Shared
|
||||
include Fog::Brightbox::OAuth2
|
||||
|
||||
# Creates a new instance of the Brightbox Compute service
|
||||
#
|
||||
# @note If you open a connection using just a refresh token when it
|
||||
# expires the service will no longer be able to authenticate.
|
||||
#
|
||||
# @param [Hash] options
|
||||
# @option options [String] :brightbox_api_url Override the default (or configured) API endpoint
|
||||
# @option options [String] :brightbox_auth_url Override the default (or configured) API authentication endpoint
|
||||
# @option options [String] :brightbox_client_id Client identifier to authenticate with (overrides configured)
|
||||
# @option options [String] :brightbox_secret Client secret to authenticate with (overrides configured)
|
||||
# @option options [String] :brightbox_username Email or user identifier for user based authentication
|
||||
# @option options [String] :brightbox_password Password for user based authentication
|
||||
# @option options [String] :brightbox_account Account identifier to scope this connection to
|
||||
# @option options [String] :connection_options Settings to pass to underlying {Fog::Connection}
|
||||
# @option options [Boolean] :persistent Sets a persistent HTTP {Fog::Connection}
|
||||
# @option options [String] :brightbox_access_token Sets the OAuth access token to use rather than requesting a new token
|
||||
# @option options [String] :brightbox_refresh_token Sets the refresh token to use when requesting a newer access token
|
||||
# @option options [String] :brightbox_token_management Overide the existing behaviour to request access tokens if expired (default is `true`)
|
||||
#
|
||||
def initialize(options)
|
||||
# Currently authentication and api endpoints are the same but may change
|
||||
@auth_url = options[:brightbox_auth_url] || Fog.credentials[:brightbox_auth_url] || API_URL
|
||||
@auth_connection = Fog::Connection.new(@auth_url)
|
||||
|
||||
@api_url = options[:brightbox_api_url] || Fog.credentials[:brightbox_api_url] || API_URL
|
||||
@connection_options = options[:connection_options] || {}
|
||||
@persistent = options[:persistent] || false
|
||||
@connection = Fog::Connection.new(@api_url, @persistent, @connection_options)
|
||||
|
||||
# Authentication options
|
||||
client_id = options[:brightbox_client_id] || Fog.credentials[:brightbox_client_id]
|
||||
client_secret = options[:brightbox_secret] || Fog.credentials[:brightbox_secret]
|
||||
|
||||
username = options[:brightbox_username] || Fog.credentials[:brightbox_username]
|
||||
password = options[:brightbox_password] || Fog.credentials[:brightbox_password]
|
||||
@configured_account = options[:brightbox_account] || Fog.credentials[:brightbox_account]
|
||||
# Request account can be changed at anytime and changes behaviour of future requests
|
||||
@scoped_account = @configured_account
|
||||
|
||||
credential_options = {:username => username, :password => password}
|
||||
@credentials = CredentialSet.new(client_id, client_secret, credential_options)
|
||||
|
||||
# If existing tokens have been cached, allow continued use of them in the service
|
||||
@credentials.update_tokens(options[:brightbox_access_token], options[:brightbox_refresh_token])
|
||||
|
||||
@token_management = options.fetch(:brightbox_token_management, true)
|
||||
end
|
||||
|
||||
# Sets the scoped account for future requests
|
||||
# @param [String] scoped_account Identifier of the account to scope request to
|
||||
def scoped_account=(scoped_account)
|
||||
@scoped_account = scoped_account
|
||||
end
|
||||
|
||||
# This returns the account identifier that the request should be scoped by
|
||||
# based on the options passed to the request and current configuration
|
||||
#
|
||||
# @param [String] options_account Any identifier passed into the request
|
||||
#
|
||||
# @return [String, nil] The account identifier to scope the request to or nil
|
||||
def scoped_account(options_account = nil)
|
||||
[options_account, @scoped_account].compact.first
|
||||
end
|
||||
|
||||
# Resets the scoped account back to intially configured one
|
||||
def scoped_account_reset
|
||||
@scoped_account = @configured_account
|
||||
end
|
||||
|
||||
# Returns the scoped account being used for requests
|
||||
#
|
||||
# * For API clients this is the owning account
|
||||
# * For User applications this is the account specified by either +account_id+
|
||||
# option on a connection or the +brightbox_account+ setting in your configuration
|
||||
#
|
||||
# @return [Fog::Compute::Brightbox::Account]
|
||||
#
|
||||
def account
|
||||
Fog::Compute::Brightbox::Account.new(get_scoped_account).tap do |acc|
|
||||
# Connection is more like the compute 'service'
|
||||
acc.connection = self
|
||||
end
|
||||
end
|
||||
|
||||
# Returns true if authentication is being performed as a user
|
||||
# @return [Boolean]
|
||||
def authenticating_as_user?
|
||||
@credentials.user_details?
|
||||
end
|
||||
|
||||
# Returns true if an access token is set
|
||||
# @return [Boolean]
|
||||
def access_token_available?
|
||||
!! @credentials.access_token
|
||||
end
|
||||
|
||||
# Returns the current access token or nil
|
||||
# @return [String,nil]
|
||||
def access_token
|
||||
@credentials.access_token
|
||||
end
|
||||
|
||||
# Returns the current refresh token or nil
|
||||
# @return [String,nil]
|
||||
def refresh_token
|
||||
@credentials.refresh_token
|
||||
end
|
||||
|
||||
# Requests a new access token
|
||||
#
|
||||
# @return [String] New access token
|
||||
def get_access_token
|
||||
begin
|
||||
get_access_token!
|
||||
rescue Excon::Errors::Unauthorized, Excon::Errors::BadRequest
|
||||
@credentials.update_tokens(nil, nil)
|
||||
end
|
||||
@credentials.access_token
|
||||
end
|
||||
|
||||
# Requests a new access token and raises if there is a problem
|
||||
#
|
||||
# @return [String] New access token
|
||||
# @raise [Excon::Errors::BadRequest] The credentials are expired or incorrect
|
||||
#
|
||||
def get_access_token!
|
||||
response = request_access_token(@auth_connection, @credentials)
|
||||
update_credentials_from_response(@credentials, response)
|
||||
@credentials.access_token
|
||||
end
|
||||
|
||||
# Returns an identifier for the default image for use
|
||||
#
|
||||
# Currently tries to find the latest version Ubuntu LTS (i686) widening
|
||||
|
@ -140,59 +280,91 @@ module Fog
|
|||
return @default_image_id unless @default_image_id.nil?
|
||||
@default_image_id = Fog.credentials[:brightbox_default_image] || select_default_image
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# This makes a request of the API based on the configured setting for
|
||||
# token management.
|
||||
#
|
||||
# @param [Hash] options Excon compatible options
|
||||
# @see https://github.com/geemus/excon/blob/master/lib/excon/connection.rb
|
||||
#
|
||||
# @return [Hash] Data of response body
|
||||
#
|
||||
def make_request(options)
|
||||
if @token_management
|
||||
managed_token_request(options)
|
||||
else
|
||||
authenticated_request(options)
|
||||
end
|
||||
end
|
||||
|
||||
# This request checks for access tokens and will ask for a new one if
|
||||
# it receives Unauthorized from the API before repeating the request
|
||||
#
|
||||
# @param [Hash] options Excon compatible options
|
||||
#
|
||||
# @return [Excon::Response]
|
||||
def managed_token_request(options)
|
||||
begin
|
||||
get_access_token unless access_token_available?
|
||||
response = authenticated_request(options)
|
||||
rescue Excon::Errors::Unauthorized
|
||||
get_access_token
|
||||
response = authenticated_request(options)
|
||||
end
|
||||
end
|
||||
|
||||
# This request makes an authenticated request of the API using currently
|
||||
# setup credentials.
|
||||
#
|
||||
# @param [Hash] options Excon compatible options
|
||||
#
|
||||
# @return [Excon::Response]
|
||||
def authenticated_request(options)
|
||||
headers = options[:headers] || {}
|
||||
headers.merge!("Authorization" => "OAuth #{@credentials.access_token}", "Content-Type" => "application/json")
|
||||
options[:headers] = headers
|
||||
# TODO This is just a wrapper around a call to Excon::Connection#request
|
||||
# so can be extracted from Compute by passing in the connection,
|
||||
# credentials and options
|
||||
@connection.request(options)
|
||||
end
|
||||
end
|
||||
|
||||
# The Mock Service allows you to run a fake instance of the Service
|
||||
# which makes no real connections.
|
||||
#
|
||||
# @todo Implement
|
||||
#
|
||||
class Mock
|
||||
include Shared
|
||||
|
||||
def initialize(options)
|
||||
@brightbox_client_id = options[:brightbox_client_id] || Fog.credentials[:brightbox_client_id]
|
||||
@brightbox_secret = options[:brightbox_secret] || Fog.credentials[:brightbox_secret]
|
||||
def request(method, path, expected_responses, parameters = {})
|
||||
_request
|
||||
end
|
||||
|
||||
def request(options)
|
||||
raise "Not implemented"
|
||||
def request_access_token(connection, credentials)
|
||||
_request
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _request
|
||||
raise Fog::Errors::MockNotImplemented
|
||||
end
|
||||
|
||||
def select_default_image
|
||||
"img-mockd"
|
||||
end
|
||||
end
|
||||
|
||||
# The Real Service actually makes real connections to the Brightbox
|
||||
# service.
|
||||
#
|
||||
class Real
|
||||
include Shared
|
||||
|
||||
# Creates a new instance of the Brightbox Compute service
|
||||
#
|
||||
# @param [Hash] options
|
||||
# @option options [String] :brightbox_api_url Override the default (or configured) API endpoint
|
||||
# @option options [String] :brightbox_auth_url Override the default (or configured) API authentication endpoint
|
||||
# @option options [String] :brightbox_client_id Client identifier to authenticate with (overrides configured)
|
||||
# @option options [String] :brightbox_secret Client secret to authenticate with (overrides configured)
|
||||
# @option options [String] :brightbox_username Email or user identifier for user based authentication
|
||||
# @option options [String] :brightbox_password Password for user based authentication
|
||||
# @option options [String] :brightbox_account Account identifier to scope this connection to
|
||||
# @option options [String] :connection_options Settings to pass to underlying {Fog::Connection}
|
||||
# @option options [Boolean] :persistent Sets a persistent HTTP {Fog::Connection}
|
||||
#
|
||||
def initialize(options)
|
||||
# Currently authentication and api endpoints are the same but may change
|
||||
@auth_url = options[:brightbox_auth_url] || Fog.credentials[:brightbox_auth_url] || API_URL
|
||||
@api_url = options[:brightbox_api_url] || Fog.credentials[:brightbox_api_url] || API_URL
|
||||
@connection_options = options[:connection_options] || {}
|
||||
@persistent = options[:persistent] || false
|
||||
@connection = Fog::Connection.new(@api_url, @persistent, @connection_options)
|
||||
|
||||
# Authentication options
|
||||
@brightbox_client_id = options[:brightbox_client_id] || Fog.credentials[:brightbox_client_id]
|
||||
@brightbox_secret = options[:brightbox_secret] || Fog.credentials[:brightbox_secret]
|
||||
|
||||
@brightbox_username = options[:brightbox_username] || Fog.credentials[:brightbox_username]
|
||||
@brightbox_password = options[:brightbox_password] || Fog.credentials[:brightbox_password]
|
||||
@brightbox_account = options[:brightbox_account] || Fog.credentials[:brightbox_account]
|
||||
end
|
||||
|
||||
# Makes an API request to the given path using passed options or those
|
||||
# set with the service setup
|
||||
#
|
||||
|
@ -214,81 +386,27 @@ module Fog
|
|||
:path => path,
|
||||
:expects => expected_responses
|
||||
}
|
||||
parameters[:account_id] = @brightbox_account if parameters[:account_id].nil? && @brightbox_account
|
||||
|
||||
# Select the account to scope for this request
|
||||
account = scoped_account(parameters.fetch(:account_id, nil))
|
||||
if account
|
||||
request_options[:query] = { :account_id => account }
|
||||
end
|
||||
|
||||
request_options[:body] = Fog::JSON.encode(parameters) unless parameters.empty?
|
||||
make_request(request_options)
|
||||
end
|
||||
|
||||
# Returns the scoped account being used for requests
|
||||
#
|
||||
# * For API clients this is the owning account
|
||||
# * For User applications this is the account specified by either +account_id+
|
||||
# option on a connection or the +brightbox_account+ setting in your configuration
|
||||
#
|
||||
# @return [Fog::Compute::Brightbox::Account]
|
||||
#
|
||||
def account
|
||||
Fog::Compute::Brightbox::Account.new(get_scoped_account).tap do |acc|
|
||||
# Connection is more like the compute 'service'
|
||||
acc.connection = self
|
||||
end
|
||||
end
|
||||
response = make_request(request_options)
|
||||
|
||||
# Returns true if authentication is being performed as a user
|
||||
# @return [Boolean]
|
||||
def authenticating_as_user?
|
||||
@brightbox_username && @brightbox_password
|
||||
end
|
||||
private
|
||||
def get_oauth_token(options = {})
|
||||
auth_url = options[:brightbox_auth_url] || @auth_url
|
||||
|
||||
connection = Fog::Connection.new(auth_url)
|
||||
authentication_body_hash = if authenticating_as_user?
|
||||
{
|
||||
'client_id' => @brightbox_client_id,
|
||||
'grant_type' => 'password',
|
||||
'username' => @brightbox_username,
|
||||
'password' => @brightbox_password
|
||||
}
|
||||
else
|
||||
{'client_id' => @brightbox_client_id, 'grant_type' => 'none'}
|
||||
end
|
||||
@authentication_body = Fog::JSON.encode(authentication_body_hash)
|
||||
|
||||
response = connection.request({
|
||||
:path => "/token",
|
||||
:expects => 200,
|
||||
:headers => {
|
||||
'Authorization' => "Basic " + Base64.encode64("#{@brightbox_client_id}:#{@brightbox_secret}").chomp,
|
||||
'Content-Type' => 'application/json'
|
||||
},
|
||||
:method => 'POST',
|
||||
:body => @authentication_body
|
||||
})
|
||||
@oauth_token = Fog::JSON.decode(response.body)["access_token"]
|
||||
return @oauth_token
|
||||
end
|
||||
|
||||
def make_request(params)
|
||||
begin
|
||||
get_oauth_token if @oauth_token.nil?
|
||||
response = authenticated_request(params)
|
||||
rescue Excon::Errors::Unauthorized
|
||||
get_oauth_token
|
||||
response = authenticated_request(params)
|
||||
end
|
||||
# FIXME We should revert to returning the Excon::Request after a suitable
|
||||
# configuration option is in place to switch back to this incorrect behaviour
|
||||
unless response.body.empty?
|
||||
response = Fog::JSON.decode(response.body)
|
||||
Fog::JSON.decode(response.body)
|
||||
else
|
||||
response
|
||||
end
|
||||
end
|
||||
|
||||
def authenticated_request(options)
|
||||
headers = options[:headers] || {}
|
||||
headers.merge!("Authorization" => "OAuth #{@oauth_token}", "Content-Type" => "application/json")
|
||||
options[:headers] = headers
|
||||
@connection.request(options)
|
||||
end
|
||||
private
|
||||
|
||||
# Queries the API and tries to select the most suitable official Image
|
||||
# to use if the user chooses not to select their own.
|
||||
|
|
164
lib/fog/brightbox/oauth2.rb
Normal file
164
lib/fog/brightbox/oauth2.rb
Normal file
|
@ -0,0 +1,164 @@
|
|||
# This module covers Brightbox's partial implementation of OAuth 2.0
|
||||
# and enables fog clients to implement several authentictication strategies
|
||||
#
|
||||
# @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10
|
||||
#
|
||||
module Fog::Brightbox::OAuth2
|
||||
|
||||
# This builds the simplest form of requesting an access token
|
||||
# based on the arguments passed in
|
||||
#
|
||||
# @param [Fog::Connection] connection
|
||||
# @param [CredentialSet] credentials
|
||||
#
|
||||
# @return [Excon::Response]
|
||||
def request_access_token(connection, credentials)
|
||||
token_strategy = credentials.best_grant_strategy
|
||||
|
||||
header_content = "#{credentials.client_id}:#{credentials.client_secret}"
|
||||
encoded_credentials = Base64.encode64(header_content).chomp
|
||||
|
||||
connection.request({
|
||||
:path => "/token",
|
||||
:expects => 200,
|
||||
:headers => {
|
||||
'Authorization' => "Basic #{encoded_credentials}",
|
||||
'Content-Type' => 'application/json'
|
||||
},
|
||||
:method => 'POST',
|
||||
:body => Fog::JSON.encode(token_strategy.authorization_body_data)
|
||||
})
|
||||
end
|
||||
|
||||
# Encapsulates credentials required to request access tokens from the
|
||||
# Brightbox authorisation servers
|
||||
#
|
||||
# @todo Interface to update certain credentials (after password change)
|
||||
#
|
||||
class CredentialSet
|
||||
attr_reader :client_id, :client_secret, :username, :password
|
||||
attr_reader :access_token, :refresh_token
|
||||
#
|
||||
# @param [String] client_id
|
||||
# @param [String] client_secret
|
||||
# @param [Hash] options
|
||||
# @option options [String] :username
|
||||
# @option options [String] :password
|
||||
#
|
||||
def initialize(client_id, client_secret, options = {})
|
||||
@client_id = client_id
|
||||
@client_secret = client_secret
|
||||
@username = options[:username]
|
||||
@password = options[:password]
|
||||
@access_token = options[:access_token]
|
||||
@refresh_token = options[:refresh_token]
|
||||
end
|
||||
|
||||
# Returns true if user details are available
|
||||
# @return [Boolean]
|
||||
def user_details?
|
||||
!!(@username && @password)
|
||||
end
|
||||
|
||||
# Is an access token available for these credentials?
|
||||
def access_token?
|
||||
!!@access_token
|
||||
end
|
||||
|
||||
# Is a refresh token available for these credentials?
|
||||
def refresh_token?
|
||||
!!@refresh_token
|
||||
end
|
||||
|
||||
# Updates the credentials with newer tokens
|
||||
def update_tokens(access_token, refresh_token = nil)
|
||||
@access_token = access_token
|
||||
@refresh_token = refresh_token
|
||||
end
|
||||
|
||||
# Based on available credentials returns the best strategy
|
||||
#
|
||||
# @todo Add a means to dictate which should or shouldn't be used
|
||||
#
|
||||
def best_grant_strategy
|
||||
if refresh_token?
|
||||
RefreshTokenStrategy.new(self)
|
||||
elsif user_details?
|
||||
UserCredentialsStrategy.new(self)
|
||||
else
|
||||
ClientCredentialsStrategy.new(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# This strategy class is the basis for OAuth2 grant types
|
||||
#
|
||||
# @abstract Need to implement {#authorization_body_data} to return a
|
||||
# Hash matching the expected parameter form for the OAuth request
|
||||
#
|
||||
# @todo Strategies should be able to validate if credentials are suitable
|
||||
# so just client credentials cannot be used with user strategies
|
||||
#
|
||||
class GrantTypeStrategy
|
||||
def initialize(credentials)
|
||||
@credentials = credentials
|
||||
end
|
||||
|
||||
def authorization_body_data
|
||||
raise "Not implemented"
|
||||
end
|
||||
end
|
||||
|
||||
# This implements client based authentication/authorization
|
||||
# based on the existing trust relationship using the `none`
|
||||
# grant type.
|
||||
#
|
||||
class ClientCredentialsStrategy < GrantTypeStrategy
|
||||
def authorization_body_data
|
||||
{
|
||||
"grant_type" => "none",
|
||||
"client_id" => @credentials.client_id
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# This passes user details through so the returned token
|
||||
# carries the privileges of the user not account limited
|
||||
# by the client
|
||||
#
|
||||
class UserCredentialsStrategy < GrantTypeStrategy
|
||||
def authorization_body_data
|
||||
{
|
||||
"grant_type" => "password",
|
||||
"client_id" => @credentials.client_id,
|
||||
"username" => @credentials.username,
|
||||
"password" => @credentials.password
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# This strategy attempts to use a refresh_token gained during an earlier
|
||||
# request to reuse the credentials given originally
|
||||
#
|
||||
class RefreshTokenStrategy < GrantTypeStrategy
|
||||
def authorization_body_data
|
||||
{
|
||||
"grant_type" => "refresh_token",
|
||||
"client_id" => @credentials.client_id,
|
||||
"refresh_token" => @credentials.refresh_token
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# This updates the current credentials if passed a valid response
|
||||
#
|
||||
# @param [CredentialSet] credentials Credentials to update
|
||||
# @param [Excon::Response] response Response object to parse value from
|
||||
#
|
||||
def update_credentials_from_response(credentials, response)
|
||||
response_data = Fog::JSON.decode(response.body)
|
||||
credentials.update_tokens(response_data["access_token"], response_data["refresh_token"])
|
||||
end
|
||||
end
|
|
@ -18,7 +18,10 @@ Shindo.tests('Fog::Compute.new', ['brightbox']) do
|
|||
:brightbox_secret => "12345abdef6789",
|
||||
:brightbox_username => "user-12345",
|
||||
:brightbox_password => "password1234",
|
||||
:brightbox_account => "acc-12345"
|
||||
:brightbox_account => "acc-12345",
|
||||
:brightbox_access_token => "12345abdef6789",
|
||||
:brightbox_refresh_token => "12345abdef6789",
|
||||
:brightbox_token_management => false
|
||||
}.each_pair do |option, sample|
|
||||
tests("recognises :#{option}").returns(true) do
|
||||
options = {:provider => "Brightbox"}
|
||||
|
@ -32,4 +35,67 @@ Shindo.tests('Fog::Compute.new', ['brightbox']) do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
tests("automatic token management") do
|
||||
service_options = {:provider => "Brightbox"}
|
||||
|
||||
tests("when enabled (default)") do
|
||||
service_options[:brightbox_token_management] = true
|
||||
|
||||
tests("using bad token") do
|
||||
service_options[:brightbox_access_token] = "bad-token"
|
||||
|
||||
tests("#request").returns(true, "returns a Hash") do
|
||||
pending if Fog.mocking?
|
||||
service = Fog::Compute.new(service_options)
|
||||
response = service.get_authenticated_user
|
||||
response.is_a?(Hash) # This is an outstanding issue, should be Excon::Response
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tests("when disabled") do
|
||||
service_options[:brightbox_token_management] = false
|
||||
|
||||
tests("using bad token") do
|
||||
service_options[:brightbox_access_token] = "bad-token"
|
||||
|
||||
tests("#request").raises(Excon::Errors::Unauthorized) do
|
||||
pending if Fog.mocking?
|
||||
service = Fog::Compute.new(service_options)
|
||||
service.get_authenticated_user
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tests("account scoping") do
|
||||
service = Fog::Compute.new(:provider => "Brightbox")
|
||||
configured_account = Fog.credentials[:brightbox_account]
|
||||
tests("when Fog.credentials are #{configured_account}") do
|
||||
test("#scoped_account == #{configured_account}") { service.scoped_account == configured_account }
|
||||
end
|
||||
|
||||
set_account = "acc-35791"
|
||||
tests("when Compute instance is updated to #{set_account}") do
|
||||
service.scoped_account = set_account
|
||||
test("#scoped_account == #{set_account}") { service.scoped_account == set_account }
|
||||
end
|
||||
|
||||
tests("when Compute instance is reset") do
|
||||
service.scoped_account_reset
|
||||
test("#scoped_account == #{configured_account}") { service.scoped_account == configured_account }
|
||||
end
|
||||
|
||||
optioned_account = "acc-56789"
|
||||
tests("when Compute instance created with :brightbox_account => #{optioned_account}") do
|
||||
service = Fog::Compute.new(:provider => "Brightbox", :brightbox_account => optioned_account )
|
||||
test("#scoped_account == #{optioned_account}") { service.scoped_account == optioned_account }
|
||||
end
|
||||
|
||||
request_account = "acc-24680"
|
||||
tests("when requested with #{request_account}") do
|
||||
test("#scoped_account(#{request_account}) == #{request_account}") { service.scoped_account(request_account) == request_account }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
103
tests/brightbox/oauth2_tests.rb
Normal file
103
tests/brightbox/oauth2_tests.rb
Normal file
|
@ -0,0 +1,103 @@
|
|||
Shindo.tests("Fog::Brightbox::OAuth2", ["brightbox"]) do
|
||||
|
||||
tests("CredentialSet") do
|
||||
@client_id = "app-12345"
|
||||
@client_secret = "__mashed_keys_123__"
|
||||
@username = "usr-12345"
|
||||
@password = "__mushed_keys_321__"
|
||||
@access_token = "12efde32fdfe4989"
|
||||
@refresh_token = "7894389f9074f071"
|
||||
|
||||
tests("with client credentials") do
|
||||
credentials = Fog::Brightbox::OAuth2::CredentialSet.new(@client_id, @client_secret)
|
||||
tests("#user_details?").returns(false) { credentials.user_details? }
|
||||
tests("#access_token?").returns(false) { credentials.access_token? }
|
||||
tests("#refresh_token?").returns(false) { credentials.refresh_token? }
|
||||
tests("#best_grant_strategy").returns(true) do
|
||||
credentials.best_grant_strategy.is_a?(Fog::Brightbox::OAuth2::ClientCredentialsStrategy)
|
||||
end
|
||||
end
|
||||
|
||||
tests("with user credentials") do
|
||||
options = {:username => @username, :password => @password}
|
||||
credentials = Fog::Brightbox::OAuth2::CredentialSet.new(@client_id, @client_secret, options)
|
||||
tests("#user_details?").returns(true) { credentials.user_details? }
|
||||
tests("#access_token?").returns(false) { credentials.access_token? }
|
||||
tests("#refresh_token?").returns(false) { credentials.refresh_token? }
|
||||
tests("#best_grant_strategy").returns(true) do
|
||||
credentials.best_grant_strategy.is_a?(Fog::Brightbox::OAuth2::UserCredentialsStrategy)
|
||||
end
|
||||
end
|
||||
|
||||
tests("with existing tokens") do
|
||||
options = {:username => @username, :access_token => @access_token, :refresh_token => @refresh_token}
|
||||
credentials = Fog::Brightbox::OAuth2::CredentialSet.new(@client_id, @client_secret, options)
|
||||
tests("#user_details?").returns(false) { credentials.user_details? }
|
||||
tests("#access_token?").returns(true) { credentials.access_token? }
|
||||
tests("#refresh_token?").returns(true) { credentials.refresh_token? }
|
||||
tests("#best_grant_strategy").returns(true) do
|
||||
credentials.best_grant_strategy.is_a?(Fog::Brightbox::OAuth2::RefreshTokenStrategy)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tests("GrantTypeStrategy") do
|
||||
credentials = Fog::Brightbox::OAuth2::CredentialSet.new(@client_id, @client_secret)
|
||||
strategy = Fog::Brightbox::OAuth2::GrantTypeStrategy.new(credentials)
|
||||
|
||||
tests("#respond_to? :authorization_body_data").returns(true) do
|
||||
strategy.respond_to?(:authorization_body_data)
|
||||
end
|
||||
end
|
||||
|
||||
tests("ClientCredentialsStrategy") do
|
||||
credentials = Fog::Brightbox::OAuth2::CredentialSet.new(@client_id, @client_secret)
|
||||
strategy = Fog::Brightbox::OAuth2::ClientCredentialsStrategy.new(credentials)
|
||||
|
||||
tests("#respond_to? :authorization_body_data").returns(true) do
|
||||
strategy.respond_to?(:authorization_body_data)
|
||||
end
|
||||
|
||||
tests("#authorization_body_data") do
|
||||
authorization_body_data = strategy.authorization_body_data
|
||||
test("grant_type == none") { authorization_body_data["grant_type"] == "none" }
|
||||
test("client_id == #{@client_id}") { authorization_body_data["client_id"] == @client_id }
|
||||
end
|
||||
end
|
||||
|
||||
tests("UserCredentialsStrategy") do
|
||||
options = {:username => @username, :password => @password}
|
||||
credentials = Fog::Brightbox::OAuth2::CredentialSet.new(@client_id, @client_secret, options)
|
||||
strategy = Fog::Brightbox::OAuth2::UserCredentialsStrategy.new(credentials)
|
||||
|
||||
tests("#respond_to? :authorization_body_data").returns(true) do
|
||||
strategy.respond_to?(:authorization_body_data)
|
||||
end
|
||||
|
||||
tests("#authorization_body_data") do
|
||||
authorization_body_data = strategy.authorization_body_data
|
||||
test("grant_type == password") { authorization_body_data["grant_type"] == "password" }
|
||||
test("client_id == #{@client_id}") { authorization_body_data["client_id"] == @client_id }
|
||||
test("username == #{@username}") { authorization_body_data["username"] == @username }
|
||||
test("password == #{@password}") { authorization_body_data["password"] == @password }
|
||||
end
|
||||
end
|
||||
|
||||
tests("RefreshTokenStrategy") do
|
||||
refresh_token = "ab4b39dddf909"
|
||||
options = {:refresh_token => refresh_token}
|
||||
credentials = Fog::Brightbox::OAuth2::CredentialSet.new(@client_id, @client_secret, options)
|
||||
strategy = Fog::Brightbox::OAuth2::RefreshTokenStrategy.new(credentials)
|
||||
|
||||
tests("#respond_to? :authorization_body_data").returns(true) do
|
||||
strategy.respond_to?(:authorization_body_data)
|
||||
end
|
||||
|
||||
tests("#authorization_body_data") do
|
||||
authorization_body_data = strategy.authorization_body_data
|
||||
test("grant_type == refresh_token") { authorization_body_data["grant_type"] == "refresh_token" }
|
||||
test("client_id == #{@client_id}") { authorization_body_data["client_id"] == @client_id }
|
||||
test("refresh_token == #{refresh_token}") { authorization_body_data["refresh_token"] == refresh_token }
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue