Skip to content

Commit d108f32

Browse files
authored
KVM: Prevent regenerating keystore on provisionCertificate API (#3075)
* Prevent regenerating keystore and add background task to upload certificates * Remove background task to upload certificates * keystore-setup: delete old key in jks Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com> * also don't allow ca-cert alias Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
1 parent 8fb388e commit d108f32

4 files changed

Lines changed: 30 additions & 30 deletions

File tree

api/src/org/apache/cloudstack/api/command/admin/direct/download/UploadTemplateDirectDownloadCertificateCmd.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@
1616
// under the License.
1717
package org.apache.cloudstack.api.command.admin.direct.download;
1818

19-
import com.cloud.exception.ConcurrentOperationException;
20-
import com.cloud.exception.InsufficientCapacityException;
21-
import com.cloud.exception.ResourceAllocationException;
22-
import com.cloud.exception.ResourceUnavailableException;
23-
import com.cloud.exception.NetworkRuleConflictException;
2419
import org.apache.cloudstack.acl.RoleType;
2520
import org.apache.cloudstack.api.APICommand;
2621
import org.apache.cloudstack.api.ApiConstants;
@@ -62,15 +57,15 @@ public class UploadTemplateDirectDownloadCertificateCmd extends BaseCmd {
6257
private String hypervisor;
6358

6459
@Override
65-
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
60+
public void execute() {
6661
if (!hypervisor.equalsIgnoreCase("kvm")) {
6762
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Currently supporting KVM hosts only");
6863
}
6964

70-
SuccessResponse response = new SuccessResponse(getCommandName());
7165
try {
7266
LOG.debug("Uploading certificate " + name + " to agents for Direct Download");
7367
boolean result = directDownloadManager.uploadCertificateToHosts(certificate, name, hypervisor);
68+
SuccessResponse response = new SuccessResponse(getCommandName());
7469
response.setSuccess(result);
7570
setResponseObject(response);
7671
} catch (Exception e) {

scripts/util/keystore-cert-import

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ if [ -z "${KS_PASS// }" ]; then
3838
exit 1
3939
fi
4040

41-
# Use a new keystore file
42-
NEW_KS_FILE="$KS_FILE.new"
43-
4441
# Import certificate
4542
if [ ! -z "${CERT// }" ]; then
4643
echo "$CERT" > "$CERT_FILE"
@@ -54,30 +51,28 @@ fi
5451
# Import cacerts into the keystore
5552
awk '/-----BEGIN CERTIFICATE-----?/{n++}{print > "cloudca." n }' "$CACERT_FILE"
5653
for caChain in $(ls cloudca.*); do
57-
keytool -delete -noprompt -alias "$caChain" -keystore "$NEW_KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true
58-
keytool -import -noprompt -storepass "$KS_PASS" -trustcacerts -alias "$caChain" -file "$caChain" -keystore "$NEW_KS_FILE" > /dev/null 2>&1
54+
keytool -delete -noprompt -alias "$caChain" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true
55+
keytool -import -noprompt -storepass "$KS_PASS" -trustcacerts -alias "$caChain" -file "$caChain" -keystore "$KS_FILE" > /dev/null 2>&1
5956
done
6057
rm -f cloudca.*
6158

6259
# Import private key if available
6360
if [ ! -z "${PRIVKEY// }" ]; then
6461
echo "$PRIVKEY" > "$PRIVKEY_FILE"
6562
# Re-initialize keystore when private key is provided
66-
keytool -delete -noprompt -alias "$ALIAS" -keystore "$NEW_KS_FILE" -storepass "$KS_PASS" 2>/dev/null || true
67-
openssl pkcs12 -export -name "$ALIAS" -in "$CERT_FILE" -inkey "$PRIVKEY_FILE" -out "$NEW_KS_FILE.p12" -password pass:"$KS_PASS" > /dev/null 2>&1
68-
keytool -importkeystore -srckeystore "$NEW_KS_FILE.p12" -destkeystore "$NEW_KS_FILE" -srcstoretype PKCS12 -alias "$ALIAS" -deststorepass "$KS_PASS" -destkeypass "$KS_PASS" -srcstorepass "$KS_PASS" -srckeypass "$KS_PASS" > /dev/null 2>&1
63+
keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" 2>/dev/null || true
64+
openssl pkcs12 -export -name "$ALIAS" -in "$CERT_FILE" -inkey "$PRIVKEY_FILE" -out "$KS_FILE.p12" -password pass:"$KS_PASS" > /dev/null 2>&1
65+
keytool -importkeystore -srckeystore "$KS_FILE.p12" -destkeystore "$KS_FILE" -srcstoretype PKCS12 -alias "$ALIAS" -deststorepass "$KS_PASS" -destkeypass "$KS_PASS" -srcstorepass "$KS_PASS" -srckeypass "$KS_PASS" > /dev/null 2>&1
6966
else
7067
# Import certificate into the keystore
71-
keytool -import -storepass "$KS_PASS" -alias "$ALIAS" -file "$CERT_FILE" -keystore "$NEW_KS_FILE" > /dev/null 2>&1 || true
68+
keytool -import -storepass "$KS_PASS" -alias "$ALIAS" -file "$CERT_FILE" -keystore "$KS_FILE" > /dev/null 2>&1 || true
7269
# Export private key from keystore
7370
rm -f "$PRIVKEY_FILE"
74-
keytool -importkeystore -srckeystore "$NEW_KS_FILE" -destkeystore "$NEW_KS_FILE.p12" -deststoretype PKCS12 -srcalias "$ALIAS" -deststorepass "$KS_PASS" -destkeypass "$KS_PASS" -srcstorepass "$KS_PASS" -srckeypass "$KS_PASS" > /dev/null 2>&1
75-
openssl pkcs12 -in "$NEW_KS_FILE.p12" -nodes -nocerts -nomac -password pass:"$KS_PASS" 2>/dev/null | openssl rsa -out "$PRIVKEY_FILE" > /dev/null 2>&1
71+
keytool -importkeystore -srckeystore "$KS_FILE" -destkeystore "$KS_FILE.p12" -deststoretype PKCS12 -srcalias "$ALIAS" -deststorepass "$KS_PASS" -destkeypass "$KS_PASS" -srcstorepass "$KS_PASS" -srckeypass "$KS_PASS" > /dev/null 2>&1
72+
openssl pkcs12 -in "$KS_FILE.p12" -nodes -nocerts -nomac -password pass:"$KS_PASS" 2>/dev/null | openssl rsa -out "$PRIVKEY_FILE" > /dev/null 2>&1
7673
fi
7774

78-
# Commit the new keystore
79-
rm -f "$NEW_KS_FILE.p12"
80-
mv -f "$NEW_KS_FILE" "$KS_FILE"
75+
rm -f "$KS_FILE.p12"
8176

8277
# Secure libvirtd on cert import
8378
if [ -f "$LIBVIRTD_FILE" ]; then

scripts/util/keystore-setup

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# under the License.
1818

1919
PROPS_FILE="$1"
20-
KS_FILE="$2.new"
20+
KS_FILE="$2"
2121
KS_PASS="$3"
2222
KS_VALIDITY="$4"
2323
CSR_FILE="$5"
@@ -35,8 +35,10 @@ if [ -f "$PROPS_FILE" ]; then
3535
fi
3636
fi
3737

38-
# Generate keystore
39-
rm -f "$KS_FILE"
38+
if [ -f "$KS_FILE" ]; then
39+
keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true
40+
fi
41+
4042
CN=$(hostname --fqdn)
4143
keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1
4244

server/src/org/apache/cloudstack/direct/download/DirectDownloadManagerImpl.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,17 @@ public class DirectDownloadManagerImpl extends ManagerBase implements DirectDown
8585
protected final static String LINE_SEPARATOR = "\n";
8686

8787
@Inject
88-
VMTemplateDao vmTemplateDao;
88+
private VMTemplateDao vmTemplateDao;
8989
@Inject
90-
PrimaryDataStoreDao primaryDataStoreDao;
90+
private PrimaryDataStoreDao primaryDataStoreDao;
9191
@Inject
92-
HostDao hostDao;
92+
private HostDao hostDao;
9393
@Inject
94-
AgentManager agentManager;
94+
private AgentManager agentManager;
9595
@Inject
96-
VMTemplatePoolDao vmTemplatePoolDao;
96+
private VMTemplatePoolDao vmTemplatePoolDao;
9797
@Inject
98-
DataStoreManager dataStoreManager;
98+
private DataStoreManager dataStoreManager;
9999

100100
@Override
101101
public List<Class<?>> getCommands() {
@@ -366,29 +366,37 @@ protected void certificateSanity(String certificatePem) {
366366

367367
@Override
368368
public boolean uploadCertificateToHosts(String certificateCer, String alias, String hypervisor) {
369+
if (alias != null && (alias.equalsIgnoreCase("cloud") || alias.startsWith("cloudca"))) {
370+
throw new CloudRuntimeException("Please provide a different alias name for the certificate");
371+
}
372+
369373
HypervisorType hypervisorType = HypervisorType.getType(hypervisor);
370374
List<HostVO> hosts = getRunningHostsToUploadCertificate(hypervisorType);
371375

372376
String certificatePem = getPretifiedCertificate(certificateCer);
373377
certificateSanity(certificatePem);
374378

375379
s_logger.info("Attempting to upload certificate: " + alias + " to " + hosts.size() + " hosts");
380+
int hostCount = 0;
376381
if (CollectionUtils.isNotEmpty(hosts)) {
377382
for (HostVO host : hosts) {
378383
if (!uploadCertificate(certificatePem, alias, host.getId())) {
379384
String msg = "Could not upload certificate " + alias + " on host: " + host.getName() + " (" + host.getUuid() + ")";
380385
s_logger.error(msg);
381386
throw new CloudRuntimeException(msg);
382387
}
388+
hostCount++;
383389
}
384390
}
391+
s_logger.info("Certificate was successfully uploaded to " + hostCount + " hosts");
385392
return true;
386393
}
387394

388395
/**
389396
* Upload and import certificate to hostId on keystore
390397
*/
391398
protected boolean uploadCertificate(String certificate, String certificateName, long hostId) {
399+
s_logger.debug("Uploading certificate: " + certificateName + " to host " + hostId);
392400
SetupDirectDownloadCertificateCommand cmd = new SetupDirectDownloadCertificateCommand(certificate, certificateName);
393401
Answer answer = agentManager.easySend(hostId, cmd);
394402
if (answer == null || !answer.getResult()) {

0 commit comments

Comments
 (0)