class AuthenticationStrategies::KeystoneStrategy
Constants
- ALLOWED_MAPPING_TYPES
- SUPPORTED_CERT_SOURCES
Public Instance Methods
allowed_access?(tenant_name)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 201 def allowed_access?(tenant_name) return false if tenant_name.blank? case OPTIONS.access_policy when 'blacklist' !blacklisted_tenant?(tenant_name) when 'whitelist' whitelisted_tenant?(tenant_name) else raise Errors::ConfigurationParsingError, "Unsupported Keystone access policy #{OPTIONS.access_policy.inspect}!" end end
auth_request()
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 15 def auth_request @auth_request ||= ::ActionDispatch::Request.new(env) end
authenticate!()
click to toggle source
@see AuthenticationStrategies::DummyStrategy
# File lib/authentication_strategies/keystone_strategy.rb, line 34 def authenticate! Rails.logger.debug "[AuthN] [#{self.class}] Authenticating with X-Auth-Token" if self.class.revoked_token?(auth_request.headers['X-Auth-Token']) fail! 'Your Keystone token has been revoked!' return end store = self.class.init_x509_store( OPTIONS.keystone_pki_trust.ca_cert, OPTIONS.keystone_pki_trust.ca_path ) crt = OpenSSL::X509::Certificate.new(File.read(OPTIONS.keystone_pki_trust.signing_cert)) verified = begin cms_token = OpenSSL::CMS.read_cms(self.class.keystone2cms(auth_request.headers['X-Auth-Token'])) cms_token.verify([crt], store, nil, nil) rescue => e Rails.logger.warn "[AuthN] [#{self.class}] OpenSSL::CMS validation " "failed with #{e.message.inspect} on: #{auth_request.headers['X-Auth-Token']}" fail! 'Your Keystone token is invalid!' return end unless verified fail! 'Failed to verify your Keystone token!' return end extracted_token = self.class.extract_token(cms_token) unless extracted_token fail! 'Your Keystone token is expired or malformed!' return end unless self.class.allowed_access?(extracted_token.access_.token_.tenant_.name) fail! "Tenant #{extracted_token.access_.token_.tenant_.name.inspect} is not allowed!" return end user = self.class.user_factory(extracted_token) unless user fail! 'Couldn\t retrieve user and tenant information from the token!' return end Rails.logger.debug "[AuthN] [#{self.class}] Authenticated #{user.to_hash.inspect}" success! user.deep_freeze end
blacklisted_tenant?(tenant_name)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 215 def blacklisted_tenant?(tenant_name) blacklist = AuthenticationStrategies::Helpers::YamlHelper.read_yaml(OPTIONS.blacklist) || [] blacklist.include?(tenant_name) end
expired_token?(extracted_token)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 145 def expired_token?(extracted_token) exp_time = extracted_token.access_.token_.expires return true unless exp_time DateTime.iso8601(exp_time) < DateTime.now end
extract_token(cms_token)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 125 def extract_token(cms_token) begin data = Hashie::Mash.new(JSON.parse(cms_token.data)) expired_token?(data) ? nil : data rescue => e Rails.logger.error "[AuthN] [#{self.name}] Failed to " "extract data from CMS token! #{e.message}" raise e end end
file_marcopolo?(path)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 196 def file_marcopolo?(path) return false if path.blank? File.readable?(path) && !File.zero?(path) end
get_memcaches()
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 176 def get_memcaches return unless OPTIONS.memcaches OPTIONS.memcaches.respond_to?(:each) ? OPTIONS.memcaches : OPTIONS.memcaches.split end
get_trl(url)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 151 def get_trl(url) dalli = Backend.dalli_instance_factory( "keystone_strategy_trl_cache", get_memcaches, { expire_after: 2.minutes }, url.gsub(/\W+/, '_') ) trl_parsed = nil begin unless trl = dalli.get('trl') trl = open(url).read dalli.set('trl', trl) end trl_parsed = Hashie::Mash.new(JSON.parse(trl)) rescue => e Rails.logger.error "[AuthN] [#{self.name}] Failed to " "retrieve and parse TRL from #{url.inspect}! #{e.message}" dalli.delete('trl') raise e end trl_parsed end
have_certs?()
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 86 def have_certs? # TODO: implement 'url' as a cert_source option unless SUPPORTED_CERT_SOURCES.include?(OPTIONS.keystone_pki_trust_.cert_source) raise Errors::ConfigurationParsingError, "Unsupported cert_source #{OPTIONS.keystone_pki_trust_.cert_source.inspect} for Keystone! " "Only #{SUPPORTED_CERT_SOURCES.join(', ').inspect} are allowed!" end result = file_marcopolo?(OPTIONS.keystone_pki_trust_.ca_cert) && file_marcopolo?(OPTIONS.keystone_pki_trust_.signing_cert) Rails.logger.warn "[AuthN] [#{self.name}] Certificates are not present or empty! Bailing out ..." unless result result end
init_x509_store(ca_cert, ca_path = nil)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 115 def init_x509_store(ca_cert, ca_path = nil) store = OpenSSL::X509::Store.new store.add_path(ca_path) unless ca_path.blank? ca_crt = OpenSSL::X509::Certificate.new(File.read(ca_cert)) store.add_cert ca_crt store end
keystone2cms(token)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 100 def keystone2cms(token) # Wrap lines to 64 chars per line ary = token.scan(/.{64}/) size_rest = token.length - (ary.length*64) ary << token.scan(Regexp.new(".{#{size_rest}}$")) ary.flatten! token = ary.join("\n") # Fix some OS Keystone stuff (why??) token.gsub!('-', '/') # Add CMS header & trailer "-----BEGIN CMS-----\n#{token}\n-----END CMS-----\n" end
mapped_name(name, type)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 225 def mapped_name(name, type) raise "Unsupported mapping request! Type #{type.to_s.inspect} " "is not registered!" unless ALLOWED_MAPPING_TYPES.include?(type) return name unless OPTIONS.send("#{type.to_s}_mapping") map = AuthenticationStrategies::Helpers::YamlHelper.read_yaml(OPTIONS.send("#{type.to_s}_mapfile")) || {} new_name = map[name] || name Rails.logger.debug "[AuthN] [#{self}] #{type.to_s.capitalize} name mapped #{name.inspect} -> #{new_name.inspect}" new_name end
revoked_token?(original_token)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 136 def revoked_token?(original_token) return false unless OPTIONS.keystone_pki_trust.trl_url trl = get_trl(OPTIONS.keystone_pki_trust.trl_url) return true unless trl && trl.revoked token_md5 = Digest::MD5.digest(original_token) trl.revoked.select { |rev| rev.id == token_md5 }.any? end
store?()
click to toggle source
@see AuthenticationStrategies::DummyStrategy
# File lib/authentication_strategies/keystone_strategy.rb, line 20 def store? false end
user_factory(extracted_token)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 181 def user_factory(extracted_token) return if extracted_token.access_.token_.tenant_.name.blank? return if extracted_token.access_.user_.username.blank? user = Hashie::Mash.new user.auth!.type = 'keystone' user.auth!.credentials!.tenant = mapped_name(extracted_token.access.token.tenant.name, :tenant) user.auth!.credentials!.username = mapped_name(extracted_token.access.user.username, :user) user.auth!.credentials!.token = extracted_token user.auth!.credentials!.verification_status = 'SUCCESS' user.identity = user.auth.credentials.username user end
valid?()
click to toggle source
@see AuthenticationStrategies::DummyStrategy
# File lib/authentication_strategies/keystone_strategy.rb, line 25 def valid? Rails.logger.debug "[AuthN] [#{self.class}] Checking for applicability" result = !auth_request.headers['X-Auth-Token'].blank? && self.class.have_certs? Rails.logger.debug "[AuthN] [#{self.class}] Strategy is #{result ? '' : 'not '}applicable!" result end
whitelisted_tenant?(tenant_name)
click to toggle source
# File lib/authentication_strategies/keystone_strategy.rb, line 220 def whitelisted_tenant?(tenant_name) whitelist = AuthenticationStrategies::Helpers::YamlHelper.read_yaml(OPTIONS.whitelist) || [] whitelist.include?(tenant_name) end