diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js
index 88f267d6..723f94b2 100644
--- a/backend/internal/certificate.js
+++ b/backend/internal/certificate.js
@@ -552,13 +552,18 @@ const internalCertificate = {
})
.then(() => {
return new Promise((resolve, reject) => {
- fs.writeFile(dir + '/privkey.pem', certificate.meta.certificate_key, function (err) {
- if (err) {
- reject(err);
- } else {
- resolve();
- }
- });
+ if (certificate.provider === 'clientca') {
+ // Client CAs have no private key associated, so just succeed.
+ resolve();
+ } else {
+ fs.writeFile(dir + '/privkey.pem', certificate.meta.certificate_key, function (err) {
+ if (err) {
+ reject(err);
+ } else {
+ resolve();
+ }
+ });
+ }
});
});
},
@@ -639,7 +644,7 @@ const internalCertificate = {
upload: (access, data) => {
return internalCertificate.get(access, {id: data.id})
.then((row) => {
- if (row.provider !== 'other') {
+ if (row.provider !== 'other' && row.provider !== 'clientca') {
throw new error.ValidationError('Cannot upload certificates for this type of provider');
}
diff --git a/backend/schema/definitions.json b/backend/schema/definitions.json
index 4b4f3405..136b0235 100644
--- a/backend/schema/definitions.json
+++ b/backend/schema/definitions.json
@@ -219,7 +219,7 @@
},
"ssl_provider": {
"type": "string",
- "pattern": "^(letsencrypt|other)$"
+ "pattern": "^(letsencrypt|other|clientca)$"
},
"http2_support": {
"description": "HTTP2 Protocol Support",
diff --git a/frontend/js/app/nginx/certificates/form.ejs b/frontend/js/app/nginx/certificates/form.ejs
index 7fc12785..6b87261d 100644
--- a/frontend/js/app/nginx/certificates/form.ejs
+++ b/frontend/js/app/nginx/certificates/form.ejs
@@ -173,7 +173,23 @@
-
+ <% } else if (provider === 'clientca') { %>
+
+
+
+
+
+
+
+
<% } %>
diff --git a/frontend/js/app/nginx/certificates/form.js b/frontend/js/app/nginx/certificates/form.js
index a56c3f8e..eb6fb708 100644
--- a/frontend/js/app/nginx/certificates/form.js
+++ b/frontend/js/app/nginx/certificates/form.js
@@ -45,7 +45,9 @@ module.exports = Mn.View.extend({
propagation_seconds: 'input[name="meta[propagation_seconds]"]',
other_certificate_key_label: '#other_certificate_key_label',
other_intermediate_certificate: '#other_intermediate_certificate',
- other_intermediate_certificate_label: '#other_intermediate_certificate_label'
+ other_intermediate_certificate_label: '#other_intermediate_certificate_label',
+ clientca_certificate: '#clientca_certificate',
+ clientca_certificate_label: '#clientca_certificate_label'
},
events: {
@@ -156,6 +158,18 @@ module.exports = Mn.View.extend({
}
ssl_files.push({name: 'intermediate_certificate', file: this.ui.other_intermediate_certificate[0].files[0]});
}
+ } else if (data.provider === 'clientca' && !this.model.hasSslFiles()) {
+ // check files are attached
+ if (!this.ui.clientca_certificate[0].files.length || !this.ui.clientca_certificate[0].files[0].size) {
+ alert('Certificate file is not attached');
+ return;
+ } else {
+ if (this.ui.clientca_certificate[0].files[0].size > this.max_file_size) {
+ alert('Certificate file is too large (> 100kb)');
+ return;
+ }
+ ssl_files.push({name: 'certificate', file: this.ui.clientca_certificate[0].files[0]});
+ }
}
this.ui.loader_content.show();
@@ -163,14 +177,14 @@ module.exports = Mn.View.extend({
// compile file data
let form_data = new FormData();
- if (data.provider === 'other' && ssl_files.length) {
+ if ((data.provider === 'other' || data.provider === 'clientca') && ssl_files.length) {
ssl_files.map(function (file) {
form_data.append(file.name, file.file);
});
}
new Promise(resolve => {
- if (data.provider === 'other') {
+ if (data.provider === 'other' || data.provider === 'clientca') {
resolve(App.Api.Nginx.Certificates.validate(form_data));
} else {
resolve();
@@ -183,7 +197,7 @@ module.exports = Mn.View.extend({
this.model.set(result);
// Now upload the certs if we need to
- if (data.provider === 'other') {
+ if (data.provider === 'other' || data.provider === 'clientca') {
return App.Api.Nginx.Certificates.upload(this.model.get('id'), form_data)
.then(result => {
this.model.set('meta', _.assign({}, this.model.get('meta'), result));
@@ -234,6 +248,9 @@ module.exports = Mn.View.extend({
},
'change @ui.other_intermediate_certificate': function(e){
this.setFileName("other_intermediate_certificate_label", e)
+ },
+ 'change @ui.clientca_certificate': function(e){
+ this.setFileName("clientca_certificate_label", e)
}
},
setFileName(ui, e){
diff --git a/frontend/js/app/nginx/certificates/main.ejs b/frontend/js/app/nginx/certificates/main.ejs
index dbd6fa85..5d49c47a 100644
--- a/frontend/js/app/nginx/certificates/main.ejs
+++ b/frontend/js/app/nginx/certificates/main.ejs
@@ -20,6 +20,7 @@
<% } %>
diff --git a/frontend/js/i18n/messages.json b/frontend/js/i18n/messages.json
index 4f12f72b..148d3261 100644
--- a/frontend/js/i18n/messages.json
+++ b/frontend/js/i18n/messages.json
@@ -99,6 +99,7 @@
"ssl": {
"letsencrypt": "Let's Encrypt",
"other": "Custom",
+ "clientca": "Client Certificate Authority",
"none": "HTTP only",
"letsencrypt-email": "Email Address for Let's Encrypt",
"letsencrypt-agree": "I Agree to the Let's Encrypt Terms of Service",
@@ -185,7 +186,7 @@
"title": "SSL Certificates",
"empty": "There are no SSL Certificates",
"add": "Add SSL Certificate",
- "form-title": "Add {provider, select, letsencrypt{Let's Encrypt} other{Custom}} Certificate",
+ "form-title": "Add {provider, select, letsencrypt{Let's Encrypt Certificate} other{Custom Certificate} clientca{Client Certificate Authority}}",
"delete": "Delete SSL Certificate",
"delete-confirm": "Are you sure you want to delete this SSL Certificate? Any hosts using it will need to be updated later.",
"help-title": "SSL Certificates",
@@ -193,6 +194,7 @@
"other-certificate": "Certificate",
"other-certificate-key": "Certificate Key",
"other-intermediate-certificate": "Intermediate Certificate",
+ "clientca-certificate": "Certificate",
"force-renew": "Renew Now",
"test-reachability": "Test Server Reachability",
"reachability-title": "Test Server Reachability",
@@ -231,7 +233,8 @@
"pass-auth": "Pass Auth to Host",
"access-add": "Add",
"auth-add": "Add",
- "search": "Search Access…"
+ "search": "Search Access…",
+ "client-certificates": "Client Certificates"
},
"users": {
"title": "Users",