22
33import com .rabbitmq .client .Connection ;
44import com .rabbitmq .client .ConnectionFactory ;
5+ import io .netty .handler .ssl .SslContext ;
6+ import io .netty .handler .ssl .SslContextBuilder ;
57import lombok .AccessLevel ;
68import lombok .NoArgsConstructor ;
79import lombok .extern .java .Log ;
3133import reactor .rabbitmq .Utils ;
3234import reactor .util .retry .Retry ;
3335
34- import javax .net .ssl .KeyManager ;
3536import javax .net .ssl .KeyManagerFactory ;
36- import javax .net .ssl .SSLContext ;
37- import javax .net .ssl .TrustManager ;
3837import javax .net .ssl .TrustManagerFactory ;
39- import javax .net .ssl .X509TrustManager ;
4038import java .io .FileInputStream ;
4139import java .io .IOException ;
4240import java .io .InputStream ;
43- import java .security .KeyManagementException ;
4441import java .security .KeyStore ;
4542import java .security .KeyStoreException ;
4643import java .security .NoSuchAlgorithmException ;
47- import java .security .SecureRandom ;
4844import java .security .UnrecoverableKeyException ;
4945import java .security .cert .CertificateException ;
5046import java .time .Duration ;
51- import java .util .Arrays ;
5247import java .util .concurrent .ConcurrentHashMap ;
5348import java .util .concurrent .ConcurrentMap ;
5449import java .util .logging .Level ;
5752@ NoArgsConstructor (access = AccessLevel .PRIVATE )
5853public final class RabbitMQSetupUtils {
5954 private static final String SHARED_TYPE = "shared" ;
60- private static final String DEFAULT_PROTOCOL ;
6155 public static final int START_INTERVAL = 300 ;
6256 public static final int MAX_BACKOFF_INTERVAL = 3000 ;
6357
6458 private static final ConcurrentMap <AsyncProps , ConnectionFactory > FACTORY_CACHE = new ConcurrentHashMap <>();
6559 private static final ConcurrentMap <ConnectionFactory , Mono <Connection >> CONNECTION_CACHE = new ConcurrentHashMap <>();
6660
67- static {
68- String protocol = "TLSv1.1" ;
69- try {
70- String [] protocols = SSLContext .getDefault ().getSupportedSSLParameters ().getProtocols ();
71- for (String prot : protocols ) {
72- if ("TLSv1.2" .equals (prot )) {
73- protocol = "TLSv1.2" ;
74- break ;
75- }
76- }
77- } catch (NoSuchAlgorithmException e ) {
78- // nothing
79- }
80- DEFAULT_PROTOCOL = protocol ;
81- }
82-
8361 public static ConnectionFactoryProvider connectionFactoryProvider (AsyncProps asyncProps ,
8462 ConnectionFactoryCustomizer cfCustomizer ) {
8563 final ConnectionFactory factory = FACTORY_CACHE .computeIfAbsent (asyncProps , props -> {
@@ -177,54 +155,56 @@ private static Mono<Connection> createConnectionMono(ConnectionFactory factory,
177155
178156 // SSL based on RabbitConnectionFactoryBean
179157 // https://github.com/spring-projects/spring-amqp/blob/main/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/connection/RabbitConnectionFactoryBean.java
158+ // Adapted for Netty: https://www.rabbitmq.com/client-libraries/java-api-guide#netty
180159
181160 private static void setUpSSL (ConnectionFactory factory , RabbitProperties properties )
182- throws NoSuchAlgorithmException , KeyManagementException , KeyStoreException , UnrecoverableKeyException ,
161+ throws NoSuchAlgorithmException , KeyStoreException , UnrecoverableKeyException ,
183162 CertificateException , IOException {
184163 var ssl = properties .getSsl ();
185164 if (ssl != null && ssl .isEnabled ()) {
186- var keyManagers = configureKeyManagers (ssl );
187- var trustManagers = configureTrustManagers (ssl );
188- var secureRandom = SecureRandom .getInstanceStrong ();
165+ SslContextBuilder sslContextBuilder = SslContextBuilder .forClient ();
166+
167+ // Configure TrustManager
168+ var trustManagerFactory = configureTrustManagerFactory (ssl );
169+ sslContextBuilder .trustManager (trustManagerFactory );
189170
190- if (log .isLoggable (Level .FINE )) {
191- log .fine ("Initializing SSLContext with KM: " + Arrays .toString (keyManagers ) +
192- ", TM: " + Arrays .toString (trustManagers ) + ", random: " + secureRandom );
171+ // Configure KeyManager if keystore is provided
172+ if (ssl .getKeyStore () != null ) {
173+ var keyManagerFactory = configureKeyManagerFactory (ssl );
174+ sslContextBuilder .keyManager (keyManagerFactory );
193175 }
194- var context = createSSLContext (ssl );
195- context .init (keyManagers , trustManagers , secureRandom );
196- factory .useSslProtocol (context );
197176
198- logDetails (trustManagers );
177+ // Set SSL protocol if specified
178+ if (ssl .getAlgorithm () != null ) {
179+ log .info ("Using SSL protocol: " + ssl .getAlgorithm ());
180+ }
181+
182+ SslContext sslContext = sslContextBuilder .build ();
183+ factory .netty ().sslContext (sslContext );
199184
200185 if (ssl .isVerifyHostname ()) {
201186 factory .enableHostnameVerification ();
202187 }
203188 }
204189 }
205190
206- private static KeyManager [] configureKeyManagers (RabbitPropertiesBase .Ssl ssl ) throws KeyStoreException ,
207- IOException ,
208- NoSuchAlgorithmException ,
191+ private static KeyManagerFactory configureKeyManagerFactory (RabbitPropertiesBase .Ssl ssl )
192+ throws KeyStoreException , IOException , NoSuchAlgorithmException ,
209193 CertificateException , UnrecoverableKeyException {
210- KeyManager [] keyManagers = null ;
211- if (ssl .getKeyStore () != null ) {
212- var ks = KeyStore .getInstance (ssl .getKeyStoreType ());
213- char [] keyPassphrase = null ;
214- if (ssl .getKeyStorePassword () != null ) {
215- keyPassphrase = ssl .getKeyStorePassword ().toCharArray ();
216- }
217- try (var inputStream = new FileInputStream (ssl .getKeyStore ())) {
218- ks .load (inputStream , keyPassphrase );
219- }
220- var kmf = KeyManagerFactory .getInstance (KeyManagerFactory .getDefaultAlgorithm ());
221- kmf .init (ks , keyPassphrase );
222- keyManagers = kmf .getKeyManagers ();
194+ var ks = KeyStore .getInstance (ssl .getKeyStoreType ());
195+ char [] keyPassphrase = null ;
196+ if (ssl .getKeyStorePassword () != null ) {
197+ keyPassphrase = ssl .getKeyStorePassword ().toCharArray ();
223198 }
224- return keyManagers ;
199+ try (var inputStream = new FileInputStream (ssl .getKeyStore ())) {
200+ ks .load (inputStream , keyPassphrase );
201+ }
202+ var kmf = KeyManagerFactory .getInstance (KeyManagerFactory .getDefaultAlgorithm ());
203+ kmf .init (ks , keyPassphrase );
204+ return kmf ;
225205 }
226206
227- private static TrustManager [] configureTrustManagers (RabbitPropertiesBase .Ssl ssl )
207+ private static TrustManagerFactory configureTrustManagerFactory (RabbitPropertiesBase .Ssl ssl )
228208 throws KeyStoreException , IOException , NoSuchAlgorithmException , CertificateException {
229209 KeyStore tks = null ;
230210 if (ssl .getTrustStore () != null ) {
@@ -240,24 +220,7 @@ private static TrustManager[] configureTrustManagers(RabbitPropertiesBase.Ssl ss
240220
241221 var tmf = TrustManagerFactory .getInstance (TrustManagerFactory .getDefaultAlgorithm ());
242222 tmf .init (tks );
243- return tmf .getTrustManagers ();
244- }
245-
246- private static SSLContext createSSLContext (RabbitPropertiesBase .Ssl ssl ) throws NoSuchAlgorithmException {
247- return SSLContext .getInstance (ssl .getAlgorithm () != null ? ssl .getAlgorithm () : DEFAULT_PROTOCOL );
248- }
249-
250- private static void logDetails (TrustManager [] managers ) {
251- var found = false ;
252- for (var trustManager : managers ) {
253- if (trustManager instanceof X509TrustManager x509TrustManager ) {
254- found = true ;
255- log .info ("Loaded " + x509TrustManager .getAcceptedIssuers ().length + " accepted issuers for rabbitmq" );
256- }
257- }
258- if (!found ) {
259- log .warning ("No X509TrustManager found in the truststore." );
260- }
223+ return tmf ;
261224 }
262225
263226}
0 commit comments