RedissonManager.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2026 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.pdd.core.controllo_traffico.policy.driver.redisson;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import javax.net.ssl.TrustManagerFactory;
import org.openspcoop2.utils.UtilsException;
import org.openspcoop2.utils.certificate.KeystoreUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.BaseConfig;
import org.redisson.config.Config;
import org.redisson.config.ReadMode;
import org.redisson.config.SslVerificationMode;
import org.slf4j.Logger;
/**
* RedissonManager
*
* @author Francesco Scarlato (scarlato@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class RedissonManager {
private RedissonManager() {}
private static Logger logStartup;
private static Logger log;
private static List<String> connectionUrl = null;
private static RedissonConnectionMode connectionMode = RedissonConnectionMode.CLUSTER;
private static RedissonSSLConfig sslConfig = null;
private static final String INIZIALIZZAZIONE_FALLITA = "Inizializzazione RedissonClient fallita: ";
public static synchronized void initialize(Logger logStartup, Logger log, List<String> connectionUrl,
RedissonConnectionMode connectionMode, RedissonSSLConfig sslConfig) {
if(RedissonManager.connectionUrl==null){
RedissonManager.logStartup = logStartup;
RedissonManager.log = log;
RedissonManager.connectionUrl = connectionUrl;
if(connectionMode!=null) {
RedissonManager.connectionMode = connectionMode;
}
RedissonManager.sslConfig = sslConfig;
}
}
private static RedissonClient redisson = null;
private static synchronized void initRedissonClient(boolean throwInitializingException) throws UtilsException {
if(redisson==null) {
String msg = buildInitMessage();
RedissonManager.logStartup.info(msg);
RedissonManager.log.info(msg);
try {
Config redisConf = new Config();
if(RedissonConnectionMode.SINGLE.equals(RedissonManager.connectionMode)) {
String address = RedissonManager.connectionUrl.get(0);
applySslConfig(
redisConf.useSingleServer()
.setAddress(address)
);
}
else {
applySslConfig(
redisConf.useClusterServers()
.addNodeAddress(RedissonManager.connectionUrl.toArray(new String[1]))
.setReadMode(ReadMode.MASTER_SLAVE)
);
}
redisson = Redisson.create(redisConf);
RedissonManager.logStartup.info("Inizializzazione RedissonClient effettuata con successo");
RedissonManager.log.info("Inizializzazione RedissonClient effettuata con successo");
}catch(Exception t) {
if(throwInitializingException) {
throw new UtilsException(INIZIALIZZAZIONE_FALLITA+t.getMessage(),t);
}
else {
RedissonManager.logStartup.error(INIZIALIZZAZIONE_FALLITA+t.getMessage(),t);
RedissonManager.log.error(INIZIALIZZAZIONE_FALLITA+t.getMessage(),t);
}
}
}
}
private static String buildInitMessage() {
StringBuilder sb = new StringBuilder();
sb.append("Inizializzazione RedissonClient (mode: ").append(RedissonManager.connectionMode.getValue()).append(")");
// URL (con password mascherata)
sb.append(" url: ");
for(int i=0; i<RedissonManager.connectionUrl.size(); i++) {
if(i>0) {
sb.append(", ");
}
sb.append(maskPassword(RedissonManager.connectionUrl.get(i)));
}
// TLS
addTLSMessage(sb);
sb.append(" ...");
return sb.toString();
}
private static void addTLSMessage(StringBuilder sb) {
boolean tls = false;
for(String url : RedissonManager.connectionUrl) {
if(url.startsWith("rediss://")) {
tls = true;
break;
}
}
sb.append(" tls: ").append(tls ? "enabled" : "disabled");
if(tls && RedissonManager.sslConfig!=null) {
addTLSConfigMessage(sb);
}
}
private static void addTLSConfigMessage(StringBuilder sb) {
if(RedissonManager.sslConfig.isTrustAll()) {
sb.append(" (trustAll)");
}
else {
if(RedissonManager.sslConfig.getTruststorePath()!=null) {
sb.append(" (truststore: ").append(RedissonManager.sslConfig.getTruststorePath());
sb.append(", type: ").append(RedissonManager.sslConfig.getTruststoreType());
sb.append(", password: ").append(RedissonManager.sslConfig.getTruststorePassword()!=null ? "***" : "n/a");
sb.append(")");
}
sb.append(" hostnameVerifier: ").append(RedissonManager.sslConfig.isHostnameVerifier());
}
}
private static String maskPassword(String url) {
// Maschera la password in url del tipo redis://user:password@host:port
int schemeEnd = url.indexOf("://");
if(schemeEnd<0) {
return url;
}
int atSign = url.indexOf('@', schemeEnd+3);
if(atSign<0) {
return url;
}
String credentials = url.substring(schemeEnd+3, atSign);
int colonIdx = credentials.indexOf(':');
if(colonIdx<0) {
return url;
}
String user = credentials.substring(0, colonIdx);
return url.substring(0, schemeEnd+3) + user + ":***@" + url.substring(atSign+1);
}
/*
* Mapping proprietà SSL -> SslVerificationMode di Redisson:
* trustAll=true -> NONE (nessuna verifica: ne' certificato ne' hostname)
* hostnameVerifier=true (default)-> STRICT (verifica certificato CA + verifica hostname CN/SAN)
* hostnameVerifier=false -> CA_ONLY (verifica certificato CA, ma non l'hostname)
*/
private static <T extends BaseConfig<T>> void applySslConfig(T serverConfig) throws FileNotFoundException, UtilsException, NoSuchAlgorithmException, KeyStoreException {
if(RedissonManager.sslConfig==null) {
// backward compatibility: hostnameVerifier abilitato di default
serverConfig.setSslVerificationMode(SslVerificationMode.STRICT);
return;
}
serverConfig.setSslVerificationMode(RedissonManager.sslConfig.isHostnameVerifier() ? SslVerificationMode.STRICT : SslVerificationMode.CA_ONLY);
if(RedissonManager.sslConfig.isTrustAll()) {
serverConfig.setSslVerificationMode(SslVerificationMode.NONE);
}
else if(RedissonManager.sslConfig.getTruststorePath()!=null) {
KeyStore ks = KeystoreUtils.readKeystore(
new FileInputStream(RedissonManager.sslConfig.getTruststorePath()),
RedissonManager.sslConfig.getTruststoreType(),
RedissonManager.sslConfig.getTruststorePassword());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
serverConfig.setSslTrustManagerFactory(tmf);
}
}
public static RedissonClient getRedissonClient(boolean throwInitializingException) throws UtilsException {
if(redisson==null) {
initRedissonClient(throwInitializingException);
}
return RedissonManager.redisson;
}
public static boolean isRedissonClientInitialized() {
return RedissonManager.redisson!=null;
}
}