提交 db5f1a46 编写于 作者: B Benjamin Fleischer

`secret_token` is now saved in `Rails.application.secrets.secret_token`

- `secrets.secret_token` is now used in all places `config.secret_token` was
  - `secrets.secret_token`, when not present in `config/secrets.yml`,
    now falls back to the value of `config.secret_token`
  - when `secrets.secret_token` is set, it over-writes
    `config.secret_token` so they are the same (for backwards-compatibility)
  - Update docs to reference app.secrets in all places
    - Remove references to `config.secret_token`, `config.secret_key_base`
- Warn that missing secret_key_base is deprecated
- Add tests for secret_token, key_generator, and message_verifier
  - the legacy key generator is used with the message verifier when
    secrets.secret_key_base is blank and secret_token is set
  - app.key_generator raises when neither secrets.secret_key_base nor
    secret_token are set
  - app.env_config    raises when neither secrets.secret_key_base nor
    secret_token are set
- Add changelog

Run focused tests via
ruby -w -Itest test/application/configuration_test.rb -n '/secret_|key_/'
上级 1d6d0cc2
......@@ -120,7 +120,7 @@ def permanent
# the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed
# cookie was tampered with by the user (or a 3rd party), nil will be returned.
#
# If +secrets.secret_key_base+ and +config.secret_token+ (deprecated) are both set,
# If +secrets.secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,
# legacy cookies signed with the old key generator will be transparently upgraded.
#
# This jar requires that you set a suitable secret for the verification on your app's +secrets.secret_key_base+.
......@@ -143,7 +143,7 @@ def signed
# Returns a jar that'll automatically encrypt cookie values before sending them to the client and will decrypt them for read.
# If the cookie was tampered with by the user (or a 3rd party), nil will be returned.
#
# If +secrets.secret_key_base+ and +config.secret_token+ (deprecated) are both set,
# If +secrets.secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,
# legacy cookies signed with the old key generator will be transparently upgraded.
#
# This jar requires that you set a suitable secret for the verification on your app's +secrets.secret_key_base+.
......@@ -479,7 +479,7 @@ def verify(signed_message)
end
# UpgradeLegacySignedCookieJar is used instead of SignedCookieJar if
# config.secret_token and secrets.secret_key_base are both set. It reads
# secrets.secret_token and secrets.secret_key_base are both set. It reads
# legacy cookies signed with the old dummy key generator and re-saves
# them using the new key generator to provide a smooth upgrade path.
class UpgradeLegacySignedCookieJar < SignedCookieJar #:nodoc:
......@@ -537,7 +537,7 @@ def decrypt_and_verify(encrypted_message)
end
# UpgradeLegacyEncryptedCookieJar is used by ActionDispatch::Session::CookieStore
# instead of EncryptedCookieJar if config.secret_token and secrets.secret_key_base
# instead of EncryptedCookieJar if secrets.secret_token and secrets.secret_key_base
# are both set. It reads legacy cookies signed with the old dummy key generator and
# encrypts and re-saves them using the new key generator to provide a smooth upgrade path.
class UpgradeLegacyEncryptedCookieJar < EncryptedCookieJar #:nodoc:
......
......@@ -7,8 +7,8 @@
class TestApp < Rails::Application
config.root = File.dirname(__FILE__)
config.session_store :cookie_store, key: 'cookie_store_key'
config.secret_token = 'secret_token'
config.secret_key_base = 'secret_key_base'
secrets.secret_token = 'secret_token'
secrets.secret_key_base = 'secret_key_base'
config.logger = Logger.new($stdout)
Rails.logger = config.logger
......
......@@ -19,8 +19,8 @@
class TestApp < Rails::Application
config.root = File.dirname(__FILE__)
config.session_store :cookie_store, key: 'cookie_store_key'
config.secret_token = 'secret_token'
config.secret_key_base = 'secret_key_base'
secrets.secret_token = 'secret_token'
secrets.secret_key_base = 'secret_key_base'
config.logger = Logger.new($stdout)
Rails.logger = config.logger
......
* `secret_token` is now saved in `Rails.application.secrets.secret_token`
and it falls back to the value of `config.secret_token` when it is not
present in `config/secrets.yml`.
*Benjamin Fleischer*
* Remove `--skip-action-view` option from `Rails::Generators::AppBase`.
Fixes #17023.
......
......@@ -175,7 +175,7 @@ def key_generator
key_generator = ActiveSupport::KeyGenerator.new(secrets.secret_key_base, iterations: 1000)
ActiveSupport::CachingKeyGenerator.new(key_generator)
else
ActiveSupport::LegacyKeyGenerator.new(config.secret_token)
ActiveSupport::LegacyKeyGenerator.new(secrets.secret_token)
end
end
......@@ -245,7 +245,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.secret_token" => secrets.secret_token,
"action_dispatch.secret_key_base" => secrets.secret_key_base,
"action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions,
"action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local,
......@@ -378,6 +378,13 @@ def secrets #:nodoc:
# Fallback to config.secret_key_base if secrets.secret_key_base isn't set
secrets.secret_key_base ||= config.secret_key_base
# Sync secrets.secret_token with config.secret_token, preferring secrets.secret_token
# note that unset config's default to "", secrets default to nil
if secrets.secret_token.blank? && config.secret_token.present?
secrets.secret_token = config.secret_token
elsif secrets.secret_token.present?
config.secret_token = secrets.secret_token
end
secrets
end
......@@ -507,8 +514,13 @@ def build_original_fullpath(env) #:nodoc:
end
def validate_secret_key_config! #:nodoc:
if secrets.secret_key_base.blank? && config.secret_token.blank?
raise "Missing `secret_key_base` for '#{Rails.env}' environment, set this value in `config/secrets.yml`"
if secrets.secret_key_base.blank?
ActiveSupport::Deprecation.warn "You didn't set `secret_key_base`. " +
"Read the upgrade documentation to learn more about this new config option."
if secrets.secret_token.blank?
raise "Missing `secret_token` and `secret_key_base` for '#{Rails.env}' environment, set these values in `config/secrets.yml`"
end
end
end
end
......
......@@ -301,6 +301,53 @@ def index
assert_equal 'some_value', verifier.verify(message)
end
test "application message verifier can be used when the key_generator is ActiveSupport::LegacyKeyGenerator" do
app_file 'config/initializers/secret_token.rb', <<-RUBY
Rails.application.config.secret_token = "b3c631c314c0bbca50c1b2843150fe33"
RUBY
app_file 'config/secrets.yml', <<-YAML
development:
secret_key_base:
YAML
require "#{app_path}/config/environment"
assert_equal app.env_config['action_dispatch.key_generator'], Rails.application.key_generator
assert_equal app.env_config['action_dispatch.key_generator'].class, ActiveSupport::LegacyKeyGenerator
message = app.message_verifier(:sensitive_value).generate("some_value")
assert_equal 'some_value', Rails.application.message_verifier(:sensitive_value).verify(message)
end
test "warns when secrets.secret_key_base is blank and config.secret_token is set" do
app_file 'config/initializers/secret_token.rb', <<-RUBY
Rails.application.config.secret_token = "b3c631c314c0bbca50c1b2843150fe33"
RUBY
app_file 'config/secrets.yml', <<-YAML
development:
secret_key_base:
YAML
require "#{app_path}/config/environment"
assert_deprecated(/You didn't set `secret_key_base`./) do
app.env_config
end
end
test "uses secrets.secret_token when secrets.secret_key_base and config.secret_token are blank" do
app_file 'config/initializers/secret_token.rb', <<-RUBY
Rails.application.config.secret_token = ""
RUBY
app_file 'config/secrets.yml', <<-YAML
development:
secret_key_base:
secret_token: 3b7cd727ee24e8444053437c36cc66c3
YAML
require "#{app_path}/config/environment"
assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.secrets.secret_token
assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.config.secret_token
end
test "application verifier can build different verifiers" do
make_basic_app do |app|
app.secrets.secret_key_base = 'b3c631c314c0bbca50c1b2843150fe33'
......@@ -341,6 +388,51 @@ def index
assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.secrets.secret_key_base
end
test "config.secret_token over-writes a blank secrets.secret_token" do
app_file 'config/initializers/secret_token.rb', <<-RUBY
Rails.application.config.secret_token = "b3c631c314c0bbca50c1b2843150fe33"
RUBY
app_file 'config/secrets.yml', <<-YAML
development:
secret_key_base:
secret_token:
YAML
require "#{app_path}/config/environment"
assert_equal 'b3c631c314c0bbca50c1b2843150fe33', app.secrets.secret_token
assert_equal 'b3c631c314c0bbca50c1b2843150fe33', app.config.secret_token
end
test "secret_token is copied from secrets to config when set" do
app_file 'config/initializers/secret_token.rb', <<-RUBY
Rails.application.config.secret_token = ""
RUBY
app_file 'config/secrets.yml', <<-YAML
development:
secret_key_base:
secret_token: 3b7cd727ee24e8444053437c36cc66c3
YAML
require "#{app_path}/config/environment"
assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.secrets.secret_token
assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.config.secret_token
end
test "secret_token is copied from secrets to config when different" do
app_file 'config/initializers/secret_token.rb', <<-RUBY
Rails.application.config.secret_token = "b3c631c314c0bbca50c1b2843150fe33"
RUBY
app_file 'config/secrets.yml', <<-YAML
development:
secret_key_base:
secret_token: 3b7cd727ee24e8444053437c36cc66c3
YAML
require "#{app_path}/config/environment"
assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.secrets.secret_token
assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.config.secret_token
end
test "custom secrets saved in config/secrets.yml are loaded in app secrets" do
app_file 'config/secrets.yml', <<-YAML
development:
......@@ -362,6 +454,51 @@ def index
assert_nil app.secrets.not_defined
end
test "config.secret_key_base over-writes a blank secrets.secret_key_base" do
app_file 'config/initializers/secret_token.rb', <<-RUBY
Rails.application.config.secret_key_base = "iaminallyoursecretkeybase"
RUBY
app_file 'config/secrets.yml', <<-YAML
development:
secret_key_base:
YAML
require "#{app_path}/config/environment"
assert_equal "iaminallyoursecretkeybase", app.secrets.secret_key_base
end
test "uses ActiveSupport::LegacyKeyGenerator as app.key_generator when secrets.secret_key_base is blank" do
app_file 'config/initializers/secret_token.rb', <<-RUBY
Rails.application.config.secret_token = "b3c631c314c0bbca50c1b2843150fe33"
RUBY
app_file 'config/secrets.yml', <<-YAML
development:
secret_key_base:
YAML
require "#{app_path}/config/environment"
assert_equal 'b3c631c314c0bbca50c1b2843150fe33', app.config.secret_token
assert_equal nil, app.secrets.secret_key_base
assert_equal app.key_generator.class, ActiveSupport::LegacyKeyGenerator
end
test "uses ActiveSupport::LegacyKeyGenerator with config.secret_token as app.key_generator when secrets.secret_key_base is blank" do
app_file 'config/initializers/secret_token.rb', <<-RUBY
Rails.application.config.secret_token = ""
RUBY
app_file 'config/secrets.yml', <<-YAML
development:
secret_key_base:
YAML
require "#{app_path}/config/environment"
assert_equal '', app.config.secret_token
assert_equal nil, app.secrets.secret_key_base
assert_raise ArgumentError, /\AA secret is required/ do
app.key_generator
end
end
test "protect from forgery is the default in a new app" do
make_basic_app
......
......@@ -203,7 +203,7 @@ def read_raw_cookie
RUBY
add_to_config <<-RUBY
config.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
secrets.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
RUBY
require "#{app_path}/config/environment"
......@@ -258,7 +258,7 @@ def read_raw_cookie
RUBY
add_to_config <<-RUBY
config.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
secrets.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
RUBY
require "#{app_path}/config/environment"
......@@ -317,7 +317,7 @@ def read_raw_cookie
RUBY
add_to_config <<-RUBY
config.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
secrets.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
secrets.secret_key_base = nil
RUBY
......@@ -334,7 +334,7 @@ def read_raw_cookie
get '/foo/read_signed_cookie'
assert_equal '2', last_response.body
verifier = ActiveSupport::MessageVerifier.new(app.config.secret_token)
verifier = ActiveSupport::MessageVerifier.new(app.secrets.secret_token)
get '/foo/read_raw_cookie'
assert_equal 2, verifier.verify(last_response.body)['foo']
......
......@@ -8,6 +8,7 @@ def setup
build_app(initializers: true)
boot_rails
require "#{rails_root}/config/environment"
Rails.application.config.some_setting = 'something_or_other'
end
def teardown
......@@ -18,7 +19,7 @@ def test_cloning_an_application_makes_a_shallow_copy_of_config
clone = Rails.application.clone
assert_equal Rails.application.config, clone.config, "The cloned application should get a copy of the config"
assert_equal Rails.application.config.secret_key_base, clone.config.secret_key_base, "The base secret key on the config should be the same"
assert_equal Rails.application.config.some_setting, clone.config.some_setting, "The some_setting on the config should be the same"
end
def test_inheriting_multiple_times_from_application
......@@ -160,13 +161,14 @@ def test_isolate_namespace_on_an_application
def test_inserting_configuration_into_application
app = AppTemplate::Application.new(config: Rails.application.config)
new_config = Rails::Application::Configuration.new("root_of_application")
new_config.secret_key_base = "some_secret_key_dude"
app.config.secret_key_base = "a_different_secret_key"
app.config.some_setting = "a_different_setting"
assert_equal "a_different_setting", app.config.some_setting, "The configuration's some_setting should be set."
assert_equal "a_different_secret_key", app.config.secret_key_base, "The configuration's secret key should be set."
new_config = Rails::Application::Configuration.new("root_of_application")
new_config.some_setting = "some_setting_dude"
app.config = new_config
assert_equal "some_secret_key_dude", app.config.secret_key_base, "The configuration's secret key should have changed."
assert_equal "some_setting_dude", app.config.some_setting, "The configuration's some_setting should have changed."
assert_equal "root_of_application", app.config.root, "The root should have changed to the new config's root."
assert_equal new_config, app.config, "The application's config should have changed to the new config."
end
......
......@@ -15,7 +15,7 @@ def app
require "action_view/railtie"
class MyApp < Rails::Application
config.secret_key_base = "3b7cd727ee24e8444053437c36cc66c4"
secrets.secret_key_base = "3b7cd727ee24e8444053437c36cc66c4"
config.session_store :cookie_store, key: "_myapp_session"
config.active_support.deprecation = :log
config.eager_load = false
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册