rack-ssl-enforcer 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Tobias Matthies
1
+ Copyright (c) 2009-2012 Tobias Matthies
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
@@ -0,0 +1,220 @@
1
+ # Rack::SslEnforcer [![Build Status](https://secure.travis-ci.org/tobmatth/rack-ssl-enforcer.png?branch=master)](http://travis-ci.org/tobmatth/rack-ssl-enforcer)
2
+
3
+ Rack::SslEnforcer is a simple Rack middleware to enforce SSL connections. As of Version 0.2.0, Rack::SslEnforcer marks
4
+ Cookies as secure by default (HSTS must be set manually).
5
+
6
+ Tested against Ruby 1.8.7, 1.9.2, 1.9.3, ruby-head, REE and the latest versions of Rubinius & JRuby.
7
+
8
+ ## Installation
9
+
10
+ The simplest way to install Rack::SslEnforcer is to use [Bundler](http://gembundler.com/).
11
+
12
+ Add Rack::SslEnforcer to your `Gemfile`:
13
+
14
+ ```ruby
15
+ gem 'rack-ssl-enforcer'
16
+ ```
17
+
18
+ ### Installing on Sinatra / Padrino application
19
+
20
+ In order for Rack::SslEnforcer to properly work it has to be at the top
21
+ of the Rack Middleware.
22
+
23
+ Using `enable :session` will place Rack::Session::Cookie before Rack::Ssl::Enforcer
24
+ and will prevent Rack::Ssl::Enforcer from marking cookies as secure.
25
+
26
+ To fix this issue do not use `enable :sessions` instead add the
27
+ Rack::Session::Cookie middleware after Rack::Ssl::Enforcer.
28
+
29
+ Eg:
30
+
31
+ use Rack::SslEnforcer
32
+ set :session_secret, 'asdfa2342923422f1adc05c837fa234230e3594b93824b00e930ab0fb94b'
33
+
34
+ #Enable sinatra sessions
35
+ use Rack::Session::Cookie, :key => '_rack_session',
36
+ :path => '/',
37
+ :expire_after => 2592000, # In seconds
38
+ :secret => session_secret
39
+
40
+
41
+ ## Basic Usage
42
+
43
+ If you don't use Bundler, be sure to require Rack::SslEnforcer manually before actually using the middleware:
44
+
45
+ ```ruby
46
+ require 'rack/ssl-enforcer'
47
+ use Rack::SslEnforcer
48
+ ```
49
+
50
+ To use Rack::SslEnforcer in your Rails application, add the following line to your application config file (`config/application.rb` for Rails 3, `config/environment.rb` for Rails 2):
51
+
52
+ ```ruby
53
+ config.middleware.use Rack::SslEnforcer
54
+ ```
55
+
56
+ If all you want is SSL for your whole application, you are done! Otherwise, you can specify some options described below.
57
+
58
+ ## Options
59
+
60
+ ### Host constraints
61
+
62
+ You can enforce SSL connections only for certain hosts with `:only_hosts`, or prevent certain hosts from being forced to SSL with `:except_hosts`. Constraints can be a `String`, a `Regex` or an array of `String` or `Regex` (possibly mixed), as shown in the following examples:
63
+
64
+ ```ruby
65
+ config.middleware.use Rack::SslEnforcer, :only_hosts => 'api.example.com'
66
+ # Please note that, for instance, both http://help.example.com/demo and https://help.example.com/demo would be accessible here
67
+
68
+ config.middleware.use Rack::SslEnforcer, :except_hosts => /[help|blog]\.example\.com$/
69
+
70
+ config.middleware.use Rack::SslEnforcer, :only_hosts => [/[secure|admin]\.example\.org$/, 'api.example.com']
71
+ ```
72
+
73
+ ### Path constraints
74
+
75
+ You can enforce SSL connections only for certain paths with `:only`, or prevent certain paths from being forced to SSL with `:except`. Constraints can be a `String`, a `Regex` or an array of `String` or `Regex` (possibly mixed), as shown in the following examples:
76
+
77
+ ```ruby
78
+ config.middleware.use Rack::SslEnforcer, :only => '/login'
79
+ # Please note that, for instance, both http://example.com/demo and https://example.com/demo would be accessible here
80
+
81
+ config.middleware.use Rack::SslEnforcer, :only => %r{^/admin/}
82
+
83
+ config.middleware.use Rack::SslEnforcer, :except => ['/demo', %r{^/public/}]
84
+ ```
85
+
86
+ ### Method constraints
87
+
88
+ You can enforce SSL connections only for certain HTTP methods with `:only_methods`, or prevent certain HTTP methods from being forced to SSL with `:except_methods`. Constraints can be a `String` or an array of `String`, as shown in the following examples:
89
+
90
+ ```ruby
91
+ # constraint as a String
92
+ config.middleware.use Rack::SslEnforcer, :only_methods => 'POST'
93
+ # Please note that, for instance, GET requests would be accessible via SSL and non-SSL connection here
94
+
95
+ config.middleware.use Rack::SslEnforcer, :except_methods => ['GET', 'HEAD']
96
+ ```
97
+
98
+ Note: The `:hosts` constraint takes precedence over the `:path` constraint. Please see the tests for examples.
99
+
100
+ ### Force-redirection to non-SSL connection if constraint is not matched
101
+
102
+ Use the `:strict` option to force non-SSL connection for all requests not matching the constraints you set. Examples:
103
+
104
+ ```ruby
105
+ config.middleware.use Rack::SslEnforcer, :only => ["/login", /\.xml$/], :strict => true
106
+ # https://example.com/demo would be redirected to http://example.com/demo
107
+
108
+ config.middleware.use Rack::SslEnforcer, :except_hosts => 'demo.example.com', :strict => true
109
+ # https://demo.example.com would be redirected to http://demo.example.com
110
+ ```
111
+
112
+ ### Automatic method constraints
113
+
114
+ In the case where you have matching URLs with different HTTP methods – for instance Rails RESTful routes: `GET /users`, `POST /users`, `GET /user/:id` and `PUT /user/:id` – you may need to force POST and PUT requests to SSL connection but redirect to non-SSL connection on GET.
115
+
116
+ ```ruby
117
+ config.middleware.use Rack::SslEnforcer, :only => [%r{^/users/}], :mixed => true
118
+ ```
119
+
120
+ The above will allow you to POST/PUT from the secure/non-secure URLs keeping the original schema.
121
+
122
+ ### HTTP Strict Transport Security (HSTS)
123
+
124
+ To set HSTS expiry and subdomain inclusion (defaults respectively to `one year` and `true`).
125
+
126
+ ```ruby
127
+ config.middleware.use Rack::SslEnforcer, :hsts => { :expires => 500, :subdomains => false }
128
+ config.middleware.use Rack::SslEnforcer, :hsts => true # equivalent to { :expires => 31536000, :subdomains => true }
129
+ ```
130
+ Please note that the strict option disables HSTS.
131
+
132
+ ### Redirect to specific URL (e.g. if you're using a proxy)
133
+
134
+ You might need the `:redirect_to` option if the requested URL can't be determined.
135
+
136
+ ```ruby
137
+ config.middleware.use Rack::SslEnforcer, :redirect_to => 'https://example.org'
138
+ ```
139
+
140
+ ### Custom HTTP port
141
+
142
+ If you're using a different port than the default (80) for HTTP, you can specify it with the `:http_port` option:
143
+
144
+ ```ruby
145
+ config.middleware.use Rack::SslEnforcer, :http_port => 8080
146
+ ```
147
+
148
+ ### Custom HTTPS port
149
+
150
+ If you're using a different port than the default (443) for HTTPS, you can specify it with the `:https_port` option:
151
+
152
+ ```ruby
153
+ config.middleware.use Rack::SslEnforcer, :https_port => 444
154
+ ```
155
+
156
+ ### Secure cookies disabling
157
+
158
+ Finally you might want to share a cookie based session between HTTP and HTTPS.
159
+ This is not possible by default with Rack::SslEnforcer for [security reasons](http://en.wikipedia.org/wiki/HTTP_cookie#Cookie_theft_and_session_hijacking).
160
+
161
+ Nevertheless, you can set the `:force_secure_cookies` option to `false` in order to be able to share a cookie based session between HTTP and HTTPS:
162
+
163
+ ```ruby
164
+ config.middleware.use Rack::SslEnforcer, :only => "/login", :force_secure_cookies => false
165
+ ```
166
+
167
+ But be aware that if you do so, you have to make sure that the content of you cookie is encoded.
168
+ This can be done using a coder with [Rack::Session::Cookie](https://github.com/rack/rack/blob/master/lib/rack/session/cookie.rb#L28-42).
169
+
170
+ ## Deployment
171
+
172
+ If you run your application behind a proxy (e.g. Nginx) you may need to do some configuration on that side. If you don't you may experience an infinite redirect loop.
173
+
174
+ The reason this happens is that Rack::SslEnforcer can't detect if you are running SSL or not. The solution is to have your front-end server send extra headers for Rack::SslEnforcer to identify the request protocol.
175
+
176
+ ### Nginx
177
+
178
+ In the `location` block for your app's SSL configuration, include the following proxy header configuration:
179
+
180
+ `proxy_set_header X-Forwarded-Proto https;`
181
+
182
+ ### Passenger
183
+
184
+ Or, if you're using mod_rails/passenger (which will ignore the proxy_xxx directives):
185
+
186
+ `passenger_set_cgi_param HTTP_X_FORWARDED_PROTO https;`
187
+
188
+ If you're sharing a single `server` block for http AND https access you can add:
189
+
190
+ `passenger_set_cgi_param HTTP_X_FORWARDED_PROTO $scheme;`
191
+
192
+ This makes sure that Rack::SslEnforcer knows it's being accessed over SSL. Just restart Nginx for these changes to take effect.
193
+
194
+ ## TODO
195
+
196
+ * Cleanup tests
197
+
198
+ ## Contributors
199
+
200
+ * [Dan Mayer](http://github.com/danmayer)
201
+ * [Rémy Coutable](http://github.com/rymai)
202
+ * [Thibaud Guillaume-Gentil](http://github.com/thibaudgg)
203
+ * [Paul Annesley](https://github.com/pda)
204
+ * [Saimon Moore](https://github.com/saimonmoore)
205
+
206
+ ## Credits
207
+
208
+ Flagging cookies as secure functionality and HSTS support is greatly inspired by [Joshua Peek's Rack::SSL](https://github.com/josh/rack-ssl).
209
+
210
+ ## Note on Patches / Pull Requests
211
+
212
+ * Fork the project.
213
+ * Code your feature addition or bug fix.
214
+ * **Add tests for it.** This is important so we don't break it in a future version unintentionally.
215
+ * Commit, do not mess with Rakefile or version number. If you want to have your own version, that's fine but bump version in a commit by itself so we can ignore it when merging.
216
+ * Send a pull request. Bonus points for topic branches.
217
+
218
+ ## Copyright
219
+
220
+ Copyright (c) 2010-2012 Tobias Matthies. See LICENSE for details.
@@ -1,38 +1,46 @@
1
+ require 'rack/ssl-enforcer/constraint'
2
+
1
3
  module Rack
4
+
2
5
  class SslEnforcer
3
6
 
7
+ CONSTRAINTS_BY_TYPE = {
8
+ :hosts => [:only_hosts, :except_hosts],
9
+ :path => [:only, :except],
10
+ :methods => [:only_methods, :except_methods]
11
+ }
12
+
4
13
  # Warning: If you set the option force_secure_cookies to false, make sure that your cookies
5
- # are encoded and that you understand the consequences (see documentation)
14
+ # are encoded and that you understand the consequences (see documentation)
6
15
  def initialize(app, options={})
7
16
  default_options = {
8
- :redirect_to => nil,
9
- :only => nil,
10
- :only_hosts => nil,
11
- :except => nil,
12
- :except_hosts => nil,
13
- :strict => false,
14
- :mixed => false,
15
- :hsts => nil,
16
- :http_port => nil,
17
- :https_port => nil,
17
+ :redirect_to => nil,
18
+ :strict => false,
19
+ :mixed => false,
20
+ :hsts => nil,
21
+ :http_port => nil,
22
+ :https_port => nil,
18
23
  :force_secure_cookies => true
19
24
  }
25
+ CONSTRAINTS_BY_TYPE.values.each { |constraint| default_options[constraint] = nil }
26
+
20
27
  @app, @options = app, default_options.merge(options)
21
28
  end
22
29
 
23
30
  def call(env)
24
- @req = Rack::Request.new(env)
25
- if enforce_ssl?(@req)
26
- scheme = 'https' unless ssl_request?(env)
27
- elsif ssl_request?(env) && enforcement_non_ssl?(env)
28
- scheme = 'http'
31
+ @request = Rack::Request.new(env)
32
+
33
+ return @app.call(env) if ignore?
34
+
35
+ @scheme = if enforce_ssl?
36
+ 'https'
37
+ elsif enforce_non_ssl?
38
+ 'http'
29
39
  end
30
40
 
31
- if scheme
32
- location = replace_scheme(@req, scheme)
33
- body = "<html><body>You are being <a href=\"#{location}\">redirected</a>.</body></html>"
34
- [301, { 'Content-Type' => 'text/html', 'Location' => location }, [body]]
35
- elsif ssl_request?(env)
41
+ if redirect_required?
42
+ modify_location_and_redirect
43
+ elsif ssl_request?
36
44
  status, headers, body = @app.call(env)
37
45
  flag_cookies_as_secure!(headers) if @options[:force_secure_cookies]
38
46
  set_hsts_headers!(headers) if @options[:hsts] && !@options[:strict]
@@ -43,105 +51,113 @@ module Rack
43
51
  end
44
52
 
45
53
  private
54
+
55
+ def redirect_required?
56
+ scheme_mismatch? || host_mismatch?
57
+ end
46
58
 
47
- def enforcement_non_ssl?(env)
48
- true if @options[:strict] || @options[:mixed] && !(env['REQUEST_METHOD'] == 'PUT' || env['REQUEST_METHOD'] == 'POST')
59
+ def ignore?
60
+ if @options[:ignore]
61
+ rules = [@options[:ignore]].flatten.compact
62
+ rules.any? do |rule|
63
+ SslEnforcerConstraint.new(:ignore, rule, @request).matches?
64
+ end
65
+ else
66
+ false
67
+ end
68
+ end
69
+
70
+ def scheme_mismatch?
71
+ @scheme && @scheme != current_scheme
72
+ end
73
+
74
+ def host_mismatch?
75
+ destination_host && destination_host != @request.host
76
+ end
77
+
78
+ def modify_location_and_redirect
79
+ location = "#{current_scheme}://#{@request.host}#{@request.fullpath}"
80
+ location = replace_scheme(location, @scheme)
81
+ location = replace_host(location, @options[:redirect_to])
82
+ redirect_to(location)
83
+ end
84
+
85
+ def redirect_to(location)
86
+ body = "<html><body>You are being <a href=\"#{location}\">redirected</a>.</body></html>"
87
+ [301, { 'Content-Type' => 'text/html', 'Location' => location }, [body]]
49
88
  end
50
89
 
51
- def ssl_request?(env)
52
- scheme(env) == 'https'
90
+ def ssl_request?
91
+ current_scheme == 'https'
92
+ end
93
+
94
+ def destination_host
95
+ if @options[:redirect_to]
96
+ host_parts = URI.split(@options[:redirect_to])
97
+ host_parts[2] || host_parts[5]
98
+ end
53
99
  end
54
100
 
55
101
  # Fixed in rack >= 1.3
56
- def scheme(env)
57
- if env['HTTPS'] == 'on'
102
+ def current_scheme
103
+ if @request.env['HTTPS'] == 'on'
58
104
  'https'
59
- elsif env['HTTP_X_FORWARDED_PROTO']
60
- env['HTTP_X_FORWARDED_PROTO'].split(',')[0]
105
+ elsif @request.env['HTTP_X_FORWARDED_PROTO']
106
+ @request.env['HTTP_X_FORWARDED_PROTO'].split(',')[0]
61
107
  else
62
- env['rack.url_scheme']
108
+ @request.scheme
63
109
  end
64
110
  end
65
111
 
66
- def matches?(key, pattern, req)
67
- if pattern.is_a?(Regexp)
68
- case key
69
- when :only
70
- req.path =~ pattern
71
- when :except
72
- req.path !~ pattern
73
- when :only_hosts
74
- req.host =~ pattern
75
- when :except_hosts
76
- req.host !~ pattern
77
- end
112
+ def enforce_ssl_for?(keys)
113
+ provided_keys = keys.select { |key| @options[key] }
114
+ if provided_keys.empty?
115
+ true
78
116
  else
79
- case key
80
- when :only
81
- req.path[0,pattern.length] == pattern
82
- when :except
83
- req.path[0,pattern.length] != pattern
84
- when :only_hosts
85
- req.host == pattern
86
- when :except_hosts
87
- req.host != pattern
88
- end
89
- end
90
- end
91
-
92
- def enforce_ssl_for?(keys, req)
93
- if keys.any? { |option| @options[option] }
94
- keys.any? do |key|
117
+ provided_keys.all? do |key|
95
118
  rules = [@options[key]].flatten.compact
96
- unless rules.empty?
97
- rules.send(key == :except_hosts || key == :except ? "all?" : "any?") do |pattern|
98
- matches?(key, pattern, req)
99
- end
119
+ rules.send([:except_hosts, :except].include?(key) ? :all? : :any?) do |rule|
120
+ SslEnforcerConstraint.new(key, rule, @request).matches?
100
121
  end
101
122
  end
102
- else
103
- false
104
123
  end
105
124
  end
106
125
 
107
- def enforce_ssl?(req)
108
- path_keys = [:only, :except]
109
- hosts_keys = [:only_hosts, :except_hosts]
110
- if hosts_keys.any? { |option| @options[option] }
111
- if enforce_ssl_for?(hosts_keys, req)
112
- if path_keys.any? { |option| @options[option] }
113
- enforce_ssl_for?(path_keys, req)
114
- else
115
- true
116
- end
117
- else
118
- false
119
- end
120
- elsif path_keys.any? { |option| @options[option] }
121
- enforce_ssl_for?(path_keys, req)
122
- else
123
- true
124
- end
126
+ def enforce_non_ssl?
127
+ @options[:strict] || @options[:mixed] && !(@request.request_method == 'PUT' || @request.request_method == 'POST')
125
128
  end
126
129
 
127
- def replace_scheme(req, scheme)
128
- if @options[:redirect_to]
129
- uri = URI.split(@options[:redirect_to])
130
- uri = uri[2] || uri[5]
131
- else
132
- uri = nil
130
+ def enforce_ssl?
131
+ CONSTRAINTS_BY_TYPE.inject(true) do |memo, (type, keys)|
132
+ memo && enforce_ssl_for?(keys)
133
133
  end
134
- host = uri || req.host
135
- port = port_for(scheme).to_s
136
-
137
- URI.parse("#{scheme}://#{host}:#{port}#{req.fullpath}").to_s
138
134
  end
139
135
 
140
- def port_for(scheme)
136
+ def replace_scheme(uri, scheme)
137
+ return uri if not scheme_mismatch?
138
+
139
+ port = adjust_port_to(scheme)
140
+ uri_parts = URI.split(uri)
141
+ uri_parts[3] = port unless port.nil?
142
+ uri_parts[0] = scheme
143
+ URI::HTTP.new(*uri_parts).to_s
144
+ end
145
+
146
+ def replace_host(uri, host)
147
+ return uri unless host_mismatch?
148
+
149
+ host_parts = URI.split(host)
150
+ new_host = host_parts[2] || host_parts[5]
151
+ uri_parts = URI.split(uri)
152
+ uri_parts[2] = new_host
153
+ URI::HTTPS.new(*uri_parts).to_s
154
+ end
155
+
156
+ def adjust_port_to(scheme)
141
157
  if scheme == 'https'
142
- @options[:https_port] || 443
143
- else
144
- @options[:http_port] || 80
158
+ @options[:https_port] if @options[:https_port] && @options[:https_port] != URI::HTTPS.default_port
159
+ elsif scheme == 'http'
160
+ @options[:http_port] if @options[:http_port] && @options[:http_port] != URI::HTTP.default_port
145
161
  end
146
162
  end
147
163
 
@@ -0,0 +1,38 @@
1
+ class SslEnforcerConstraint
2
+ def initialize(name, rule, request)
3
+ @name = name
4
+ @rule = rule
5
+ @request = request
6
+ end
7
+
8
+ def matches?
9
+ if @rule.is_a?(String) && [:only, :except].include?(@name)
10
+ result = tested_string[0, @rule.size].send(operator, @rule)
11
+ else
12
+ result = tested_string.send(operator, @rule)
13
+ end
14
+
15
+ negate_result? ? !result : result
16
+ end
17
+
18
+ private
19
+
20
+ def negate_result?
21
+ @name.to_s =~ /except/
22
+ end
23
+
24
+ def operator
25
+ @rule.is_a?(Regexp) ? "=~" : "=="
26
+ end
27
+
28
+ def tested_string
29
+ case @name.to_s
30
+ when /hosts/
31
+ @request.host
32
+ when /methods/
33
+ @request.request_method
34
+ else
35
+ @request.path
36
+ end
37
+ end
38
+ end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class SslEnforcer
3
- VERSION = "0.2.4"
3
+ VERSION = "0.2.5"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-ssl-enforcer
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ hash: 29
5
+ prerelease:
5
6
  segments:
6
7
  - 0
7
8
  - 2
8
- - 4
9
- version: 0.2.4
9
+ - 5
10
+ version: 0.2.5
10
11
  platform: ruby
11
12
  authors:
12
13
  - Tobias Matthies
@@ -15,8 +16,7 @@ autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2011-09-05 00:00:00 +02:00
19
- default_executable:
19
+ date: 2012-11-14 00:00:00 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: bundler
@@ -26,6 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
+ hash: 15
29
30
  segments:
30
31
  - 1
31
32
  - 0
@@ -40,6 +41,7 @@ dependencies:
40
41
  requirements:
41
42
  - - ~>
42
43
  - !ruby/object:Gem::Version
44
+ hash: 5
43
45
  segments:
44
46
  - 2
45
47
  - 3
@@ -54,6 +56,7 @@ dependencies:
54
56
  requirements:
55
57
  - - ~>
56
58
  - !ruby/object:Gem::Version
59
+ hash: 37
57
60
  segments:
58
61
  - 2
59
62
  - 11
@@ -69,6 +72,7 @@ dependencies:
69
72
  requirements:
70
73
  - - ~>
71
74
  - !ruby/object:Gem::Version
75
+ hash: 31
72
76
  segments:
73
77
  - 1
74
78
  - 2
@@ -84,6 +88,7 @@ dependencies:
84
88
  requirements:
85
89
  - - ~>
86
90
  - !ruby/object:Gem::Version
91
+ hash: 3
87
92
  segments:
88
93
  - 0
89
94
  - 5
@@ -102,12 +107,12 @@ extensions: []
102
107
  extra_rdoc_files: []
103
108
 
104
109
  files:
110
+ - lib/rack/ssl-enforcer/constraint.rb
105
111
  - lib/rack/ssl-enforcer/version.rb
106
112
  - lib/rack/ssl-enforcer.rb
107
113
  - lib/rack-ssl-enforcer.rb
108
114
  - LICENSE
109
- - README.rdoc
110
- has_rdoc: true
115
+ - README.md
111
116
  homepage: http://github.com/tobmatth/rack-ssl-enforcer
112
117
  licenses: []
113
118
 
@@ -121,6 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
121
126
  requirements:
122
127
  - - ">="
123
128
  - !ruby/object:Gem::Version
129
+ hash: 3
124
130
  segments:
125
131
  - 0
126
132
  version: "0"
@@ -129,6 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
135
  requirements:
130
136
  - - ">="
131
137
  - !ruby/object:Gem::Version
138
+ hash: 23
132
139
  segments:
133
140
  - 1
134
141
  - 3
@@ -137,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
144
  requirements: []
138
145
 
139
146
  rubyforge_project: rack-ssl-enforcer
140
- rubygems_version: 1.3.7
147
+ rubygems_version: 1.8.24
141
148
  signing_key:
142
149
  specification_version: 3
143
150
  summary: A simple Rack middleware to enforce SSL
@@ -1,111 +0,0 @@
1
- = Rack::SslEnforcer
2
-
3
- Rack::SslEnforcer is a simple Rack middleware to enforce SSL connections. As of Version 0.2.0, Rack::SslEnforcer marks
4
- Cookies as secure by default (HSTS must be set manually).
5
-
6
- Tested on Ruby 1.8.7, 1.9.2, REE, JRuby and Rubinius.
7
-
8
- == Installation
9
-
10
- gem install rack-ssl-enforcer
11
-
12
-
13
- == Basic Usage
14
-
15
- require 'rack/ssl-enforcer'
16
- use Rack::SslEnforcer
17
-
18
- Or, if you are using Bundler, just add this to your Gemfile:
19
-
20
- gem 'rack-ssl-enforcer'
21
-
22
- To use Rack::SslEnforcer in your Rails application, add the following line to your application
23
- config file (<tt>config/application.rb</tt> for Rails 3, <tt>config/environment.rb</tt> for Rails 2):
24
-
25
- config.middleware.use Rack::SslEnforcer
26
-
27
- If all you want is SSL for your whole application, you are done! However, you can specify some
28
-
29
-
30
- == Options
31
-
32
- You might need the :redirect_to option if the requested URL can't be determined (e.g. if using a proxy).
33
-
34
- config.middleware.use Rack::SslEnforcer, :redirect_to => 'https://example.org'
35
-
36
- You can also define specific regex patterns or paths or hosts to redirect.
37
-
38
- config.middleware.use Rack::SslEnforcer, :only => /^\/admin\//
39
- config.middleware.use Rack::SslEnforcer, :only => "/login"
40
- config.middleware.use Rack::SslEnforcer, :only => ["/login", /\.xml$/]
41
- config.middleware.use Rack::SslEnforcer, :only_hosts => 'api.example.com'
42
- config.middleware.use Rack::SslEnforcer, :only_hosts => [/[www|api]\.example\.org$/, 'example.com']
43
- config.middleware.use Rack::SslEnforcer, :except_hosts => 'help.example.com'
44
- config.middleware.use Rack::SslEnforcer, :except_hosts => /[help|blog]\.example\.com$/
45
-
46
- Note: hosts options take precedence over the path options. See tests for examples.
47
-
48
- Use the :strict option to force http for all requests not matching your :only specification
49
-
50
- config.middleware.use Rack::SslEnforcer, :only => ["/login", /\.xml$/], :strict => true
51
- config.middleware.use Rack::SslEnforcer, :only_hosts => 'api.example.com', :strict => true
52
-
53
- Or in the case where you have matching urls with different methods (Rails RESTful routes: get#users post#users || get#user/:id put#user/:id) you may need to post and put to secure but redirect to http on get.
54
-
55
- config.middleware.use Rack::SslEnforcer, :only => [%r{^/users/}], :mixed => true
56
-
57
- The above will allow you to post/put from the secure/non-secure urls keeping the original schema.
58
-
59
- To set HSTS expiry and subdomain inclusion (defaults: one year, true). Strict option disables HSTS.
60
-
61
- config.middleware.use Rack::SslEnforcer, :hsts => { :expires => 500, :subdomains => false }
62
- config.middleware.use Rack::SslEnforcer, :hsts => true # equivalent to { :expires => 31536000, :subdomains => true }
63
-
64
- Finally you might want to share a cookie based session between http and https.
65
- This is not possible by default with Rack::SslEnforcer for security reasons.
66
- See: [http://en.wikipedia.org/wiki/HTTP_cookie#Cookie_theft_and_session_hijacking]
67
-
68
- Nevertheless, you can set the option :force_secure_cookies to false in order to be able to share a cookie based session between http and https:
69
-
70
- config.middleware.use Rack::SslEnforcer, :only => "/login", :force_secure_cookies => false
71
-
72
- But be aware that if you do so, you have to make sure that the content of you cookie is encoded.
73
- This can be done using a coder with Rack::Session::Cookie.
74
- See: [https://github.com/rack/rack/blob/master/lib/rack/session/cookie.rb#L28-42]
75
-
76
-
77
- == TODO
78
-
79
- * Add configuration option to specify local http / https ports
80
- * Cleanup tests
81
-
82
-
83
- == Contributors
84
-
85
- * {Dan Mayer}[http://github.com/danmayer]
86
- * {Rémy Coutable}[http://github.com/rymai]
87
- * {Thibaud Guillaume-Gentil}[http://github.com/thibaudgg]
88
- * {Paul Annesley}[https://github.com/pda]
89
- * {Saimon Moore}[https://github.com/saimonmoore]
90
-
91
-
92
- == Credits
93
-
94
- Flagging cookies as secure functionality and HSTS support is greatly inspired by {Joshua Peek's Rack::SSL}[https://github.com/josh/rack-ssl]
95
-
96
-
97
- == Note on Patches/Pull Requests
98
-
99
- * Fork the project.
100
- * Make your feature addition or bug fix.
101
- * Add tests for it. This is important so I don't break it in a
102
- future version unintentionally.
103
- * Commit, do not mess with rakefile, version, or history.
104
- (if you want to have your own version,
105
- that is fine but bump version in a commit by itself I can ignore when I pull)
106
- * Send me a pull request. Bonus points for topic branches.
107
-
108
-
109
- == Copyright
110
-
111
- Copyright (c) 2010 Tobias Matthies. See LICENSE for details.