1
0
Fork 0
mirror of https://github.com/mperham/sidekiq.git synced 2022-11-09 13:52:34 -05:00
mperham--sidekiq/test/test_redis_connection.rb
Geoff Harcourt dd0a8476ea
Remove SSL parameters from Redis connection logging to avoid exception (#4532)
In 3f9c4bf9 the Redis connection options began to be cloned (via dumping
and re-marshalling) to avoid issues with password redaction in logging
altering the connection options and breaking authentication with Sentinels.

Unfortunately, this change caused an exception on boot for users of
Redis over SSL. The `OpenSSL::X509::Store` object used for SSL certs is
not yet dumpable in the bundled OpenSSL wrapper for current Rubies
(although it does in master as of ruby/openssl#281).

The fix here prunes the `ssl_params` options out of the Redis
configuration options before the dumping and marshalling. It's probably
better not to include those in logging anyway for privacy purposes.

Fix #4531
2020-04-18 13:00:29 -07:00

300 lines
8.8 KiB
Ruby

# frozen_string_literal: true
require_relative 'helper'
require 'sidekiq/cli'
describe Sidekiq::RedisConnection do
describe "create" do
before do
Sidekiq.options = Sidekiq::DEFAULTS.dup
@old = ENV['REDIS_URL']
ENV['REDIS_URL'] = 'redis://localhost/15'
end
after do
ENV['REDIS_URL'] = @old
end
# To support both redis-rb 3.3.x #client and 4.0.x #_client
def client_for(redis)
if redis.respond_to?(:_client)
redis._client
else
redis.client
end
end
it "creates a pooled redis connection" do
pool = Sidekiq::RedisConnection.create
assert_equal Redis, pool.checkout.class
end
# Readers for these ivars should be available in the next release of
# `connection_pool`, until then we need to reach into the internal state to
# verify the setting.
describe "size" do
def client_connection(*args)
Sidekiq.stub(:server?, nil) do
Sidekiq::RedisConnection.create(*args)
end
end
def server_connection(*args)
Sidekiq.stub(:server?, "constant") do
Sidekiq::RedisConnection.create(*args)
end
end
it "uses the specified custom pool size" do
pool = client_connection(size: 42)
assert_equal 42, pool.instance_eval{ @size }
assert_equal 42, pool.instance_eval{ @available.length }
pool = server_connection(size: 42)
assert_equal 42, pool.instance_eval{ @size }
assert_equal 42, pool.instance_eval{ @available.length }
end
it "defaults server pool sizes based on concurrency with padding" do
_expected_padding = 5
prev_concurrency = Sidekiq.options[:concurrency]
Sidekiq.options[:concurrency] = 6
pool = server_connection
assert_equal 11, pool.instance_eval{ @size }
assert_equal 11, pool.instance_eval{ @available.length }
ensure
Sidekiq.options[:concurrency] = prev_concurrency
end
it "defaults client pool sizes to 5" do
pool = client_connection
assert_equal 5, pool.instance_eval{ @size }
assert_equal 5, pool.instance_eval{ @available.length }
end
it "changes client pool sizes with ENV" do
begin
ENV['RAILS_MAX_THREADS'] = '9'
pool = client_connection
assert_equal 9, pool.instance_eval{ @size }
assert_equal 9, pool.instance_eval{ @available.length }
ensure
ENV.delete('RAILS_MAX_THREADS')
end
end
end
it "disables client setname with nil id" do
pool = Sidekiq::RedisConnection.create(:id => nil)
assert_equal Redis, pool.checkout.class
assert_equal "redis://localhost:6379/15", pool.checkout.connection.fetch(:id)
end
describe "network_timeout" do
it "sets a custom network_timeout if specified" do
pool = Sidekiq::RedisConnection.create(:network_timeout => 8)
redis = pool.checkout
assert_equal 8, client_for(redis).timeout
end
it "uses the default network_timeout if none specified" do
pool = Sidekiq::RedisConnection.create
redis = pool.checkout
assert_equal 5, client_for(redis).timeout
end
end
describe "namespace" do
it "uses a given :namespace set by a symbol key" do
pool = Sidekiq::RedisConnection.create(:namespace => "xxx")
assert_equal "xxx", pool.checkout.namespace
end
it "uses a given :namespace set by a string key" do
pool = Sidekiq::RedisConnection.create("namespace" => "xxx")
assert_equal "xxx", pool.checkout.namespace
end
it "uses given :namespace over :namespace from Sidekiq.options" do
Sidekiq.options[:namespace] = "xxx"
pool = Sidekiq::RedisConnection.create(:namespace => "yyy")
assert_equal "yyy", pool.checkout.namespace
end
end
describe "socket path" do
it "uses a given :path" do
pool = Sidekiq::RedisConnection.create(:path => "/var/run/redis.sock")
assert_equal "unix", client_for(pool.checkout).scheme
assert_equal "/var/run/redis.sock", pool.checkout.connection.fetch(:location)
assert_equal 15, pool.checkout.connection.fetch(:db)
end
it "uses a given :path and :db" do
pool = Sidekiq::RedisConnection.create(:path => "/var/run/redis.sock", :db => 8)
assert_equal "unix", client_for(pool.checkout).scheme
assert_equal "/var/run/redis.sock", pool.checkout.connection.fetch(:location)
assert_equal 8, pool.checkout.connection.fetch(:db)
end
end
describe "pool_timeout" do
it "uses a given :timeout over the default of 1" do
pool = Sidekiq::RedisConnection.create(:pool_timeout => 5)
assert_equal 5, pool.instance_eval{ @timeout }
end
it "uses the default timeout of 1 if no override" do
pool = Sidekiq::RedisConnection.create
assert_equal 1, pool.instance_eval{ @timeout }
end
end
describe "driver" do
it "uses redis' ruby driver" do
pool = Sidekiq::RedisConnection.create
redis = pool.checkout
assert_equal Redis::Connection::Ruby, redis.instance_variable_get(:@client).driver
end
it "uses redis' default driver if there are many available" do
begin
redis_driver = Object.new
Redis::Connection.drivers << redis_driver
pool = Sidekiq::RedisConnection.create
redis = pool.checkout
assert_equal redis_driver, redis.instance_variable_get(:@client).driver
ensure
Redis::Connection.drivers.pop
end
end
it "uses a given :driver" do
redis_driver = Object.new
pool = Sidekiq::RedisConnection.create(:driver => redis_driver)
redis = pool.checkout
assert_equal redis_driver, redis.instance_variable_get(:@client).driver
end
end
describe 'logging redis options' do
it 'redacts credentials' do
options = {
role: 'master',
master_name: 'mymaster',
sentinels: [
{ host: 'host1', port: 26379, password: 'secret'},
{ host: 'host2', port: 26379, password: 'secret'},
{ host: 'host3', port: 26379, password: 'secret'},
],
password: 'secret'
}
output = capture_logging do
Sidekiq::RedisConnection.create(options)
end
refute_includes(options.inspect, "REDACTED")
assert_includes(output, ':host=>"host1", :port=>26379, :password=>"REDACTED"')
assert_includes(output, ':host=>"host2", :port=>26379, :password=>"REDACTED"')
assert_includes(output, ':host=>"host3", :port=>26379, :password=>"REDACTED"')
assert_includes(output, ':password=>"REDACTED"')
end
it 'prunes SSL parameters from the logging' do
options = {
ssl_params: {
cert_store: OpenSSL::X509::Store.new
}
}
output = capture_logging do
Sidekiq::RedisConnection.create(options)
end
assert_includes(options.inspect, "ssl_params")
refute_includes(output, "ssl_params")
end
end
end
describe ".determine_redis_provider" do
before do
@old_env = ENV.to_hash
end
after do
ENV.update(@old_env)
end
def with_env_var(var, uri, skip_provider=false)
vars = ['REDISTOGO_URL', 'REDIS_PROVIDER', 'REDIS_URL'] - [var]
vars.each do |v|
next if skip_provider
ENV[v] = nil
end
ENV[var] = uri
assert_equal uri, Sidekiq::RedisConnection.__send__(:determine_redis_provider)
ENV[var] = nil
end
describe "with REDISTOGO_URL and a parallel REDIS_PROVIDER set" do
it "sets connection URI to the provider" do
uri = 'redis://sidekiq-redis-provider:6379/0'
provider = 'SIDEKIQ_REDIS_PROVIDER'
ENV['REDIS_PROVIDER'] = provider
ENV[provider] = uri
ENV['REDISTOGO_URL'] = 'redis://redis-to-go:6379/0'
with_env_var provider, uri, true
ENV[provider] = nil
end
end
describe "with REDIS_PROVIDER set" do
it "rejects URLs in REDIS_PROVIDER" do
uri = 'redis://sidekiq-redis-provider:6379/0'
ENV['REDIS_PROVIDER'] = uri
assert_raises RuntimeError do
Sidekiq::RedisConnection.__send__(:determine_redis_provider)
end
ENV['REDIS_PROVIDER'] = nil
end
it "sets connection URI to the provider" do
uri = 'redis://sidekiq-redis-provider:6379/0'
provider = 'SIDEKIQ_REDIS_PROVIDER'
ENV['REDIS_PROVIDER'] = provider
ENV[provider] = uri
with_env_var provider, uri, true
ENV[provider] = nil
end
end
describe "with REDIS_URL set" do
it "sets connection URI to custom uri" do
with_env_var 'REDIS_URL', 'redis://redis-uri:6379/0'
end
end
end
end