mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-6695: Added support to the UI for uploading a chain of certificates
In the "SSL Certificate" dialog we added: - new field for the root certificate; - a button to add intermediate certificates if necessary; when this is pressed, a new field, called "Intermediate certificate 1" is added; pressed again, "Intermediate certificate 2" field is added, and so on. We upload the certificates in order: first the root certificate (with id=1), then the intermediate certificates (with id=2,3,..) and finally the server certificate. When uploading a certificate, we wait for the upload to be completed successfully and only then we proceed to uploading the next one. If one fails, we report failure and don't continue with the remaining. Signed-off-by: Mihaela Stoica <mihaela.stoica@citrix.com>
This commit is contained in:
parent
ffe0f2f60f
commit
57f611df16
@ -313,6 +313,7 @@ label.add.firewall=Add firewall rule
|
||||
label.add.guest.network=Add guest network
|
||||
label.add.host=Add Host
|
||||
label.add.ingress.rule=Add Ingress Rule
|
||||
label.add.intermediate.certificate=Add intermediate certificate
|
||||
label.add.ip.range=Add IP Range
|
||||
label.add.load.balancer=Add Load Balancer
|
||||
label.add.more=Add More
|
||||
@ -431,7 +432,7 @@ label.cancel=Cancel
|
||||
label.capacity=Capacity
|
||||
label.capacity.bytes=Capacity Bytes
|
||||
label.capacity.iops=Capacity IOPS
|
||||
label.certificate=Certificate
|
||||
label.certificate=Server certificate
|
||||
label.change.service.offering=Change service offering
|
||||
label.change.value=Change value
|
||||
label.character=Character
|
||||
@ -678,6 +679,7 @@ label.instance.limits=Instance Limits
|
||||
label.instance.name=Instance Name
|
||||
label.instance=Instance
|
||||
label.instances=Instances
|
||||
label.intermediate.certificate=Intermediate certificate {0}
|
||||
label.internal.dns.1=Internal DNS 1
|
||||
label.internal.dns.2=Internal DNS 2
|
||||
label.internal.name=Internal name
|
||||
@ -1020,6 +1022,7 @@ label.retry.interval=Retry Interval
|
||||
label.review=Review
|
||||
label.revoke.project.invite=Revoke invitation
|
||||
label.role=Role
|
||||
label.root.certificate=Root certificate
|
||||
label.root.disk.controller=Root disk controller
|
||||
label.root.disk.offering=Root Disk Offering
|
||||
label.round.robin=Round-robin
|
||||
@ -1820,7 +1823,7 @@ message.tooltip.reserved.system.netmask=The network prefix that defines the pod
|
||||
message.tooltip.zone.name=A name for the zone.
|
||||
message.update.os.preference=Please choose a OS preference for this host. All virtual instances with similar preferences will be first allocated to this host before choosing another.
|
||||
message.update.resource.count=Please confirm that you want to update resource counts for this account.
|
||||
message.update.ssl=Please submit a new X.509 compliant SSL certificate to be updated to each console proxy and secondary storage virtual instance\:
|
||||
message.update.ssl=Please submit a new X.509 compliant SSL certificate chain to be updated to each console proxy and secondary storage virtual instance\:
|
||||
message.validate.instance.name=Instance name can not be longer than 63 characters. Only ASCII letters a~z, A~Z, digits 0~9, hyphen are allowed. Must start with a letter and end with a letter or a digit.
|
||||
message.virtual.network.desc=A dedicated virtualized network for your account. The broadcast domain is contained within a VLAN and all public network access is routed out by a virtual router.
|
||||
message.vm.create.template.confirm=Create Template will reboot the VM automatically.
|
||||
|
||||
@ -4053,7 +4053,7 @@ Dialogs*/
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ui-dialog div.form-container div.value input {
|
||||
.ui-dialog div.form-container div.value input, textarea {
|
||||
width: 98%;
|
||||
font-size: 14px;
|
||||
padding: 4px;
|
||||
@ -12984,3 +12984,21 @@ div.gpugroups div.list-view {
|
||||
padding: 12px 12px 5px;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-button.add {
|
||||
background: linear-gradient(to bottom, #f7f7f7 1%, #eaeaea 100%) repeat scroll 0px 0px transparent;
|
||||
font-size: 12px;
|
||||
height: 12px;
|
||||
width: auto;
|
||||
margin: 0px 0px 12px;
|
||||
padding: 5px 7px 5px 6px;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-button.add:hover {
|
||||
background: none repeat scroll 0px 0px #e5e5e5;
|
||||
box-shadow: 0px 0px 5px #c3c3c3 inset;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-button.add span {
|
||||
background: url("../images/icons.png") no-repeat scroll -626px -209px transparent;
|
||||
padding: 0 0 3px 18px;
|
||||
}
|
||||
@ -1898,7 +1898,10 @@ dictionary = {
|
||||
'message.confirm.enable.vpc.offering': '<fmt:message key="message.confirm.enable.vpc.offering" />',
|
||||
'message.enabling.vpc.offering': '<fmt:message key="message.enabling.vpc.offering" />',
|
||||
'message.confirm.remove.vpc.offering': '<fmt:message key="message.confirm.remove.vpc.offering" />',
|
||||
'message.confirm.disable.vpc.offering': '<fmt:message key="message.confirm.disable.vpc.offering" />'
|
||||
'message.confirm.disable.vpc.offering': '<fmt:message key="message.confirm.disable.vpc.offering" />',
|
||||
'label.root.certificate': '<fmt:message key="label.root.certificate" />',
|
||||
'label.intermediate.certificate': '<fmt:message key="label.intermediate.certificate" />',
|
||||
'label.add.intermediate.certificate': '<fmt:message key="label.add.intermediate.certificate" />'
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -96,72 +96,165 @@
|
||||
form: {
|
||||
title: 'label.update.ssl',
|
||||
desc: 'message.update.ssl',
|
||||
preFilter: function (args) {
|
||||
var $form = args.$form;
|
||||
|
||||
// insert the "Add intermediate certificate" button
|
||||
var $addButton = $('<div>')
|
||||
.addClass('add ui-button')
|
||||
.append(
|
||||
$('<span>').html(_l('label.add.intermediate.certificate'))
|
||||
);
|
||||
var $servercertificate = $form.find('.form-item[rel=certificate]');
|
||||
$addButton.insertBefore($servercertificate);
|
||||
var count = 0;
|
||||
var $intermediatecertificate = $form.find('.form-item[rel=intermediatecertificate]');
|
||||
|
||||
$addButton.click(function() {
|
||||
// clone the template intermediate certificate and make it visible
|
||||
var $newcertificate = $intermediatecertificate.clone().attr('id','intermediate'+count);
|
||||
$newcertificate.insertBefore($addButton);
|
||||
$newcertificate.css('display', 'inline-block');
|
||||
$newcertificate.addClass('sslcertificate');
|
||||
count++;
|
||||
// change label
|
||||
var $label = $newcertificate.find('label');
|
||||
$label.html($label.html().replace('{0}', count)); // 'Intermediate certificate ' + count + ':'
|
||||
});
|
||||
},
|
||||
fields: {
|
||||
rootcertificate: {
|
||||
label: 'label.root.certificate',
|
||||
isTextarea: true,
|
||||
validation: { required: true }
|
||||
},
|
||||
intermediatecertificate: { // this is the template 'intermediate certificate', always hidden
|
||||
label: 'label.intermediate.certificate',
|
||||
isTextarea: true,
|
||||
isHidden: true
|
||||
},
|
||||
certificate: {
|
||||
label: 'label.certificate',
|
||||
isTextarea: true
|
||||
isTextarea: true,
|
||||
validation: { required: true }
|
||||
},
|
||||
privatekey: {
|
||||
label: 'label.privatekey',
|
||||
isTextarea: true
|
||||
isTextarea: true,
|
||||
validation: { required: true }
|
||||
},
|
||||
domainsuffix: {
|
||||
label: 'label.domain.suffix'
|
||||
label: 'label.domain.suffix',
|
||||
validation: { required: true }
|
||||
}
|
||||
}
|
||||
},
|
||||
after: function(args) {
|
||||
var $loading = $('<div>').addClass('loading-overlay');
|
||||
$('.system-dashboard-view:visible').prepend($loading);
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: createURL('uploadCustomCertificate'),
|
||||
data: {
|
||||
certificate: args.data.certificate,
|
||||
privatekey: args.data.privatekey,
|
||||
|
||||
// build a list with all certificates that need to be uploaded
|
||||
var certificates = [];
|
||||
certificates.push(args.data.rootcertificate);
|
||||
if ($.isArray(args.data.intermediatecertificate))
|
||||
{
|
||||
$.merge(certificates, args.data.intermediatecertificate);
|
||||
}
|
||||
else
|
||||
{
|
||||
certificates.push(args.data.intermediatecertificate);
|
||||
}
|
||||
certificates.push(args.data.certificate);
|
||||
|
||||
// Recursively uploads certificates.
|
||||
// When the upload succeeds, proceeds to uploading the next certificate.
|
||||
// When the upload fails, stops and reports failure.
|
||||
var uploadCertificate = function(index) {
|
||||
if (index >= certificates.length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ( !$.trim(certificates[index])) // skip empty certificate
|
||||
{
|
||||
uploadCertificate(index + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// build certificate data
|
||||
var certificateData = {
|
||||
id: index + 1, // id start from 1
|
||||
certificate: certificates[index],
|
||||
domainsuffix: args.data.domainsuffix
|
||||
},
|
||||
dataType: 'json',
|
||||
success: function(json) {
|
||||
var jid = json.uploadcustomcertificateresponse.jobid;
|
||||
var uploadCustomCertificateIntervalID = setInterval(function() {
|
||||
$.ajax({
|
||||
url: createURL("queryAsyncJobResult&jobId=" + jid),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var result = json.queryasyncjobresultresponse;
|
||||
if (result.jobstatus == 0) {
|
||||
return; //Job has not completed
|
||||
} else {
|
||||
clearInterval(uploadCustomCertificateIntervalID);
|
||||
if (result.jobstatus == 1) {
|
||||
cloudStack.dialog.notice({
|
||||
message: 'Update SSL Certificate succeeded'
|
||||
});
|
||||
} else if (result.jobstatus == 2) {
|
||||
cloudStack.dialog.notice({
|
||||
message: 'Failed to update SSL Certificate. ' + _s(result.jobresult.errortext)
|
||||
});
|
||||
};
|
||||
switch (index) {
|
||||
case (0): //first certificate is the root certificate
|
||||
certificateData['name'] = 'root';
|
||||
break;
|
||||
case (certificates.length - 1): // last certificate is the server certificate
|
||||
certificateData['privatekey'] = args.data.privatekey;
|
||||
break;
|
||||
default: // intermediate certificates
|
||||
certificateData['name'] = 'intermediate' + index;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: createURL('uploadCustomCertificate'),
|
||||
data: certificateData,
|
||||
dataType: 'json',
|
||||
success: function(json) {
|
||||
var jid = json.uploadcustomcertificateresponse.jobid;
|
||||
var uploadCustomCertificateIntervalID = setInterval(function() {
|
||||
$.ajax({
|
||||
url: createURL("queryAsyncJobResult&jobId=" + jid),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var result = json.queryasyncjobresultresponse;
|
||||
if (result.jobstatus == 0) {
|
||||
return; //Job has not completed
|
||||
} else {
|
||||
clearInterval(uploadCustomCertificateIntervalID);
|
||||
if (result.jobstatus == 1) {
|
||||
if (index == certificates.length - 1) // last one, report success
|
||||
{
|
||||
cloudStack.dialog.notice({
|
||||
message: 'Update SSL Certificates succeeded'
|
||||
});
|
||||
$loading.remove();
|
||||
}
|
||||
else // upload next certificate
|
||||
{
|
||||
uploadCertificate(index + 1);
|
||||
}
|
||||
} else if (result.jobstatus == 2) {
|
||||
cloudStack.dialog.notice({
|
||||
message: 'Failed to update SSL Certificate. ' + _s(result.jobresult.errortext)
|
||||
});
|
||||
$loading.remove();
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
cloudStack.dialog.notice({
|
||||
message: 'Failed to update SSL Certificate. ' + parseXMLHttpResponse(XMLHttpResponse)
|
||||
});
|
||||
$loading.remove();
|
||||
}
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
cloudStack.dialog.notice({
|
||||
message: 'Failed to update SSL Certificate. ' + parseXMLHttpResponse(XMLHttpResponse)
|
||||
});
|
||||
$loading.remove();
|
||||
}
|
||||
});
|
||||
}, g_queryAsyncJobResultInterval);
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
cloudStack.dialog.notice({
|
||||
message: 'Failed to update SSL Certificate. ' + parseXMLHttpResponse(XMLHttpResponse)
|
||||
});
|
||||
}, g_queryAsyncJobResultInterval);
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
cloudStack.dialog.notice({
|
||||
message: 'Failed to update SSL Certificate. ' + parseXMLHttpResponse(XMLHttpResponse)
|
||||
});
|
||||
$loading.remove();
|
||||
}
|
||||
});
|
||||
$loading.remove();
|
||||
}
|
||||
});
|
||||
return;
|
||||
};
|
||||
|
||||
// start uploading the certificates
|
||||
uploadCertificate(0);
|
||||
},
|
||||
context: {}
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user