FEATUE: automatically validate token is stored in redis

This ensures we have some handling for redis flushall

We attempt to recover our in-memory session token once every 30 seconds

Code is careful to only set the token if it is nil, to allow for manual
cycling to remain safe if needed
This commit is contained in:
Sam 2017-03-13 10:19:02 -04:00
parent 82ca0e368e
commit ef24fd54ba
2 changed files with 35 additions and 0 deletions

View File

@ -11,6 +11,8 @@ class GlobalSetting
# for legacy reasons
REDIS_SECRET_KEY = 'SECRET_TOKEN'
REDIS_VALIDATE_SECONDS = 30
# In Rails secret_key_base is used to encrypt the cookie store
# the cookie store contains session data
# Discourse also uses this secret key to digest user auth tokens
@ -19,9 +21,21 @@ class GlobalSetting
# - generate a token on the fly if needed and cache in redis
# - enforce rules about token format falling back to redis if needed
def self.safe_secret_key_base
if @safe_secret_key_base && @token_in_redis && (@token_last_validated + REDIS_VALIDATE_SECONDS) < Time.now
token = $redis.without_namespace.get(REDIS_SECRET_KEY)
if token.nil?
$redis.without_namespace.set(REDIS_SECRET_KEY, @safe_secret_key_base)
end
end
@safe_secret_key_base ||= begin
token = secret_key_base
if token.blank? || token !~ VALID_SECRET_KEY
@token_in_redis = true
@token_last_validated = Time.now
token = $redis.without_namespace.get(REDIS_SECRET_KEY)
unless token && token =~ VALID_SECRET_KEY
token = SecureRandom.hex(64)

View File

@ -2,6 +2,27 @@ require 'rails_helper'
require 'tempfile'
describe GlobalSetting do
describe '.safe_secret_key_base' do
it 'sets redis token if it is somehow flushed after 30 seconds' do
token = GlobalSetting.safe_secret_key_base
$redis.without_namespace.del(GlobalSetting::REDIS_SECRET_KEY)
freeze_time 20.seconds.from_now
GlobalSetting.safe_secret_key_base
new_token = $redis.without_namespace.get(GlobalSetting::REDIS_SECRET_KEY)
expect(new_token).to eq(nil)
freeze_time 31.seconds.from_now
GlobalSetting.safe_secret_key_base
new_token = $redis.without_namespace.get(GlobalSetting::REDIS_SECRET_KEY)
expect(new_token).to eq(token)
end
end
describe '.redis_config' do
describe 'when slave config is not present' do
it "should not set any connector" do