@@ -106,17 +106,21 @@ public final class RootCAProvider extends AdapterBase implements CAProvider, Con
106106 private static ConfigKey <String > rootCAPrivateKey = new ConfigKey <>("Hidden" , String .class ,
107107 "ca.plugin.root.private.key" ,
108108 null ,
109- "The ROOT CA private key." , true );
109+ "The ROOT CA private key in PEM format (PKCS#8: must start with '-----BEGIN PRIVATE KEY-----'). " +
110+ "When set along with the public key and certificate, CloudStack uses this custom CA instead of auto-generating one. " +
111+ "All three ca.plugin.root.* keys must be set together. Restart management server(s) when changed." , true );
110112
111113 private static ConfigKey <String > rootCAPublicKey = new ConfigKey <>("Hidden" , String .class ,
112114 "ca.plugin.root.public.key" ,
113115 null ,
114- "The ROOT CA public key." , true );
116+ "The ROOT CA public key in PEM format (X.509/SPKI: must start with '-----BEGIN PUBLIC KEY-----'). " +
117+ "Required when providing a custom CA. Restart management server(s) when changed." , true );
115118
116119 private static ConfigKey <String > rootCACertificate = new ConfigKey <>("Hidden" , String .class ,
117120 "ca.plugin.root.ca.certificate" ,
118121 null ,
119- "The ROOT CA certificate." , true );
122+ "The ROOT CA X.509 certificate in PEM format (must start with '-----BEGIN CERTIFICATE-----'). " +
123+ "Required when providing a custom CA. Restart management server(s) when changed." , true );
120124
121125 private static ConfigKey <String > rootCAIssuerDN = new ConfigKey <>("Advanced" , String .class ,
122126 "ca.plugin.root.issuer.dn" ,
@@ -422,13 +426,29 @@ protected void addConfiguredManagementIp(List<String> ipList) {
422426
423427
424428 private boolean setupCA () {
425- if (!loadRootCAKeyPair () && !saveNewRootCAKeypair ()) {
426- logger .error ("Failed to save and load root CA keypair" );
427- return false ;
429+ if (!loadRootCAKeyPair ()) {
430+ if (hasUserProvidedCAKeys ()) {
431+ logger .error ("Failed to load user-provided CA keys from configuration. " +
432+ "Check that ca.plugin.root.private.key, ca.plugin.root.public.key, and " +
433+ "ca.plugin.root.ca.certificate are all set and in the correct PEM format " +
434+ "(private key must be PKCS#8: '-----BEGIN PRIVATE KEY-----'). " +
435+ "Overwriting with auto-generated keys." );
436+ }
437+ if (!saveNewRootCAKeypair ()) {
438+ logger .error ("Failed to save and load root CA keypair" );
439+ return false ;
440+ }
428441 }
429- if (!loadRootCACertificate () && !saveNewRootCACertificate ()) {
430- logger .error ("Failed to save and load root CA certificate" );
431- return false ;
442+ if (!loadRootCACertificate ()) {
443+ if (hasUserProvidedCAKeys ()) {
444+ logger .error ("Failed to load user-provided CA certificate. " +
445+ "Check that ca.plugin.root.ca.certificate is set and in PEM format. " +
446+ "Overwriting with auto-generated certificate." );
447+ }
448+ if (!saveNewRootCACertificate ()) {
449+ logger .error ("Failed to save and load root CA certificate" );
450+ return false ;
451+ }
432452 }
433453 if (!loadManagementKeyStore ()) {
434454 logger .error ("Failed to check and configure management server keystore" );
@@ -437,10 +457,16 @@ private boolean setupCA() {
437457 return true ;
438458 }
439459
460+ private boolean hasUserProvidedCAKeys () {
461+ return StringUtils .isNotEmpty (rootCAPublicKey .value ())
462+ || StringUtils .isNotEmpty (rootCAPrivateKey .value ())
463+ || StringUtils .isNotEmpty (rootCACertificate .value ());
464+ }
465+
440466 @ Override
441467 public boolean start () {
442468 managementCertificateCustomSAN = CAManager .CertManagementCustomSubjectAlternativeName .value ();
443- return loadRootCAKeyPair () && loadRootCAKeyPair () && loadManagementKeyStore ();
469+ return loadRootCAKeyPair () && loadRootCACertificate () && loadManagementKeyStore ();
444470 }
445471
446472 @ Override
0 commit comments