From f85694acfdaf57c113bba49ca2aef949b16d4141 Mon Sep 17 00:00:00 2001 From: David Roetzel Date: Thu, 5 Sep 2024 16:06:58 +0200 Subject: [PATCH] Add credentials to redis sentinel configuration (#31768) --- lib/mastodon/redis_configuration.rb | 45 ++++++++++++------- spec/lib/mastodon/redis_configuration_spec.rb | 23 +++++++--- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/lib/mastodon/redis_configuration.rb b/lib/mastodon/redis_configuration.rb index 5a096a1bf2..3d739a2ac6 100644 --- a/lib/mastodon/redis_configuration.rb +++ b/lib/mastodon/redis_configuration.rb @@ -57,39 +57,50 @@ class Mastodon::RedisConfiguration def setup_config(prefix: nil, defaults: {}) prefix = "#{prefix}REDIS_" - url = ENV.fetch("#{prefix}URL", nil) - user = ENV.fetch("#{prefix}USER", nil) - password = ENV.fetch("#{prefix}PASSWORD", nil) - host = ENV.fetch("#{prefix}HOST", defaults[:host]) - port = ENV.fetch("#{prefix}PORT", defaults[:port]) - db = ENV.fetch("#{prefix}DB", defaults[:db]) - name = ENV.fetch("#{prefix}SENTINEL_MASTER", nil) - sentinel_port = ENV.fetch("#{prefix}SENTINEL_PORT", 26_379) - sentinel_list = ENV.fetch("#{prefix}SENTINELS", nil) + url = ENV.fetch("#{prefix}URL", nil) + user = ENV.fetch("#{prefix}USER", nil) + password = ENV.fetch("#{prefix}PASSWORD", nil) + host = ENV.fetch("#{prefix}HOST", defaults[:host]) + port = ENV.fetch("#{prefix}PORT", defaults[:port]) + db = ENV.fetch("#{prefix}DB", defaults[:db]) return { url:, driver: } if url - sentinels = parse_sentinels(sentinel_list, default_port: sentinel_port) + sentinel_options = setup_sentinels(prefix, default_user: user, default_password: password) - if name.present? && sentinels.present? - host = name + if sentinel_options.present? + host = sentinel_options[:name] port = nil db ||= 0 - else - sentinels = nil end url = construct_uri(host, port, db, user, password) if url.present? - { url:, driver:, name:, sentinels: } + { url:, driver: }.merge(sentinel_options) else - # Fall back to base config. This has defaults for the URL - # so this cannot lead to an endless loop. + # Fall back to base config, which has defaults for the URL + # so this cannot lead to endless recursion. base end end + def setup_sentinels(prefix, default_user: nil, default_password: nil) + name = ENV.fetch("#{prefix}SENTINEL_MASTER", nil) + sentinel_port = ENV.fetch("#{prefix}SENTINEL_PORT", 26_379) + sentinel_list = ENV.fetch("#{prefix}SENTINELS", nil) + sentinel_username = ENV.fetch("#{prefix}SENTINEL_USERNAME", default_user) + sentinel_password = ENV.fetch("#{prefix}SENTINEL_PASSWORD", default_password) + + sentinels = parse_sentinels(sentinel_list, default_port: sentinel_port) + + if name.present? && sentinels.present? + { name:, sentinels:, sentinel_username:, sentinel_password: } + else + {} + end + end + def construct_uri(host, port, db, user, password) return nil if host.blank? diff --git a/spec/lib/mastodon/redis_configuration_spec.rb b/spec/lib/mastodon/redis_configuration_spec.rb index d14adf9518..e36dcfba0a 100644 --- a/spec/lib/mastodon/redis_configuration_spec.rb +++ b/spec/lib/mastodon/redis_configuration_spec.rb @@ -100,10 +100,27 @@ RSpec.describe Mastodon::RedisConfiguration do expect(subject[:url]).to eq 'redis://:testpass1@mainsentinel/0' end + it 'uses the redis password to authenticate with sentinels' do + expect(subject[:sentinel_password]).to eq 'testpass1' + end + it 'includes the sentinel master name and list of sentinels' do expect(subject[:name]).to eq 'mainsentinel' expect(subject[:sentinels]).to contain_exactly({ host: '192.168.0.1', port: 3000 }, { host: '192.168.0.2', port: 4000 }) end + + context "when giving dedicated credentials in `#{prefix}REDIS_SENTINEL_USERNAME` and `#{prefix}REDIS_SENTINEL_PASSWORD`" do + around do |example| + ClimateControl.modify "#{prefix}REDIS_SENTINEL_USERNAME": 'sentinel_user', "#{prefix}REDIS_SENTINEL_PASSWORD": 'sentinel_pass1' do + example.run + end + end + + it 'uses the credential to authenticate with sentinels' do + expect(subject[:sentinel_username]).to eq 'sentinel_user' + expect(subject[:sentinel_password]).to eq 'sentinel_pass1' + end + end end context 'when giving sentinels without port numbers' do @@ -154,8 +171,6 @@ RSpec.describe Mastodon::RedisConfiguration do url: 'redis://localhost:6379/0', driver: :hiredis, namespace: nil, - name: nil, - sentinels: nil, }) end end @@ -188,8 +203,6 @@ RSpec.describe Mastodon::RedisConfiguration do url: 'redis://:testpass@redis.example.com:3333/3', driver: :hiredis, namespace: nil, - name: nil, - sentinels: nil, }) end end @@ -218,8 +231,6 @@ RSpec.describe Mastodon::RedisConfiguration do namespace: 'cache', expires_in: 10.minutes, connect_timeout: 5, - name: nil, - sentinels: nil, pool: { size: 5, timeout: 5,