Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Filter redirects #8404

Merged
merged 1 commit into from

4 participants

@freegenie

Given the latest discussion on rails-core google group, rather than just discussing this one I'm providing working code. I think Rails is missing a way to filter redirect logs. It makes sense to me, given redirect logs could hold sensible informations the same way POST params do.
The typical example is when you redirect to S3 signed URLs, which is my case. People is sending out logs to third party services for analysis, this feature will at least give them a way to have more control over what they send.

I was thinking about a way to make a gem out of it, but I seems that the current implementation does not leave room for anything to plug other than a monkeypatch. Advices on how to make a gem for this are of welcome of course.

actionpack/lib/action_controller/redirect_log_filter.rb
@@ -0,0 +1,36 @@
+module ActionController
+ module RedirectLogFilter #:nodoc:
+ extend ActiveSupport::Concern
+
+ FILTERED = '[FILTERED]'.freeze
@steveklabnik Collaborator

Is there any particular reason to freeze this string, or is this just defensive?

The only reason is I saw it's frozen in actionpack/lib/action_dispatch/http/parameter_filter.rb, so I did it just to be consistent.

@steveklabnik Collaborator

That's reasonable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
actionpack/lib/action_controller/redirect_log_filter.rb
@@ -0,0 +1,36 @@
+module ActionController
+ module RedirectLogFilter #:nodoc:
+ extend ActiveSupport::Concern
+
+ FILTERED = '[FILTERED]'.freeze
+
+ included do
+ config_accessor :filter_redirect_logs
+ extend ClassMethods
@steveklabnik Collaborator

Is this needed, since this is a Concern?

@pixeltrix Owner

No it isn't - @freegenie please remove this line

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@steveklabnik
Collaborator

I like it. :)

@pixeltrix
Owner

I'm assuming that the use case for this is to filter sensitive data out of log files like secure download urls? If so we need some documentation and an example to show this and also a CHANGELOG entry.

@pixeltrix
Owner

Also squash the commits - thanks!

@freegenie

fixed and squashed. Looking to add some docs and CHANGELOG entry.

@freegenie

CHANGELOG and docs added.

@pixeltrix
Owner

Was there a particular reason you put this under ActionController, rather than ActionDispatch like the one for params?

@Trevoke

This feature is required to use Intuit's API - when we redirect to Intuit, the oauth_token shows in the log, and in order to fulfill their security questionnaires, no token can appear in the logs. I'm looking forward to this being added to Rails.

@freegenie

@pixeltrix thanks for pointing this out. I admit that implementing more closely to what we have in params_filter is a very attractive idea. After all they share similar security concerns, and maybe they should also share some common behaviour in terms of code. That would be more consistent, and less surprising for the user. I realized it while editing the guide. But at the same time this is a tiny change, doing it the other way would probably require to go touch a lot of code, expecially if we want to abstract something out from FilterParameters. @steveklabnik what do you think about this? Would it be better to propose this change in an action_dispatch fashon?

@steveklabnik
Collaborator

If the one for params is in ActionDispatch, it makes sense to put this one there as well. I didn't realize that it was there in the first place; I'm still learning my way around some parts of the codebase, and @pixeltrix knows what he's talking about. :)

@freegenie

Well then, I'm going to rework this a little.

@freegenie

I updated this branch with a second attempt. I kept the previous commit and reverted it just to provide some context for future readers. I'll squash eventually if it gets approved. This time I used the same approach as the one used by filter_parameters. Paths of the two are quite different though, since one is in the scope of the request, while the other one belongs to the reponse.

guides/source/action_controller_overview.md
@@ -751,8 +751,12 @@ Now the user can request to get a PDF version of a client just by adding ".pdf"
GET /clients/1.pdf
```
-Parameter Filtering
--------------------
+Log Filtering
+-------------
+
+Rails keeps a log file for each environment in the `log` folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file.
+
+### Parameters Filtering
Rails keeps a log file for each environment in the `log` folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. You can filter certain request parameters from your log files by appending them to `config.filter_parameters` in the application configuration. These parameters will be marked [FILTERED] in the log.
@pixeltrix Owner

This sentence is repeated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@pixeltrix
Owner

@freegenie it's looking much better - can you fix the guide and squash the commits and then I'll merge it, thanks!

@freegenie

@pixeltrix Done! Many thanks to you for your precious review.

@pixeltrix pixeltrix merged commit e905639 into rails:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 5, 2012
  1. @freegenie
This page is out of date. Refresh to see the latest.
View
6 actionpack/CHANGELOG.md
@@ -1,4 +1,10 @@
## Rails 4.0.0 (unreleased) ##
+* Add filter capability to ActionController logs for redirect locations:
+
+ config.filter_redirect << 'http://please.hide.it/'
+
+ *Fabrizio Regini*
+
* Fixed a bug that ignores constraints on a glob route. This was caused because the constraint
regular expression is overwritten when the `routes.rb` file is processed. Fixes #7924
View
2  actionpack/lib/action_controller/metal/instrumentation.rb
@@ -60,7 +60,7 @@ def redirect_to(*args)
ActiveSupport::Notifications.instrument("redirect_to.action_controller") do |payload|
result = super
payload[:status] = response.status
- payload[:location] = response.location
+ payload[:location] = response.filtered_location
result
end
end
View
1  actionpack/lib/action_dispatch.rb
@@ -75,6 +75,7 @@ module Http
autoload :Parameters
autoload :ParameterFilter
autoload :FilterParameters
+ autoload :FilterRedirect
autoload :Upload
autoload :UploadedFile, 'action_dispatch/http/upload'
autoload :URL
View
37 actionpack/lib/action_dispatch/http/filter_redirect.rb
@@ -0,0 +1,37 @@
+module ActionDispatch
+ module Http
+ module FilterRedirect
+
+ FILTERED = '[FILTERED]'.freeze # :nodoc:
+
+ def filtered_location
+ if !location_filter.empty? && location_filter_match?
+ FILTERED
+ else
+ location
+ end
+ end
+
+ private
+
+ def location_filter
+ if request.present?
+ request.env['action_dispatch.redirect_filter'] || []
+ else
+ []
+ end
+ end
+
+ def location_filter_match?
+ location_filter.any? do |filter|
+ if String === filter
+ location.include?(filter)
+ elsif Regexp === filter
+ location.match(filter)
+ end
+ end
+ end
+
+ end
+ end
+end
View
1  actionpack/lib/action_dispatch/http/response.rb
@@ -61,6 +61,7 @@ class Response
cattr_accessor(:default_headers)
include Rack::Response::Helpers
+ include ActionDispatch::Http::FilterRedirect
include ActionDispatch::Http::Cache::Response
include MonitorMixin
View
22 actionpack/test/controller/log_subscriber_test.rb
@@ -26,6 +26,10 @@ def redirector
redirect_to "http://foo.bar/"
end
+ def filterable_redirector
+ redirect_to "http://secret.foo.bar/"
+ end
+
def data_sender
send_data "cool data", :filename => "file.txt"
end
@@ -152,6 +156,24 @@ def test_redirect_to
assert_equal "Redirected to http://foo.bar/", logs[1]
end
+ def test_filter_redirect_url_by_string
+ @request.env['action_dispatch.redirect_filter'] = ['secret']
+ get :filterable_redirector
+ wait
+
+ assert_equal 3, logs.size
+ assert_equal "Redirected to [FILTERED]", logs[1]
+ end
+
+ def test_filter_redirect_url_by_regexp
+ @request.env['action_dispatch.redirect_filter'] = [/secret\.foo.+/]
+ get :filterable_redirector
+ wait
+
+ assert_equal 3, logs.size
+ assert_equal "Redirected to [FILTERED]", logs[1]
+ end
+
def test_send_data
get :data_sender
wait
View
27 guides/source/action_controller_overview.md
@@ -751,15 +751,36 @@ Now the user can request to get a PDF version of a client just by adding ".pdf"
GET /clients/1.pdf
```
-Parameter Filtering
--------------------
+Log Filtering
+-------------
+
+Rails keeps a log file for each environment in the `log` folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file.
-Rails keeps a log file for each environment in the `log` folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. You can filter certain request parameters from your log files by appending them to `config.filter_parameters` in the application configuration. These parameters will be marked [FILTERED] in the log.
+### Parameters Filtering
+
+You can filter certain request parameters from your log files by appending them to `config.filter_parameters` in the application configuration. These parameters will be marked [FILTERED] in the log.
```ruby
config.filter_parameters << :password
```
+### Redirects Filtering
+
+Sometimes it's desirable to filter out from log files some sensible locations your application is redirecting to.
+You can do that by using the `config.filter_redirect` configuration option:
+
+```ruby
+config.filter_redirect << 's3.amazonaws.com'
+```
+
+You can set it to a String, a Regexp, or an array of both.
+
+```ruby
+config.filter_redirect.concat ['s3.amazonaws.com', /private_path/]
+```
+
+Matching URLs will be marked as '[FILTERED]'.
+
Rescue
------
View
2  railties/lib/rails/application.rb
@@ -123,6 +123,7 @@ def key_generator
# Currently stores:
#
# * "action_dispatch.parameter_filter" => config.filter_parameters
+ # * "action_dispatch.redirect_filter" => config.filter_redirect
# * "action_dispatch.secret_token" => config.secret_token,
# * "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions
# * "action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local
@@ -149,6 +150,7 @@ def env_config
super.merge({
"action_dispatch.parameter_filter" => config.filter_parameters,
+ "action_dispatch.redirect_filter" => config.filter_redirect,
"action_dispatch.secret_token" => config.secret_token,
"action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions,
"action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local,
View
3  railties/lib/rails/application/configuration.rb
@@ -13,7 +13,7 @@ class Configuration < ::Rails::Engine::Configuration
:railties_order, :relative_url_root, :secret_key_base, :secret_token,
:serve_static_assets, :ssl_options, :static_cache_control, :session_options,
:time_zone, :reload_classes_only_on_change,
- :queue, :queue_consumer, :beginning_of_week
+ :queue, :queue_consumer, :beginning_of_week, :filter_redirect
attr_writer :log_level
attr_reader :encoding
@@ -23,6 +23,7 @@ def initialize(*)
self.encoding = "utf-8"
@consider_all_requests_local = false
@filter_parameters = []
+ @filter_redirect = []
@helpers_paths = []
@serve_static_assets = true
@static_cache_control = nil
Something went wrong with that request. Please try again.