mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-07-17 15:04:34 +00:00
Add storing for Client CA certificates in the database
Add initial support for managing Client Certificate Authority public certificates as certificate objects in the database. The new provider type 'clientca' is defined to implement this.
This commit is contained in:
@ -552,6 +552,10 @@ const internalCertificate = {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
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) {
|
fs.writeFile(dir + '/privkey.pem', certificate.meta.certificate_key, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
@ -559,6 +563,7 @@ const internalCertificate = {
|
|||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -639,7 +644,7 @@ const internalCertificate = {
|
|||||||
upload: (access, data) => {
|
upload: (access, data) => {
|
||||||
return internalCertificate.get(access, {id: data.id})
|
return internalCertificate.get(access, {id: data.id})
|
||||||
.then((row) => {
|
.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');
|
throw new error.ValidationError('Cannot upload certificates for this type of provider');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@
|
|||||||
},
|
},
|
||||||
"ssl_provider": {
|
"ssl_provider": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"pattern": "^(letsencrypt|other)$"
|
"pattern": "^(letsencrypt|other|clientca)$"
|
||||||
},
|
},
|
||||||
"http2_support": {
|
"http2_support": {
|
||||||
"description": "HTTP2 Protocol Support",
|
"description": "HTTP2 Protocol Support",
|
||||||
|
@ -173,7 +173,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<% } else if (provider === 'clientca') { %>
|
||||||
|
<!-- Client Certificate Authority -->
|
||||||
|
<div class="col-sm-12 col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label"><%- i18n('str', 'name') %> <span class="form-required">*</span></label>
|
||||||
|
<input name="nice_name" type="text" class="form-control" placeholder="" value="<%- nice_name %>" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12 col-md-12 other-ssl">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="form-label"><%- i18n('certificates', 'clientca-certificate') %><span class="form-required">*</span></div>
|
||||||
|
<div class="custom-file">
|
||||||
|
<input type="file" class="custom-file-input" name="meta[clientca_certificate]" id="clientca_certificate">
|
||||||
|
<label id="clientca_certificate_label" class="custom-file-label"><%- i18n('str', 'choose-file') %></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -45,7 +45,9 @@ module.exports = Mn.View.extend({
|
|||||||
propagation_seconds: 'input[name="meta[propagation_seconds]"]',
|
propagation_seconds: 'input[name="meta[propagation_seconds]"]',
|
||||||
other_certificate_key_label: '#other_certificate_key_label',
|
other_certificate_key_label: '#other_certificate_key_label',
|
||||||
other_intermediate_certificate: '#other_intermediate_certificate',
|
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: {
|
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]});
|
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();
|
this.ui.loader_content.show();
|
||||||
@ -163,14 +177,14 @@ module.exports = Mn.View.extend({
|
|||||||
|
|
||||||
// compile file data
|
// compile file data
|
||||||
let form_data = new FormData();
|
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) {
|
ssl_files.map(function (file) {
|
||||||
form_data.append(file.name, file.file);
|
form_data.append(file.name, file.file);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
new Promise(resolve => {
|
new Promise(resolve => {
|
||||||
if (data.provider === 'other') {
|
if (data.provider === 'other' || data.provider === 'clientca') {
|
||||||
resolve(App.Api.Nginx.Certificates.validate(form_data));
|
resolve(App.Api.Nginx.Certificates.validate(form_data));
|
||||||
} else {
|
} else {
|
||||||
resolve();
|
resolve();
|
||||||
@ -183,7 +197,7 @@ module.exports = Mn.View.extend({
|
|||||||
this.model.set(result);
|
this.model.set(result);
|
||||||
|
|
||||||
// Now upload the certs if we need to
|
// 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)
|
return App.Api.Nginx.Certificates.upload(this.model.get('id'), form_data)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
this.model.set('meta', _.assign({}, this.model.get('meta'), 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){
|
'change @ui.other_intermediate_certificate': function(e){
|
||||||
this.setFileName("other_intermediate_certificate_label", e)
|
this.setFileName("other_intermediate_certificate_label", e)
|
||||||
|
},
|
||||||
|
'change @ui.clientca_certificate': function(e){
|
||||||
|
this.setFileName("clientca_certificate_label", e)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setFileName(ui, e){
|
setFileName(ui, e){
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
<a class="dropdown-item add-item" data-cert="letsencrypt" href="#"><%- i18n('ssl', 'letsencrypt') %></a>
|
<a class="dropdown-item add-item" data-cert="letsencrypt" href="#"><%- i18n('ssl', 'letsencrypt') %></a>
|
||||||
<a class="dropdown-item add-item" data-cert="other" href="#"><%- i18n('ssl', 'other') %></a>
|
<a class="dropdown-item add-item" data-cert="other" href="#"><%- i18n('ssl', 'other') %></a>
|
||||||
|
<a class="dropdown-item add-item" data-cert="clientca" href="#"><%- i18n('ssl', 'clientca') %></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
@ -99,6 +99,7 @@
|
|||||||
"ssl": {
|
"ssl": {
|
||||||
"letsencrypt": "Let's Encrypt",
|
"letsencrypt": "Let's Encrypt",
|
||||||
"other": "Custom",
|
"other": "Custom",
|
||||||
|
"clientca": "Client Certificate Authority",
|
||||||
"none": "HTTP only",
|
"none": "HTTP only",
|
||||||
"letsencrypt-email": "Email Address for Let's Encrypt",
|
"letsencrypt-email": "Email Address for Let's Encrypt",
|
||||||
"letsencrypt-agree": "I Agree to the <a href=\"{url}\" target=\"_blank\">Let's Encrypt Terms of Service</a>",
|
"letsencrypt-agree": "I Agree to the <a href=\"{url}\" target=\"_blank\">Let's Encrypt Terms of Service</a>",
|
||||||
@ -185,7 +186,7 @@
|
|||||||
"title": "SSL Certificates",
|
"title": "SSL Certificates",
|
||||||
"empty": "There are no SSL Certificates",
|
"empty": "There are no SSL Certificates",
|
||||||
"add": "Add SSL Certificate",
|
"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": "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.",
|
"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",
|
"help-title": "SSL Certificates",
|
||||||
@ -193,6 +194,7 @@
|
|||||||
"other-certificate": "Certificate",
|
"other-certificate": "Certificate",
|
||||||
"other-certificate-key": "Certificate Key",
|
"other-certificate-key": "Certificate Key",
|
||||||
"other-intermediate-certificate": "Intermediate Certificate",
|
"other-intermediate-certificate": "Intermediate Certificate",
|
||||||
|
"clientca-certificate": "Certificate",
|
||||||
"force-renew": "Renew Now",
|
"force-renew": "Renew Now",
|
||||||
"test-reachability": "Test Server Reachability",
|
"test-reachability": "Test Server Reachability",
|
||||||
"reachability-title": "Test Server Reachability",
|
"reachability-title": "Test Server Reachability",
|
||||||
@ -231,7 +233,8 @@
|
|||||||
"pass-auth": "Pass Auth to Host",
|
"pass-auth": "Pass Auth to Host",
|
||||||
"access-add": "Add",
|
"access-add": "Add",
|
||||||
"auth-add": "Add",
|
"auth-add": "Add",
|
||||||
"search": "Search Access…"
|
"search": "Search Access…",
|
||||||
|
"client-certificates": "Client Certificates"
|
||||||
},
|
},
|
||||||
"users": {
|
"users": {
|
||||||
"title": "Users",
|
"title": "Users",
|
||||||
|
Reference in New Issue
Block a user