From 8e153d6350ffc5eab8f8dc2d64492a9500843397 Mon Sep 17 00:00:00 2001 From: Sojan Jose Date: Thu, 24 Mar 2022 19:25:07 +0530 Subject: [PATCH] fix: Redis 6 on Heroku breaks ActionCable config (#4269) Heroku made some SSL/TLS changes with Redis 6, which is breaking the ActionCable configuration. Hence providing an environment variable configuration `REDIS_OPENSSL_VERIFY_MODE` to fix that. set the value `none` for this environment variable in your Heroku installations where breakage occurs. fixes: #2420 --- .env.example | 5 +++++ app.json | 4 ++++ config/application.rb | 9 +++++++++ config/cable.yml | 2 ++ lib/redis/config.rb | 1 + spec/lib/redis/config_spec.rb | 4 ++-- 6 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 36ca66be1..cc7e1c2dd 100644 --- a/.env.example +++ b/.env.example @@ -32,6 +32,11 @@ REDIS_SENTINELS= # You can find list of master using "SENTINEL masters" command REDIS_SENTINEL_MASTER_NAME= +# Redis premium breakage in heroku fix +# enable the following configuration +# ref: https://github.com/chatwoot/chatwoot/issues/2420 +# REDIS_OPENSSL_VERIFY_MODE=none + # Postgres Database config variables POSTGRES_HOST=postgres POSTGRES_USERNAME=postgres diff --git a/app.json b/app.json index 0d908761c..64edc4a81 100644 --- a/app.json +++ b/app.json @@ -32,6 +32,10 @@ "INSTALLATION_ENV": { "description": "Installation method used for Chatwoot.", "value": "heroku" + }, + "REDIS_OPENSSL_VERIFY_MODE":{ + "description": "OpenSSL verification mode for Redis connections. ref https://help.heroku.com/HC0F8CUS/redis-connection-issues", + "value": "none" } }, "formation": { diff --git a/config/application.rb b/config/application.rb index 0c7490dd7..4a114e0d7 100644 --- a/config/application.rb +++ b/config/application.rb @@ -33,4 +33,13 @@ module Chatwoot def self.config @config ||= Rails.configuration.x end + + def self.redis_ssl_verify_mode + # Introduced this method to fix the issue in heroku where redis connections fail for redis 6 + # ref: https://github.com/chatwoot/chatwoot/issues/2420 + # + # unless the redis verify mode is explicitly specified as none, we will fall back to the default 'verify peer' + # ref: https://www.rubydoc.info/stdlib/openssl/OpenSSL/SSL/SSLContext#DEFAULT_PARAMS-constant + ENV['REDIS_OPENSSL_VERIFY_MODE'] == 'none' ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER + end end diff --git a/config/cable.yml b/config/cable.yml index 6bb7a7844..3ecf68ee8 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -2,6 +2,8 @@ default: &default adapter: redis url: <%= ENV.fetch('REDIS_URL', 'redis://127.0.0.1:6379') %> password: <%= ENV.fetch('REDIS_PASSWORD', nil).presence %> + ssl_params: + verify_mode: <%= Chatwoot.redis_ssl_verify_mode %> channel_prefix: <%= "chatwoot_#{Rails.env}_action_cable" %> development: diff --git a/lib/redis/config.rb b/lib/redis/config.rb index 6e286f142..8e91b5bb0 100644 --- a/lib/redis/config.rb +++ b/lib/redis/config.rb @@ -13,6 +13,7 @@ module Redis::Config { url: ENV.fetch('REDIS_URL', 'redis://127.0.0.1:6379'), password: ENV.fetch('REDIS_PASSWORD', nil).presence, + ssl_params: { verify_mode: Chatwoot.redis_ssl_verify_mode }, reconnect_attempts: 2, network_timeout: 5 } diff --git a/spec/lib/redis/config_spec.rb b/spec/lib/redis/config_spec.rb index a82065328..a9093c341 100644 --- a/spec/lib/redis/config_spec.rb +++ b/spec/lib/redis/config_spec.rb @@ -16,7 +16,7 @@ describe ::Redis::Config do it 'checks for app redis config' do app_config = described_class.app - expect(app_config.keys).to match_array([:url, :password, :network_timeout, :reconnect_attempts]) + expect(app_config.keys).to match_array([:url, :password, :network_timeout, :reconnect_attempts, :ssl_params]) expect(app_config[:url]).to eq(redis_url) expect(app_config[:password]).to eq(redis_pasword) end @@ -46,7 +46,7 @@ describe ::Redis::Config do end it 'checks for app redis config' do - expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :network_timeout, :reconnect_attempts]) + expect(described_class.app.keys).to match_array([:url, :password, :sentinels, :network_timeout, :reconnect_attempts, :ssl_params]) expect(described_class.app[:url]).to eq("redis://#{redis_master_name}") expect(described_class.app[:sentinels]).to match_array(expected_sentinels) end