global_session 3.0.5 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b314fdf883f6db5a94056c8f4425b645ce26ce26
4
+ data.tar.gz: f2598c6bc89cf364070919a0d7d4704660721664
5
+ SHA512:
6
+ metadata.gz: cce6b5236c84c60d94df3342a78c2f63bb5289c9d8c31c089983d1e3eb7905b83f5aa5e50f444061d3bd320745411a564db932153c71d04f7a40e2afecad3032
7
+ data.tar.gz: d2e8e7feb7641b439ff2e44f3e145c6f7f1f131ece9044c5edcc662c3a73a49ba590b7de1a623c751808c35dad02ffe18d06a251e7a5c18520e0d0b3fb849056
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 1.8.7
5
+ - 2.1
6
+ script:
7
+ - bundle exec rake ci:spec
8
+ bundler_args: --without development
data/CHANGELOG.rdoc CHANGED
@@ -1,4 +1,22 @@
1
- == 2.0
1
+ == 3.1 (2015-01-27)
2
+
3
+ Split Directory class into Directory & Keystore, retaining some backward-compatibility shims
4
+ inside Directory. In v4, these shims will be removed and all key management concerns will be
5
+ handled by Keystore; the Directory class will be limited to session creation, renewal, and
6
+ validity checking.
7
+
8
+ == 3.0 (2013-10-03)
9
+
10
+ The format of the global session cookie has been reinvented again! It once again uses JSON
11
+ (because msgpack was not widely supported in other languages/OSes) but retains the compact
12
+ array encoding introduced in v2.
13
+
14
+ The cryptographic signature scheme has been changed for better compatibility; we now use
15
+ PKCS1 v1.5 sign and verify operations instead of "raw" RSA. v2 and v1 sessions are fully
16
+ supported for read/write, but any session created with the v3 gem will use the v3 crypto
17
+ scheme.
18
+
19
+ == 2.0 (2012-11-06)
2
20
 
3
21
  The format of the global session cookie has been reinvented; it now uses msgpack and delegates
4
22
  all crypto to RightSupport::Crypto::SignedHash. Together with a few other optimizations, the
@@ -11,16 +29,15 @@ The "integrated" feature is no longer supported for the Rails integration layer;
11
29
  attributes must always be accessed separately from local session attributes, through the
12
30
  #global_session reader method that is mixed into ActionController::Base.
13
31
 
14
- == 1.0
32
+ == 1.0 (2011-01-01)
15
33
 
16
- Mostly interface-compatible with 0.9.
34
+ General Availability release. Mostly interface-compatible with 0.9.
17
35
 
18
- == 0.9
36
+ == 0.9 (2010-12-07)
19
37
 
20
38
  Rack middleware implementation is feature-complete and has major spec coverage. Rails integration
21
39
  is untested and may contain bugs.
22
40
 
23
41
  === 0.9.0 (2010-12-22)
24
42
 
25
- * Initial commit ported from 'rack' branch of old has_global_session project
26
-
43
+ Initial commit ported from 'rack' branch of old has_global_session project
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009-2012 RightScale, Inc.
1
+ Copyright (c) 2009-2015 RightScale, Inc.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.rdoc CHANGED
@@ -1,39 +1,40 @@
1
+ Copyright (c) 2009-2015 RightScale, Inc. <support@rightscale.com>; see LICENSE for more details.
2
+
1
3
  = Introduction
2
4
 
3
5
  GlobalSession enables multiple heterogeneous Web applications to share
4
6
  session state in a cryptographically secure way, facilitating single sign-on
5
- and enabling easier development of distributed applications that
6
- make use of architectural strategies such as sharding or separation of concerns.
7
+ and enabling easier development of distributed applications that make use of
8
+ architectural strategies such as sharding or separation of concerns.
7
9
 
8
- In other words: it glues your semi-related Web apps together so they share the
9
- same bits of session state. This is done by putting the session itself into
10
- cookies.
10
+ In other words: it glues your Web apps together by letting them share session state.
11
+ This is done by putting the session itself into a cookie and adding some crypto to
12
+ protect against tampering.
11
13
 
12
14
  Maintained by
13
- - [Sapphire Team](https://wookiee.rightscale.com/display/rightscale/Meet+the+Sapphire+Team)
15
+ - [RightScale Engineering](https://github.com/rightscale)
14
16
 
15
17
  Merge to master whitelist
16
18
  - @tony-spataro-rs
17
- - @ryanwilliamson
18
19
 
19
20
  == What Is It Not?
20
21
 
21
- This plugin does not provide a complete solution for identity management. In
22
+ This gem does not provide a complete solution for identity management. In
22
23
  particular, it does not provide any of the following:
23
24
 
24
- * <b>federation</b> -- aka cross-domain single sign-on -- use OpenID for that.
25
+ * <b>federation</b> -- aka cross-domain single sign-on -- use SAML for that.
25
26
 
26
27
  * <b>authentication</b> -- the application must authenticate the user.
27
28
 
28
29
  * <b>authorization</b> -- the application is responsible for using the contents
29
30
  of the global session to make authorization decisions.
30
31
 
31
- * <b>secrecy</b> -- global session attributes can be signed but never encrypted;
32
- protect against third-party snooping using SSL. Group secrecy is expensive;
32
+ * <b>secrecy</b> -- global session attributes can be signed but never encrypted.
33
+ Protect against third-party snooping using SSL. Group secrecy is expensive;
33
34
  if you don't want your users to see their session state, put it in a database,
34
35
  or in an encrypted local session cookie.
35
36
 
36
- * <b>replication</b> -- the authentication authorities must have some way to
37
+ * <b>replication</b> -- the session authorities must have some way to
37
38
  share information about the database of users in order to authenticate
38
39
  them and place identifying information into the global session.
39
40
 
@@ -41,7 +42,9 @@ particular, it does not provide any of the following:
41
42
  notification when sessions are invalidated; they can override the default
42
43
  Directory implementation to do realtime revocation checking.
43
44
 
44
- = Example
45
+ = Examples
46
+
47
+ == Integration with Rails
45
48
 
46
49
  1) Create a basic config file and edit it to suit your needs:
47
50
  $ script/generate global_session_config mycoolapp.com
@@ -59,32 +62,45 @@ particular, it does not provide any of the following:
59
62
  ...
60
63
  @current_user = User.find(global_session['user'])
61
64
 
65
+ == Integration with Other Ruby Web Frameworks
66
+
67
+ Install the GlobalSession middleware into your Rack stack; pass a config and a directory
68
+ object to its initializer. For instance, in config.ru:
69
+
70
+ configuration = GlobalSession::Configuration.new('path/to/config.yml', RACK_ENV)
71
+ directory = GlobalSession::Directory.new(configuration, 'path/to/keystore')
72
+ use ::GlobalSession::Rack::Middleware, configuration, directory
73
+
62
74
  = Global Session Contents
63
75
 
64
- Global session state is stored as a cookie in the user's browser. The cookie
65
- is a Zlib-compressed JSON dictionary containing the following stuff:
76
+ Global session state is stored as a cookie in the user's browser and/or sent
77
+ with every request as an HTTP Authorization header. If your app uses the
78
+ Authorization header, then it's responsible for communicating new or changed
79
+ header values to clients out-of-band (i.e. as part of an OAuth refresh-token
80
+ operation). If your app uses the cookie, GlobalSession will take care of
81
+ updating the cookie whenever session values change.
82
+
83
+ Data-wise, the session is a JSON dictionary containing the following stuff:
66
84
  * session metadata (UUID, created-at, expires-at, signing-authority)
67
85
  * signed session attributes (e.g. the authenticated user ID)
68
86
  * insecure session attributes (e.g. the last-visited URL)
69
87
  * a cryptographic signature of the metadata and signed attributes
70
88
 
71
89
  The global session is unserialized and its signature is verified whenever
72
- a controller asks for one of its attributes. The cookie's value is updated
73
- whenever attributes change. As an optimization, the signature is only
74
- recomputed when the metadata or signed attributes have changed; insecure
75
- attributes can change "for free."
90
+ Rack receives a request. The cookie's value is updated whenever attributes
91
+ change. As an optimization, the signature is only recomputed when the metadata
92
+ or signed attributes have changed; insecure attributes can change "for free."
76
93
 
77
94
  Because the security properties of attributes can vary, GlobalSession
78
95
  requires all _possible_ attributes to be declared up-front in the config
79
96
  file. The 'attributes' section of the config file defines the _schema_
80
97
  for the global session: which attributes can be used, which can be trusted
81
- to make authorization decisions (because they are signed), and are insecure
82
- and therefore act only as "hints" about the session.
98
+ to make authorization decisions (because they are signed), and which are
99
+ insecure and act only as "hints" about the session.
83
100
 
84
101
  Since the session is serialized as JSON, only a limited range of object
85
- types can be stored in it: strings, numbers, lists, hashes and other Ruby
86
- primitives. Ruby booleans (true/false) do not translate well into JSON
87
- and should be avoided.
102
+ types can be stored in it: nil, strings, numbers, lists, hashes, booleans
103
+ and other Ruby primitives.
88
104
 
89
105
  = Detailed Information
90
106
 
@@ -109,6 +125,9 @@ cookie's domain is "example.com". My app nodes at app1.example.com and
109
125
  app2.example.com would be part of the global session domain, but my business
110
126
  partner's application at app3.partner.com could not participate.
111
127
 
128
+ If your app uses an Authorization header instead of cookies, the domain-name
129
+ constraint does not apply!
130
+
112
131
  == Authorities and Relying Parties
113
132
 
114
133
  A node that can create or update the global session is said to be an "authority"
@@ -135,19 +154,19 @@ Here are some reasons you might consider dividing your systems into different
135
154
  authorities:
136
155
  * beta/staging system vs. production system
137
156
  * system hosted by a third party vs. system hosted internally
138
- * e-commerce node vs. storefront node vs. admin node
157
+ * e-commerce app vs. storefront app vs. admin app
139
158
 
140
- == The Directory
159
+ == The Keystore
141
160
 
142
- The Directory is a Ruby object instantiated by GlobalSession in order to
143
- perform lookups of public and private keys. Given an authority name (as found
144
- in a session cookie), the Directory can find the corresponding public key.
161
+ The Directory is a Ruby object that provides lookups of public and private
162
+ keys. Given an authority name (as found in a session cookie), the Directory
163
+ can find the corresponding RSA public key.
145
164
 
146
- If the local system is an authority itself, #local_authority_name will
147
- return non-nil and #private_key will return a private key suitable for
148
- signing session attributes.
165
+ If the local system is an authority itself, #private_key_name will
166
+ return the authority name and #private_key will return an RSA private key
167
+ suitable for signing session attributes.
149
168
 
150
- The Directory implementation included with GlobalSession uses the filesystem
169
+ The Keystore implementation included with GlobalSession uses the filesystem
151
170
  as the backing store for its key pairs. Its #initialize method accepts a
152
171
  filesystem path that will be searched for files containing PEM-encoded public
153
172
  and private keys (the same format used by OpenSSH). This simple Directory
@@ -161,11 +180,39 @@ implementation relies on the following conventions:
161
180
  When used with a Rails app, GlobalSession expects to find its keystore in
162
181
  config/authorities. You can use the global_session generator to create new key
163
182
  pairs. Remember never to check a *.key file into a public repository!! (*.pub
164
- files can be checked into source control and distributed freely.)
183
+ files can be checked into source control and distributed freely.)
165
184
 
166
185
  If you wish all of the systems to stop trusting an authority, simply delete
167
186
  its public key from config/authorities and re-deploy your app.
168
187
 
188
+ The keystore needs to be told where to find its keys. This is accomplished by
189
+ setting some configuration attributes like so:
190
+
191
+ keystore:
192
+ public:
193
+ - config/authorities
194
+ - config/more_authorities
195
+ private: config/authorities/my_private.key
196
+
197
+ The filename of keys is relevant; after stripping the *.pub or *.key extension,
198
+ the remainder of the file's basename is taken to be the authority name. For
199
+ instance, "production.pub" is the public key of the authority named "production"
200
+ and "development.key" is the private key of the authority named "development."
201
+
202
+ == The Directory
203
+
204
+ The Directory is a Ruby object that performs session management operations,
205
+ including:
206
+ * Checking whether sessions have become invalid (e.g. after sign-out)
207
+ * Creating new sessions
208
+ * Unserializing existing sessions
209
+ * Renewing sessions if they will expire
210
+ * Updating session signatures
211
+
212
+ In GlobalSession v3, Directory also presents methods for key management, but
213
+ these are all delegated to the Keystore class. In v4, the concerns of Directory
214
+ and Keystore will be fully separated.
215
+
169
216
  === Implementing Your Own Directory Provider
170
217
 
171
218
  To replace or enhance the built-in Directory, simply create a new class that
@@ -173,7 +220,6 @@ extends Directory and put the class somewhere in your app (the lib directory
173
220
  is a good choice). In the GlobalSession configuration file, specify the
174
221
  class name of the directory under the 'common' section, like so:
175
222
 
176
- common:
177
- directory: MyCoolDirectory
178
-
179
- Copyright (c) 2010 Tony Spataro <code@tracker.xeger.net>, released under the MIT license
223
+ common:
224
+ directory:
225
+ class: MyCoolDirectory
data/Rakefile CHANGED
@@ -2,6 +2,7 @@
2
2
  require 'rubygems'
3
3
  require 'rake'
4
4
  require 'right_develop'
5
+ require 'right_support'
5
6
  require 'spec/rake/spectask'
6
7
  require 'rubygems/package_task'
7
8
  require 'rake/clean'
@@ -17,28 +18,29 @@ Spec::Rake::SpecTask.new do |t|
17
18
  end
18
19
  end
19
20
 
20
- desc "run functional tests"
21
+ desc "Run functional tests"
21
22
  Cucumber::Rake::Task.new do |t|
22
23
  t.cucumber_opts = %w{--tags ~@slow --color --format pretty}
23
24
  end
24
25
 
25
- require 'jeweler'
26
- Jeweler::Tasks.new do |gem|
27
- # gem is a Gem::Specification; see http://docs.rubygems.org/read/chapter/20 for more options
28
- gem.name = "global_session"
29
- gem.homepage = "https://github.com/rightscale/global_session"
30
- gem.license = "MIT"
31
- gem.summary = %Q{Secure single-domain session sharing plugin for Rack and Rails.}
32
- gem.description = %Q{This Rack middleware allows several web apps in an authentication domain to share session state, facilitating single sign-on in a distributed web app. It only provides session sharing and does not concern itself with authentication or replication of the user database.}
33
- gem.email = "support@rightscale.com"
34
- gem.authors = ['Tony Spataro']
35
- gem.files.exclude 'Gemfile*'
36
- gem.files.exclude 'features/**/*'
37
- gem.files.exclude 'fixtures/**/*'
38
- gem.files.exclude 'features/**/*'
39
- gem.files.exclude 'spec/**/*'
26
+ if require_succeeds? 'jeweler'
27
+ Jeweler::Tasks.new do |gem|
28
+ # gem is a Gem::Specification; see http://docs.rubygems.org/read/chapter/20 for more options
29
+ gem.name = "global_session"
30
+ gem.homepage = "https://github.com/rightscale/global_session"
31
+ gem.license = "MIT"
32
+ gem.summary = %Q{Secure single-domain session sharing plugin for Rack and Rails.}
33
+ gem.description = %Q{This Rack middleware allows several web apps in an authentication domain to share session state, facilitating single sign-on in a distributed web app. It only provides session sharing and does not concern itself with authentication or replication of the user database.}
34
+ gem.email = "support@rightscale.com"
35
+ gem.authors = ['Tony Spataro']
36
+ gem.files.exclude 'Gemfile*'
37
+ gem.files.exclude 'features/**/*'
38
+ gem.files.exclude 'fixtures/**/*'
39
+ gem.files.exclude 'features/**/*'
40
+ gem.files.exclude 'spec/**/*'
41
+ end
42
+ Jeweler::RubygemsDotOrgTasks.new
40
43
  end
41
- Jeweler::RubygemsDotOrgTasks.new
42
44
 
43
45
  CLEAN.include('pkg')
44
46
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.0.5
1
+ 3.1.0
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: global_session 3.0.5 ruby lib
5
+ # stub: global_session 3.1.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "global_session"
9
- s.version = "3.0.5"
9
+ s.version = "3.1.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Tony Spataro"]
14
- s.date = "2014-11-12"
14
+ s.date = "2014-12-31"
15
15
  s.description = "This Rack middleware allows several web apps in an authentication domain to share session state, facilitating single sign-on in a distributed web app. It only provides session sharing and does not concern itself with authentication or replication of the user database."
16
16
  s.email = "support@rightscale.com"
17
17
  s.extra_rdoc_files = [
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19
19
  "README.rdoc"
20
20
  ]
21
21
  s.files = [
22
+ ".travis.yml",
22
23
  "CHANGELOG.rdoc",
23
24
  "LICENSE",
24
25
  "README.rdoc",
@@ -30,6 +31,7 @@ Gem::Specification.new do |s|
30
31
  "lib/global_session/configuration.rb",
31
32
  "lib/global_session/directory.rb",
32
33
  "lib/global_session/encoding.rb",
34
+ "lib/global_session/keystore.rb",
33
35
  "lib/global_session/rack.rb",
34
36
  "lib/global_session/rails.rb",
35
37
  "lib/global_session/rails/action_controller_class_methods.rb",
@@ -48,7 +50,7 @@ Gem::Specification.new do |s|
48
50
  ]
49
51
  s.homepage = "https://github.com/rightscale/global_session"
50
52
  s.licenses = ["MIT"]
51
- s.rubygems_version = "2.2.0"
53
+ s.rubygems_version = "2.2.2"
52
54
  s.summary = "Secure single-domain session sharing plugin for Rack and Rails."
53
55
 
54
56
  if s.respond_to? :specification_version then
@@ -57,49 +59,31 @@ Gem::Specification.new do |s|
57
59
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
60
  s.add_runtime_dependency(%q<json>, ["~> 1.4"])
59
61
  s.add_runtime_dependency(%q<rack-contrib>, ["~> 1.0"])
60
- s.add_runtime_dependency(%q<right_support>, ["< 3.0", ">= 2.8.2"])
62
+ s.add_runtime_dependency(%q<right_support>, ["< 4.0", ">= 2.8.2"])
61
63
  s.add_runtime_dependency(%q<simple_uuid>, [">= 0.2.0"])
62
- s.add_development_dependency(%q<cucumber>, ["~> 1.0"])
63
- s.add_development_dependency(%q<debugger>, ["~> 1.5"])
64
- s.add_development_dependency(%q<flexmock>, ["~> 0.8"])
65
- s.add_development_dependency(%q<httpclient>, [">= 0"])
66
- s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
67
- s.add_development_dependency(%q<msgpack>, ["~> 0.4"])
68
- s.add_development_dependency(%q<rake>, ["~> 0.8"])
69
- s.add_development_dependency(%q<right_develop>, ["~> 1.2"])
70
- s.add_development_dependency(%q<rspec>, ["~> 1.3"])
71
64
  s.add_development_dependency(%q<ruby-debug>, ["~> 0.10"])
65
+ s.add_development_dependency(%q<pry>, ["~> 0.10"])
66
+ s.add_development_dependency(%q<pry-byebug>, ["~> 2.0"])
67
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
72
68
  else
73
69
  s.add_dependency(%q<json>, ["~> 1.4"])
74
70
  s.add_dependency(%q<rack-contrib>, ["~> 1.0"])
75
- s.add_dependency(%q<right_support>, ["< 3.0", ">= 2.8.2"])
71
+ s.add_dependency(%q<right_support>, ["< 4.0", ">= 2.8.2"])
76
72
  s.add_dependency(%q<simple_uuid>, [">= 0.2.0"])
77
- s.add_dependency(%q<cucumber>, ["~> 1.0"])
78
- s.add_dependency(%q<debugger>, ["~> 1.5"])
79
- s.add_dependency(%q<flexmock>, ["~> 0.8"])
80
- s.add_dependency(%q<httpclient>, [">= 0"])
81
- s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
82
- s.add_dependency(%q<msgpack>, ["~> 0.4"])
83
- s.add_dependency(%q<rake>, ["~> 0.8"])
84
- s.add_dependency(%q<right_develop>, ["~> 1.2"])
85
- s.add_dependency(%q<rspec>, ["~> 1.3"])
86
73
  s.add_dependency(%q<ruby-debug>, ["~> 0.10"])
74
+ s.add_dependency(%q<pry>, ["~> 0.10"])
75
+ s.add_dependency(%q<pry-byebug>, ["~> 2.0"])
76
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
87
77
  end
88
78
  else
89
79
  s.add_dependency(%q<json>, ["~> 1.4"])
90
80
  s.add_dependency(%q<rack-contrib>, ["~> 1.0"])
91
- s.add_dependency(%q<right_support>, ["< 3.0", ">= 2.8.2"])
81
+ s.add_dependency(%q<right_support>, ["< 4.0", ">= 2.8.2"])
92
82
  s.add_dependency(%q<simple_uuid>, [">= 0.2.0"])
93
- s.add_dependency(%q<cucumber>, ["~> 1.0"])
94
- s.add_dependency(%q<debugger>, ["~> 1.5"])
95
- s.add_dependency(%q<flexmock>, ["~> 0.8"])
96
- s.add_dependency(%q<httpclient>, [">= 0"])
97
- s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
98
- s.add_dependency(%q<msgpack>, ["~> 0.4"])
99
- s.add_dependency(%q<rake>, ["~> 0.8"])
100
- s.add_dependency(%q<right_develop>, ["~> 1.2"])
101
- s.add_dependency(%q<rspec>, ["~> 1.3"])
102
83
  s.add_dependency(%q<ruby-debug>, ["~> 0.10"])
84
+ s.add_dependency(%q<pry>, ["~> 0.10"])
85
+ s.add_dependency(%q<pry-byebug>, ["~> 2.0"])
86
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
103
87
  end
104
88
  end
105
89
 
@@ -87,6 +87,7 @@ require 'openssl'
87
87
 
88
88
  #Require the core suite of GlobalSession classes and modules
89
89
  require 'global_session/configuration'
90
+ require 'global_session/keystore'
90
91
  require 'global_session/directory'
91
92
  require 'global_session/encoding'
92
93
  require 'global_session/session'