Skip to content

Commit f213950

Browse files
committed
NO-JIRA: allow loading of keystore and truststore by mean of system properties
1 parent a248f02 commit f213950

File tree

4 files changed

+417
-246
lines changed

4 files changed

+417
-246
lines changed

qpid-jms-client/src/main/java/org/apache/qpid/jms/transports/TransportOptions.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,14 @@
1616
*/
1717
package org.apache.qpid.jms.transports;
1818

19+
import javax.net.ssl.SSLContext;
1920
import java.util.Arrays;
2021
import java.util.Collections;
2122
import java.util.HashMap;
2223
import java.util.List;
2324
import java.util.Map;
2425
import java.util.function.Supplier;
2526

26-
import javax.net.ssl.SSLContext;
27-
2827
/**
2928
* Encapsulates all the Transport options in one configuration object.
3029
*/
@@ -77,8 +76,10 @@ public class TransportOptions implements Cloneable {
7776
private int sharedEventLoopThreads = DEFAULT_SHARED_EVENT_LOOP_THREADS;
7877

7978
private String keyStoreLocation;
79+
private String keyStoreBase64Property;
8080
private String keyStorePassword;
8181
private String trustStoreLocation;
82+
private String trustStoreBase64Property;
8283
private String trustStorePassword;
8384
private String keyStoreType;
8485
private String trustStoreType;
@@ -323,6 +324,23 @@ public void setKeyStoreLocation(String keyStoreLocation) {
323324
this.keyStoreLocation = keyStoreLocation;
324325
}
325326

327+
/**
328+
* @return the keyStoreBase64Property currently configured.
329+
*/
330+
public String getKeyStoreBase64Property() {
331+
return keyStoreBase64Property;
332+
}
333+
334+
/**
335+
* Sets the system property containing the base64 definition of the key store to use.
336+
*
337+
* @param keyStoreBase64Property
338+
* the keyStoreBase64Property to use to create the key manager.
339+
*/
340+
public void setKeyStoreBase64Property(final String keyStoreBase64Property) {
341+
this.keyStoreBase64Property = keyStoreBase64Property;
342+
}
343+
326344
/**
327345
* @return the keyStorePassword
328346
*/
@@ -351,6 +369,23 @@ public void setTrustStoreLocation(String trustStoreLocation) {
351369
this.trustStoreLocation = trustStoreLocation;
352370
}
353371

372+
/**
373+
* @return the trustStoreBase64Property
374+
*/
375+
public String getTrustStoreBase64Property() {
376+
return trustStoreBase64Property;
377+
}
378+
379+
/**
380+
* Sets the system property containing the base64 definition of the trust store to use.
381+
*
382+
* @param trustStoreBase64Property
383+
* the trustStoreBase64Property to set.
384+
*/
385+
public void setTrustStoreBase64Property(final String trustStoreBase64Property) {
386+
this.trustStoreBase64Property = trustStoreBase64Property;
387+
}
388+
354389
/**
355390
* @return the trustStorePassword
356391
*/
@@ -581,8 +616,10 @@ protected TransportOptions copyOptions(TransportOptions copy) {
581616
copy.setUseEpoll(isUseEpoll());
582617
copy.setTraceBytes(isTraceBytes());
583618
copy.setKeyStoreLocation(getKeyStoreLocation());
619+
copy.setKeyStoreBase64Property(getKeyStoreBase64Property());
584620
copy.setKeyStorePassword(getKeyStorePassword());
585621
copy.setTrustStoreLocation(getTrustStoreLocation());
622+
copy.setTrustStoreBase64Property(getTrustStoreBase64Property());
586623
copy.setTrustStorePassword(getTrustStorePassword());
587624
copy.setKeyStoreType(getKeyStoreType());
588625
copy.setTrustStoreType(getTrustStoreType());

qpid-jms-client/src/main/java/org/apache/qpid/jms/transports/TransportSupport.java

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@
1616
*/
1717
package org.apache.qpid.jms.transports;
1818

19-
import java.io.File;
20-
import java.io.FileInputStream;
21-
import java.io.InputStream;
22-
import java.net.URI;
23-
import java.security.KeyStore;
24-
import java.security.KeyStoreException;
25-
import java.security.SecureRandom;
26-
import java.util.ArrayList;
27-
import java.util.Arrays;
28-
import java.util.List;
19+
import io.netty.buffer.ByteBufAllocator;
20+
import io.netty.handler.ssl.OpenSsl;
21+
import io.netty.handler.ssl.OpenSslX509KeyManagerFactory;
22+
import io.netty.handler.ssl.SslContext;
23+
import io.netty.handler.ssl.SslContextBuilder;
24+
import io.netty.handler.ssl.SslHandler;
25+
import io.netty.handler.ssl.SslProvider;
26+
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
27+
import org.slf4j.Logger;
28+
import org.slf4j.LoggerFactory;
2929

3030
import javax.net.ssl.KeyManager;
3131
import javax.net.ssl.KeyManagerFactory;
@@ -35,18 +35,17 @@
3535
import javax.net.ssl.TrustManager;
3636
import javax.net.ssl.TrustManagerFactory;
3737
import javax.net.ssl.X509ExtendedKeyManager;
38-
39-
import org.slf4j.Logger;
40-
import org.slf4j.LoggerFactory;
41-
42-
import io.netty.buffer.ByteBufAllocator;
43-
import io.netty.handler.ssl.OpenSsl;
44-
import io.netty.handler.ssl.OpenSslX509KeyManagerFactory;
45-
import io.netty.handler.ssl.SslContext;
46-
import io.netty.handler.ssl.SslContextBuilder;
47-
import io.netty.handler.ssl.SslHandler;
48-
import io.netty.handler.ssl.SslProvider;
49-
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
38+
import java.io.ByteArrayInputStream;
39+
import java.io.FileInputStream;
40+
import java.io.InputStream;
41+
import java.net.URI;
42+
import java.security.KeyStore;
43+
import java.security.KeyStoreException;
44+
import java.security.SecureRandom;
45+
import java.util.ArrayList;
46+
import java.util.Arrays;
47+
import java.util.Base64;
48+
import java.util.List;
5049

5150
/**
5251
* Static class that provides various utility methods used by Transport implementations.
@@ -341,39 +340,39 @@ private static TrustManagerFactory loadTrustManagerFactory(TransportOptions opti
341340
return InsecureTrustManagerFactory.INSTANCE;
342341
}
343342

344-
if (options.getTrustStoreLocation() == null) {
343+
String storeLocation = options.getTrustStoreLocation();
344+
String storeBase64Property = options.getTrustStoreBase64Property();
345+
if (storeLocation == null && storeBase64Property == null) {
345346
return null;
347+
} else if (storeLocation != null && storeBase64Property != null) {
348+
throw new IllegalArgumentException("Only one of trustStoreLocation and trustStoreBase64Property should be defined");
346349
}
347350

348351
TrustManagerFactory fact = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
349352

350-
String storeLocation = options.getTrustStoreLocation();
351353
String storePassword = options.getTrustStorePassword();
352354
String storeType = options.getTrustStoreType();
353-
354-
LOG.trace("Attempt to load TrustStore from location {} of type {}", storeLocation, storeType);
355-
356-
KeyStore trustStore = loadStore(storeLocation, storePassword, storeType);
355+
KeyStore trustStore = loadStore(storeLocation, storeBase64Property, storePassword, storeType);
357356
fact.init(trustStore);
358357

359358
return fact;
360359
}
361360

362361
private static KeyManager[] loadKeyManagers(TransportOptions options) throws Exception {
363-
if (options.getKeyStoreLocation() == null) {
362+
String storeLocation = options.getKeyStoreLocation();
363+
String storeBase64Property = options.getKeyStoreBase64Property();
364+
if (storeLocation == null && storeBase64Property == null) {
364365
return null;
366+
} else if (storeLocation != null && storeBase64Property != null) {
367+
throw new IllegalArgumentException("Only one of keyStoreLocation and keyStoreBase64Property should be defined");
365368
}
366369

367370
KeyManagerFactory fact = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
368371

369-
String storeLocation = options.getKeyStoreLocation();
370372
String storePassword = options.getKeyStorePassword();
371373
String storeType = options.getKeyStoreType();
372374
String alias = options.getKeyAlias();
373-
374-
LOG.trace("Attempt to load KeyStore from location {} of type {}", storeLocation, storeType);
375-
376-
KeyStore keyStore = loadStore(storeLocation, storePassword, storeType);
375+
KeyStore keyStore = loadStore(storeLocation, storeBase64Property, storePassword, storeType);
377376
fact.init(keyStore, storePassword != null ? storePassword.toCharArray() : null);
378377

379378
if (alias == null) {
@@ -385,8 +384,12 @@ private static KeyManager[] loadKeyManagers(TransportOptions options) throws Exc
385384
}
386385

387386
private static KeyManagerFactory loadKeyManagerFactory(TransportOptions options, SslProvider provider) throws Exception {
388-
if (options.getKeyStoreLocation() == null) {
387+
String storeLocation = options.getKeyStoreLocation();
388+
String storeBase64Property = options.getKeyStoreBase64Property();
389+
if (storeLocation == null && storeBase64Property == null) {
389390
return null;
391+
} else if (storeLocation != null && storeBase64Property != null) {
392+
throw new IllegalArgumentException("Only one of keyStoreLocation and keyStoreBase64Property should be defined");
390393
}
391394

392395
final KeyManagerFactory factory;
@@ -396,13 +399,9 @@ private static KeyManagerFactory loadKeyManagerFactory(TransportOptions options,
396399
factory = new OpenSslX509KeyManagerFactory();
397400
}
398401

399-
String storeLocation = options.getKeyStoreLocation();
400402
String storePassword = options.getKeyStorePassword();
401403
String storeType = options.getKeyStoreType();
402-
403-
LOG.trace("Attempt to load KeyStore from location {} of type {}", storeLocation, storeType);
404-
405-
KeyStore keyStore = loadStore(storeLocation, storePassword, storeType);
404+
KeyStore keyStore = loadStore(storeLocation, storeBase64Property, storePassword, storeType);
406405
factory.init(keyStore, storePassword != null ? storePassword.toCharArray() : null);
407406

408407
return factory;
@@ -432,12 +431,33 @@ private static void validateAlias(KeyStore store, String alias) throws IllegalAr
432431
}
433432
}
434433

435-
private static KeyStore loadStore(String storePath, final String password, String storeType) throws Exception {
434+
private static KeyStore loadStore(final String storeLocation, final String storeBase64Property, final String password, String storeType) throws Exception {
435+
KeyStore store;
436+
if (storeLocation != null) {
437+
LOG.trace("Attempt to load store from location {} of type {}", storeLocation, storeType);
438+
store = loadStoreFromFile(storeLocation, password, storeType);
439+
} else {
440+
LOG.trace("Attempt to load store from system property {} of type {}", storeBase64Property, storeType);
441+
store = loadStoreFromSystemProperty(storeBase64Property, password, storeType);
442+
}
443+
return store;
444+
}
445+
446+
private static KeyStore loadStoreFromFile(final String storePath, final String password, final String storeType) throws Exception {
436447
KeyStore store = KeyStore.getInstance(storeType);
437-
try (InputStream in = new FileInputStream(new File(storePath));) {
448+
try (InputStream in = new FileInputStream(storePath)) {
438449
store.load(in, password != null ? password.toCharArray() : null);
439450
}
440451

441452
return store;
442453
}
454+
455+
private static KeyStore loadStoreFromSystemProperty(final String property, final String password, final String storeType) throws Exception {
456+
KeyStore store = KeyStore.getInstance(storeType);
457+
String keyStoreBase64 = System.getProperty(property);
458+
byte[] keyStoreBytes = Base64.getDecoder().decode(keyStoreBase64);
459+
store.load(new ByteArrayInputStream(keyStoreBytes), password != null ? password.toCharArray() : null);
460+
461+
return store;
462+
}
443463
}

qpid-jms-client/src/test/java/org/apache/qpid/jms/transports/TransportOptionsTest.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,20 @@
1616
*/
1717
package org.apache.qpid.jms.transports;
1818

19+
import io.netty.handler.proxy.ProxyHandler;
20+
import org.apache.qpid.jms.test.QpidJmsTestCase;
21+
import org.junit.jupiter.api.Test;
22+
import org.mockito.Mockito;
23+
24+
import javax.net.ssl.SSLContext;
25+
import java.util.function.Supplier;
26+
1927
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
2028
import static org.junit.jupiter.api.Assertions.assertEquals;
2129
import static org.junit.jupiter.api.Assertions.assertNotEquals;
2230
import static org.junit.jupiter.api.Assertions.assertNull;
2331
import static org.junit.jupiter.api.Assertions.fail;
2432

25-
import java.util.function.Supplier;
26-
27-
import javax.net.ssl.SSLContext;
28-
29-
import org.apache.qpid.jms.test.QpidJmsTestCase;
30-
import org.junit.jupiter.api.Test;
31-
import org.mockito.Mockito;
32-
33-
import io.netty.handler.proxy.ProxyHandler;
34-
3533
/**
3634
* Test for class TransportOptions
3735
*/
@@ -54,7 +52,9 @@ public class TransportOptionsTest extends QpidJmsTestCase {
5452

5553
private static final String PASSWORD = "password";
5654
private static final String CLIENT_KEYSTORE = "src/test/resources/client-jks.keystore";
55+
private static final String CLIENT_KEYSTORE_BASE64_PROPERTY = "base64.keystore.property";
5756
private static final String CLIENT_TRUSTSTORE = "src/test/resources/client-jks.truststore";
57+
private static final String CLIENT_TRUSTSTORE_BASE64_PROPERTY = "base64.truststore.property";
5858
private static final String KEYSTORE_TYPE = "jks";
5959
private static final String KEY_ALIAS = "myTestAlias";
6060
private static final String CONTEXT_PROTOCOL = "TLSv1.1";
@@ -93,8 +93,10 @@ public void testCreate() {
9393
assertNull(options.getDisabledCipherSuites());
9494

9595
assertNull(options.getKeyStoreLocation());
96+
assertNull(options.getKeyStoreBase64Property());
9697
assertNull(options.getKeyStorePassword());
9798
assertNull(options.getTrustStoreLocation());
99+
assertNull(options.getTrustStoreBase64Property());
98100
assertNull(options.getTrustStorePassword());
99101
assertNull(options.getKeyAlias());
100102
assertNull(options.getSslContextOverride());
@@ -136,8 +138,10 @@ public void testClone() {
136138
assertEquals(TEST_USE_EPOLL_VALUE, options.isUseEpoll());
137139
assertEquals(TEST_TRACE_BYTES_VALUE, options.isTraceBytes());
138140
assertEquals(CLIENT_KEYSTORE, options.getKeyStoreLocation());
141+
assertEquals(CLIENT_KEYSTORE_BASE64_PROPERTY, options.getKeyStoreBase64Property());
139142
assertEquals(PASSWORD, options.getKeyStorePassword());
140143
assertEquals(CLIENT_TRUSTSTORE, options.getTrustStoreLocation());
144+
assertEquals(CLIENT_TRUSTSTORE_BASE64_PROPERTY, options.getTrustStoreBase64Property());
141145
assertEquals(PASSWORD, options.getTrustStorePassword());
142146
assertEquals(KEYSTORE_TYPE, options.getKeyStoreType());
143147
assertEquals(KEYSTORE_TYPE, options.getTrustStoreType());
@@ -221,8 +225,10 @@ public void testCreateAndConfigure() {
221225
assertEquals(TEST_CONNECT_TIMEOUT, options.getConnectTimeout());
222226

223227
assertEquals(CLIENT_KEYSTORE, options.getKeyStoreLocation());
228+
assertEquals(CLIENT_KEYSTORE_BASE64_PROPERTY, options.getKeyStoreBase64Property());
224229
assertEquals(PASSWORD, options.getKeyStorePassword());
225230
assertEquals(CLIENT_TRUSTSTORE, options.getTrustStoreLocation());
231+
assertEquals(CLIENT_TRUSTSTORE_BASE64_PROPERTY, options.getTrustStoreBase64Property());
226232
assertEquals(PASSWORD, options.getTrustStorePassword());
227233
assertEquals(KEYSTORE_TYPE, options.getKeyStoreType());
228234
assertEquals(KEYSTORE_TYPE, options.getTrustStoreType());
@@ -240,7 +246,9 @@ private TransportOptions createSslOptions() {
240246
TransportOptions options = new TransportOptions();
241247

242248
options.setKeyStoreLocation(CLIENT_KEYSTORE);
249+
options.setKeyStoreBase64Property(CLIENT_KEYSTORE_BASE64_PROPERTY);
243250
options.setTrustStoreLocation(CLIENT_TRUSTSTORE);
251+
options.setTrustStoreBase64Property(CLIENT_TRUSTSTORE_BASE64_PROPERTY);
244252
options.setKeyStorePassword(PASSWORD);
245253
options.setTrustStorePassword(PASSWORD);
246254
options.setStoreType(KEYSTORE_TYPE);
@@ -327,8 +335,10 @@ private TransportOptions createNonDefaultOptions() {
327335
options.setUseEpoll(TEST_USE_EPOLL_VALUE);
328336
options.setTraceBytes(TEST_TRACE_BYTES_VALUE);
329337
options.setKeyStoreLocation(CLIENT_KEYSTORE);
338+
options.setKeyStoreBase64Property(CLIENT_KEYSTORE_BASE64_PROPERTY);
330339
options.setKeyStorePassword(PASSWORD);
331340
options.setTrustStoreLocation(CLIENT_TRUSTSTORE);
341+
options.setTrustStoreBase64Property(CLIENT_TRUSTSTORE_BASE64_PROPERTY);
332342
options.setTrustStorePassword(PASSWORD);
333343
options.setKeyAlias(KEY_ALIAS);
334344
options.setContextProtocol(CONTEXT_PROTOCOL);

0 commit comments

Comments
 (0)