Skip to content

Commit 48e745c

Browse files
Add certificate validation to check headers (#9255)
1 parent 674129c commit 48e745c

3 files changed

Lines changed: 39 additions & 14 deletions

File tree

framework/security/src/main/java/org/apache/cloudstack/framework/security/keystore/KeystoreManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.cloud.agent.api.LogLevel;
2020
import com.cloud.agent.api.LogLevel.Log4jLevel;
21+
import com.cloud.utils.Pair;
2122
import com.cloud.utils.component.Manager;
2223

2324
public interface KeystoreManager extends Manager {
@@ -59,7 +60,7 @@ public String getRootCACert() {
5960
}
6061
}
6162

62-
boolean validateCertificate(String certificate, String key, String domainSuffix);
63+
Pair<Boolean, String> validateCertificate(String certificate, String key, String domainSuffix);
6364

6465
void saveCertificate(String name, String certificate, String key, String domainSuffix);
6566

framework/security/src/main/java/org/apache/cloudstack/framework/security/keystore/KeystoreManagerImpl.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
import javax.inject.Inject;
3232

33+
import com.cloud.utils.Pair;
3334
import org.apache.commons.lang3.StringUtils;
3435
import org.apache.log4j.Logger;
3536
import org.springframework.stereotype.Component;
@@ -47,24 +48,28 @@ public class KeystoreManagerImpl extends ManagerBase implements KeystoreManager
4748
private KeystoreDao _ksDao;
4849

4950
@Override
50-
public boolean validateCertificate(String certificate, String key, String domainSuffix) {
51+
public Pair<Boolean, String> validateCertificate(String certificate, String key, String domainSuffix) {
52+
String errMsg = null;
5153
if (StringUtils.isAnyEmpty(certificate, key, domainSuffix)) {
52-
s_logger.error("Invalid parameter found in (certificate, key, domainSuffix) tuple for domain: " + domainSuffix);
53-
return false;
54+
errMsg = String.format("Invalid parameter found in (certificate, key, domainSuffix) tuple for domain: %s", domainSuffix);
55+
s_logger.error(errMsg);
56+
return new Pair<>(false, errMsg);
5457
}
5558

5659
try {
5760
String ksPassword = "passwordForValidation";
5861
byte[] ksBits = CertificateHelper.buildAndSaveKeystore(domainSuffix, certificate, getKeyContent(key), ksPassword);
5962
KeyStore ks = CertificateHelper.loadKeystore(ksBits, ksPassword);
60-
if (ks != null)
61-
return true;
62-
63-
s_logger.error("Unabled to construct keystore for domain: " + domainSuffix);
63+
if (ks != null) {
64+
return new Pair<>(true, errMsg);
65+
}
66+
errMsg = String.format("Unable to construct keystore for domain: %s", domainSuffix);
67+
s_logger.error(errMsg);
6468
} catch (Exception e) {
65-
s_logger.error("Certificate validation failed due to exception for domain: " + domainSuffix, e);
69+
errMsg = String.format("Certificate validation failed due to exception for domain: %s", domainSuffix);
70+
s_logger.error(errMsg, e);
6671
}
67-
return false;
72+
return new Pair<>(false, errMsg);
6873
}
6974

7075
@Override

server/src/main/java/com/cloud/server/ManagementServerImpl.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.cloud.server;
1818

1919
import java.lang.reflect.Field;
20+
import java.security.cert.CertificateException;
2021
import java.util.ArrayList;
2122
import java.util.Arrays;
2223
import java.util.Calendar;
@@ -43,6 +44,7 @@
4344
import javax.inject.Inject;
4445
import javax.naming.ConfigurationException;
4546

47+
import com.cloud.utils.security.CertificateHelper;
4648
import org.apache.cloudstack.acl.ControlledEntity;
4749
import org.apache.cloudstack.acl.SecurityChecker;
4850
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
@@ -4484,13 +4486,12 @@ public String uploadCertificate(final UploadCustomCertificateCmd cmd) {
44844486

44854487
final String certificate = cmd.getCertificate();
44864488
final String key = cmd.getPrivateKey();
4489+
String domainSuffix = cmd.getDomainSuffix();
44874490

4488-
if (cmd.getPrivateKey() != null && !_ksMgr.validateCertificate(certificate, key, cmd.getDomainSuffix())) {
4489-
throw new InvalidParameterValueException("Failed to pass certificate validation check");
4490-
}
4491+
validateCertificate(certificate, key, domainSuffix);
44914492

44924493
if (cmd.getPrivateKey() != null) {
4493-
_ksMgr.saveCertificate(ConsoleProxyManager.CERTIFICATE_NAME, certificate, key, cmd.getDomainSuffix());
4494+
_ksMgr.saveCertificate(ConsoleProxyManager.CERTIFICATE_NAME, certificate, key, domainSuffix);
44944495

44954496
// Reboot ssvm here since private key is present - meaning server cert being passed
44964497
final List<SecondaryStorageVmVO> alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(null, State.Running, State.Migrating, State.Starting);
@@ -4507,6 +4508,24 @@ public String uploadCertificate(final UploadCustomCertificateCmd cmd) {
45074508
+ "please give a few minutes for console access and storage services service to be up and working again";
45084509
}
45094510

4511+
private void validateCertificate(String certificate, String key, String domainSuffix) {
4512+
if (key != null) {
4513+
Pair<Boolean, String> result = _ksMgr.validateCertificate(certificate, key, domainSuffix);
4514+
if (!result.first()) {
4515+
throw new InvalidParameterValueException(String.format("Failed to pass certificate validation check with error: %s", result.second()));
4516+
}
4517+
} else {
4518+
try {
4519+
s_logger.debug(String.format("Trying to validate the root certificate format"));
4520+
CertificateHelper.buildCertificate(certificate);
4521+
} catch (CertificateException e) {
4522+
String errorMsg = String.format("Failed to pass certificate validation check with error: Certificate validation failed due to exception: %s", e.getMessage());
4523+
s_logger.error(errorMsg);
4524+
throw new InvalidParameterValueException(errorMsg);
4525+
}
4526+
}
4527+
}
4528+
45104529
@Override
45114530
public List<String> getHypervisors(final Long zoneId) {
45124531
final List<String> result = new ArrayList<String>();

0 commit comments

Comments
 (0)