|
22 | 22 | import java.security.GeneralSecurityException; |
23 | 23 | import java.security.KeyStore; |
24 | 24 | import java.security.KeyStoreException; |
| 25 | +import java.security.SecureRandom; |
25 | 26 | import java.security.cert.CertificateExpiredException; |
26 | 27 | import java.security.cert.CertificateNotYetValidException; |
27 | 28 | import java.security.cert.CertificateParsingException; |
|
39 | 40 | import javax.naming.ConfigurationException; |
40 | 41 | import javax.net.ssl.SSLContext; |
41 | 42 | import javax.net.ssl.SSLEngine; |
| 43 | +import javax.net.ssl.TrustManagerFactory; |
| 44 | +import javax.net.ssl.X509TrustManager; |
42 | 45 |
|
43 | 46 | import org.apache.cloudstack.api.ApiErrorCode; |
44 | 47 | import org.apache.cloudstack.api.ServerApiException; |
@@ -400,9 +403,54 @@ public boolean start() { |
400 | 403 | logger.error("Failed to find valid configured CA provider, please check!"); |
401 | 404 | return false; |
402 | 405 | } |
| 406 | + if (CaInjectDefaultTruststore.value()) { |
| 407 | + injectCaCertIntoDefaultTruststore(); |
| 408 | + } |
403 | 409 | return true; |
404 | 410 | } |
405 | 411 |
|
| 412 | + private void injectCaCertIntoDefaultTruststore() { |
| 413 | + try { |
| 414 | + final List<X509Certificate> caCerts = configuredCaProvider.getCaCertificate(); |
| 415 | + if (caCerts == null || caCerts.isEmpty()) { |
| 416 | + logger.debug("No CA certificates found from the configured provider, skipping JVM truststore injection"); |
| 417 | + return; |
| 418 | + } |
| 419 | + |
| 420 | + final KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); |
| 421 | + trustStore.load(null, null); |
| 422 | + |
| 423 | + // Copy existing default trusted certs |
| 424 | + final TrustManagerFactory defaultTmf = TrustManagerFactory.getInstance("SunX509"); |
| 425 | + defaultTmf.init((KeyStore) null); |
| 426 | + final X509TrustManager defaultTm = (X509TrustManager) defaultTmf.getTrustManagers()[0]; |
| 427 | + for (final X509Certificate cert : defaultTm.getAcceptedIssuers()) { |
| 428 | + final String alias = cert.getSubjectX500Principal().getName(); |
| 429 | + trustStore.setCertificateEntry(alias, cert); |
| 430 | + } |
| 431 | + |
| 432 | + // Add CA provider's certificates |
| 433 | + int count = 0; |
| 434 | + for (final X509Certificate caCert : caCerts) { |
| 435 | + final String alias = "cloudstack-ca-" + count; |
| 436 | + trustStore.setCertificateEntry(alias, caCert); |
| 437 | + count++; |
| 438 | + logger.info("Injected CA certificate into JVM default truststore: subject={}, alias={}", |
| 439 | + caCert.getSubjectX500Principal().getName(), alias); |
| 440 | + } |
| 441 | + |
| 442 | + // Reinitialize default SSLContext with the updated truststore |
| 443 | + final TrustManagerFactory updatedTmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); |
| 444 | + updatedTmf.init(trustStore); |
| 445 | + final SSLContext sslContext = SSLContext.getInstance("TLS"); |
| 446 | + sslContext.init(null, updatedTmf.getTrustManagers(), new SecureRandom()); |
| 447 | + SSLContext.setDefault(sslContext); |
| 448 | + logger.info("Successfully injected {} CA certificate(s) into JVM default truststore", count); |
| 449 | + } catch (final GeneralSecurityException | IOException e) { |
| 450 | + logger.error("Failed to inject CA certificate into JVM default truststore", e); |
| 451 | + } |
| 452 | + } |
| 453 | + |
406 | 454 | @Override |
407 | 455 | public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException { |
408 | 456 | backgroundPollManager.submitTask(new CABackgroundTask(this, hostDao)); |
@@ -433,7 +481,7 @@ public String getConfigComponentName() { |
433 | 481 | public ConfigKey<?>[] getConfigKeys() { |
434 | 482 | return new ConfigKey<?>[] {CAProviderPlugin, CertKeySize, CertSignatureAlgorithm, CertValidityPeriod, |
435 | 483 | AutomaticCertRenewal, AllowHostIPInSysVMAgentCert, CABackgroundJobDelay, CertExpiryAlertPeriod, |
436 | | - CertManagementCustomSubjectAlternativeName |
| 484 | + CertManagementCustomSubjectAlternativeName, CaInjectDefaultTruststore |
437 | 485 | }; |
438 | 486 | } |
439 | 487 |
|
|
0 commit comments