1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package nl.altindag.ssl;
18
19 import nl.altindag.log.LogCaptor;
20 import nl.altindag.ssl.exception.GenericKeyManagerException;
21 import nl.altindag.ssl.exception.GenericKeyStoreException;
22 import nl.altindag.ssl.exception.GenericSecurityException;
23 import nl.altindag.ssl.exception.GenericTrustManagerException;
24 import nl.altindag.ssl.keymanager.CompositeX509ExtendedKeyManager;
25 import nl.altindag.ssl.keymanager.HotSwappableX509ExtendedKeyManager;
26 import nl.altindag.ssl.trustmanager.HotSwappableX509ExtendedTrustManager;
27 import nl.altindag.ssl.trustmanager.UnsafeX509ExtendedTrustManager;
28 import nl.altindag.ssl.util.KeyManagerUtils;
29 import nl.altindag.ssl.util.KeyStoreUtils;
30 import nl.altindag.ssl.util.TrustManagerUtils;
31 import org.junit.jupiter.api.Test;
32 import org.junit.jupiter.api.extension.ExtendWith;
33 import org.mockito.junit.jupiter.MockitoExtension;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import javax.net.ssl.HostnameVerifier;
38 import javax.net.ssl.KeyManager;
39 import javax.net.ssl.KeyManagerFactory;
40 import javax.net.ssl.SSLEngine;
41 import javax.net.ssl.SSLSession;
42 import javax.net.ssl.SSLSessionContext;
43 import javax.net.ssl.TrustManager;
44 import javax.net.ssl.TrustManagerFactory;
45 import javax.net.ssl.X509ExtendedKeyManager;
46 import javax.net.ssl.X509ExtendedTrustManager;
47 import javax.security.auth.x500.X500Principal;
48 import java.io.IOException;
49 import java.io.InputStream;
50 import java.net.URI;
51 import java.nio.file.Files;
52 import java.nio.file.Path;
53 import java.nio.file.Paths;
54 import java.security.KeyStore;
55 import java.security.KeyStoreException;
56 import java.security.NoSuchAlgorithmException;
57 import java.security.PrivateKey;
58 import java.security.SecureRandom;
59 import java.security.Security;
60 import java.security.UnrecoverableKeyException;
61 import java.security.cert.Certificate;
62 import java.security.cert.CertificateException;
63 import java.security.cert.X509Certificate;
64 import java.util.Arrays;
65 import java.util.Collections;
66 import java.util.Objects;
67 import java.util.regex.Matcher;
68 import java.util.regex.Pattern;
69
70 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
71 import static nl.altindag.ssl.TestConstants.EMPTY;
72 import static nl.altindag.ssl.TestConstants.IDENTITY_FILE_NAME;
73 import static nl.altindag.ssl.TestConstants.IDENTITY_PASSWORD;
74 import static nl.altindag.ssl.TestConstants.KEYSTORE_LOCATION;
75 import static nl.altindag.ssl.TestConstants.TEMPORALLY_KEYSTORE_LOCATION;
76 import static nl.altindag.ssl.TestConstants.TRUSTSTORE_FILE_NAME;
77 import static nl.altindag.ssl.TestConstants.TRUSTSTORE_PASSWORD;
78 import static org.assertj.core.api.Assertions.assertThat;
79 import static org.assertj.core.api.Assertions.assertThatThrownBy;
80 import static org.assertj.core.api.Assertions.fail;
81 import static org.mockito.Mockito.mock;
82 import static org.mockito.Mockito.spy;
83 import static org.mockito.Mockito.when;
84
85
86
87
88 @ExtendWith(MockitoExtension.class)
89 class SSLFactoryShould {
90
91 private static final Logger LOGGER = LoggerFactory.getLogger(SSLFactoryShould.class);
92
93 private static final String GENERIC_IDENTITY_VALIDATION_EXCEPTION_MESSAGE = "Identity details are empty, which are required to be present when SSL/TLS is enabled";
94 private static final String GENERIC_TRUSTSTORE_VALIDATION_EXCEPTION_MESSAGE = "TrustStore details are empty, which are required to be present when SSL/TLS is enabled";
95
96 @Test
97 void buildSSLFactoryWithTrustMaterial() {
98 SSLFactory sslFactory = SSLFactory.builder()
99 .withTrustMaterial(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD)
100 .build();
101
102 assertThat(sslFactory.getSslContext()).isNotNull();
103
104 assertThat(sslFactory.getTrustManager()).isPresent();
105 assertThat(sslFactory.getTrustManager().get()).isNotInstanceOf(HotSwappableX509ExtendedTrustManager.class);
106 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
107 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
108 assertThat(sslFactory.getTrustStores()).isNotEmpty();
109 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
110 assertThat(sslFactory.getKeyManager()).isNotPresent();
111 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
112 }
113
114 @Test
115 void buildSSLFactoryWithSwappableTrustMaterial() {
116 SSLFactory sslFactory = SSLFactory.builder()
117 .withTrustMaterial(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD)
118 .withSwappableTrustMaterial()
119 .build();
120
121 assertThat(sslFactory.getSslContext()).isNotNull();
122
123 assertThat(sslFactory.getTrustManager()).isPresent();
124 assertThat(sslFactory.getTrustManager().get()).isInstanceOf(HotSwappableX509ExtendedTrustManager.class);
125 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
126 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
127 assertThat(sslFactory.getTrustStores()).isNotEmpty();
128 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
129 assertThat(sslFactory.getKeyManager()).isNotPresent();
130 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
131 }
132
133 @Test
134 void buildSSLFactoryWithTrustMaterialWithoutPassword() {
135 SSLFactory sslFactory = SSLFactory.builder()
136 .withTrustMaterial(KEYSTORE_LOCATION + "truststore-without-password.jks", null)
137 .build();
138
139 assertThat(sslFactory.getSslContext()).isNotNull();
140
141 assertThat(sslFactory.getTrustManager()).isPresent();
142 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
143 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
144 assertThat(sslFactory.getTrustStores()).isNotEmpty();
145 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
146
147 assertThat(sslFactory.getKeyManager()).isNotPresent();
148 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
149 assertThat(sslFactory.getIdentities()).isEmpty();
150 }
151
152 @Test
153 void buildSSLFactoryWithTrustMaterialFromPath() throws IOException {
154 Path trustStorePath = copyKeystoreToHomeDirectory(KEYSTORE_LOCATION, TRUSTSTORE_FILE_NAME);
155
156 SSLFactory sslFactory = SSLFactory.builder()
157 .withTrustMaterial(trustStorePath, TRUSTSTORE_PASSWORD)
158 .build();
159
160 assertThat(sslFactory.getSslContext()).isNotNull();
161
162 assertThat(sslFactory.getTrustManager()).isPresent();
163 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
164 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
165 assertThat(sslFactory.getTrustStores()).isNotEmpty();
166 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
167
168 assertThat(sslFactory.getKeyManager()).isNotPresent();
169 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
170 assertThat(sslFactory.getIdentities()).isEmpty();
171
172 Files.delete(trustStorePath);
173 }
174
175 @Test
176 void buildSSLFactoryWithTrustMaterialFromInputStream() {
177 InputStream trustStoreStream = getResourceAsStream(KEYSTORE_LOCATION, TRUSTSTORE_FILE_NAME);
178
179 SSLFactory sslFactory = SSLFactory.builder()
180 .withTrustMaterial(trustStoreStream, TRUSTSTORE_PASSWORD)
181 .build();
182
183 assertThat(sslFactory.getSslContext()).isNotNull();
184
185 assertThat(sslFactory.getTrustManager()).isPresent();
186 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
187 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
188 assertThat(sslFactory.getTrustStores()).isNotEmpty();
189 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
190 assertThat(sslFactory.getKeyManager()).isNotPresent();
191 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
192 }
193
194 @Test
195 void buildSSLFactoryWithTrustMaterialFromKeyStore() {
196 KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
197
198 SSLFactory sslFactory = SSLFactory.builder()
199 .withTrustMaterial(trustStore, TRUSTSTORE_PASSWORD)
200 .build();
201
202 assertThat(sslFactory.getSslContext()).isNotNull();
203
204 assertThat(sslFactory.getTrustManager()).isPresent();
205 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
206 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
207 assertThat(sslFactory.getTrustStores()).isNotEmpty();
208 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
209
210 assertThat(sslFactory.getKeyManager()).isNotPresent();
211 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
212 assertThat(sslFactory.getIdentities()).isEmpty();
213 }
214
215 @Test
216 void buildSSLFactoryWithTrustMaterialFromKeyStoreWithoutAdditionalPassword() {
217 KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
218
219 SSLFactory sslFactory = SSLFactory.builder()
220 .withTrustMaterial(trustStore)
221 .build();
222
223 assertThat(sslFactory.getSslContext()).isNotNull();
224
225 assertThat(sslFactory.getTrustManager()).isPresent();
226 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
227 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
228 assertThat(sslFactory.getTrustStores()).isNotEmpty();
229 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
230
231 assertThat(sslFactory.getKeyManager()).isNotPresent();
232 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
233 assertThat(sslFactory.getIdentities()).isEmpty();
234 }
235
236 @Test
237 void buildSSLFactoryWithTrustMaterialFromTrustManager() {
238 KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
239 X509ExtendedTrustManager trustManager = TrustManagerUtils.createTrustManager(trustStore);
240
241 SSLFactory sslFactory = SSLFactory.builder()
242 .withTrustMaterial(trustManager)
243 .build();
244
245 assertThat(sslFactory.getSslContext()).isNotNull();
246
247 assertThat(sslFactory.getTrustManager()).isPresent();
248 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
249 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
250 assertThat(sslFactory.getTrustStores()).isEmpty();
251 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
252
253 assertThat(sslFactory.getKeyManager()).isNotPresent();
254 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
255 assertThat(sslFactory.getIdentities()).isEmpty();
256 }
257
258 @Test
259 void buildSSLFactoryWithTrustMaterialFromTrustManagerFactory() throws NoSuchAlgorithmException, KeyStoreException {
260 KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
261 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
262 trustManagerFactory.init(trustStore);
263
264 SSLFactory sslFactory = SSLFactory.builder()
265 .withTrustMaterial(trustManagerFactory)
266 .build();
267
268 assertThat(sslFactory.getSslContext()).isNotNull();
269
270 assertThat(sslFactory.getTrustManager()).isPresent();
271 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
272 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
273 assertThat(sslFactory.getTrustStores()).isEmpty();
274 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
275
276 assertThat(sslFactory.getKeyManager()).isNotPresent();
277 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
278 assertThat(sslFactory.getIdentities()).isEmpty();
279 }
280
281 @Test
282 void buildSSLFactoryWithTrustMaterialFromCertificates() {
283 X509Certificate[] certificates = TrustManagerUtils.createTrustManagerWithJdkTrustedCertificates()
284 .getAcceptedIssuers();
285
286 SSLFactory sslFactory = SSLFactory.builder()
287 .withTrustMaterial(certificates)
288 .build();
289
290 assertThat(sslFactory.getSslContext()).isNotNull();
291
292 assertThat(sslFactory.getTrustManager()).isPresent();
293 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
294 assertThat(sslFactory.getTrustStores()).isNotEmpty();
295 assertThat(sslFactory.getTrustedCertificates()).hasSizeGreaterThan(10);
296
297 assertThat(sslFactory.getKeyManager()).isNotPresent();
298 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
299 assertThat(sslFactory.getIdentities()).isEmpty();
300 }
301
302 @Test
303 void buildSSLFactoryWithTrustMaterialFromOnlyJdkTrustedCertificates() {
304 SSLFactory sslFactory = SSLFactory.builder()
305 .withDefaultTrustMaterial()
306 .build();
307
308 assertThat(sslFactory.getSslContext()).isNotNull();
309
310 assertThat(sslFactory.getTrustManager()).isPresent();
311 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
312 assertThat(sslFactory.getTrustStores()).isEmpty();
313 assertThat(sslFactory.getTrustedCertificates()).hasSizeGreaterThan(10);
314
315 assertThat(sslFactory.getKeyManager()).isNotPresent();
316 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
317 assertThat(sslFactory.getIdentities()).isEmpty();
318 }
319
320 @Test
321 void buildSSLFactoryWithTrustMaterialFromOnlySystemTrustedCertificates() {
322 String operatingSystem = System.getProperty("os.name").toLowerCase();
323 if (operatingSystem.contains("mac") || operatingSystem.contains("windows")) {
324 SSLFactory sslFactory = SSLFactory.builder()
325 .withSystemTrustMaterial()
326 .build();
327
328 assertThat(sslFactory.getSslContext()).isNotNull();
329
330 assertThat(sslFactory.getTrustManager()).isPresent();
331 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
332 assertThat(sslFactory.getTrustStores()).isEmpty();
333
334 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
335 assertThat(sslFactory.getKeyManager()).isNotPresent();
336 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
337 assertThat(sslFactory.getIdentities()).isEmpty();
338 }
339
340 if (operatingSystem.contains("linux")) {
341 SSLFactory.Builder sslFactoryBuilder = SSLFactory.builder()
342 .withSystemTrustMaterial();
343
344 assertThatThrownBy(sslFactoryBuilder::build)
345 .isInstanceOf(GenericSecurityException.class)
346 .hasMessage("Could not create instance of SSLFactory because Identity and Trust material are not present. Please provide at least a Trust material.");
347 }
348 }
349
350 @Test
351 void buildSSLFactoryWithSecureRandom() throws NoSuchAlgorithmException {
352 SSLFactory sslFactory = SSLFactory.builder()
353 .withSecureRandom(SecureRandom.getInstanceStrong())
354 .withDefaultTrustMaterial()
355 .build();
356
357 assertThat(sslFactory.getSslContext()).isNotNull();
358
359 assertThat(sslFactory.getTrustManager()).isPresent();
360 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
361 assertThat(sslFactory.getTrustStores()).isEmpty();
362 assertThat(sslFactory.getTrustedCertificates()).hasSizeGreaterThan(10);
363
364 assertThat(sslFactory.getKeyManager()).isNotPresent();
365 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
366 assertThat(sslFactory.getIdentities()).isEmpty();
367 }
368
369 @Test
370 void buildSSLFactoryWithTrustMaterialFromJdkTrustedCertificatesAndCustomTrustStore() {
371 SSLFactory sslFactory = SSLFactory.builder()
372 .withTrustMaterial(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD)
373 .withDefaultTrustMaterial()
374 .withPasswordCaching()
375 .build();
376
377 assertThat(sslFactory.getTrustManager()).isPresent();
378 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
379 assertThat(sslFactory.getTrustStores()).isNotEmpty();
380 assertThat(sslFactory.getTrustStores().get(0).getKeyStorePassword()).isEqualTo(TRUSTSTORE_PASSWORD);
381 assertThat(sslFactory.getTrustedCertificates()).hasSizeGreaterThan(10);
382 assertThat(sslFactory.getTrustedCertificates().stream()
383 .map(X509Certificate::getSubjectX500Principal)
384 .map(X500Principal::toString)).contains("CN=*.google.com, O=Google LLC, L=Mountain View, ST=California, C=US");
385
386 assertThat(sslFactory.getKeyManager()).isNotPresent();
387 assertThat(sslFactory.getKeyManagerFactory()).isNotPresent();
388 assertThat(sslFactory.getIdentities()).isEmpty();
389 }
390
391 @Test
392 void buildSSLFactoryWithIdentityMaterial() {
393 SSLFactory sslFactory = SSLFactory.builder()
394 .withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD)
395 .withPasswordCaching()
396 .build();
397
398 assertThat(sslFactory.getSslContext()).isNotNull();
399
400 assertThat(sslFactory.getKeyManager()).isPresent();
401 assertThat(sslFactory.getKeyManager().get()).isNotInstanceOf(HotSwappableX509ExtendedKeyManager.class);
402 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
403 assertThat(sslFactory.getIdentities()).isNotEmpty();
404 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEqualTo(IDENTITY_PASSWORD);
405
406 assertThat(sslFactory.getTrustManager()).isNotPresent();
407 assertThat(sslFactory.getTrustManagerFactory()).isNotPresent();
408 assertThat(sslFactory.getTrustedCertificates()).isEmpty();
409 assertThat(sslFactory.getTrustStores()).isEmpty();
410 }
411
412 @Test
413 void buildSSLFactoryWithSwappableIdentityMaterial() {
414 SSLFactory sslFactory = SSLFactory.builder()
415 .withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD)
416 .withSwappableIdentityMaterial()
417 .build();
418
419 assertThat(sslFactory.getSslContext()).isNotNull();
420
421 assertThat(sslFactory.getKeyManager()).isPresent();
422 assertThat(sslFactory.getKeyManager().get()).isInstanceOf(HotSwappableX509ExtendedKeyManager.class);
423 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
424 assertThat(sslFactory.getIdentities()).isNotEmpty();
425
426 assertThat(sslFactory.getTrustManager()).isNotPresent();
427 assertThat(sslFactory.getTrustManagerFactory()).isNotPresent();
428 assertThat(sslFactory.getTrustedCertificates()).isEmpty();
429 assertThat(sslFactory.getTrustStores()).isEmpty();
430 }
431
432 @Test
433 void buildSSLFactoryWithIdentityMaterialAndTrustMaterial() {
434 SSLFactory sslFactory = SSLFactory.builder()
435 .withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD)
436 .withTrustMaterial(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD)
437 .withPasswordCaching()
438 .build();
439
440 assertThat(sslFactory.getSslContext()).isNotNull();
441
442 assertThat(sslFactory.getKeyManager()).isPresent();
443 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
444 assertThat(sslFactory.getIdentities()).isNotEmpty();
445 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEqualTo(IDENTITY_PASSWORD);
446
447 assertThat(sslFactory.getTrustManager()).isPresent();
448 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
449 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
450 assertThat(sslFactory.getTrustStores()).isNotEmpty();
451 assertThat(sslFactory.getTrustStores().get(0).getKeyStorePassword()).isEqualTo(TRUSTSTORE_PASSWORD);
452 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
453 }
454
455 @Test
456 void buildSSLFactoryWithIdentityMaterialWithoutPasswordAndTrustMaterialWithoutPassword() {
457 SSLFactory sslFactory = SSLFactory.builder()
458 .withIdentityMaterial(KEYSTORE_LOCATION + "identity-without-password.jks", null, "secret".toCharArray())
459 .withTrustMaterial(KEYSTORE_LOCATION + "truststore-without-password.jks", null)
460 .withPasswordCaching()
461 .build();
462
463 assertThat(sslFactory.getSslContext()).isNotNull();
464
465 assertThat(sslFactory.getKeyManager()).isPresent();
466 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
467 assertThat(sslFactory.getIdentities()).isNotEmpty();
468 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isNull();
469
470 assertThat(sslFactory.getTrustManager()).isPresent();
471 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
472 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
473 assertThat(sslFactory.getTrustStores()).isNotEmpty();
474 assertThat(sslFactory.getTrustStores().get(0).getKeyStorePassword()).isNull();
475 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
476 }
477
478 @Test
479 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialWithKeyStoreTypesIncluded() {
480 SSLFactory sslFactory = SSLFactory.builder()
481 .withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD, KeyStore.getDefaultType())
482 .withTrustMaterial(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD, KeyStore.getDefaultType())
483 .withPasswordCaching()
484 .build();
485
486 assertThat(sslFactory.getSslContext()).isNotNull();
487
488 assertThat(sslFactory.getKeyManager()).isPresent();
489 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
490 assertThat(sslFactory.getIdentities()).isNotEmpty();
491 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEqualTo(IDENTITY_PASSWORD);
492
493 assertThat(sslFactory.getTrustManager()).isPresent();
494 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
495 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
496 assertThat(sslFactory.getTrustStores()).isNotEmpty();
497 assertThat(sslFactory.getTrustStores().get(0).getKeyStorePassword()).isEqualTo(TRUSTSTORE_PASSWORD);
498 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
499 }
500
501 @Test
502 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromInputStream() {
503 InputStream identityStream = getResourceAsStream(KEYSTORE_LOCATION, IDENTITY_FILE_NAME);
504 InputStream trustStoreStream = getResourceAsStream(KEYSTORE_LOCATION, TRUSTSTORE_FILE_NAME);
505
506 SSLFactory sslFactory = SSLFactory.builder()
507 .withIdentityMaterial(identityStream, IDENTITY_PASSWORD)
508 .withTrustMaterial(trustStoreStream, TRUSTSTORE_PASSWORD)
509 .build();
510
511 assertThat(sslFactory.getSslContext()).isNotNull();
512
513 assertThat(sslFactory.getKeyManager()).isPresent();
514 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
515 assertThat(sslFactory.getIdentities()).isNotEmpty();
516
517 assertThat(sslFactory.getTrustManager()).isPresent();
518 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
519 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
520 assertThat(sslFactory.getTrustStores()).isNotEmpty();
521 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
522 }
523
524 @Test
525 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromInputStreamWithCustomKeyStoreType() {
526 InputStream identityStream = getResourceAsStream(KEYSTORE_LOCATION, IDENTITY_FILE_NAME);
527 InputStream trustStoreStream = getResourceAsStream(KEYSTORE_LOCATION, TRUSTSTORE_FILE_NAME);
528
529 SSLFactory sslFactory = SSLFactory.builder()
530 .withIdentityMaterial(identityStream, IDENTITY_PASSWORD, KeyStore.getDefaultType())
531 .withTrustMaterial(trustStoreStream, TRUSTSTORE_PASSWORD)
532 .build();
533
534 assertThat(sslFactory.getSslContext()).isNotNull();
535
536 assertThat(sslFactory.getKeyManager()).isPresent();
537 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
538 assertThat(sslFactory.getIdentities()).isNotEmpty();
539
540 assertThat(sslFactory.getTrustManager()).isPresent();
541 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
542 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
543 assertThat(sslFactory.getTrustStores()).isNotEmpty();
544 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
545 }
546
547 @Test
548 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromIdentityManagerAndTrustStore() {
549 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
550 X509ExtendedKeyManager identityManager = KeyManagerUtils.createKeyManager(identity, IDENTITY_PASSWORD);
551
552 SSLFactory sslFactory = SSLFactory.builder()
553 .withIdentityMaterial(identityManager)
554 .withTrustMaterial(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD)
555 .build();
556
557 assertThat(sslFactory.getSslContext()).isNotNull();
558
559 assertThat(sslFactory.getKeyManager()).isPresent();
560 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
561 assertThat(sslFactory.getIdentities()).isEmpty();
562
563 assertThat(sslFactory.getTrustManager()).isPresent();
564 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
565 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
566 assertThat(sslFactory.getTrustStores()).isNotEmpty();
567 assertThat(sslFactory.getTrustStores().get(0).getKeyStorePassword()).isEmpty();
568 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
569 }
570
571 @Test
572 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromIdentityManagerFactoryAndTrustStore() throws Exception {
573 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
574 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
575 keyManagerFactory.init(identity, IDENTITY_PASSWORD);
576
577 SSLFactory sslFactory = SSLFactory.builder()
578 .withIdentityMaterial(keyManagerFactory)
579 .withTrustMaterial(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD)
580 .build();
581
582 assertThat(sslFactory.getSslContext()).isNotNull();
583
584 assertThat(sslFactory.getKeyManager()).isPresent();
585 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
586 assertThat(sslFactory.getIdentities()).isEmpty();
587
588 assertThat(sslFactory.getTrustManager()).isPresent();
589 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
590 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
591 assertThat(sslFactory.getTrustStores()).isNotEmpty();
592 assertThat(sslFactory.getTrustStores().get(0).getKeyStorePassword()).isEmpty();
593 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
594 }
595
596 @Test
597 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromKeyStoreAndOnlyJdkTrustedCertificates() {
598 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
599 SSLFactory sslFactory = SSLFactory.builder()
600 .withIdentityMaterial(identity, IDENTITY_PASSWORD)
601 .withDefaultTrustMaterial()
602 .build();
603
604 assertThat(sslFactory.getSslContext()).isNotNull();
605
606 assertThat(sslFactory.getKeyManager()).isPresent();
607 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
608 assertThat(sslFactory.getIdentities()).isNotEmpty();
609 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEmpty();
610
611 assertThat(sslFactory.getTrustManager()).isPresent();
612 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
613 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
614 assertThat(sslFactory.getTrustStores()).isEmpty();
615 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
616 }
617
618 @Test
619 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromPrivateKey() throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
620 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
621 PrivateKey privateKey = (PrivateKey) identity.getKey("dummy-client", IDENTITY_PASSWORD);
622 Certificate[] certificateChain = identity.getCertificateChain("dummy-client");
623
624 SSLFactory sslFactory = SSLFactory.builder()
625 .withIdentityMaterial(privateKey, IDENTITY_PASSWORD, certificateChain)
626 .withDefaultTrustMaterial()
627 .build();
628
629 assertThat(sslFactory.getSslContext()).isNotNull();
630
631 assertThat(sslFactory.getKeyManager()).isPresent();
632 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
633 assertThat(sslFactory.getIdentities()).isNotEmpty();
634 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEmpty();
635 assertThat(sslFactory.getIdentities().get(0).getKeyStore()
636 .containsAlias("cn=prof oak,ou=oak pokémon research lab,o=oak pokémon research lab,c=pallet town")).isTrue();
637
638 assertThat(sslFactory.getTrustManager()).isPresent();
639 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
640 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
641 assertThat(sslFactory.getTrustStores()).isEmpty();
642 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
643 }
644
645 @Test
646 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromPrivateKeyWithCustomAlias() throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
647 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
648 PrivateKey privateKey = (PrivateKey) identity.getKey("dummy-client", IDENTITY_PASSWORD);
649 Certificate[] certificateChain = identity.getCertificateChain("dummy-client");
650
651 SSLFactory sslFactory = SSLFactory.builder()
652 .withIdentityMaterial(privateKey, IDENTITY_PASSWORD, "thunder-client", certificateChain)
653 .withDefaultTrustMaterial()
654 .build();
655
656 assertThat(sslFactory.getSslContext()).isNotNull();
657
658 assertThat(sslFactory.getKeyManager()).isPresent();
659 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
660 assertThat(sslFactory.getIdentities()).isNotEmpty();
661 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEmpty();
662 assertThat(sslFactory.getIdentities().get(0).getKeyStore().containsAlias("thunder-client")).isTrue();
663
664 assertThat(sslFactory.getTrustManager()).isPresent();
665 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
666 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
667 assertThat(sslFactory.getTrustStores()).isEmpty();
668 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
669 }
670
671 @Test
672 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromKeyStoreWithDifferentKeyPasswordAndOnlyJdkTrustedCertificates() {
673 SSLFactory sslFactory = SSLFactory.builder()
674 .withIdentityMaterial(KEYSTORE_LOCATION + "identity-with-different-key-password.jks", IDENTITY_PASSWORD, "my-precious".toCharArray())
675 .withDefaultTrustMaterial()
676 .withPasswordCaching()
677 .build();
678
679 assertThat(sslFactory.getSslContext()).isNotNull();
680
681 assertThat(sslFactory.getKeyManager()).isPresent();
682 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
683 assertThat(sslFactory.getIdentities()).isNotEmpty();
684 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEqualTo(IDENTITY_PASSWORD);
685 assertThat(sslFactory.getIdentities().get(0).getKeyPassword()).isEqualTo("my-precious".toCharArray());
686
687 assertThat(sslFactory.getTrustManager()).isPresent();
688 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
689 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
690 assertThat(sslFactory.getTrustStores()).isEmpty();
691 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
692 }
693
694 @Test
695 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromKeyStorePathWithDifferentKeyPasswordAndOnlyJdkTrustedCertificates() throws IOException {
696 Path identityPath = copyKeystoreToHomeDirectory(KEYSTORE_LOCATION, "identity-with-different-key-password.jks");
697
698 SSLFactory sslFactory = SSLFactory.builder()
699 .withIdentityMaterial(identityPath, IDENTITY_PASSWORD, "my-precious".toCharArray())
700 .withDefaultTrustMaterial()
701 .withPasswordCaching()
702 .build();
703
704 assertThat(sslFactory.getSslContext()).isNotNull();
705
706 assertThat(sslFactory.getKeyManager()).isPresent();
707 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
708 assertThat(sslFactory.getIdentities()).isNotEmpty();
709 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEqualTo(IDENTITY_PASSWORD);
710 assertThat(sslFactory.getIdentities().get(0).getKeyPassword()).isEqualTo("my-precious".toCharArray());
711
712 assertThat(sslFactory.getTrustManager()).isPresent();
713 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
714 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
715 assertThat(sslFactory.getTrustStores()).isEmpty();
716 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
717
718 Files.delete(identityPath);
719 }
720
721 @Test
722 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromKeyStoreAndTrustStoreWithPath() throws IOException {
723 Path identityPath = copyKeystoreToHomeDirectory(KEYSTORE_LOCATION, IDENTITY_FILE_NAME);
724 Path trustStorePath = copyKeystoreToHomeDirectory(KEYSTORE_LOCATION, TRUSTSTORE_FILE_NAME);
725
726 SSLFactory sslFactory = SSLFactory.builder()
727 .withIdentityMaterial(identityPath, IDENTITY_PASSWORD)
728 .withTrustMaterial(trustStorePath, TRUSTSTORE_PASSWORD)
729 .withPasswordCaching()
730 .build();
731
732 assertThat(sslFactory.getSslContext()).isNotNull();
733
734 assertThat(sslFactory.getKeyManager()).isPresent();
735 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
736 assertThat(sslFactory.getIdentities()).isNotEmpty();
737 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEqualTo(IDENTITY_PASSWORD);
738
739 assertThat(sslFactory.getTrustManager()).isPresent();
740 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
741 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
742 assertThat(sslFactory.getTrustStores()).isNotEmpty();
743 assertThat(sslFactory.getTrustStores().get(0).getKeyStorePassword()).isEqualTo(TRUSTSTORE_PASSWORD);
744 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
745
746 Files.delete(identityPath);
747 Files.delete(trustStorePath);
748 }
749
750 @Test
751 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromKeyStoreAndTrustStoreWithPathAndWithKeyStoreTypesIncluded() throws IOException {
752 Path identityPath = copyKeystoreToHomeDirectory(KEYSTORE_LOCATION, IDENTITY_FILE_NAME);
753 Path trustStorePath = copyKeystoreToHomeDirectory(KEYSTORE_LOCATION, TRUSTSTORE_FILE_NAME);
754
755 SSLFactory sslFactory = SSLFactory.builder()
756 .withIdentityMaterial(identityPath, IDENTITY_PASSWORD, KeyStore.getDefaultType())
757 .withTrustMaterial(trustStorePath, TRUSTSTORE_PASSWORD, KeyStore.getDefaultType())
758 .withPasswordCaching()
759 .build();
760
761 assertThat(sslFactory.getSslContext()).isNotNull();
762
763 assertThat(sslFactory.getKeyManager()).isPresent();
764 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
765 assertThat(sslFactory.getIdentities()).isNotEmpty();
766 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEqualTo(IDENTITY_PASSWORD);
767
768 assertThat(sslFactory.getTrustManager()).isPresent();
769 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
770 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
771 assertThat(sslFactory.getTrustStores()).isNotEmpty();
772 assertThat(sslFactory.getTrustStores().get(0).getKeyStorePassword()).isEqualTo(TRUSTSTORE_PASSWORD);
773 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
774
775 Files.delete(identityPath);
776 Files.delete(trustStorePath);
777 }
778
779 @Test
780 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromKeyStoreAndTrustStore() {
781 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
782 KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
783
784 SSLFactory sslFactory = SSLFactory.builder()
785 .withIdentityMaterial(identity, IDENTITY_PASSWORD)
786 .withTrustMaterial(trustStore, TRUSTSTORE_PASSWORD)
787 .withPasswordCaching()
788 .build();
789
790 assertThat(sslFactory.getSslContext()).isNotNull();
791
792 assertThat(sslFactory.getKeyManager()).isPresent();
793 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
794 assertThat(sslFactory.getIdentities()).isNotEmpty();
795 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEqualTo(IDENTITY_PASSWORD);
796
797 assertThat(sslFactory.getTrustManager()).isPresent();
798 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
799 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
800 assertThat(sslFactory.getTrustStores()).isNotEmpty();
801 assertThat(sslFactory.getTrustStores().get(0).getKeyStorePassword()).isEqualTo(TRUSTSTORE_PASSWORD);
802 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
803 }
804
805 @Test
806 void buildSSLFactoryWithIdentityMaterialAndTrustMaterialFromKeyStoreAndTrustStoreWithoutCachingPasswords() {
807 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
808 KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
809
810 SSLFactory sslFactory = SSLFactory.builder()
811 .withIdentityMaterial(identity, IDENTITY_PASSWORD)
812 .withTrustMaterial(trustStore, TRUSTSTORE_PASSWORD)
813 .build();
814
815 assertThat(sslFactory.getSslContext()).isNotNull();
816
817 assertThat(sslFactory.getKeyManager()).isPresent();
818 assertThat(sslFactory.getKeyManagerFactory()).isPresent();
819 assertThat(sslFactory.getIdentities()).isNotEmpty();
820 assertThat(sslFactory.getIdentities().get(0).getKeyStorePassword()).isEmpty();
821
822 assertThat(sslFactory.getTrustManager()).isPresent();
823 assertThat(sslFactory.getTrustManagerFactory()).isPresent();
824 assertThat(sslFactory.getTrustedCertificates()).isNotEmpty();
825 assertThat(sslFactory.getTrustStores()).isNotEmpty();
826 assertThat(sslFactory.getTrustStores().get(0).getKeyStorePassword()).isEmpty();
827 assertThat(sslFactory.getHostnameVerifier()).isNotNull();
828 }
829
830 @Test
831 void buildSSLFactoryByDefaultWithTlsSslContextAlgorithm() {
832 SSLFactory sslFactory = SSLFactory.builder()
833 .withDefaultTrustMaterial()
834 .build();
835
836 assertThat(sslFactory.getSslContext().getProtocol()).isEqualTo("TLS");
837 }
838
839 @Test
840 void buildSSLFactoryWithSslContextAlgorithm() {
841 SSLFactory sslFactory = SSLFactory.builder()
842 .withDefaultTrustMaterial()
843 .withSslContextAlgorithm("TLSv1.2")
844 .build();
845
846 assertThat(sslFactory.getSslContext().getProtocol()).isEqualTo("TLSv1.2");
847 }
848
849 @Test
850 void buildSSLFactoryWithCustomHostnameVerifier() {
851 SSLFactory sslFactory = SSLFactory.builder()
852 .withTrustMaterial(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD)
853 .withHostnameVerifier((host, sslSession) -> true)
854 .build();
855
856 HostnameVerifier hostnameVerifier = sslFactory.getHostnameVerifier();
857 assertThat(hostnameVerifier.verify("qwerty", null)).isTrue();
858 }
859
860 @Test
861 void buildSSLFactoryWithoutHostnameVerifierProvidesDefaultHostnameVerifier() {
862 SSLFactory sslFactory = SSLFactory.builder()
863 .withTrustMaterial(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD)
864 .build();
865
866 SSLSession sslSession = mock(SSLSession.class);
867 when(sslSession.getPeerHost()).thenReturn("localhost");
868
869 HostnameVerifier hostnameVerifier = sslFactory.getHostnameVerifier();
870 assertThat(hostnameVerifier.verify("localhost", sslSession)).isTrue();
871 }
872
873 @Test
874 void buildSSLFactoryWithTrustingAllCertificatesWithoutValidation() {
875 LogCaptor logCaptor = LogCaptor.forClass(SSLFactory.class);
876
877 SSLFactory sslFactory = SSLFactory.builder()
878 .withTrustingAllCertificatesWithoutValidation()
879 .build();
880
881 assertThat(sslFactory.getSslContext()).isNotNull();
882 assertThat(sslFactory.getTrustedCertificates()).isEmpty();
883 assertThat(sslFactory.getTrustStores()).isEmpty();
884 assertThat(sslFactory.getTrustManager()).isPresent();
885 assertThat(sslFactory.getTrustManager().get()).isInstanceOf(UnsafeX509ExtendedTrustManager.class);
886 assertThat(logCaptor.getWarnLogs()).contains("UnsafeTrustManager is being used. Client/Server certificates will be accepted without validation.");
887 }
888
889 @Test
890 void buildSSLFactoryWithSecurityProvider() {
891 SSLFactory sslFactory = SSLFactory.builder()
892 .withDefaultTrustMaterial()
893 .withSslContextAlgorithm("TLS")
894 .withSecurityProvider(Security.getProvider("SunJSSE"))
895 .build();
896
897 assertThat(sslFactory.getSslContext()).isNotNull();
898 assertThat(sslFactory.getSslContext().getProvider().getName()).isEqualTo("SunJSSE");
899 }
900
901 @Test
902 void buildSSLFactoryWithSecurityProviderName() {
903 SSLFactory sslFactory = SSLFactory.builder()
904 .withDefaultTrustMaterial()
905 .withSslContextAlgorithm("TLS")
906 .withSecurityProvider("SunJSSE")
907 .build();
908
909 assertThat(sslFactory.getSslContext()).isNotNull();
910 assertThat(sslFactory.getSslContext().getProvider().getName()).isEqualTo("SunJSSE");
911 }
912
913 @Test
914 void throwExceptionWhenSSLFactoryIsBuildWithoutIdentityAndTrustMaterial() {
915 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
916
917 assertThatThrownBy(factoryBuilder::build)
918 .isInstanceOf(GenericSecurityException.class)
919 .hasMessage("Could not create instance of SSLFactory because Identity and Trust material are not present. Please provide at least a Trust material.");
920 }
921
922 @Test
923 void buildSSLFactoryWithTLSProtocolVersionOneDotThreeIfJavaVersionIsElevenOrGreater() {
924 Pattern valueBeforeDotPattern = Pattern.compile("^([^.]+)");
925
926 String javaVersion = System.getProperty("java.version");
927 Matcher matcher = valueBeforeDotPattern.matcher(javaVersion);
928 if (!matcher.find()) {
929 fail("Could not find the java version");
930 }
931
932 int javaMajorVersion = Integer.parseInt(matcher.group(0));
933 if (javaMajorVersion < 11) {
934 LOGGER.info("skipping unit test [{}] because TLSv1.3 is not available for this java {} version",
935 new Object() {}.getClass().getEnclosingMethod().getName(),
936 javaVersion);
937 return;
938 }
939
940 LOGGER.info("Found java version {}, including testing SSLFactory with TLSv1.3 protocol", javaMajorVersion);
941 SSLFactory sslFactory = SSLFactory.builder()
942 .withDefaultTrustMaterial()
943 .build();
944
945 assertThat(sslFactory.getSslContext()).isNotNull();
946 assertThat(sslFactory.getProtocols()).contains("TLSv1.3");
947 }
948
949 @Test
950 void returnSslSocketFactory() {
951 SSLFactory sslFactory = SSLFactory.builder()
952 .withDefaultTrustMaterial()
953 .withCiphers("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384")
954 .build();
955
956 assertThat(sslFactory.getSslContext()).isNotNull();
957 assertThat(sslFactory.getSslSocketFactory()).isNotNull();
958 assertThat(sslFactory.getSslSocketFactory().getDefaultCipherSuites()).containsExactly("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384");
959 assertThat(sslFactory.getSslSocketFactory().getSupportedCipherSuites()).containsExactly("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384");
960 }
961
962 @Test
963 void returnSslServerSocketFactory() {
964 SSLFactory sslFactory = SSLFactory.builder()
965 .withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD)
966 .withDefaultTrustMaterial()
967 .withCiphers("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384")
968 .build();
969
970 assertThat(sslFactory.getSslContext()).isNotNull();
971 assertThat(sslFactory.getSslServerSocketFactory()).isNotNull();
972 assertThat(sslFactory.getSslServerSocketFactory().getDefaultCipherSuites()).containsExactly("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384");
973 assertThat(sslFactory.getSslServerSocketFactory().getSupportedCipherSuites()).containsExactly("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384");
974 }
975
976 @Test
977 void returnDefaultCiphersWhenNoneSpecified() {
978 SSLFactory sslFactory = SSLFactory.builder()
979 .withDefaultTrustMaterial()
980 .build();
981
982 assertThat(sslFactory.getSslContext()).isNotNull();
983 assertThat(sslFactory.getCiphers()).isNotEmpty();
984 assertThat(sslFactory.getCiphers()).containsExactlyInAnyOrder(sslFactory.getSslContext().getDefaultSSLParameters().getCipherSuites());
985 }
986
987 @Test
988 void returnSpecifiedCiphers() {
989 SSLFactory sslFactory = SSLFactory.builder()
990 .withDefaultTrustMaterial()
991 .withCiphers("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384")
992 .build();
993
994 assertThat(sslFactory.getSslContext()).isNotNull();
995 assertThat(sslFactory.getCiphers())
996 .containsExactlyInAnyOrder("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384");
997 }
998
999 @Test
1000 void returnSpecifiedCiphersAndProtocolsWithinSslParameters() {
1001 SSLFactory sslFactory = SSLFactory.builder()
1002 .withDefaultTrustMaterial()
1003 .withCiphers("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384")
1004 .withProtocols("TLSv1.2", "TLSv1.1")
1005 .build();
1006
1007 assertThat(sslFactory.getSslContext()).isNotNull();
1008 assertThat(sslFactory.getSslParameters().getCipherSuites())
1009 .containsExactlyInAnyOrder("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384");
1010 assertThat(sslFactory.getSslParameters().getProtocols())
1011 .containsExactlyInAnyOrder("TLSv1.2", "TLSv1.1");
1012 assertThat(sslFactory.getSslParameters())
1013 .isNotEqualTo(sslFactory.getSslContext().getDefaultSSLParameters());
1014 }
1015
1016 @Test
1017 void returnDefaultProtocolsWhenNoneSpecified() {
1018 SSLFactory sslFactory = SSLFactory.builder()
1019 .withDefaultTrustMaterial()
1020 .build();
1021
1022 assertThat(sslFactory.getSslContext()).isNotNull();
1023 assertThat(sslFactory.getProtocols()).containsExactlyInAnyOrder(sslFactory.getSslContext().getDefaultSSLParameters().getProtocols());
1024 }
1025
1026 @Test
1027 void returnSpecifiedProtocols() {
1028 SSLFactory sslFactory = SSLFactory.builder()
1029 .withDefaultTrustMaterial()
1030 .withProtocols("TLSv1.2", "TLSv1.1")
1031 .build();
1032
1033 assertThat(sslFactory.getSslContext()).isNotNull();
1034 assertThat(sslFactory.getProtocols()).containsExactlyInAnyOrder("TLSv1.2", "TLSv1.1");
1035 }
1036
1037 @Test
1038 void returnSpecifiedNeedClientAuthenticationWithoutOptions() {
1039 SSLFactory sslFactory = SSLFactory.builder()
1040 .withDefaultTrustMaterial()
1041 .withNeedClientAuthentication()
1042 .build();
1043
1044 assertThat(sslFactory.getSslParameters().getNeedClientAuth()).isTrue();
1045 assertThat(sslFactory.getSslParameters().getWantClientAuth()).isFalse();
1046 }
1047
1048 @Test
1049 void returnSpecifiedNeedClientAuthenticationWithOptions() {
1050 SSLFactory sslFactory = SSLFactory.builder()
1051 .withDefaultTrustMaterial()
1052 .withNeedClientAuthentication(true)
1053 .build();
1054
1055 assertThat(sslFactory.getSslParameters().getNeedClientAuth()).isTrue();
1056 assertThat(sslFactory.getSslParameters().getWantClientAuth()).isFalse();
1057 }
1058
1059 @Test
1060 void returnSpecifiedWantClientAuthenticationWithoutOptions() {
1061 SSLFactory sslFactory = SSLFactory.builder()
1062 .withDefaultTrustMaterial()
1063 .withWantClientAuthentication()
1064 .build();
1065
1066 assertThat(sslFactory.getSslParameters().getWantClientAuth()).isTrue();
1067 assertThat(sslFactory.getSslParameters().getNeedClientAuth()).isFalse();
1068 }
1069
1070 @Test
1071 void returnSpecifiedWantClientAuthenticationWithOptions() {
1072 SSLFactory sslFactory = SSLFactory.builder()
1073 .withDefaultTrustMaterial()
1074 .withWantClientAuthentication(true)
1075 .build();
1076
1077 assertThat(sslFactory.getSslParameters().getWantClientAuth()).isTrue();
1078 assertThat(sslFactory.getSslParameters().getNeedClientAuth()).isFalse();
1079 }
1080
1081 @Test
1082 void returnSslEngineWithSslParameters() {
1083 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
1084 KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
1085
1086 SSLFactory sslFactory = SSLFactory.builder()
1087 .withIdentityMaterial(identity, IDENTITY_PASSWORD)
1088 .withTrustMaterial(trustStore, TRUSTSTORE_PASSWORD)
1089 .withNeedClientAuthentication()
1090 .build();
1091
1092 SSLEngine sslEngine = sslFactory.getSSLEngine();
1093
1094 assertThat(sslEngine).isNotNull();
1095 assertThat(sslEngine.getPeerHost()).isNull();
1096 assertThat(sslEngine.getPeerPort()).isEqualTo(-1);
1097 assertThat(sslEngine.getNeedClientAuth()).isTrue();
1098 }
1099
1100 @Test
1101 void returnSslEngineWithoutHostAndPortIfOnlyHostIsDefined() {
1102 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
1103 KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
1104
1105 SSLFactory sslFactory = SSLFactory.builder()
1106 .withIdentityMaterial(identity, IDENTITY_PASSWORD)
1107 .withTrustMaterial(trustStore, TRUSTSTORE_PASSWORD)
1108 .withNeedClientAuthentication()
1109 .build();
1110
1111 SSLEngine sslEngine = sslFactory.getSSLEngine("localhost", null);
1112
1113 assertThat(sslEngine).isNotNull();
1114 assertThat(sslEngine.getPeerHost()).isNull();
1115 assertThat(sslEngine.getPeerPort()).isEqualTo(-1);
1116 assertThat(sslEngine.getNeedClientAuth()).isTrue();
1117 }
1118
1119 @Test
1120 void returnSslEngineWithHostAndPortAndWithSslParameters() {
1121 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
1122 KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
1123
1124 SSLFactory sslFactory = SSLFactory.builder()
1125 .withIdentityMaterial(identity, IDENTITY_PASSWORD)
1126 .withTrustMaterial(trustStore, TRUSTSTORE_PASSWORD)
1127 .withNeedClientAuthentication()
1128 .build();
1129
1130 SSLEngine sslEngine = sslFactory.getSSLEngine("localhost", 8443);
1131
1132 assertThat(sslEngine).isNotNull();
1133 assertThat(sslEngine.getPeerHost()).isEqualTo("localhost");
1134 assertThat(sslEngine.getPeerPort()).isEqualTo(8443);
1135 assertThat(sslEngine.getNeedClientAuth()).isTrue();
1136 }
1137
1138 @Test
1139 void createMultipleRoutesForSingleClientIdentity() {
1140 SSLFactory sslFactory = SSLFactory.builder()
1141 .withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD)
1142 .withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD)
1143 .withClientIdentityRoute("some-client-alias", "https://localhost:8443", "https://localhost:8444")
1144 .build();
1145
1146 assertThat(sslFactory.getKeyManager()).isPresent();
1147 assertThat(KeyManagerUtils.getClientIdentityRoute(sslFactory.getKeyManager().get()))
1148 .containsKey("some-client-alias")
1149 .containsValue(Arrays.asList("https://localhost:8443", "https://localhost:8444"));
1150
1151 assertThat(((CompositeX509ExtendedKeyManager)sslFactory.getKeyManager().get()).getPreferredClientAliasToHosts())
1152 .containsKey("some-client-alias")
1153 .containsValue(Arrays.asList(URI.create("https://localhost:8443"), URI.create("https://localhost:8444")));
1154 }
1155
1156 @Test
1157 void createMultipleRoutesForSingleClientIdentityAndUpdateAfterCreation() {
1158 SSLFactory sslFactory = SSLFactory.builder()
1159 .withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD)
1160 .withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD)
1161 .withClientIdentityRoute("some-client-alias", "https://localhost:8443", "https://localhost:8444")
1162 .build();
1163
1164 assertThat(sslFactory.getKeyManager()).isPresent();
1165 assertThat(KeyManagerUtils.getClientIdentityRoute(sslFactory.getKeyManager().get()))
1166 .containsKey("some-client-alias")
1167 .containsValue(Arrays.asList("https://localhost:8443", "https://localhost:8444"))
1168 .doesNotContainValue(Collections.singletonList("https://localhost:8445"));
1169
1170 KeyManagerUtils.addClientIdentityRoute(sslFactory.getKeyManager().get(), "some-client-alias", "https://localhost:8445");
1171
1172 assertThat(KeyManagerUtils.getClientIdentityRoute(sslFactory.getKeyManager().get()))
1173 .containsKey("some-client-alias")
1174 .containsValue(Arrays.asList("https://localhost:8443", "https://localhost:8444", "https://localhost:8445"));
1175 }
1176
1177 @Test
1178 void createSSLFactoryWithSessionTimeout() {
1179 SSLFactory sslFactory = SSLFactory.builder()
1180 .withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD)
1181 .withDefaultTrustMaterial()
1182 .withSessionTimeout(10)
1183 .build();
1184
1185 int clientSessionTimeout = sslFactory.getSslContext()
1186 .getClientSessionContext()
1187 .getSessionTimeout();
1188
1189 int serverSessionTimeout = sslFactory.getSslContext()
1190 .getServerSessionContext()
1191 .getSessionTimeout();
1192
1193 assertThat(clientSessionTimeout).isEqualTo(10);
1194 assertThat(serverSessionTimeout).isEqualTo(10);
1195 }
1196
1197 @Test
1198 void createSSLFactoryWithSessionCacheSize() {
1199 SSLFactory sslFactory = SSLFactory.builder()
1200 .withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD)
1201 .withDefaultTrustMaterial()
1202 .withSessionCacheSize(1024)
1203 .build();
1204
1205 int clientSessionCacheSize = sslFactory.getSslContext()
1206 .getClientSessionContext()
1207 .getSessionCacheSize();
1208
1209 int serverSessionCacheSize = sslFactory.getSslContext()
1210 .getServerSessionContext()
1211 .getSessionCacheSize();
1212
1213 assertThat(clientSessionCacheSize).isEqualTo(1024);
1214 assertThat(serverSessionCacheSize).isEqualTo(1024);
1215 }
1216
1217 @Test
1218 void throwExceptionWhenBuildingSSLFactoryWithTrustStoreWhileProvidingWrongPassword() {
1219 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1220 char[] trustStorePassword = "password".toCharArray();
1221
1222 assertThatThrownBy(() -> factoryBuilder.withTrustMaterial(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, trustStorePassword))
1223 .isInstanceOf(GenericKeyStoreException.class)
1224 .hasMessageContaining("keystore password was incorrect");
1225 }
1226
1227 @Test
1228 void throwExceptionWhenBuildingSSLFactoryWithTrustStoreFromPathWhileProvidingWrongPassword() throws IOException {
1229 Path trustStorePath = copyKeystoreToHomeDirectory(KEYSTORE_LOCATION, TRUSTSTORE_FILE_NAME);
1230 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1231 char[] trustStorePassword = "password".toCharArray();
1232
1233 assertThatThrownBy(() -> factoryBuilder.withTrustMaterial(trustStorePath, trustStorePassword))
1234 .isInstanceOf(GenericKeyStoreException.class)
1235 .hasMessageContaining("keystore password was incorrect");
1236
1237 Files.delete(trustStorePath);
1238 }
1239
1240 @Test
1241 void throwExceptionWhenBuildingSSLFactoryWithIdentityWhileProvidingWrongPassword() {
1242 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1243 char[] identityStorePassword = "password".toCharArray();
1244
1245 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, identityStorePassword))
1246 .isInstanceOf(GenericKeyStoreException.class)
1247 .hasMessageContaining("keystore password was incorrect");
1248 }
1249
1250 @Test
1251 void throwExceptionWhenBuildingSSLFactoryWithIdentityFromPathWhileProvidingWrongPassword() throws IOException {
1252 Path identityPath = copyKeystoreToHomeDirectory(KEYSTORE_LOCATION, IDENTITY_FILE_NAME);
1253 char[] identityStorePassword = "password".toCharArray();
1254 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1255
1256 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial(identityPath, identityStorePassword))
1257 .isInstanceOf(GenericKeyStoreException.class)
1258 .hasMessageContaining("keystore password was incorrect");
1259
1260 Files.delete(identityPath);
1261 }
1262
1263 @Test
1264 void throwExceptionWhenBuildingSSLFactoryWithNullAsTrustStorePath() {
1265 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1266
1267 assertThatThrownBy(() -> factoryBuilder.withTrustMaterial((Path) null, TRUSTSTORE_PASSWORD))
1268 .isInstanceOf(GenericKeyStoreException.class)
1269 .hasMessage(GENERIC_TRUSTSTORE_VALIDATION_EXCEPTION_MESSAGE);
1270 }
1271
1272 @Test
1273 void throwExceptionWhenBuildingSSLFactoryWithEmptyTrustStoreType() throws IOException {
1274 Path trustStorePath = copyKeystoreToHomeDirectory(KEYSTORE_LOCATION, TRUSTSTORE_FILE_NAME);
1275 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1276
1277 assertThatThrownBy(() -> factoryBuilder.withTrustMaterial(trustStorePath, TRUSTSTORE_PASSWORD, EMPTY))
1278 .isInstanceOf(GenericKeyStoreException.class)
1279 .hasMessage(GENERIC_TRUSTSTORE_VALIDATION_EXCEPTION_MESSAGE);
1280
1281 Files.delete(trustStorePath);
1282 }
1283
1284 @Test
1285 void throwExceptionWhenBuildingSSLFactoryWithTrustStoreAsNull() {
1286 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1287
1288 assertThatThrownBy(() -> factoryBuilder.withTrustMaterial((KeyStore) null, TRUSTSTORE_PASSWORD))
1289 .isInstanceOf(GenericKeyStoreException.class)
1290 .hasMessage(GENERIC_TRUSTSTORE_VALIDATION_EXCEPTION_MESSAGE);
1291 }
1292
1293 @Test
1294 void throwExceptionWhenKeyStoreFileIsNotFound() {
1295 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1296
1297 assertThatThrownBy(() -> factoryBuilder.withTrustMaterial(KEYSTORE_LOCATION + "not-existing-truststore.jks", TRUSTSTORE_PASSWORD))
1298 .isInstanceOf(GenericKeyStoreException.class)
1299 .hasMessageContaining("KeyStore is not present for the giving input");
1300 }
1301
1302 @Test
1303 void throwExceptionWhenTrustStorePathIsNotProvided() {
1304 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1305
1306 assertThatThrownBy(() -> factoryBuilder.withTrustMaterial(EMPTY, TRUSTSTORE_PASSWORD))
1307 .isInstanceOf(GenericKeyStoreException.class)
1308 .hasMessage(GENERIC_TRUSTSTORE_VALIDATION_EXCEPTION_MESSAGE);
1309 }
1310
1311 @Test
1312 void throwExceptionWhenIdentityPathIsNotProvided() {
1313 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1314
1315 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial(EMPTY, IDENTITY_PASSWORD))
1316 .isInstanceOf(GenericKeyStoreException.class)
1317 .hasMessage(GENERIC_IDENTITY_VALIDATION_EXCEPTION_MESSAGE);
1318 }
1319
1320 @Test
1321 void throwExceptionWhenIdentityPathAsStringIsNull() {
1322 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1323
1324 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial((String) null, IDENTITY_PASSWORD))
1325 .isInstanceOf(GenericKeyStoreException.class)
1326 .hasMessage(GENERIC_IDENTITY_VALIDATION_EXCEPTION_MESSAGE);
1327 }
1328
1329 @Test
1330 void throwExceptionWhenIdentityPathAsStringContainsOnlyWhiteSpace() {
1331 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1332
1333 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial(" ", IDENTITY_PASSWORD))
1334 .isInstanceOf(GenericKeyStoreException.class)
1335 .hasMessage(GENERIC_IDENTITY_VALIDATION_EXCEPTION_MESSAGE);
1336 }
1337
1338 @Test
1339 void throwExceptionWhenIdentityTypeIsNotProvided() {
1340 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1341
1342 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD, EMPTY))
1343 .isInstanceOf(GenericKeyStoreException.class)
1344 .hasMessage(GENERIC_IDENTITY_VALIDATION_EXCEPTION_MESSAGE);
1345 }
1346
1347 @Test
1348 void throwExceptionWhenIdentityPathIsNull() {
1349 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1350
1351 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial((Path) null, IDENTITY_PASSWORD))
1352 .isInstanceOf(GenericKeyStoreException.class)
1353 .hasMessage(GENERIC_IDENTITY_VALIDATION_EXCEPTION_MESSAGE);
1354 }
1355
1356 @Test
1357 void throwExceptionWhenIdentityIsNull() {
1358 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1359
1360 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial((KeyStore) null, IDENTITY_PASSWORD))
1361 .isInstanceOf(GenericKeyStoreException.class)
1362 .hasMessage(GENERIC_IDENTITY_VALIDATION_EXCEPTION_MESSAGE);
1363 }
1364
1365 @Test
1366 void throwExceptionWhenIdentityTypeIsNotProvidedWhileUsingPath() throws IOException {
1367 Path identityPath = copyKeystoreToHomeDirectory(KEYSTORE_LOCATION, IDENTITY_FILE_NAME);
1368 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1369
1370 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial(identityPath, IDENTITY_PASSWORD, EMPTY))
1371 .isInstanceOf(GenericKeyStoreException.class)
1372 .hasMessage(GENERIC_IDENTITY_VALIDATION_EXCEPTION_MESSAGE);
1373
1374 Files.delete(identityPath);
1375 }
1376
1377 @Test
1378 void throwExceptionWhenIdentityStreamIsNull() {
1379 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1380
1381 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial((InputStream) null, IDENTITY_PASSWORD))
1382 .isInstanceOf(GenericKeyStoreException.class)
1383 .hasMessage(GENERIC_IDENTITY_VALIDATION_EXCEPTION_MESSAGE);
1384 }
1385
1386 @Test
1387 void throwExceptionWhenIdentityTypeIsNotProvidedWhileUsingInputStream() {
1388 InputStream identityStream = getResourceAsStream(KEYSTORE_LOCATION, IDENTITY_FILE_NAME);
1389 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1390
1391 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial(identityStream, IDENTITY_PASSWORD, EMPTY))
1392 .isInstanceOf(GenericKeyStoreException.class)
1393 .hasMessage(GENERIC_IDENTITY_VALIDATION_EXCEPTION_MESSAGE);
1394 }
1395
1396 @Test
1397 void throwExceptionWhenUnknownIdentityTypeIsProvidedWhileUsingInputStream() {
1398 InputStream identityStream = getResourceAsStream(KEYSTORE_LOCATION, IDENTITY_FILE_NAME);
1399 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1400
1401 assertThatThrownBy(() -> factoryBuilder.withIdentityMaterial(identityStream, IDENTITY_PASSWORD, "KABOOM"))
1402 .isInstanceOf(GenericKeyStoreException.class)
1403 .hasMessageContaining("KABOOM not found");
1404 }
1405
1406 @Test
1407 void throwExceptionWhenUnknownTrustStoreTypeIsProvidedWhileUsingInputStream() {
1408 InputStream trustStoreStream = getResourceAsStream(KEYSTORE_LOCATION, TRUSTSTORE_FILE_NAME);
1409 SSLFactory.Builder factoryBuilder = SSLFactory.builder();
1410
1411 assertThatThrownBy(() -> factoryBuilder.withTrustMaterial(trustStoreStream, TRUSTSTORE_PASSWORD, "KABOOM"))
1412 .isInstanceOf(GenericKeyStoreException.class)
1413 .hasMessageContaining("KABOOM not found");
1414 }
1415
1416 @Test
1417 void throwExceptionWhenProvidingWrongKeyPassword() {
1418 SSLFactory.Builder factoryBuilder = SSLFactory.builder()
1419 .withIdentityMaterial(
1420 KEYSTORE_LOCATION + "identity-with-different-key-password.jks",
1421 IDENTITY_PASSWORD,
1422 IDENTITY_PASSWORD)
1423 .withDefaultTrustMaterial();
1424
1425 assertThatThrownBy(factoryBuilder::build)
1426 .isInstanceOf(GenericSecurityException.class)
1427 .hasMessage("java.security.UnrecoverableKeyException: Get Key failed: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.");
1428 }
1429
1430 @Test
1431 void throwExceptionWhenUnknownSslContextAlgorithmIsProvided() {
1432 SSLFactory.Builder factoryBuilder = SSLFactory.builder()
1433 .withDefaultTrustMaterial()
1434 .withSslContextAlgorithm("KABOOM");
1435
1436 assertThatThrownBy(factoryBuilder::build)
1437 .isInstanceOf(GenericSecurityException.class)
1438 .hasMessage("java.security.NoSuchAlgorithmException: KABOOM SSLContext not available");
1439 }
1440
1441 @Test
1442 void throwExceptionWhenUnknownSecurityProviderNameIsProvided() {
1443 SSLFactory.Builder factoryBuilder = SSLFactory.builder()
1444 .withDefaultTrustMaterial()
1445 .withSslContextAlgorithm("TLS")
1446 .withSecurityProvider("KABOOOM");
1447
1448 assertThatThrownBy(factoryBuilder::build)
1449 .isInstanceOf(GenericSecurityException.class)
1450 .hasMessage("java.security.NoSuchProviderException: no such provider: KABOOOM");
1451 }
1452
1453 @Test
1454 void throwExceptionNullIsIsProvidedWhenUsingPrivateKey() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, UnrecoverableKeyException {
1455 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
1456 Certificate[] certificateChain = identity.getCertificateChain("dummy-client");
1457
1458 SSLFactory.Builder sslFactoryBuilder = SSLFactory.builder();
1459
1460 assertThatThrownBy(() -> sslFactoryBuilder.withIdentityMaterial(null, IDENTITY_PASSWORD, certificateChain))
1461 .isInstanceOf(GenericSecurityException.class)
1462 .hasMessageContaining("Unsupported Key type");
1463 }
1464
1465 @Test
1466 void throwExceptionWhenKeyManagerFactoryDoesNotContainsKeyManagersOfX509KeyManagerType() throws Exception {
1467 KeyStore identity = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + IDENTITY_FILE_NAME, IDENTITY_PASSWORD);
1468 KeyManagerFactory keyManagerFactory = spy(KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()));
1469 keyManagerFactory.init(identity, IDENTITY_PASSWORD);
1470
1471 when(keyManagerFactory.getKeyManagers()).thenReturn(new KeyManager[] { mock(KeyManager.class) });
1472 SSLFactory.Builder sslFactoryBuilder = SSLFactory.builder();
1473
1474 assertThatThrownBy(() -> sslFactoryBuilder.withIdentityMaterial(keyManagerFactory))
1475 .isInstanceOf(GenericKeyManagerException.class)
1476 .hasMessage("Input does not contain KeyManagers");
1477 }
1478
1479 @Test
1480 void throwExceptionWhenTrustManagerFactoryDoesNotContainsTrustManagersOfX509TrustManagerType() throws Exception {
1481 KeyStore trustStore = KeyStoreUtils.loadKeyStore(KEYSTORE_LOCATION + TRUSTSTORE_FILE_NAME, TRUSTSTORE_PASSWORD);
1482 TrustManagerFactory trustManagerFactory = spy(TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()));
1483 trustManagerFactory.init(trustStore);
1484
1485 when(trustManagerFactory.getTrustManagers()).thenReturn(new TrustManager[] { mock(TrustManager.class) });
1486 SSLFactory.Builder sslFactoryBuilder = SSLFactory.builder();
1487
1488 assertThatThrownBy(() -> sslFactoryBuilder.withTrustMaterial(trustManagerFactory))
1489 .isInstanceOf(GenericTrustManagerException.class)
1490 .hasMessage("Input does not contain TrustManager");
1491 }
1492
1493 @Test
1494 void throwExceptionWhenClientAliasIsNotPresentWhenRoutingIdentities() {
1495 SSLFactory.Builder sslFactoryBuilder = SSLFactory.builder();
1496 assertThatThrownBy(() -> sslFactoryBuilder.withClientIdentityRoute(null, "https://localhost:8443"))
1497 .isInstanceOf(IllegalArgumentException.class)
1498 .hasMessage("clientAlias should be present");
1499 }
1500
1501 @Test
1502 void throwExceptionWhenRouteIsNotPresentForClientIdentityRoute() {
1503 SSLFactory.Builder sslFactoryBuilder = SSLFactory.builder();
1504 assertThatThrownBy(() -> sslFactoryBuilder.withClientIdentityRoute("some-client-alias"))
1505 .isInstanceOf(IllegalArgumentException.class)
1506 .hasMessage("At least one host should be present. No host(s) found for the given alias: [some-client-alias]");
1507 }
1508
1509 @SuppressWarnings("SameParameterValue")
1510 private Path copyKeystoreToHomeDirectory(String path, String fileName) throws IOException {
1511 try (InputStream keystoreInputStream = getResourceAsStream(path, fileName)) {
1512 Path destination = Paths.get(TEMPORALLY_KEYSTORE_LOCATION, fileName);
1513 Files.copy(Objects.requireNonNull(keystoreInputStream), destination, REPLACE_EXISTING);
1514 return destination;
1515 }
1516 }
1517
1518 private InputStream getResourceAsStream(String path, String fileName) {
1519 return Thread.currentThread().getContextClassLoader().getResourceAsStream(path + fileName);
1520 }
1521
1522 }