global_session 3.2.10 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/global_session.gemspec +21 -86
- data/lib/global_session.rb +12 -7
- data/lib/global_session/directory.rb +8 -6
- data/lib/global_session/keystore.rb +28 -6
- data/lib/global_session/rack.rb +1 -1
- data/lib/global_session/session.rb +11 -6
- data/lib/global_session/session/abstract.rb +123 -4
- data/lib/global_session/session/v1.rb +6 -14
- data/lib/global_session/session/v2.rb +9 -17
- data/lib/global_session/session/v3.rb +11 -137
- data/lib/global_session/session/v4.rb +140 -0
- data/lib/global_session/version.rb +3 -0
- metadata +18 -91
- data/.ruby-version +0 -1
- data/.travis.yml +0 -11
- data/CHANGELOG.md +0 -94
- data/LICENSE +0 -20
- data/README.rdoc +0 -298
- data/Rakefile +0 -48
- data/VERSION +0 -1
- data/init.rb +0 -4
- data/rails/init.rb +0 -23
- data/rails_generators/global_session/USAGE +0 -1
- data/rails_generators/global_session/global_session_generator.rb +0 -51
- data/rails_generators/global_session/templates/global_session.yml.erb +0 -41
- data/rails_generators/global_session_authority/USAGE +0 -1
- data/rails_generators/global_session_authority/global_session_authority_generator.rb +0 -53
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: global_session
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Spataro
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -42,22 +42,22 @@ dependencies:
|
|
42
42
|
name: right_support
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "<"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '4.0'
|
48
45
|
- - ">="
|
49
46
|
- !ruby/object:Gem::Version
|
50
|
-
version: 2.
|
47
|
+
version: 2.14.1
|
48
|
+
- - "<"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '3.0'
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
|
-
- - "<"
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
version: '4.0'
|
58
55
|
- - ">="
|
59
56
|
- !ruby/object:Gem::Version
|
60
|
-
version: 2.
|
57
|
+
version: 2.14.1
|
58
|
+
- - "<"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3.0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: simple_uuid
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,82 +72,13 @@ dependencies:
|
|
72
72
|
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: 0.2.0
|
75
|
-
|
76
|
-
|
77
|
-
requirement: !ruby/object:Gem::Requirement
|
78
|
-
requirements:
|
79
|
-
- - "~>"
|
80
|
-
- !ruby/object:Gem::Version
|
81
|
-
version: '0.10'
|
82
|
-
type: :development
|
83
|
-
prerelease: false
|
84
|
-
version_requirements: !ruby/object:Gem::Requirement
|
85
|
-
requirements:
|
86
|
-
- - "~>"
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
version: '0.10'
|
89
|
-
- !ruby/object:Gem::Dependency
|
90
|
-
name: pry
|
91
|
-
requirement: !ruby/object:Gem::Requirement
|
92
|
-
requirements:
|
93
|
-
- - "~>"
|
94
|
-
- !ruby/object:Gem::Version
|
95
|
-
version: '0.10'
|
96
|
-
type: :development
|
97
|
-
prerelease: false
|
98
|
-
version_requirements: !ruby/object:Gem::Requirement
|
99
|
-
requirements:
|
100
|
-
- - "~>"
|
101
|
-
- !ruby/object:Gem::Version
|
102
|
-
version: '0.10'
|
103
|
-
- !ruby/object:Gem::Dependency
|
104
|
-
name: pry-byebug
|
105
|
-
requirement: !ruby/object:Gem::Requirement
|
106
|
-
requirements:
|
107
|
-
- - "~>"
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '2.0'
|
110
|
-
type: :development
|
111
|
-
prerelease: false
|
112
|
-
version_requirements: !ruby/object:Gem::Requirement
|
113
|
-
requirements:
|
114
|
-
- - "~>"
|
115
|
-
- !ruby/object:Gem::Version
|
116
|
-
version: '2.0'
|
117
|
-
- !ruby/object:Gem::Dependency
|
118
|
-
name: jeweler
|
119
|
-
requirement: !ruby/object:Gem::Requirement
|
120
|
-
requirements:
|
121
|
-
- - "~>"
|
122
|
-
- !ruby/object:Gem::Version
|
123
|
-
version: '1.8'
|
124
|
-
type: :development
|
125
|
-
prerelease: false
|
126
|
-
version_requirements: !ruby/object:Gem::Requirement
|
127
|
-
requirements:
|
128
|
-
- - "~>"
|
129
|
-
- !ruby/object:Gem::Version
|
130
|
-
version: '1.8'
|
131
|
-
description: This Rack middleware allows several web apps in an authentication domain
|
132
|
-
to share session state, facilitating single sign-on in a distributed web app. It
|
133
|
-
only provides session sharing and does not concern itself with authentication or
|
134
|
-
replication of the user database.
|
135
|
-
email: support@rightscale.com
|
75
|
+
description: A toolkit of useful, reusable foundation code created by RightScale.
|
76
|
+
email: rubygems@rightscale.com
|
136
77
|
executables: []
|
137
78
|
extensions: []
|
138
|
-
extra_rdoc_files:
|
139
|
-
- LICENSE
|
140
|
-
- README.rdoc
|
79
|
+
extra_rdoc_files: []
|
141
80
|
files:
|
142
|
-
- ".ruby-version"
|
143
|
-
- ".travis.yml"
|
144
|
-
- CHANGELOG.md
|
145
|
-
- LICENSE
|
146
|
-
- README.rdoc
|
147
|
-
- Rakefile
|
148
|
-
- VERSION
|
149
81
|
- global_session.gemspec
|
150
|
-
- init.rb
|
151
82
|
- lib/global_session.rb
|
152
83
|
- lib/global_session/configuration.rb
|
153
84
|
- lib/global_session/directory.rb
|
@@ -162,13 +93,9 @@ files:
|
|
162
93
|
- lib/global_session/session/v1.rb
|
163
94
|
- lib/global_session/session/v2.rb
|
164
95
|
- lib/global_session/session/v3.rb
|
165
|
-
-
|
166
|
-
-
|
167
|
-
|
168
|
-
- rails_generators/global_session/templates/global_session.yml.erb
|
169
|
-
- rails_generators/global_session_authority/USAGE
|
170
|
-
- rails_generators/global_session_authority/global_session_authority_generator.rb
|
171
|
-
homepage: https://github.com/rightscale/global_session
|
96
|
+
- lib/global_session/session/v4.rb
|
97
|
+
- lib/global_session/version.rb
|
98
|
+
homepage: https://github.com/rightscale/right_support
|
172
99
|
licenses:
|
173
100
|
- MIT
|
174
101
|
metadata: {}
|
@@ -180,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
180
107
|
requirements:
|
181
108
|
- - "~>"
|
182
109
|
- !ruby/object:Gem::Version
|
183
|
-
version: '2.
|
110
|
+
version: '2.1'
|
184
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
112
|
requirements:
|
186
113
|
- - ">="
|
@@ -191,5 +118,5 @@ rubyforge_project:
|
|
191
118
|
rubygems_version: 2.2.3
|
192
119
|
signing_key:
|
193
120
|
specification_version: 4
|
194
|
-
summary:
|
121
|
+
summary: Reusable foundation code.
|
195
122
|
test_files: []
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.1.6
|
data/.travis.yml
DELETED
data/CHANGELOG.md
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
3.2.1 (2015-07-10)
|
2
|
-
---------------
|
3
|
-
|
4
|
-
Fixed a bug with automatic cookie renewal; cookies were not being renewed unless
|
5
|
-
the `authority` directive was present in the configuration.
|
6
|
-
|
7
|
-
3.2.0 (2015-07-08)
|
8
|
-
------------------
|
9
|
-
|
10
|
-
If cookie domain is omitted from configuration, the Rack middleware will
|
11
|
-
guess a suitable domain by looking at the HTTP Host header (or `X-Forwarded-Host`
|
12
|
-
if it is present, i.e. the request has passed through a load balancer). The
|
13
|
-
heuristic for HTTP-host-to-cookie-domain is:
|
14
|
-
|
15
|
-
* Numeric IPv4: `127.0.0.1` -> _no_ domain
|
16
|
-
* 1-component: `localhost` -> _no_ domain
|
17
|
-
* 2-component: `example.com` -> `example.com`
|
18
|
-
* N-component: `foo.test.example.com` -> `test.example.com`
|
19
|
-
|
20
|
-
This doesn't handle country-code TLDs (`.co.uk`) so you'll still need to specify
|
21
|
-
the cookie domain for Web sites under a ccTLD.
|
22
|
-
|
23
|
-
The Rack middleware will guess whether to add the `secure` flag to cookies
|
24
|
-
based on `rack.url_scheme` (or `X-Forwarded-Proto` if it is present).
|
25
|
-
|
26
|
-
3.1 (2015-01-27)
|
27
|
-
----------------
|
28
|
-
|
29
|
-
Split Directory class into Directory & Keystore, retaining some backward-compatibility shims
|
30
|
-
inside Directory. In v4, these shims will be removed and all key management concerns will be
|
31
|
-
handled by Keystore; the Directory class will be limited to session creation, renewal, and
|
32
|
-
validity checking.
|
33
|
-
|
34
|
-
The `trust` and `authority` configuration elements have been deprecated, as ha
|
35
|
-
the ability to pass a keystore directory to `Directory.new`. Instead, the
|
36
|
-
configuration should contain a `keystore` that tells the gem where to find its
|
37
|
-
public and private keys; every public key is implicitly trusted, and if some
|
38
|
-
private key is found, the app is an authority (otherwise it's not an authority
|
39
|
-
and sessions are read-only). Example new configuration:
|
40
|
-
|
41
|
-
keystore:
|
42
|
-
public:
|
43
|
-
- config/authorities
|
44
|
-
- config/other_dir_with_keys_i_should_trust
|
45
|
-
private: /etc/my_private.key
|
46
|
-
|
47
|
-
As with any other Global Session configuration, this stanza can appear under
|
48
|
-
`common` or under an enivronment-specific section (`staging`, `production`, etc).
|
49
|
-
|
50
|
-
Finally, you can pass a private key location in the environment variable named
|
51
|
-
`GLOBAL_SESSION_PRIVATE_KEY` instead of including that information in the
|
52
|
-
configuration.
|
53
|
-
|
54
|
-
3.0 (2013-10-03)
|
55
|
-
----------------
|
56
|
-
|
57
|
-
The format of the global session cookie has been reinvented again! It once again uses JSON
|
58
|
-
(because msgpack was not widely supported in other languages/OSes) but retains the compact
|
59
|
-
array encoding introduced in v2.
|
60
|
-
|
61
|
-
The cryptographic signature scheme has been changed for better compatibility; we now use
|
62
|
-
PKCS1 v1.5 sign and verify operations instead of "raw" RSA. v2 and v1 sessions are fully
|
63
|
-
supported for read/write, but any session created with the v3 gem will use the v3 crypto
|
64
|
-
scheme.
|
65
|
-
|
66
|
-
2.0 (2012-11-06)
|
67
|
-
----------------
|
68
|
-
|
69
|
-
The format of the global session cookie has been reinvented; it now uses msgpack and delegates
|
70
|
-
all crypto to RightSupport::Crypto::SignedHash. Together with a few other optimizations, the
|
71
|
-
size of the cookie has shrunk by about 30%.
|
72
|
-
|
73
|
-
The gem remains capable of reading and writing V1 format cookies, but all new cookies are created
|
74
|
-
with the V2 format.
|
75
|
-
|
76
|
-
The "integrated" feature is no longer supported for the Rails integration layer; global session
|
77
|
-
attributes must always be accessed separately from local session attributes, through the
|
78
|
-
#global_session reader method that is mixed into ActionController::Base.
|
79
|
-
|
80
|
-
1.0 (2011-01-01)
|
81
|
-
----------------
|
82
|
-
|
83
|
-
General Availability release. Mostly interface-compatible with 0.9.
|
84
|
-
|
85
|
-
0.9 (2010-12-07)
|
86
|
-
----------------
|
87
|
-
|
88
|
-
Rack middleware implementation is feature-complete and has major spec coverage. Rails integration
|
89
|
-
is untested and may contain bugs.
|
90
|
-
|
91
|
-
0.9.0 (2010-12-22)
|
92
|
-
----------------
|
93
|
-
|
94
|
-
Initial commit ported from 'rack' branch of old has_global_session project
|
data/LICENSE
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
Copyright (c) 2009-2015 RightScale, Inc.
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
a copy of this software and associated documentation files (the
|
5
|
-
'Software'), to deal in the Software without restriction, including
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
9
|
-
the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
included in all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
17
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
18
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
19
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
20
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
DELETED
@@ -1,298 +0,0 @@
|
|
1
|
-
Copyright (c) 2009-2015 RightScale, Inc. <support@rightscale.com>; see LICENSE for more details.
|
2
|
-
|
3
|
-
= Preamble
|
4
|
-
|
5
|
-
<b>WARNING:</b> This RubyGem was authored in 2010 when Rails 2.1 was state of
|
6
|
-
the art. Its Rails integration has not been kept up to date over time; it is
|
7
|
-
untested with Rails 3, 4 and 5, and its generators are broken with Rails above
|
8
|
-
2.3.5.
|
9
|
-
|
10
|
-
We continue to support the Rack middleware and other components of this gem,
|
11
|
-
and recommend using it as a plain old Rack middleware in your Rails apps.
|
12
|
-
Instructions for doing so are provided in this README.
|
13
|
-
|
14
|
-
= Introduction
|
15
|
-
|
16
|
-
GlobalSession enables multiple heterogeneous Web applications to share
|
17
|
-
session state in a cryptographically secure way, facilitating single sign-on
|
18
|
-
and enabling easier development of distributed applications that make use of
|
19
|
-
architectural strategies such as sharding or separation of concerns.
|
20
|
-
|
21
|
-
In other words: it glues your Web apps together by letting them share session state.
|
22
|
-
This is done by putting the session itself into a cookie and adding some crypto to
|
23
|
-
protect against tampering.
|
24
|
-
|
25
|
-
Maintained by
|
26
|
-
- [RightScale Engineering](https://github.com/rightscale)
|
27
|
-
|
28
|
-
Merge to master whitelist
|
29
|
-
- @tony-spataro-rs
|
30
|
-
|
31
|
-
== What Is It Not?
|
32
|
-
|
33
|
-
This gem does not provide a complete solution for identity management. In
|
34
|
-
particular, it does not provide any of the following:
|
35
|
-
|
36
|
-
* <b>federation</b> -- aka cross-domain single sign-on -- use SAML for that.
|
37
|
-
|
38
|
-
* <b>authentication</b> -- the application must authenticate the user.
|
39
|
-
|
40
|
-
* <b>authorization</b> -- the application is responsible for using the contents
|
41
|
-
of the global session to make authorization decisions.
|
42
|
-
|
43
|
-
* <b>secrecy</b> -- global session attributes can be signed but never encrypted.
|
44
|
-
Protect against third-party snooping using SSL. Group secrecy is expensive;
|
45
|
-
if you don't want your users to see their session state, put it in a database,
|
46
|
-
or in an encrypted local session cookie.
|
47
|
-
|
48
|
-
* <b>replication</b> -- the session authorities must have some way to
|
49
|
-
share information about the database of users in order to authenticate
|
50
|
-
them and place identifying information into the global session.
|
51
|
-
|
52
|
-
* <b>single sign-out</b> -- the authorities must have some way to broadcast a
|
53
|
-
notification when sessions are invalidated; they can override the default
|
54
|
-
Directory implementation to do realtime revocation checking.
|
55
|
-
|
56
|
-
= Examples
|
57
|
-
|
58
|
-
== Make a YML configuration file
|
59
|
-
|
60
|
-
The config file format is designed to be self-documenting. The most important
|
61
|
-
data are: what data can be in your global session (`attributes`), what
|
62
|
-
directory contains your `.pub` files with authorities' public keys (`keystore.public`),
|
63
|
-
and the locatio nof `.key` private key file, if any, used by this app (`keystore.private`).
|
64
|
-
|
65
|
-
You can omit `keystore.private` if the app should be able to read, but not
|
66
|
-
write, global sessions.
|
67
|
-
|
68
|
-
If you have asymmetrical trust (e.g. dev trusts production but not vice-versa),
|
69
|
-
you can include an optional `trust` list. By default, every public key file is
|
70
|
-
trusted.
|
71
|
-
|
72
|
-
common:
|
73
|
-
attributes:
|
74
|
-
signed:
|
75
|
-
- user
|
76
|
-
insecure:
|
77
|
-
- favorite_color
|
78
|
-
cookie:
|
79
|
-
name: global_session
|
80
|
-
keystore:
|
81
|
-
public: config/authorities
|
82
|
-
renew: 30
|
83
|
-
timeout: 60
|
84
|
-
development:
|
85
|
-
keystore:
|
86
|
-
private: config/authorities/dev
|
87
|
-
production:
|
88
|
-
trust:
|
89
|
-
- prod
|
90
|
-
keystore:
|
91
|
-
private: config/authorities/prod
|
92
|
-
|
93
|
-
== Make a new keypair for a GlobalSession authority
|
94
|
-
|
95
|
-
Decide on a name for your authority. The name is a short string that identifies
|
96
|
-
a pair of key files on disk (one public, one private) which will be used to
|
97
|
-
sign and verify sessions. If you have mutual trust between every app in your
|
98
|
-
architecture, then you only need one authority and your domain name, e.g.
|
99
|
-
`example-com`, is a fine choice of name. If you want partition trust within your
|
100
|
-
architecture, then authorities could be named after environments
|
101
|
-
(`staging`, `production`), regions (`us`, `eu`) or even specific apps
|
102
|
-
(`frontend`, `api`) depending on where you draw the trust boundaries.
|
103
|
-
|
104
|
-
Figure out where key files live in your application. This is whatever value
|
105
|
-
you set in the `keystore: public: ...` directive in the configuration.
|
106
|
-
|
107
|
-
If you have complete, mutual trust between all components of your architecture,
|
108
|
-
then something based on your organization's domain name (e.g. `example-com`)
|
109
|
-
is a fine choice.
|
110
|
-
|
111
|
-
Open irb or your console of choice and require the `global_session` gem.
|
112
|
-
|
113
|
-
# default is RSA cryptosystem with 1024-bit keys.
|
114
|
-
keypair = GlobalSession::Keystore.create_keypair(:RSA, 1024)
|
115
|
-
public_pem = keypair.public_key.to_pem
|
116
|
-
private_pem = keypair.to_pem
|
117
|
-
|
118
|
-
# write keys to disk
|
119
|
-
File.open('config/authorities/example-com.pub', 'w') { |f| f.write public_pem }
|
120
|
-
File.open('config/authorities/example-com.key', 'w') { |f| f.write private_pem }
|
121
|
-
|
122
|
-
== Integration with Rails
|
123
|
-
|
124
|
-
Install the GlobalSession middleware in your application startup. Open
|
125
|
-
`environment.rb` or `application.rb` (depending on your Rails version) and
|
126
|
-
add a new file to `config/initializers` to configure and install the
|
127
|
-
middleware:
|
128
|
-
|
129
|
-
configuration = GlobalSession::Configuration.new('config/global_session.yml', Rails.env)
|
130
|
-
directory = GlobalSession::Directory.new(configuration)
|
131
|
-
|
132
|
-
== Integration with Rack
|
133
|
-
|
134
|
-
Install the GlobalSession middleware into your Rack stack; pass a config and a directory
|
135
|
-
object to its initializer. For instance, in config.ru:
|
136
|
-
|
137
|
-
configuration = GlobalSession::Configuration.new('path/to/config.yml', RACK_ENV)
|
138
|
-
directory = GlobalSession::Directory.new(configuration)
|
139
|
-
use ::GlobalSession::Rack::Middleware, configuration, directory
|
140
|
-
|
141
|
-
Application.config.middleware.insert_before(Application.config.session_store, ::Rack::Cookies)
|
142
|
-
Application.config.middleware.insert_before(Application.config.session_store, ::Rack::GlobalSession, configuration, directory)
|
143
|
-
|
144
|
-
Note that the GlobalSession middleware depends on `Rack::Cookies`; be sure
|
145
|
-
to install them both, and in the proper order.
|
146
|
-
|
147
|
-
= Global Session Contents
|
148
|
-
|
149
|
-
Global session state is stored as a cookie in the user's browser and/or sent
|
150
|
-
with every request as an HTTP Authorization header. If your app uses the
|
151
|
-
Authorization header, then it's responsible for communicating new or changed
|
152
|
-
header values to clients out-of-band (i.e. as part of an OAuth refresh-token
|
153
|
-
operation). If your app uses the cookie, GlobalSession will take care of
|
154
|
-
updating the cookie whenever session values change.
|
155
|
-
|
156
|
-
Data-wise, the session is a JSON dictionary containing the following stuff:
|
157
|
-
* session metadata (UUID, created at, expires at, signing authority)
|
158
|
-
* signed session attributes (e.g. the authenticated user ID)
|
159
|
-
* insecure session attributes (e.g. the last-visited URL)
|
160
|
-
* a cryptographic signature of the metadata and signed attributes
|
161
|
-
|
162
|
-
The global session is unserialized and its signature is verified whenever
|
163
|
-
Rack receives a request. The cookie's value is updated whenever attributes
|
164
|
-
change. As an optimization, the signature is only recomputed when the metadata
|
165
|
-
or signed attributes have changed; insecure attributes can change "for free."
|
166
|
-
|
167
|
-
Because the security properties of attributes can vary, GlobalSession
|
168
|
-
requires all _possible_ attributes to be declared up-front in the config
|
169
|
-
file. The 'attributes' section of the config file defines the _schema_
|
170
|
-
for the global session: which attributes can be used, which can be trusted
|
171
|
-
to make authorization decisions (because they are signed), and which are
|
172
|
-
insecure and act only as "hints" about the session.
|
173
|
-
|
174
|
-
Since the session is serialized as JSON, only a limited range of object
|
175
|
-
types can be stored in it: nil, strings, numbers, lists, hashes, booleans
|
176
|
-
and other Ruby primitives.
|
177
|
-
|
178
|
-
= Detailed Information
|
179
|
-
|
180
|
-
== Global Session Domain
|
181
|
-
|
182
|
-
We refer to collection of _all_ Web application instances capable of using the
|
183
|
-
global session as the "domain." The global session domain may consist of any
|
184
|
-
number of distinct nodes, possibly hidden behind load balancers or proxies.
|
185
|
-
The nodes within the domain may all be running the same Rails application,
|
186
|
-
or they may be running different codebases that represent different parts of
|
187
|
-
a distributed application. (They may also be using app frameworks other than
|
188
|
-
Rails.)
|
189
|
-
|
190
|
-
The only constraint imposed by GlobalSession is that all nodes within the
|
191
|
-
domain must have end-user-facing URLs within the same second-level DNS domain.
|
192
|
-
This is due to limitations imposed by the HTTP cookie mechanism: for privacy
|
193
|
-
reasons, cookies will only be sent to nodes within the same domain as the
|
194
|
-
node that first created them.
|
195
|
-
|
196
|
-
For example, in my GlobalSession configuration file I might specify that my
|
197
|
-
cookie's domain is "example.com". My app nodes at app1.example.com and
|
198
|
-
app2.example.com would be part of the global session domain, but my business
|
199
|
-
partner's application at app3.partner.com could not participate.
|
200
|
-
|
201
|
-
If your app uses an Authorization header instead of cookies, the domain-name
|
202
|
-
constraint does not apply!
|
203
|
-
|
204
|
-
== Authorities and Relying Parties
|
205
|
-
|
206
|
-
A node that can create or update the global session is said to be an "authority"
|
207
|
-
(because it's trusted by other parties to make assertions about global session
|
208
|
-
state). An application that can read the global session is said to be a "relying
|
209
|
-
party." In practice, every application is a relying party, but not all of them
|
210
|
-
need to be authorities.
|
211
|
-
|
212
|
-
There is an RSA key pair associated with each authority. The authority's
|
213
|
-
public key is distribued to all relying parties, but the private key must
|
214
|
-
remain a secret to that authority (which may consist of many individual
|
215
|
-
nodes).
|
216
|
-
|
217
|
-
This system allows for significant flexibility when configuring a distributed
|
218
|
-
app's global session. There must be at least one authority, but for many apps
|
219
|
-
one authority (plus an arbitrary number of relying parties, which do not need
|
220
|
-
a key pair) will be sufficient.
|
221
|
-
|
222
|
-
In general, two systems should be part of the same authority if there is no
|
223
|
-
trust boundary between them -- that is to say, trust between the two systems
|
224
|
-
is unlimited in both directions.
|
225
|
-
|
226
|
-
Here are some reasons you might consider dividing your systems into different
|
227
|
-
authorities:
|
228
|
-
* beta/staging system vs. production system
|
229
|
-
* system hosted by a third party vs. system hosted internally
|
230
|
-
* e-commerce app vs. storefront app vs. admin app
|
231
|
-
|
232
|
-
== The Keystore
|
233
|
-
|
234
|
-
The Directory is a Ruby object that provides lookups of public and private
|
235
|
-
keys. Given an authority name (as found in a session cookie), the Directory
|
236
|
-
can find the corresponding RSA public key.
|
237
|
-
|
238
|
-
If the local system is an authority itself, #private_key_name will
|
239
|
-
return the authority name and #private_key will return an RSA private key
|
240
|
-
suitable for signing session attributes.
|
241
|
-
|
242
|
-
The Keystore implementation included with GlobalSession uses the filesystem
|
243
|
-
as the backing store for its key pairs. Its #initialize method accepts a
|
244
|
-
filesystem path that will be searched for files containing PEM-encoded public
|
245
|
-
and private keys (the same format used by OpenSSH). This simple Directory
|
246
|
-
implementation relies on the following conventions:
|
247
|
-
* Public keys have a *.pub extension.
|
248
|
-
* Private keys have a *.key extension.
|
249
|
-
* If a node is an authority, then one (and *only* one) *.key file should exist.
|
250
|
-
* The local node's authority name is inferred from the name of the private key
|
251
|
-
file.
|
252
|
-
|
253
|
-
When used with a Rails app, GlobalSession expects to find its keystore in
|
254
|
-
config/authorities. You can use the global_session generator to create new key
|
255
|
-
pairs. Remember never to check a *.key file into a public repository!! (*.pub
|
256
|
-
files can be checked into source control and distributed freely.)
|
257
|
-
|
258
|
-
If you wish all of the systems to stop trusting an authority, simply delete
|
259
|
-
its public key from config/authorities and re-deploy your app.
|
260
|
-
|
261
|
-
The keystore needs to be told where to find its keys. This is accomplished by
|
262
|
-
setting some configuration attributes like so:
|
263
|
-
|
264
|
-
keystore:
|
265
|
-
public:
|
266
|
-
- config/authorities
|
267
|
-
- config/more_authorities
|
268
|
-
private: config/authorities/my_private.key
|
269
|
-
|
270
|
-
The filename of keys is relevant; after stripping the *.pub or *.key extension,
|
271
|
-
the remainder of the file's basename is taken to be the authority name. For
|
272
|
-
instance, "production.pub" is the public key of the authority named "production"
|
273
|
-
and "development.key" is the private key of the authority named "development."
|
274
|
-
|
275
|
-
== The Directory
|
276
|
-
|
277
|
-
The Directory is a Ruby object that performs session management operations,
|
278
|
-
including:
|
279
|
-
* Checking whether sessions have become invalid (e.g. after sign-out)
|
280
|
-
* Creating new sessions
|
281
|
-
* Unserializing existing sessions
|
282
|
-
* Renewing sessions if they will expire
|
283
|
-
* Updating session signatures
|
284
|
-
|
285
|
-
In GlobalSession v3, Directory also presents methods for key management, but
|
286
|
-
these are all delegated to the Keystore class. In v4, the concerns of Directory
|
287
|
-
and Keystore will be fully separated.
|
288
|
-
|
289
|
-
=== Implementing Your Own Directory Provider
|
290
|
-
|
291
|
-
To replace or enhance the built-in Directory, simply create a new class that
|
292
|
-
extends Directory and put the class somewhere in your app (the lib directory
|
293
|
-
is a good choice). In the GlobalSession configuration file, specify the
|
294
|
-
class name of the directory under the 'common' section, like so:
|
295
|
-
|
296
|
-
common:
|
297
|
-
directory:
|
298
|
-
class: MyCoolDirectory
|