Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions obp-api/src/main/resources/props/sample.props.template
Original file line number Diff line number Diff line change
Expand Up @@ -1085,10 +1085,14 @@ featured_apis=elasticSearchWarehouseV300
## Note: You do NOT need to include anything here for this to work.

# -- Redis cache -------------------------------------
# The 127.0.0.1 default is a deliberate security default: Redis must not be bound to a
# public interface. If you enable authentication (requirepass) or TLS on Redis, set the
# properties below - they are honoured by both the direct and the memoize-backed cache paths.
# cache.redis.url=127.0.0.1
# cache.redis.port=6379
# Default value is empty or omitted props
# cache.redis.password =
# redis.use.ssl=false
# ---------------------------------------------------------

# -- New Style Endpoints -----------------------
Expand Down
27 changes: 25 additions & 2 deletions obp-api/src/main/scala/code/api/cache/Redis.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,35 @@ object Redis extends MdcLoggable {
poolConfig.setNumTestsPerEvictionRun(3)
poolConfig.setBlockWhenExhausted(true)

// Lazy so the keystore/truststore files are only read when redis.use.ssl is on, and only once
// even though both jedisPool and every subscriber connection need the socket factory.
private lazy val sslContext: SSLContext = configureSslContext()

val jedisPool =
if (useSsl) {
// SSL connection: Use SSLContext with JedisPool
val sslContext = configureSslContext()
new JedisPool(poolConfig, url, port, timeout, password, true, sslContext.getSocketFactory, null, null)
} else {
// Non-SSL connection
new JedisPool(poolConfig, url, port, timeout, password)
}

/**
* Build a dedicated, non-pooled connection for a pub/sub subscriber.
*
* `subscribe`/`psubscribe` occupy their connection for the whole life of the subscription,
* so subscribers cannot lease from jedisPool. They must still apply the same password and
* TLS settings the pool uses: the plain `Jedis(url, port, timeout)` constructor is
* unencrypted, so building one directly silently ignores redis.use.ssl.
*/
def newSubscriberConnection(): Jedis = {
val jedis =
if (useSsl) new Jedis(url, port, timeout, true, sslContext.getSocketFactory, null, null)
else new Jedis(url, port, timeout)
if (password != null) jedis.auth(password)
jedis
}

// Redis startup health check
private def performStartupHealthCheck(): Unit = {
try {
Expand Down Expand Up @@ -290,7 +309,11 @@ object Redis extends MdcLoggable {
}
}

implicit val scalaCache = ScalaCache(RedisCache(url, port))
// Reuse the pool built above so the memoize-backed cache shares the same authenticated,
// optionally SSL-configured connection. The RedisCache(url, port) overload builds its own
// JedisPool internally with no password and no SSL, so with `requirepass` enabled it fails
// with NOAUTH while the jedisPool-based paths keep working.
implicit val scalaCache = ScalaCache(RedisCache(jedisPool))
implicit val flags = Flags(readsEnabled = true, writesEnabled = true)

implicit def anyToByte[T](implicit m: Manifest[T]) = new Codec[T, Array[Byte]] {
Expand Down
3 changes: 1 addition & 2 deletions obp-api/src/main/scala/code/chat/ChatEventBus.scala
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,7 @@ object ChatEventBus extends MdcLoggable {
subscriberThread = new Thread(() => {
try {
// Dedicated connection for the subscriber (not from the pool)
subscriberJedis = new Jedis(Redis.url, Redis.port, Redis.timeout)
if (Redis.password != null) subscriberJedis.auth(Redis.password)
subscriberJedis = Redis.newSubscriberConnection()
logger.info(s"ChatEventBus says: Redis subscriber started, pattern-subscribing to ${CHANNEL_PREFIX}*")
subscriberJedis.psubscribe(pubSub, s"${CHANNEL_PREFIX}*")
} catch {
Expand Down
3 changes: 1 addition & 2 deletions obp-api/src/main/scala/code/logcache/LogCacheEventBus.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ object LogCacheEventBus extends MdcLoggable {

subscriberThread = new Thread(() => {
try {
subscriberJedis = new Jedis(Redis.url, Redis.port, Redis.timeout)
if (Redis.password != null) subscriberJedis.auth(Redis.password)
subscriberJedis = Redis.newSubscriberConnection()
logger.info(s"LogCacheEventBus says: Redis subscriber started, pattern-subscribing to ${CHANNEL_PREFIX}*")
subscriberJedis.psubscribe(pubSub, s"${CHANNEL_PREFIX}*")
} catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@ object MetricsEventBus extends MdcLoggable {

subscriberThread = new Thread(() => {
try {
subscriberJedis = new Jedis(Redis.url, Redis.port, Redis.timeout)
if (Redis.password != null) subscriberJedis.auth(Redis.password)
subscriberJedis = Redis.newSubscriberConnection()
logger.info(s"MetricsEventBus says: Redis subscriber started, subscribing to $ALL_CHANNEL")
subscriberJedis.subscribe(pubSub, ALL_CHANNEL)
} catch {
Expand Down
Loading