Class: GlobalSession::Directory
- Inherits:
-
Object
- Object
- GlobalSession::Directory
- Defined in:
- lib/global_session/directory.rb
Overview
The global session directory, which provides some lookup and decision services to instances of Session.
The default implementation is simplistic, but should be suitable for most applications. Directory is designed to be specialized via subclassing. To override the behavior to suit your needs, simply create a subclass of Directory and add a configuration file setting to specify the class name of your implementation:
common:
directory: MyCoolDirectory
The Authority Keystore
Directory uses a filesystem directory as a backing store for RSA
public keys of global session authorities. The directory should
contain one or more *.pub files containing OpenSSH-format public
RSA keys. The name of the pub file determines the name of the
authority it represents.
The Local Authority
Directory will infer the name of the local authority (if any) by
looking for a private-key file in the keystore. If a *.key file
is found, then its name is taken to be the name of the local
authority and all GlobalSessions created will be signed by that
authority's private key.
If more than one key file is found, Directory will raise an error at initialization time.
Instance Attribute Summary collapse
-
#authorities ⇒ Object
readonly
Returns the value of attribute authorities.
-
#configuration ⇒ Object
readonly
Returns the value of attribute configuration.
-
#private_key ⇒ Object
readonly
Returns the value of attribute private_key.
Instance Method Summary collapse
-
#create_session(cookie = nil) ⇒ Object
Create a new Session, initialized against this directory and ready to be used by the app.
-
#initialize(configuration, keystore_directory) ⇒ Directory
constructor
Create a new Directory.
-
#inspect ⇒ Object
A representation of the object suitable for printing to the console.
-
#load_session(cookie) ⇒ Object
Unserialize an existing session cookie.
- #local_authority_name ⇒ Object
-
#report_invalid_session(uuid, expired_at) ⇒ Object
Callback used by Session objects to report when the application code calls #invalidate! on them.
-
#trusted_authority?(authority) ⇒ Boolean
Determine whether this system trusts a particular authority based on the trust settings specified in Configuration.
-
#valid_session?(uuid, expired_at) ⇒ Boolean
Determine whether the given session UUID is valid.
Constructor Details
#initialize(configuration, keystore_directory) ⇒ Directory
Create a new Directory.
Parameters
- keystore_directory(String)
Absolute path to authority keystore
Raise
- ConfigurationError
if too many or too few keys are found, or if .key/.pub files are malformatted
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/global_session/directory.rb', line 69 def initialize(configuration, keystore_directory) @configuration = configuration certs = Dir[File.join(keystore_directory, '*.pub')] keys = Dir[File.join(keystore_directory, '*.key')] @authorities = {} certs.each do |cert_file| basename = File.basename(cert_file) = basename[0...(basename.rindex('.'))] #chop trailing .ext @authorities[] = OpenSSL::PKey::RSA.new(File.read(cert_file)) raise ConfigurationError, "Expected #{basename} to contain an RSA public key" unless @authorities[].public? end if key_file = keys.detect { |kf| kf =~ /#{}.key$/ } raise ConfigurationError, "Key file #{}.key not found" unless key_file @private_key = OpenSSL::PKey::RSA.new(File.read(key_file)) raise ConfigurationError, "Expected #{key_file} to contain an RSA private key" unless @private_key.private? end @invalid_sessions = Set.new end |
Instance Attribute Details
#authorities ⇒ Object (readonly)
Returns the value of attribute authorities.
55 56 57 |
# File 'lib/global_session/directory.rb', line 55 def @authorities end |
#configuration ⇒ Object (readonly)
Returns the value of attribute configuration.
55 56 57 |
# File 'lib/global_session/directory.rb', line 55 def configuration @configuration end |
#private_key ⇒ Object (readonly)
Returns the value of attribute private_key.
55 56 57 |
# File 'lib/global_session/directory.rb', line 55 def private_key @private_key end |
Instance Method Details
#create_session(cookie = nil) ⇒ Object
Create a new Session, initialized against this directory and ready to be used by the app.
DEPRECATED: If a cookie is provided, load an existing session from its serialized form. You should use #load_session for this instead.
Parameters
- cookie(String)
DEPRECATED - Optional, serialized global session cookie. If none is supplied, a new session is created.
Return
- session(Session)
the newly-initialized session
===Raise
- InvalidSession
if the session contained in the cookie has been invalidated
- ExpiredSession
if the session contained in the cookie has expired
- MalformedCookie
if the cookie was corrupt or malformed
- SecurityError
if signature is invalid or cookie is not signed by a trusted authority
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/global_session/directory.rb', line 111 def create_session(=nil) forced_version = configuration['cookie']['version'] if .nil? # Create a legitimately new session case forced_version when 3, nil Session::V3.new(self, ) when 2 Session::V2.new(self, ) when 1 Session::V1.new(self, ) else raise ArgumentError, "Unknown value #{forced_version} for configuration.cookie.version" end else warn "GlobalSession::Directory#create_session with an existing session is DEPRECATED -- use #load_session instead" load_session() end end |
#inspect ⇒ Object
Returns a representation of the object suitable for printing to the console.
58 59 60 |
# File 'lib/global_session/directory.rb', line 58 def inspect "<#{self.class.name} @configuration=#{@configuration.inspect}>" end |
#load_session(cookie) ⇒ Object
Unserialize an existing session cookie
Parameters
- cookie(String)
Optional, serialized global session cookie. If none is supplied, a new session is created.
Return
- session(Session)
the newly-initialized session
===Raise
- InvalidSession
if the session contained in the cookie has been invalidated
- ExpiredSession
if the session contained in the cookie has expired
- MalformedCookie
if the cookie was corrupt or malformed
- SecurityError
if signature is invalid or cookie is not signed by a trusted authority
145 146 147 |
# File 'lib/global_session/directory.rb', line 145 def load_session() Session.new(self, ) end |
#local_authority_name ⇒ Object
149 150 151 |
# File 'lib/global_session/directory.rb', line 149 def @configuration['authority'] end |
#report_invalid_session(uuid, expired_at) ⇒ Object
Callback used by Session objects to report when the application code calls #invalidate! on them. The default implementation of this method records invalid session IDs using an in-memory data structure, which is not ideal for most implementations.
- uuid(String)
Global session UUID
- expired_at(Time)
When the session expired
Return
- true
Always returns true
190 191 192 |
# File 'lib/global_session/directory.rb', line 190 def report_invalid_session(uuid, expired_at) @invalid_sessions << uuid end |
#trusted_authority?(authority) ⇒ Boolean
Determine whether this system trusts a particular authority based on the trust settings specified in Configuration.
Parameters
- authority(String)
The name of the authority
Return
- trusted(true|false)
whether the local system trusts sessions signed by the specified authority
161 162 163 |
# File 'lib/global_session/directory.rb', line 161 def () @configuration['trust'].include?() end |
#valid_session?(uuid, expired_at) ⇒ Boolean
Determine whether the given session UUID is valid. The default implementation only considers a session to be invalid if its expired_at timestamp is in the past. Custom implementations might want to consider other factors, such as whether the user has signed out of this node or another node (perhaps using some sort of centralized lookup or single sign-out mechanism).
Parameters
- uuid(String)
Global session UUID
- expired_at(Time)
When the session expired (or will expire)
Return
- valid(true|false)
whether the specified session is valid
176 177 178 |
# File 'lib/global_session/directory.rb', line 176 def valid_session?(uuid, expired_at) (expired_at > Time.now) && !@invalid_sessions.include?(uuid) end |