Skip to content

Commit 9c77213

Browse files
luisgomez29luisgomez29
andauthored
fix(rabbitmq): use Netty SslContext for SSL setup (#158)
* build(deps): update jackson-databind dependency to latest version * fix: simplify SSL setup in RabbitMQSetupUtils and utilize Netty's SslContext --------- Co-authored-by: luisgomez29 <luisgaleano002@gamil.com>
1 parent 6cb9529 commit 9c77213

File tree

9 files changed

+44
-86
lines changed

9 files changed

+44
-86
lines changed

async/async-commons/async-commons.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ dependencies {
99
api project(':cloudevents-json-jackson')
1010

1111
compileOnly 'io.projectreactor:reactor-core'
12-
api 'tools.jackson.core:jackson-databind:3.0.3'
12+
api 'tools.jackson.core:jackson-databind'
1313
implementation 'commons-io:commons-io:2.21.0'
1414
implementation 'io.cloudevents:cloudevents-core:4.0.1'
1515

async/async-rabbit/async-rabbit.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ dependencies {
1313
api 'io.projectreactor:reactor-core-micrometer'
1414
api 'io.projectreactor.rabbitmq:reactor-rabbitmq:1.5.6'
1515
api 'com.rabbitmq:amqp-client'
16-
api 'tools.jackson.core:jackson-databind:3.0.3'
16+
api 'tools.jackson.core:jackson-databind'
1717

1818
implementation 'io.cloudevents:cloudevents-core:4.0.1'
1919
testImplementation 'io.projectreactor:reactor-test'

async/cloudevents-json-jackson/cloudevents-json-jackson.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ ext {
44
}
55

66
dependencies {
7-
api 'tools.jackson.core:jackson-databind:3.0.3'
7+
api 'tools.jackson.core:jackson-databind'
88
implementation 'io.cloudevents:cloudevents-api:4.0.1'
99
implementation 'io.cloudevents:cloudevents-core:4.0.1'
1010
}

async/cloudevents-json-jackson/src/main/java/io/cloudevents/jackson/CloudEventDeserializer.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,6 @@ class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
4545
private final boolean forceIgnoreInvalidExtensionNameDeserialization;
4646
private final boolean disableDataContentTypeDefaulting;
4747

48-
protected CloudEventDeserializer() {
49-
this(false, false, false);
50-
}
51-
5248
protected CloudEventDeserializer(
5349
boolean forceExtensionNameLowerCaseDeserialization,
5450
boolean forceIgnoreInvalidExtensionNameDeserialization,

async/cloudevents-json-jackson/src/test/java/io/cloudevents/jackson/data/Data.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public class Data {
125125
.withExtension("integer", 42)
126126
.withExtension("decimal", new BigDecimal("42.42"))
127127
.withExtension("float", 4.2f)
128-
.withExtension("long", new Long(4200))
128+
.withExtension("long",4200L)
129129
.build();
130130

131131
public static Stream<CloudEvent> allEvents() {

build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ buildscript {
1212

1313
plugins {
1414
id 'jacoco'
15-
id 'org.sonarqube' version '7.2.0.6526'
16-
id 'org.springframework.boot' version '4.0.0' apply false
15+
id 'org.sonarqube' version '7.2.2.6593'
16+
id 'org.springframework.boot' version '4.0.1' apply false
1717
id 'io.github.gradle-nexus.publish-plugin' version '2.0.0'
18-
id 'co.com.bancolombia.cleanArchitecture' version '3.28.0'
18+
id 'co.com.bancolombia.cleanArchitecture' version '4.0.0'
1919
}
2020

2121
repositories {
2222
mavenCentral()
2323
}
2424

2525
apply from: './main.gradle'
26-
apply plugin: 'com.github.ben-manes.versions'
26+
apply plugin: 'com.github.ben-manes.versions'

domain/domain-events/domain-events-api.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,4 @@ ext {
66
dependencies {
77
api 'org.reactivestreams:reactive-streams:1.0.4'
88
api 'io.cloudevents:cloudevents-api:4.0.1'
9-
implementation 'io.cloudevents:cloudevents-json-jackson:4.0.1'
109
}

main.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ subprojects {
6666
testCompileOnly 'org.projectlombok:lombok'
6767
}
6868

69-
//TODO: Remove once it has been updated in spring boot 4.0.1
69+
//TODO: Remove once it has been updated in spring boot
7070
ext["rabbit-amqp-client.version"] = '5.28.0'
7171

7272
test.finalizedBy(project.tasks.jacocoTestReport)
@@ -90,7 +90,7 @@ subprojects {
9090

9191
dependencyManagement {
9292
imports {
93-
mavenBom 'org.springframework.boot:spring-boot-dependencies:4.0.0'
93+
mavenBom 'org.springframework.boot:spring-boot-dependencies:4.0.1'
9494
}
9595
}
9696

starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/rabbit/RabbitMQSetupUtils.java

Lines changed: 34 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.rabbitmq.client.Connection;
44
import com.rabbitmq.client.ConnectionFactory;
5+
import io.netty.handler.ssl.SslContext;
6+
import io.netty.handler.ssl.SslContextBuilder;
57
import lombok.AccessLevel;
68
import lombok.NoArgsConstructor;
79
import lombok.extern.java.Log;
@@ -31,24 +33,17 @@
3133
import reactor.rabbitmq.Utils;
3234
import reactor.util.retry.Retry;
3335

34-
import javax.net.ssl.KeyManager;
3536
import javax.net.ssl.KeyManagerFactory;
36-
import javax.net.ssl.SSLContext;
37-
import javax.net.ssl.TrustManager;
3837
import javax.net.ssl.TrustManagerFactory;
39-
import javax.net.ssl.X509TrustManager;
4038
import java.io.FileInputStream;
4139
import java.io.IOException;
4240
import java.io.InputStream;
43-
import java.security.KeyManagementException;
4441
import java.security.KeyStore;
4542
import java.security.KeyStoreException;
4643
import java.security.NoSuchAlgorithmException;
47-
import java.security.SecureRandom;
4844
import java.security.UnrecoverableKeyException;
4945
import java.security.cert.CertificateException;
5046
import java.time.Duration;
51-
import java.util.Arrays;
5247
import java.util.concurrent.ConcurrentHashMap;
5348
import java.util.concurrent.ConcurrentMap;
5449
import java.util.logging.Level;
@@ -57,29 +52,12 @@
5752
@NoArgsConstructor(access = AccessLevel.PRIVATE)
5853
public 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

Comments
 (0)