From b81325d7bf4606a37b3c19a9ab2676c4b209e6ef Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Sun, 4 Oct 2020 23:56:02 +0200
Subject: [PATCH 01/13] Implements dns challenge provider selection in frontend
---
frontend/js/app/nginx/certificates/form.ejs | 87 +++++++++-
frontend/js/app/nginx/certificates/form.js | 75 +++++---
.../js/app/nginx/certificates/list/item.ejs | 2 +-
.../js/app/nginx/certificates/list/item.js | 12 +-
frontend/js/app/nginx/dead/form.ejs | 87 +++++++++-
frontend/js/app/nginx/dead/form.js | 99 +++++++----
frontend/js/app/nginx/proxy/form.ejs | 87 +++++++++-
frontend/js/app/nginx/proxy/form.js | 101 +++++++----
frontend/js/app/nginx/redirection/form.ejs | 87 +++++++++-
frontend/js/app/nginx/redirection/form.js | 103 +++++++----
frontend/js/i18n/messages.json | 10 +-
utils/certbot-dns-plugins.js | 160 ++++++++++++++++++
12 files changed, 755 insertions(+), 155 deletions(-)
create mode 100644 utils/certbot-dns-plugins.js
diff --git a/frontend/js/app/nginx/certificates/form.ejs b/frontend/js/app/nginx/certificates/form.ejs
index 207e59e..a3d6c07 100644
--- a/frontend/js/app/nginx/certificates/form.ejs
+++ b/frontend/js/app/nginx/certificates/form.ejs
@@ -21,21 +21,92 @@
-
+
-
-
-
-
+
+
diff --git a/frontend/js/app/nginx/certificates/form.js b/frontend/js/app/nginx/certificates/form.js
index 53a6e14..bc239df 100644
--- a/frontend/js/app/nginx/certificates/form.js
+++ b/frontend/js/app/nginx/certificates/form.js
@@ -3,6 +3,8 @@ const Mn = require('backbone.marionette');
const App = require('../../main');
const CertificateModel = require('../../../models/certificate');
const template = require('./form.ejs');
+const i18n = require('../../i18n');
+const dns_providers = require('../../../../../utils/certbot-dns-plugins');
require('jquery-serializejson');
require('selectize');
@@ -21,25 +23,46 @@ module.exports = Mn.View.extend({
other_certificate: '#other_certificate',
other_certificate_label: '#other_certificate_label',
other_certificate_key: '#other_certificate_key',
- cloudflare_switch: 'input[name="meta[cloudflare_use]"]',
- cloudflare_token: 'input[name="meta[cloudflare_token]"',
- cloudflare: '.cloudflare',
+ dns_challenge_switch: 'input[name="meta[dns_challenge]"]',
+ dns_challenge_content: '.dns-challenge',
+ dns_provider: 'select[name="meta[dns_provider]"]',
+ credentials_file_content: '.credentials-file-content',
+ dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
+ 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'
},
events: {
- 'change @ui.cloudflare_switch': function() {
- let checked = this.ui.cloudflare_switch.prop('checked');
- if (checked) {
- this.ui.cloudflare_token.prop('required', 'required');
- this.ui.cloudflare.show();
- } else {
- this.ui.cloudflare_token.prop('required', false);
- this.ui.cloudflare.hide();
+ 'change @ui.dns_challenge_switch': function () {
+ const checked = this.ui.dns_challenge_switch.prop('checked');
+ if (checked) {
+ this.ui.dns_provider.prop('required', 'required');
+ const selected_provider = this.ui.dns_provider[0].options[this.ui.dns_provider[0].selectedIndex].value;
+ if(selected_provider != '' && dns_providers[selected_provider].credentials !== false){
+ this.ui.dns_provider_credentials.prop('required', 'required');
+ }
+ this.ui.dns_challenge_content.show();
+ } else {
+ this.ui.dns_provider.prop('required', false);
+ this.ui.dns_provider_credentials.prop('required', false);
+ this.ui.dns_challenge_content.hide();
}
},
+
+ 'change @ui.dns_provider': function () {
+ const selected_provider = this.ui.dns_provider[0].options[this.ui.dns_provider[0].selectedIndex].value;
+ if (selected_provider != '' && dns_providers[selected_provider].credentials !== false) {
+ this.ui.dns_provider_credentials.prop('required', 'required');
+ this.ui.dns_provider_credentials[0].value = dns_providers[selected_provider].credentials;
+ this.ui.credentials_file_content.show();
+ } else {
+ this.ui.dns_provider_credentials.prop('required', false);
+ this.ui.credentials_file_content.hide();
+ }
+ },
+
'click @ui.save': function (e) {
e.preventDefault();
@@ -56,7 +79,7 @@ module.exports = Mn.View.extend({
let domain_err = false;
- if (!data.meta.cloudflare_use) {
+ if (!data.meta.dns_challenge) {
data.domain_names.split(',').map(function (name) {
if (name.match(/\*/im)) {
domain_err = true;
@@ -65,7 +88,7 @@ module.exports = Mn.View.extend({
}
if (domain_err) {
- alert('Cannot request Let\'s Encrypt Certificate for wildcard domains when not using CloudFlare DNS');
+ alert(i18n('ssl', 'no-wildcard-without-dns'));
return;
}
@@ -73,8 +96,9 @@ module.exports = Mn.View.extend({
if (typeof data.meta !== 'undefined' && typeof data.meta.letsencrypt_agree !== 'undefined') {
data.meta.letsencrypt_agree = !!data.meta.letsencrypt_agree;
}
- if (typeof data.meta !== 'undefined' && typeof data.meta.cloudflare_use !== 'undefined') {
- data.meta.cloudflare_use = !!data.meta.cloudflare_use;
+
+ if (typeof data.meta !== 'undefined' && typeof data.meta.dns_challenge !== 'undefined') {
+ data.meta.dns_challenge = !!data.meta.dns_challenge;
}
if (typeof data.domain_names === 'string' && data.domain_names) {
@@ -176,14 +200,22 @@ module.exports = Mn.View.extend({
getLetsencryptEmail: function () {
return typeof this.meta.letsencrypt_email !== 'undefined' ? this.meta.letsencrypt_email : App.Cache.User.get('email');
},
-
getLetsencryptAgree: function () {
return typeof this.meta.letsencrypt_agree !== 'undefined' ? this.meta.letsencrypt_agree : false;
},
-
- getCloudflareUse: function () {
- return typeof this.meta.cloudflare_use !== 'undefined' ? this.meta.cloudflare_use : false;
- }
+ getUseDnsChallenge: function () {
+ return typeof this.meta.dns_challenge !== 'undefined' ? this.meta.dns_challenge : false;
+ },
+ getDnsProvider: function () {
+ return typeof this.meta.dns_provider !== 'undefined' && this.meta.dns_provider != '' ? this.meta.dns_provider : null;
+ },
+ getDnsProviderCredentials: function () {
+ return typeof this.meta.dns_provider_credentials !== 'undefined' ? this.meta.dns_provider_credentials : '';
+ },
+ getPropagationSeconds: function () {
+ return typeof this.meta.propagation_seconds !== 'undefined' ? this.meta.propagation_seconds : '';
+ },
+ dns_plugins: dns_providers,
},
onRender: function () {
@@ -199,7 +231,8 @@ module.exports = Mn.View.extend({
},
createFilter: /^(?:[^.]+\.?)+[^.]$/
});
- this.ui.cloudflare.hide();
+ this.ui.dns_challenge_content.hide();
+ this.ui.credentials_file_content.hide();
},
initialize: function (options) {
diff --git a/frontend/js/app/nginx/certificates/list/item.ejs b/frontend/js/app/nginx/certificates/list/item.ejs
index 857a08b..67764b0 100644
--- a/frontend/js/app/nginx/certificates/list/item.ejs
+++ b/frontend/js/app/nginx/certificates/list/item.ejs
@@ -28,7 +28,7 @@
- <%- i18n('ssl', provider) %><% if (meta.cloudflare_use) { %> - CloudFlare DNS<% } %>
+ <%- i18n('ssl', provider) %><% if (meta.dns_provider) { %> - <% dns_providers[meta.dns_provider].display_name } %>
|
<%- formatDbDate(expires_on, 'Do MMMM YYYY, h:mm a') %>
diff --git a/frontend/js/app/nginx/certificates/list/item.js b/frontend/js/app/nginx/certificates/list/item.js
index 6915227..b5b2d85 100644
--- a/frontend/js/app/nginx/certificates/list/item.js
+++ b/frontend/js/app/nginx/certificates/list/item.js
@@ -1,7 +1,8 @@
-const Mn = require('backbone.marionette');
-const moment = require('moment');
-const App = require('../../../main');
-const template = require('./item.ejs');
+const Mn = require('backbone.marionette');
+const moment = require('moment');
+const App = require('../../../main');
+const template = require('./item.ejs');
+const dns_providers = require('../../../../../../utils/certbot-dns-plugins')
module.exports = Mn.View.extend({
template: template,
@@ -35,7 +36,8 @@ module.exports = Mn.View.extend({
canManage: App.Cache.User.canManage('certificates'),
isExpired: function () {
return moment(this.expires_on).isBefore(moment());
- }
+ },
+ dns_providers: dns_providers
},
initialize: function () {
diff --git a/frontend/js/app/nginx/dead/form.ejs b/frontend/js/app/nginx/dead/form.ejs
index d48820f..1d01e09 100644
--- a/frontend/js/app/nginx/dead/form.ejs
+++ b/frontend/js/app/nginx/dead/form.ejs
@@ -73,21 +73,92 @@
-
+
-
-
-
-
-
+
+
diff --git a/frontend/js/app/nginx/dead/form.js b/frontend/js/app/nginx/dead/form.js
index aca367a..393788d 100644
--- a/frontend/js/app/nginx/dead/form.js
+++ b/frontend/js/app/nginx/dead/form.js
@@ -4,6 +4,8 @@ const DeadHostModel = require('../../../models/dead-host');
const template = require('./form.ejs');
const certListItemTemplate = require('../certificates-list-item.ejs');
const Helpers = require('../../../lib/helpers');
+const i18n = require('../../i18n');
+const dns_providers = require('../../../../../utils/certbot-dns-plugins');
require('jquery-serializejson');
require('selectize');
@@ -13,20 +15,23 @@ module.exports = Mn.View.extend({
className: 'modal-dialog',
ui: {
- form: 'form',
- domain_names: 'input[name="domain_names"]',
- buttons: '.modal-footer button',
- cancel: 'button.cancel',
- save: 'button.save',
- certificate_select: 'select[name="certificate_id"]',
- ssl_forced: 'input[name="ssl_forced"]',
- hsts_enabled: 'input[name="hsts_enabled"]',
- hsts_subdomains: 'input[name="hsts_subdomains"]',
- http2_support: 'input[name="http2_support"]',
- cloudflare_switch: 'input[name="meta[cloudflare_use]"]',
- cloudflare_token: 'input[name="meta[cloudflare_token]"',
- cloudflare: '.cloudflare',
- letsencrypt: '.letsencrypt'
+ form: 'form',
+ domain_names: 'input[name="domain_names"]',
+ buttons: '.modal-footer button',
+ cancel: 'button.cancel',
+ save: 'button.save',
+ certificate_select: 'select[name="certificate_id"]',
+ ssl_forced: 'input[name="ssl_forced"]',
+ hsts_enabled: 'input[name="hsts_enabled"]',
+ hsts_subdomains: 'input[name="hsts_subdomains"]',
+ http2_support: 'input[name="http2_support"]',
+ dns_challenge_switch: 'input[name="meta[dns_challenge]"]',
+ dns_challenge_content: '.dns-challenge',
+ dns_provider: 'select[name="meta[dns_provider]"]',
+ credentials_file_content: '.credentials-file-content',
+ dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
+ propagation_seconds: 'input[name="meta[propagation_seconds]"]',
+ letsencrypt: '.letsencrypt'
},
events: {
@@ -34,7 +39,7 @@ module.exports = Mn.View.extend({
let id = this.ui.certificate_select.val();
if (id === 'new') {
this.ui.letsencrypt.show().find('input').prop('disabled', false);
- this.ui.cloudflare.hide();
+ this.ui.dns_challenge_content.hide();
} else {
this.ui.letsencrypt.hide().find('input').prop('disabled', true);
}
@@ -81,14 +86,31 @@ module.exports = Mn.View.extend({
}
},
- 'change @ui.cloudflare_switch': function() {
- let checked = this.ui.cloudflare_switch.prop('checked');
- if (checked) {
- this.ui.cloudflare_token.prop('required', 'required');
- this.ui.cloudflare.show();
- } else {
- this.ui.cloudflare_token.prop('required', false);
- this.ui.cloudflare.hide();
+ 'change @ui.dns_challenge_switch': function () {
+ const checked = this.ui.dns_challenge_switch.prop('checked');
+ if (checked) {
+ this.ui.dns_provider.prop('required', 'required');
+ const selected_provider = this.ui.dns_provider[0].options[this.ui.dns_provider[0].selectedIndex].value;
+ if(selected_provider != '' && dns_providers[selected_provider].credentials !== false){
+ this.ui.dns_provider_credentials.prop('required', 'required');
+ }
+ this.ui.dns_challenge_content.show();
+ } else {
+ this.ui.dns_provider.prop('required', false);
+ this.ui.dns_provider_credentials.prop('required', false);
+ this.ui.dns_challenge_content.hide();
+ }
+ },
+
+ 'change @ui.dns_provider': function () {
+ const selected_provider = this.ui.dns_provider[0].options[this.ui.dns_provider[0].selectedIndex].value;
+ if (selected_provider != '' && dns_providers[selected_provider].credentials !== false) {
+ this.ui.dns_provider_credentials.prop('required', 'required');
+ this.ui.dns_provider_credentials[0].value = dns_providers[selected_provider].credentials;
+ this.ui.credentials_file_content.show();
+ } else {
+ this.ui.dns_provider_credentials.prop('required', false);
+ this.ui.credentials_file_content.hide();
}
},
@@ -104,10 +126,11 @@ module.exports = Mn.View.extend({
let data = this.ui.form.serializeJSON();
// Manipulate
- data.hsts_enabled = !!data.hsts_enabled;
- data.hsts_subdomains = !!data.hsts_subdomains;
- data.http2_support = !!data.http2_support;
- data.ssl_forced = !!data.ssl_forced;
+ data.hsts_enabled = !!data.hsts_enabled;
+ data.hsts_subdomains = !!data.hsts_subdomains;
+ data.http2_support = !!data.http2_support;
+ data.ssl_forced = !!data.ssl_forced;
+ data.meta.dns_challenge = !!data.meta.dns_challenge;
if (typeof data.domain_names === 'string' && data.domain_names) {
data.domain_names = data.domain_names.split(',');
@@ -116,7 +139,7 @@ module.exports = Mn.View.extend({
// Check for any domain names containing wildcards, which are not allowed with letsencrypt
if (data.certificate_id === 'new') {
let domain_err = false;
- if (!data.meta.cloudflare_use) {
+ if (!data.meta.dns_challenge) {
data.domain_names.map(function (name) {
if (name.match(/\*/im)) {
domain_err = true;
@@ -125,11 +148,10 @@ module.exports = Mn.View.extend({
}
if (domain_err) {
- alert('Cannot request Let\'s Encrypt Certificate for wildcard domains without CloudFlare DNS.');
+ alert(i18n('ssl', 'no-wildcard-without-dns'));
return;
}
- data.meta.cloudflare_use = data.meta.cloudflare_use === '1';
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1';
} else {
data.certificate_id = parseInt(data.certificate_id, 10);
@@ -169,7 +191,20 @@ module.exports = Mn.View.extend({
templateContext: {
getLetsencryptEmail: function () {
return App.Cache.User.get('email');
- }
+ },
+ getUseDnsChallenge: function () {
+ return typeof this.meta.dns_challenge !== 'undefined' ? this.meta.dns_challenge : false;
+ },
+ getDnsProvider: function () {
+ return typeof this.meta.dns_provider !== 'undefined' && this.meta.dns_provider != '' ? this.meta.dns_provider : null;
+ },
+ getDnsProviderCredentials: function () {
+ return typeof this.meta.dns_provider_credentials !== 'undefined' ? this.meta.dns_provider_credentials : '';
+ },
+ getPropagationSeconds: function () {
+ return typeof this.meta.propagation_seconds !== 'undefined' ? this.meta.propagation_seconds : '';
+ },
+ dns_plugins: dns_providers,
},
onRender: function () {
@@ -190,6 +225,8 @@ module.exports = Mn.View.extend({
});
// Certificates
+ this.ui.dns_challenge_content.hide();
+ this.ui.credentials_file_content.hide();
this.ui.letsencrypt.hide();
this.ui.certificate_select.selectize({
valueField: 'id',
diff --git a/frontend/js/app/nginx/proxy/form.ejs b/frontend/js/app/nginx/proxy/form.ejs
index e003597..34f319c 100644
--- a/frontend/js/app/nginx/proxy/form.ejs
+++ b/frontend/js/app/nginx/proxy/form.ejs
@@ -141,21 +141,92 @@
-
+
-
-
-
-
-
+
+
diff --git a/frontend/js/app/nginx/proxy/form.js b/frontend/js/app/nginx/proxy/form.js
index 0f64281..4211050 100644
--- a/frontend/js/app/nginx/proxy/form.js
+++ b/frontend/js/app/nginx/proxy/form.js
@@ -7,6 +7,8 @@ const certListItemTemplate = require('../certificates-list-item.ejs');
const accessListItemTemplate = require('./access-list-item.ejs');
const CustomLocation = require('./location');
const Helpers = require('../../../lib/helpers');
+const i18n = require('../../i18n');
+const dns_providers = require('../../../../../utils/certbot-dns-plugins');
require('jquery-serializejson');
@@ -19,25 +21,28 @@ module.exports = Mn.View.extend({
locationsCollection: new ProxyLocationModel.Collection(),
ui: {
- form: 'form',
- domain_names: 'input[name="domain_names"]',
- forward_host: 'input[name="forward_host"]',
- buttons: '.modal-footer button',
- cancel: 'button.cancel',
- save: 'button.save',
- add_location_btn: 'button.add_location',
- locations_container:'.locations_container',
- certificate_select: 'select[name="certificate_id"]',
- access_list_select: 'select[name="access_list_id"]',
- ssl_forced: 'input[name="ssl_forced"]',
- hsts_enabled: 'input[name="hsts_enabled"]',
- hsts_subdomains: 'input[name="hsts_subdomains"]',
- http2_support: 'input[name="http2_support"]',
- cloudflare_switch: 'input[name="meta[cloudflare_use]"]',
- cloudflare_token: 'input[name="meta[cloudflare_token]"',
- cloudflare: '.cloudflare',
- forward_scheme: 'select[name="forward_scheme"]',
- letsencrypt: '.letsencrypt'
+ form: 'form',
+ domain_names: 'input[name="domain_names"]',
+ forward_host: 'input[name="forward_host"]',
+ buttons: '.modal-footer button',
+ cancel: 'button.cancel',
+ save: 'button.save',
+ add_location_btn: 'button.add_location',
+ locations_container: '.locations_container',
+ certificate_select: 'select[name="certificate_id"]',
+ access_list_select: 'select[name="access_list_id"]',
+ ssl_forced: 'input[name="ssl_forced"]',
+ hsts_enabled: 'input[name="hsts_enabled"]',
+ hsts_subdomains: 'input[name="hsts_subdomains"]',
+ http2_support: 'input[name="http2_support"]',
+ dns_challenge_switch: 'input[name="meta[dns_challenge]"]',
+ dns_challenge_content: '.dns-challenge',
+ dns_provider: 'select[name="meta[dns_provider]"]',
+ credentials_file_content: '.credentials-file-content',
+ dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
+ propagation_seconds: 'input[name="meta[propagation_seconds]"]',
+ forward_scheme: 'select[name="forward_scheme"]',
+ letsencrypt: '.letsencrypt'
},
regions: {
@@ -49,7 +54,7 @@ module.exports = Mn.View.extend({
let id = this.ui.certificate_select.val();
if (id === 'new') {
this.ui.letsencrypt.show().find('input').prop('disabled', false);
- this.ui.cloudflare.hide();
+ this.ui.dns_challenge_content.hide();
} else {
this.ui.letsencrypt.hide().find('input').prop('disabled', true);
}
@@ -95,14 +100,31 @@ module.exports = Mn.View.extend({
}
},
- 'change @ui.cloudflare_switch': function() {
- let checked = this.ui.cloudflare_switch.prop('checked');
- if (checked) {
- this.ui.cloudflare_token.prop('required', 'required');
- this.ui.cloudflare.show();
- } else {
- this.ui.cloudflare_token.prop('required', false);
- this.ui.cloudflare.hide();
+ 'change @ui.dns_challenge_switch': function () {
+ const checked = this.ui.dns_challenge_switch.prop('checked');
+ if (checked) {
+ this.ui.dns_provider.prop('required', 'required');
+ const selected_provider = this.ui.dns_provider[0].options[this.ui.dns_provider[0].selectedIndex].value;
+ if(selected_provider != '' && dns_providers[selected_provider].credentials !== false){
+ this.ui.dns_provider_credentials.prop('required', 'required');
+ }
+ this.ui.dns_challenge_content.show();
+ } else {
+ this.ui.dns_provider.prop('required', false);
+ this.ui.dns_provider_credentials.prop('required', false);
+ this.ui.dns_challenge_content.hide();
+ }
+ },
+
+ 'change @ui.dns_provider': function () {
+ const selected_provider = this.ui.dns_provider[0].options[this.ui.dns_provider[0].selectedIndex].value;
+ if (selected_provider != '' && dns_providers[selected_provider].credentials !== false) {
+ this.ui.dns_provider_credentials.prop('required', 'required');
+ this.ui.dns_provider_credentials[0].value = dns_providers[selected_provider].credentials;
+ this.ui.credentials_file_content.show();
+ } else {
+ this.ui.dns_provider_credentials.prop('required', false);
+ this.ui.credentials_file_content.hide();
}
},
@@ -143,6 +165,7 @@ module.exports = Mn.View.extend({
data.hsts_enabled = !!data.hsts_enabled;
data.hsts_subdomains = !!data.hsts_subdomains;
data.ssl_forced = !!data.ssl_forced;
+ data.meta.dns_challenge = !!data.meta.dns_challenge;
if (typeof data.domain_names === 'string' && data.domain_names) {
data.domain_names = data.domain_names.split(',');
@@ -151,7 +174,7 @@ module.exports = Mn.View.extend({
// Check for any domain names containing wildcards, which are not allowed with letsencrypt
if (data.certificate_id === 'new') {
let domain_err = false;
- if (!data.meta.cloudflare_use) {
+ if (!data.meta.dns_challenge) {
data.domain_names.map(function (name) {
if (name.match(/\*/im)) {
domain_err = true;
@@ -160,11 +183,10 @@ module.exports = Mn.View.extend({
}
if (domain_err) {
- alert('Cannot request Let\'s Encrypt Certificate for wildcard domains without CloudFlare DNS.');
+ alert(i18n('ssl', 'no-wildcard-without-dns'));
return;
}
- data.meta.cloudflare_use = data.meta.cloudflare_use === '1';
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1';
} else {
data.certificate_id = parseInt(data.certificate_id, 10);
@@ -204,7 +226,20 @@ module.exports = Mn.View.extend({
templateContext: {
getLetsencryptEmail: function () {
return App.Cache.User.get('email');
- }
+ },
+ getUseDnsChallenge: function () {
+ return typeof this.meta.dns_challenge !== 'undefined' ? this.meta.dns_challenge : false;
+ },
+ getDnsProvider: function () {
+ return typeof this.meta.dns_provider !== 'undefined' && this.meta.dns_provider != '' ? this.meta.dns_provider : null;
+ },
+ getDnsProviderCredentials: function () {
+ return typeof this.meta.dns_provider_credentials !== 'undefined' ? this.meta.dns_provider_credentials : '';
+ },
+ getPropagationSeconds: function () {
+ return typeof this.meta.propagation_seconds !== 'undefined' ? this.meta.propagation_seconds : '';
+ },
+ dns_plugins: dns_providers,
},
onRender: function () {
@@ -258,6 +293,8 @@ module.exports = Mn.View.extend({
});
// Certificates
+ this.ui.dns_challenge_content.hide();
+ this.ui.credentials_file_content.hide();
this.ui.letsencrypt.hide();
this.ui.certificate_select.selectize({
valueField: 'id',
diff --git a/frontend/js/app/nginx/redirection/form.ejs b/frontend/js/app/nginx/redirection/form.ejs
index 7d49769..f4e4375 100644
--- a/frontend/js/app/nginx/redirection/form.ejs
+++ b/frontend/js/app/nginx/redirection/form.ejs
@@ -97,21 +97,92 @@
-
+
-
-
-
-
-
+
+
diff --git a/frontend/js/app/nginx/redirection/form.js b/frontend/js/app/nginx/redirection/form.js
index 4e5b168..c1c6d9d 100644
--- a/frontend/js/app/nginx/redirection/form.js
+++ b/frontend/js/app/nginx/redirection/form.js
@@ -4,6 +4,9 @@ const RedirectionHostModel = require('../../../models/redirection-host');
const template = require('./form.ejs');
const certListItemTemplate = require('../certificates-list-item.ejs');
const Helpers = require('../../../lib/helpers');
+const i18n = require('../../i18n');
+const dns_providers = require('../../../../../utils/certbot-dns-plugins');
+
require('jquery-serializejson');
require('selectize');
@@ -13,20 +16,23 @@ module.exports = Mn.View.extend({
className: 'modal-dialog',
ui: {
- form: 'form',
- domain_names: 'input[name="domain_names"]',
- buttons: '.modal-footer button',
- cancel: 'button.cancel',
- save: 'button.save',
- certificate_select: 'select[name="certificate_id"]',
- ssl_forced: 'input[name="ssl_forced"]',
- hsts_enabled: 'input[name="hsts_enabled"]',
- hsts_subdomains: 'input[name="hsts_subdomains"]',
- http2_support: 'input[name="http2_support"]',
- cloudflare_switch: 'input[name="meta[cloudflare_use]"]',
- cloudflare_token: 'input[name="meta[cloudflare_token]"',
- cloudflare: '.cloudflare',
- letsencrypt: '.letsencrypt'
+ form: 'form',
+ domain_names: 'input[name="domain_names"]',
+ buttons: '.modal-footer button',
+ cancel: 'button.cancel',
+ save: 'button.save',
+ certificate_select: 'select[name="certificate_id"]',
+ ssl_forced: 'input[name="ssl_forced"]',
+ hsts_enabled: 'input[name="hsts_enabled"]',
+ hsts_subdomains: 'input[name="hsts_subdomains"]',
+ http2_support: 'input[name="http2_support"]',
+ dns_challenge_switch: 'input[name="meta[dns_challenge]"]',
+ dns_challenge_content: '.dns-challenge',
+ dns_provider: 'select[name="meta[dns_provider]"]',
+ credentials_file_content: '.credentials-file-content',
+ dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
+ propagation_seconds: 'input[name="meta[propagation_seconds]"]',
+ letsencrypt: '.letsencrypt'
},
events: {
@@ -34,7 +40,7 @@ module.exports = Mn.View.extend({
let id = this.ui.certificate_select.val();
if (id === 'new') {
this.ui.letsencrypt.show().find('input').prop('disabled', false);
- this.ui.cloudflare.hide();
+ this.ui.dns_challenge_content.hide();
} else {
this.ui.letsencrypt.hide().find('input').prop('disabled', true);
}
@@ -80,14 +86,31 @@ module.exports = Mn.View.extend({
}
},
- 'change @ui.cloudflare_switch': function() {
- let checked = this.ui.cloudflare_switch.prop('checked');
- if (checked) {
- this.ui.cloudflare_token.prop('required', 'required');
- this.ui.cloudflare.show();
- } else {
- this.ui.cloudflare_token.prop('required', false);
- this.ui.cloudflare.hide();
+ 'change @ui.dns_challenge_switch': function () {
+ const checked = this.ui.dns_challenge_switch.prop('checked');
+ if (checked) {
+ this.ui.dns_provider.prop('required', 'required');
+ const selected_provider = this.ui.dns_provider[0].options[this.ui.dns_provider[0].selectedIndex].value;
+ if(selected_provider != '' && dns_providers[selected_provider].credentials !== false){
+ this.ui.dns_provider_credentials.prop('required', 'required');
+ }
+ this.ui.dns_challenge_content.show();
+ } else {
+ this.ui.dns_provider.prop('required', false);
+ this.ui.dns_provider_credentials.prop('required', false);
+ this.ui.dns_challenge_content.hide();
+ }
+ },
+
+ 'change @ui.dns_provider': function () {
+ const selected_provider = this.ui.dns_provider[0].options[this.ui.dns_provider[0].selectedIndex].value;
+ if (selected_provider != '' && dns_providers[selected_provider].credentials !== false) {
+ this.ui.dns_provider_credentials.prop('required', 'required');
+ this.ui.dns_provider_credentials[0].value = dns_providers[selected_provider].credentials;
+ this.ui.credentials_file_content.show();
+ } else {
+ this.ui.dns_provider_credentials.prop('required', false);
+ this.ui.credentials_file_content.hide();
}
},
@@ -103,12 +126,13 @@ module.exports = Mn.View.extend({
let data = this.ui.form.serializeJSON();
// Manipulate
- data.block_exploits = !!data.block_exploits;
- data.preserve_path = !!data.preserve_path;
- data.http2_support = !!data.http2_support;
- data.hsts_enabled = !!data.hsts_enabled;
- data.hsts_subdomains = !!data.hsts_subdomains;
- data.ssl_forced = !!data.ssl_forced;
+ data.block_exploits = !!data.block_exploits;
+ data.preserve_path = !!data.preserve_path;
+ data.http2_support = !!data.http2_support;
+ data.hsts_enabled = !!data.hsts_enabled;
+ data.hsts_subdomains = !!data.hsts_subdomains;
+ data.ssl_forced = !!data.ssl_forced;
+ data.meta.dns_challenge = !!data.meta.dns_challenge;
if (typeof data.domain_names === 'string' && data.domain_names) {
data.domain_names = data.domain_names.split(',');
@@ -117,7 +141,7 @@ module.exports = Mn.View.extend({
// Check for any domain names containing wildcards, which are not allowed with letsencrypt
if (data.certificate_id === 'new') {
let domain_err = false;
- if (!data.meta.cloudflare_use) {
+ if (!data.meta.dns_challenge) {
data.domain_names.map(function (name) {
if (name.match(/\*/im)) {
domain_err = true;
@@ -126,7 +150,7 @@ module.exports = Mn.View.extend({
}
if (domain_err) {
- alert('Cannot request Let\'s Encrypt Certificate for wildcard domains without CloudFlare DNS.');
+ alert(i18n('ssl', 'no-wildcard-without-dns'));
return;
}
@@ -170,7 +194,20 @@ module.exports = Mn.View.extend({
templateContext: {
getLetsencryptEmail: function () {
return App.Cache.User.get('email');
- }
+ },
+ getUseDnsChallenge: function () {
+ return typeof this.meta.dns_challenge !== 'undefined' ? this.meta.dns_challenge : false;
+ },
+ getDnsProvider: function () {
+ return typeof this.meta.dns_provider !== 'undefined' && this.meta.dns_provider != '' ? this.meta.dns_provider : null;
+ },
+ getDnsProviderCredentials: function () {
+ return typeof this.meta.dns_provider_credentials !== 'undefined' ? this.meta.dns_provider_credentials : '';
+ },
+ getPropagationSeconds: function () {
+ return typeof this.meta.propagation_seconds !== 'undefined' ? this.meta.propagation_seconds : '';
+ },
+ dns_plugins: dns_providers,
},
onRender: function () {
@@ -191,6 +228,8 @@ module.exports = Mn.View.extend({
});
// Certificates
+ this.ui.dns_challenge_content.hide();
+ this.ui.credentials_file_content.hide();
this.ui.letsencrypt.hide();
this.ui.certificate_select.selectize({
valueField: 'id',
diff --git a/frontend/js/i18n/messages.json b/frontend/js/i18n/messages.json
index d0c9d8e..8826afa 100644
--- a/frontend/js/i18n/messages.json
+++ b/frontend/js/i18n/messages.json
@@ -102,7 +102,15 @@
"letsencrypt-agree": "I Agree to the Let's Encrypt Terms of Service",
"delete-ssl": "The SSL certificates attached will NOT be removed, they will need to be removed manually.",
"hosts-warning": "These domains must be already configured to point to this installation",
- "use-cloudflare": "Use CloudFlare DNS verification"
+ "no-wildcard-without-dns": "Cannot request Let's Encrypt Certificate for wildcard domains when not using DNS challenge",
+ "dns-challenge": "Use a DNS Challenge",
+ "certbot-warning": "This section requires some knowledge about Certbot and its DNS plugins. Please consult the respective plugins documentation.",
+ "dns-provider": "DNS Provider",
+ "please-choose": "Please Choose...",
+ "credentials-file-content": "Credentials File Content",
+ "credentials-file-content-info": "This plugin requires a configuration file containing an API token or other credentials to your provider",
+ "propagation-seconds": "Propagation Seconds",
+ "propagation-seconds-info": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation."
},
"proxy-hosts": {
"title": "Proxy Hosts",
diff --git a/utils/certbot-dns-plugins.js b/utils/certbot-dns-plugins.js
new file mode 100644
index 0000000..4af678e
--- /dev/null
+++ b/utils/certbot-dns-plugins.js
@@ -0,0 +1,160 @@
+/**
+ * This file contains info about available Certbot DNS plugins.
+ *
+ * File Structure:
+ *
+ * {
+ * cloudflare: {
+ * display_name: "Name displayed to the user",
+ * package_name: "Package name in PyPi repo",
+ * package_version: "Package version in PyPi repo",
+ * credentials: `Template of the credentials file`,
+ * full_plugin_name: "The full plugin name as used in the commandline with certbot, including prefixes, e.g. 'certbot-dns-njalla:dns-njalla'",
+ * credentials_file: Whether the plugin has a credentials file
+ * },
+ * ...
+ * }
+ *
+ */
+
+module.exports = {
+ cloudflare: {
+ display_name: "Cloudflare",
+ package_name: "certbot-dns-cloudflare",
+ package_version: "1.8.0",
+ credentials: `# Cloudflare API token
+dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567`,
+ full_plugin_name: "dns-cloudflare",
+ },
+ //####################################################//
+ cloudxns: {
+ display_name: "CloudXNS",
+ package_name: "certbot-dns-cloudxns",
+ package_version: "1.8.0",
+ credentials: `dns_cloudxns_api_key = 1234567890abcdef1234567890abcdef
+dns_cloudxns_secret_key = 1122334455667788`,
+ full_plugin_name: "dns-cloudxns",
+ },
+ //####################################################//
+ digitalocean: {
+ display_name: "DigitalOcean",
+ package_name: "certbot-dns-digitalocean",
+ package_version: "1.8.0",
+ credentials: `dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff`,
+ full_plugin_name: "dns-digitalocean",
+ },
+ //####################################################//
+ dnsimple: {
+ display_name: "DNSimple",
+ package_name: "certbot-dns-dnsimple",
+ package_version: "1.8.0",
+ credentials: `dns_dnsimple_token = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
+ full_plugin_name: "dns-dnsimple",
+ },
+ //####################################################//
+ dnsmadeeasy: {
+ display_name: "DNS Made Easy",
+ package_name: "certbot-dns-dnsmadeeasy",
+ package_version: "1.8.0",
+ credentials: `dns_dnsmadeeasy_api_key = 1c1a3c91-4770-4ce7-96f4-54c0eb0e457a
+dns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55`,
+ full_plugin_name: "dns-dnsmadeeasy",
+ },
+ //####################################################//
+ google: {
+ display_name: "Google",
+ package_name: "certbot-dns-google",
+ package_version: "1.8.0",
+ credentials: `{
+ "type": "service_account",
+ ...
+}`,
+ full_plugin_name: "dns-google",
+ },
+ //####################################################//
+ hetzner: {
+ display_name: "Hetzner",
+ package_name: "certbot-dns-hetzner",
+ package_version: "1.0.4",
+ credentials: `certbot_dns_hetzner:dns_hetzner_api_token = 0123456789abcdef0123456789abcdef`,
+ full_plugin_name: "certbot-dns-hetzner:dns-hetzner",
+ },
+ //####################################################//
+ linode: {
+ display_name: "Linode",
+ package_name: "certbot-dns-linode",
+ package_version: "1.8.0",
+ credentials: `dns_linode_key = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ64
+dns_linode_version = [ |3|4]`,
+ full_plugin_name: "dns-linode",
+ },
+ //####################################################//
+ luadns: {
+ display_name: "LuaDNS",
+ package_name: "certbot-dns-luadns",
+ package_version: "1.8.0",
+ credentials: `dns_luadns_email = user@example.com
+dns_luadns_token = 0123456789abcdef0123456789abcdef`,
+ full_plugin_name: "dns-luadns",
+ },
+ //####################################################//
+ netcup: {
+ display_name: "netcup",
+ package_name: "certbot-dns-netcup",
+ package_version: "1.0.0",
+ credentials: `certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567`,
+ full_plugin_name: "certbot-dns-netcup:dns-netcup",
+ },
+ //####################################################//
+ njalla: {
+ display_name: "Njalla",
+ package_name: "certbot-dns-nsone",
+ package_version: "0.0.4",
+ credentials: `certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567`,
+ full_plugin_name: "certbot-dns-njalla:dns-njalla",
+ },
+ //####################################################//
+ nsone: {
+ display_name: "NS1",
+ package_name: "certbot-dns-nsone",
+ package_version: "1.8.0",
+ credentials: `dns_nsone_api_key = MDAwMDAwMDAwMDAwMDAw`,
+ full_plugin_name: "dns-nsone",
+ },
+ //####################################################//
+ ovh: {
+ display_name: "OVH",
+ package_name: "certbot-dns-ovh",
+ package_version: "1.8.0",
+ credentials: `dns_ovh_endpoint = ovh-eu
+dns_ovh_application_key = MDAwMDAwMDAwMDAw
+dns_ovh_application_secret = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
+dns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
+ full_plugin_name: "dns-ovh",
+ },
+ //####################################################//
+ rfc2136: {
+ display_name: "RFC 2136",
+ package_name: "certbot-dns-rfc2136",
+ package_version: "1.8.0",
+ credentials: `# Target DNS server
+dns_rfc2136_server = 192.0.2.1
+# Target DNS port
+dns_rfc2136_port = 53
+# TSIG key name
+dns_rfc2136_name = keyname.
+# TSIG key secret
+dns_rfc2136_secret = 4q4wM/2I180UXoMyN4INVhJNi8V9BCV+jMw2mXgZw/CSuxUT8C7NKKFs AmKd7ak51vWKgSl12ib86oQRPkpDjg==
+# TSIG key algorithm
+dns_rfc2136_algorithm = HMAC-SHA512`,
+ full_plugin_name: "dns-rfc2136",
+ },
+ //####################################################//
+ route53: {
+ display_name: "Route 53 (Amazon)",
+ package_name: "certbot-dns-route53",
+ package_version: "1.8.0",
+ credentials: false,
+ full_plugin_name: "dns-route53",
+ },
+};
From 2523424f682d5f1da5a28324277acd4c3f1abdb8 Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Mon, 5 Oct 2020 01:04:18 +0200
Subject: [PATCH 02/13] Updates dockerfiles
---
docker/Dockerfile | 4 ++--
docker/dev/Dockerfile | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 5224416..3c99751 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -17,8 +17,8 @@ ENV NODE_ENV=production
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
&& apk update \
- && apk add python2 py-pip certbot jq \
- && pip install certbot-dns-cloudflare \
+ && apk add python3 certbot jq \
+ && python3 -m ensurepip \
&& rm -rf /var/cache/apk/*
ENV NPM_BUILD_VERSION="${BUILD_VERSION}" NPM_BUILD_COMMIT="${BUILD_COMMIT}" NPM_BUILD_DATE="${BUILD_DATE}"
diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile
index 5b67981..45ee534 100644
--- a/docker/dev/Dockerfile
+++ b/docker/dev/Dockerfile
@@ -7,8 +7,8 @@ ENV S6_FIX_ATTRS_HIDDEN=1
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
&& apk update \
- && apk add python2 py-pip certbot jq \
- && pip install certbot-dns-cloudflare \
+ && apk add python3 certbot jq \
+ && python3 -m ensurepip \
&& rm -rf /var/cache/apk/*
# Task
From 05f6a55a0b4e16e678e20c3b66588122d4c5669e Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Tue, 6 Oct 2020 14:49:02 +0200
Subject: [PATCH 03/13] Adds frontend improvements and fixes
---
frontend/js/app/api.js | 10 ++---
frontend/js/app/nginx/certificates/form.ejs | 18 +++++++--
frontend/js/app/nginx/certificates/form.js | 40 ++++++++++++++-----
.../js/app/nginx/certificates/list/item.ejs | 2 +-
frontend/js/app/nginx/dead/form.ejs | 5 +++
frontend/js/app/nginx/dead/form.js | 28 +++++++++++--
frontend/js/app/nginx/proxy/form.ejs | 5 +++
frontend/js/app/nginx/proxy/form.js | 28 +++++++++++--
frontend/js/app/nginx/redirection/form.ejs | 5 +++
frontend/js/app/nginx/redirection/form.js | 31 +++++++++++---
frontend/js/i18n/messages.json | 4 +-
utils/certbot-dns-plugins.js | 8 +++-
12 files changed, 147 insertions(+), 37 deletions(-)
diff --git a/frontend/js/app/api.js b/frontend/js/app/api.js
index 74356f0..1d7b358 100644
--- a/frontend/js/app/api.js
+++ b/frontend/js/app/api.js
@@ -53,7 +53,7 @@ function fetch(verb, path, data, options) {
contentType: options.contentType || 'application/json; charset=UTF-8',
processData: options.processData || true,
crossDomain: true,
- timeout: options.timeout ? options.timeout : 30000,
+ timeout: options.timeout ? options.timeout : 180000,
xhrFields: {
withCredentials: true
},
@@ -586,8 +586,8 @@ module.exports = {
/**
* @param {Object} data
*/
- create: function (data) {
- return fetch('post', 'nginx/certificates', data);
+ create: function (data, timeout = 180000) {
+ return fetch('post', 'nginx/certificates', data, {timeout});
},
/**
@@ -630,8 +630,8 @@ module.exports = {
* @param {Number} id
* @returns {Promise}
*/
- renew: function (id) {
- return fetch('post', 'nginx/certificates/' + id + '/renew');
+ renew: function (id, timeout = 180000) {
+ return fetch('post', 'nginx/certificates/' + id + '/renew', undefined, {timeout});
}
}
},
diff --git a/frontend/js/app/nginx/certificates/form.ejs b/frontend/js/app/nginx/certificates/form.ejs
index a3d6c07..4c7a596 100644
--- a/frontend/js/app/nginx/certificates/form.ejs
+++ b/frontend/js/app/nginx/certificates/form.ejs
@@ -1,12 +1,20 @@
-
|
- <%- i18n('ssl', provider) %><% if (meta.dns_provider) { %> - <% dns_providers[meta.dns_provider].display_name } %>
+ <%- i18n('ssl', provider) %><% if (meta.dns_provider) { %> - <%- dns_providers[meta.dns_provider].display_name %><% } %>
|
<%- formatDbDate(expires_on, 'Do MMMM YYYY, h:mm a') %>
diff --git a/frontend/js/app/nginx/dead/form.ejs b/frontend/js/app/nginx/dead/form.ejs
index 1d01e09..253c4b6 100644
--- a/frontend/js/app/nginx/dead/form.ejs
+++ b/frontend/js/app/nginx/dead/form.ejs
@@ -4,6 +4,7 @@
+
+
+ <%= i18n('ssl', 'stored-as-plaintext-info') %>
+
diff --git a/frontend/js/app/nginx/dead/form.js b/frontend/js/app/nginx/dead/form.js
index 393788d..0df24f7 100644
--- a/frontend/js/app/nginx/dead/form.js
+++ b/frontend/js/app/nginx/dead/form.js
@@ -20,6 +20,7 @@ module.exports = Mn.View.extend({
buttons: '.modal-footer button',
cancel: 'button.cancel',
save: 'button.save',
+ le_error_info: '#le-error-info',
certificate_select: 'select[name="certificate_id"]',
ssl_forced: 'input[name="ssl_forced"]',
hsts_enabled: 'input[name="hsts_enabled"]',
@@ -116,6 +117,7 @@ module.exports = Mn.View.extend({
'click @ui.save': function (e) {
e.preventDefault();
+ this.ui.le_error_info.hide();
if (!this.ui.form[0].checkValidity()) {
$('').hide().appendTo(this.ui.form).click().remove();
@@ -130,7 +132,18 @@ module.exports = Mn.View.extend({
data.hsts_subdomains = !!data.hsts_subdomains;
data.http2_support = !!data.http2_support;
data.ssl_forced = !!data.ssl_forced;
- data.meta.dns_challenge = !!data.meta.dns_challenge;
+
+ if (typeof data.meta === 'undefined') data.meta = {};
+ data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1;
+ data.meta.dns_challenge = data.meta.dns_challenge == 1;
+
+ if(!data.meta.dns_challenge){
+ data.meta.dns_provider = undefined;
+ data.meta.dns_provider_credentials = undefined;
+ data.meta.propagation_seconds = undefined;
+ } else {
+ if(data.meta.propagation_seconds === '') data.meta.propagation_seconds = undefined;
+ }
if (typeof data.domain_names === 'string' && data.domain_names) {
data.domain_names = data.domain_names.split(',');
@@ -151,8 +164,6 @@ module.exports = Mn.View.extend({
alert(i18n('ssl', 'no-wildcard-without-dns'));
return;
}
-
- data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1';
} else {
data.certificate_id = parseInt(data.certificate_id, 10);
}
@@ -181,7 +192,15 @@ module.exports = Mn.View.extend({
});
})
.catch(err => {
- alert(err.message);
+ let more_info = '';
+ if(err.code === 500){
+ try{
+ more_info = JSON.parse(err.debug).debug.stack.join("\n");
+ } catch(e) {}
+ }
+ this.ui.le_error_info[0].innerHTML = `${err.message}${more_info !== '' ? `${more_info} `:''}`;
+ this.ui.le_error_info.show();
+ this.ui.le_error_info[0].scrollIntoView();
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
this.ui.save.removeClass('btn-loading');
});
@@ -225,6 +244,7 @@ module.exports = Mn.View.extend({
});
// Certificates
+ this.ui.le_error_info.hide();
this.ui.dns_challenge_content.hide();
this.ui.credentials_file_content.hide();
this.ui.letsencrypt.hide();
diff --git a/frontend/js/app/nginx/proxy/form.ejs b/frontend/js/app/nginx/proxy/form.ejs
index 34f319c..1a49830 100644
--- a/frontend/js/app/nginx/proxy/form.ejs
+++ b/frontend/js/app/nginx/proxy/form.ejs
@@ -4,6 +4,7 @@
+
+
+ <%= i18n('ssl', 'stored-as-plaintext-info') %>
+
diff --git a/frontend/js/app/nginx/proxy/form.js b/frontend/js/app/nginx/proxy/form.js
index 4211050..3c17225 100644
--- a/frontend/js/app/nginx/proxy/form.js
+++ b/frontend/js/app/nginx/proxy/form.js
@@ -29,6 +29,7 @@ module.exports = Mn.View.extend({
save: 'button.save',
add_location_btn: 'button.add_location',
locations_container: '.locations_container',
+ le_error_info: '#le-error-info',
certificate_select: 'select[name="certificate_id"]',
access_list_select: 'select[name="access_list_id"]',
ssl_forced: 'input[name="ssl_forced"]',
@@ -137,6 +138,7 @@ module.exports = Mn.View.extend({
'click @ui.save': function (e) {
e.preventDefault();
+ this.ui.le_error_info.hide();
if (!this.ui.form[0].checkValidity()) {
$('').hide().appendTo(this.ui.form).click().remove();
@@ -165,7 +167,18 @@ module.exports = Mn.View.extend({
data.hsts_enabled = !!data.hsts_enabled;
data.hsts_subdomains = !!data.hsts_subdomains;
data.ssl_forced = !!data.ssl_forced;
- data.meta.dns_challenge = !!data.meta.dns_challenge;
+
+ if (typeof data.meta === 'undefined') data.meta = {};
+ data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1;
+ data.meta.dns_challenge = data.meta.dns_challenge == 1;
+
+ if(!data.meta.dns_challenge){
+ data.meta.dns_provider = undefined;
+ data.meta.dns_provider_credentials = undefined;
+ data.meta.propagation_seconds = undefined;
+ } else {
+ if(data.meta.propagation_seconds === '') data.meta.propagation_seconds = undefined;
+ }
if (typeof data.domain_names === 'string' && data.domain_names) {
data.domain_names = data.domain_names.split(',');
@@ -186,8 +199,6 @@ module.exports = Mn.View.extend({
alert(i18n('ssl', 'no-wildcard-without-dns'));
return;
}
-
- data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1';
} else {
data.certificate_id = parseInt(data.certificate_id, 10);
}
@@ -216,7 +227,15 @@ module.exports = Mn.View.extend({
});
})
.catch(err => {
- alert(err.message);
+ let more_info = '';
+ if(err.code === 500){
+ try{
+ more_info = JSON.parse(err.debug).debug.stack.join("\n");
+ } catch(e) {}
+ }
+ this.ui.le_error_info[0].innerHTML = `${err.message}${more_info !== '' ? `${more_info} `:''}`;
+ this.ui.le_error_info.show();
+ this.ui.le_error_info[0].scrollIntoView();
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
this.ui.save.removeClass('btn-loading');
});
@@ -293,6 +312,7 @@ module.exports = Mn.View.extend({
});
// Certificates
+ this.ui.le_error_info.hide();
this.ui.dns_challenge_content.hide();
this.ui.credentials_file_content.hide();
this.ui.letsencrypt.hide();
diff --git a/frontend/js/app/nginx/redirection/form.ejs b/frontend/js/app/nginx/redirection/form.ejs
index f4e4375..3247233 100644
--- a/frontend/js/app/nginx/redirection/form.ejs
+++ b/frontend/js/app/nginx/redirection/form.ejs
@@ -4,6 +4,7 @@
+
+
+ <%= i18n('ssl', 'stored-as-plaintext-info') %>
+
diff --git a/frontend/js/app/nginx/redirection/form.js b/frontend/js/app/nginx/redirection/form.js
index c1c6d9d..5ca3b8d 100644
--- a/frontend/js/app/nginx/redirection/form.js
+++ b/frontend/js/app/nginx/redirection/form.js
@@ -21,6 +21,7 @@ module.exports = Mn.View.extend({
buttons: '.modal-footer button',
cancel: 'button.cancel',
save: 'button.save',
+ le_error_info: '#le-error-info',
certificate_select: 'select[name="certificate_id"]',
ssl_forced: 'input[name="ssl_forced"]',
hsts_enabled: 'input[name="hsts_enabled"]',
@@ -116,6 +117,7 @@ module.exports = Mn.View.extend({
'click @ui.save': function (e) {
e.preventDefault();
+ this.ui.le_error_info.hide();
if (!this.ui.form[0].checkValidity()) {
$('').hide().appendTo(this.ui.form).click().remove();
@@ -132,7 +134,18 @@ module.exports = Mn.View.extend({
data.hsts_enabled = !!data.hsts_enabled;
data.hsts_subdomains = !!data.hsts_subdomains;
data.ssl_forced = !!data.ssl_forced;
- data.meta.dns_challenge = !!data.meta.dns_challenge;
+
+ if (typeof data.meta === 'undefined') data.meta = {};
+ data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1;
+ data.meta.dns_challenge = data.meta.dns_challenge == 1;
+
+ if(!data.meta.dns_challenge){
+ data.meta.dns_provider = undefined;
+ data.meta.dns_provider_credentials = undefined;
+ data.meta.propagation_seconds = undefined;
+ } else {
+ if(data.meta.propagation_seconds === '') data.meta.propagation_seconds = undefined;
+ }
if (typeof data.domain_names === 'string' && data.domain_names) {
data.domain_names = data.domain_names.split(',');
@@ -152,10 +165,7 @@ module.exports = Mn.View.extend({
if (domain_err) {
alert(i18n('ssl', 'no-wildcard-without-dns'));
return;
- }
-
- data.meta.cloudflare_use = data.meta.cloudflare_use === '1';
- data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1';
+ }
} else {
data.certificate_id = parseInt(data.certificate_id, 10);
}
@@ -184,7 +194,15 @@ module.exports = Mn.View.extend({
});
})
.catch(err => {
- alert(err.message);
+ let more_info = '';
+ if(err.code === 500){
+ try{
+ more_info = JSON.parse(err.debug).debug.stack.join("\n");
+ } catch(e) {}
+ }
+ this.ui.le_error_info[0].innerHTML = `${err.message}${more_info !== '' ? `${more_info} `:''}`;
+ this.ui.le_error_info.show();
+ this.ui.le_error_info[0].scrollIntoView();
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
this.ui.save.removeClass('btn-loading');
});
@@ -228,6 +246,7 @@ module.exports = Mn.View.extend({
});
// Certificates
+ this.ui.le_error_info.hide();
this.ui.dns_challenge_content.hide();
this.ui.credentials_file_content.hide();
this.ui.letsencrypt.hide();
diff --git a/frontend/js/i18n/messages.json b/frontend/js/i18n/messages.json
index 8826afa..af3e8cb 100644
--- a/frontend/js/i18n/messages.json
+++ b/frontend/js/i18n/messages.json
@@ -109,8 +109,10 @@
"please-choose": "Please Choose...",
"credentials-file-content": "Credentials File Content",
"credentials-file-content-info": "This plugin requires a configuration file containing an API token or other credentials to your provider",
+ "stored-as-plaintext-info": "This data will be stored as plaintext in the database!",
"propagation-seconds": "Propagation Seconds",
- "propagation-seconds-info": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation."
+ "propagation-seconds-info": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation.",
+ "obtaining-certificate-info": "Obtaining certificate... This might take a few minutes."
},
"proxy-hosts": {
"title": "Proxy Hosts",
diff --git a/utils/certbot-dns-plugins.js b/utils/certbot-dns-plugins.js
index 4af678e..ef533c1 100644
--- a/utils/certbot-dns-plugins.js
+++ b/utils/certbot-dns-plugins.js
@@ -1,5 +1,7 @@
/**
* This file contains info about available Certbot DNS plugins.
+ * This only works for plugins which use the standard argument structure, so:
+ * --authenticator ---credentials ---propagation-seconds
*
* File Structure:
*
@@ -102,13 +104,15 @@ dns_luadns_token = 0123456789abcdef0123456789abcdef`,
display_name: "netcup",
package_name: "certbot-dns-netcup",
package_version: "1.0.0",
- credentials: `certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567`,
+ credentials: `dns_netcup_customer_id = 123456
+dns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567
+dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`,
full_plugin_name: "certbot-dns-netcup:dns-netcup",
},
//####################################################//
njalla: {
display_name: "Njalla",
- package_name: "certbot-dns-nsone",
+ package_name: "certbot-dns-njalla",
package_version: "0.0.4",
credentials: `certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567`,
full_plugin_name: "certbot-dns-njalla:dns-njalla",
From 093b48ad7b5417968d33ee3636e000bcc37f8795 Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Tue, 6 Oct 2020 14:52:06 +0200
Subject: [PATCH 04/13] Implements backend changes to allow more dns challenges
---
backend/internal/certificate.js | 110 ++++++++++++++-------
backend/schema/endpoints/certificates.json | 16 ++-
2 files changed, 91 insertions(+), 35 deletions(-)
diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js
index 2acd895..1b6689b 100644
--- a/backend/internal/certificate.js
+++ b/backend/internal/certificate.js
@@ -13,6 +13,7 @@ const internalNginx = require('./nginx');
const internalHost = require('./host');
const certbot_command = '/usr/bin/certbot';
const le_config = '/etc/letsencrypt.ini';
+const dns_plugins = require('../../utils/certbot-dns-plugins')
function omissions() {
return ['is_deleted'];
@@ -141,11 +142,11 @@ const internalCertificate = {
});
})
.then((in_use_result) => {
- // Is CloudFlare, no config needed, so skip 3 and 5.
- if (data.meta.cloudflare_use) {
+ // With DNS challenge no config is needed, so skip 3 and 5.
+ if (certificate.meta.dns_challenge) {
return internalNginx.reload().then(() => {
// 4. Request cert
- return internalCertificate.requestLetsEncryptCloudFlareDnsSsl(certificate, data.meta.cloudflare_token);
+ return internalCertificate.requestLetsEncryptSslWithDnsChallenge(certificate);
})
.then(internalNginx.reload)
.then(() => {
@@ -772,35 +773,58 @@ const internalCertificate = {
},
/**
- * @param {Object} certificate the certificate row
- * @param {String} apiToken the cloudflare api token
+ * @param {Object} certificate the certificate row
+ * @param {String} dns_provider the dns provider name (key used in `certbot-dns-plugins.js`)
+ * @param {String | null} credentials the content of this providers credentials file
+ * @param {String} propagation_seconds the cloudflare api token
* @returns {Promise}
*/
- requestLetsEncryptCloudFlareDnsSsl: (certificate, apiToken) => {
- logger.info('Requesting Let\'sEncrypt certificates via Cloudflare DNS for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
+ requestLetsEncryptSslWithDnsChallenge: (certificate) => {
+ const dns_plugin = dns_plugins[certificate.meta.dns_provider];
- let tokenLoc = '~/cloudflare-token';
- let storeKey = 'echo "dns_cloudflare_api_token = ' + apiToken + '" > ' + tokenLoc;
+ if(!dns_plugin){
+ throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`)
+ }
- let cmd =
- storeKey + ' && ' +
+ logger.info(`Requesting Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
+
+ const credentials_loc = `/etc/letsencrypt/credentials-${certificate.id}`;
+ const credentials_cmd = `echo '${certificate.meta.dns_provider_credentials.replace("'", "\'")}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'`;
+ const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
+
+ const main_cmd =
certbot_command + ' certonly --non-interactive ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--agree-tos ' +
'--email "' + certificate.meta.letsencrypt_email + '" ' +
'--domains "' + certificate.domain_names.join(',') + '" ' +
- '--dns-cloudflare --dns-cloudflare-credentials ' + tokenLoc +
- (le_staging ? ' --staging' : '')
- + ' && rm ' + tokenLoc;
+ '--authenticator ' + dns_plugin.full_plugin_name + ' ' +
+ '--' + dns_plugin.full_plugin_name + '-credentials "' + credentials_loc + '"' +
+ (
+ certificate.meta.propagation_seconds !== undefined
+ ? ' --' + dns_plugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
+ : ''
+ ) +
+ (le_staging ? ' --staging' : '');
+
+ const teardown_cmd = `rm '${credentials_loc}'`;
if (debug_mode) {
- logger.info('Command:', cmd);
+ logger.info('Command:', `${credentials_cmd} && ${prepare_cmd} && ${main_cmd} && ${teardown_cmd}`);
}
- return utils.exec(cmd).then((result) => {
- logger.info(result);
- return result;
- });
+ return utils.exec(credentials_cmd)
+ .then(() => {
+ return utils.exec(prepare_cmd)
+ .then(() => {
+ return utils.exec(main_cmd)
+ .then(async (result) => {
+ await utils.exec(teardown_cmd);
+ logger.info(result);
+ return result;
+ });
+ });
+ });
},
@@ -817,7 +841,7 @@ const internalCertificate = {
})
.then((certificate) => {
if (certificate.provider === 'letsencrypt') {
- let renewMethod = certificate.meta.cloudflare_use ? internalCertificate.renewLetsEncryptCloudFlareSsl : internalCertificate.renewLetsEncryptSsl;
+ let renewMethod = certificate.meta.dns_challenge ? internalCertificate.renewLetsEncryptSslWithDnsChallenge : internalCertificate.renewLetsEncryptSsl;
return renewMethod(certificate)
.then(() => {
@@ -877,22 +901,42 @@ const internalCertificate = {
* @param {Object} certificate the certificate row
* @returns {Promise}
*/
- renewLetsEncryptCloudFlareSsl: (certificate) => {
- logger.info('Renewing Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
+ renewLetsEncryptSslWithDnsChallenge: (certificate) => {
+ const dns_plugin = dns_plugins[certificate.meta.dns_provider];
- let cmd = certbot_command + ' renew --non-interactive ' +
- '--cert-name "npm-' + certificate.id + '" ' +
- '--disable-hook-validation ' +
- (le_staging ? '--staging' : '');
-
- if (debug_mode) {
- logger.info('Command:', cmd);
+ if(!dns_plugin){
+ throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`)
}
- return utils.exec(cmd)
- .then((result) => {
- logger.info(result);
- return result;
+ logger.info(`Renewing Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
+
+ const credentials_loc = `/etc/letsencrypt/credentials-${certificate.id}`;
+ const credentials_cmd = `echo '${certificate.meta.dns_provider_credentials.replace("'", "\'")}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'`;
+ const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
+
+ const main_cmd =
+ certbot_command + ' renew --non-interactive ' +
+ '--cert-name "npm-' + certificate.id + '" ' +
+ '--disable-hook-validation' +
+ (le_staging ? ' --staging' : '');
+
+ const teardown_cmd = `rm '${credentials_loc}'`;
+
+ if (debug_mode) {
+ logger.info('Command:', `${credentials_cmd} && ${prepare_cmd} && ${main_cmd} && ${teardown_cmd}`);
+ }
+
+ return utils.exec(credentials_cmd)
+ .then(() => {
+ return utils.exec(prepare_cmd)
+ .then(() => {
+ return utils.exec(main_cmd)
+ .then(async (result) => {
+ await utils.exec(teardown_cmd);
+ logger.info(result);
+ return result;
+ });
+ });
});
},
diff --git a/backend/schema/endpoints/certificates.json b/backend/schema/endpoints/certificates.json
index 27ea2d2..49fd6a7 100644
--- a/backend/schema/endpoints/certificates.json
+++ b/backend/schema/endpoints/certificates.json
@@ -42,11 +42,23 @@
"letsencrypt_agree": {
"type": "boolean"
},
- "cloudflare_use": {
+ "dns_challenge": {
"type": "boolean"
},
- "cloudflare_token": {
+ "dns_provider": {
"type": "string"
+ },
+ "dns_provider_credentials": {
+ "type": "string"
+ },
+ "propagation_seconds": {
+ "anyOf": [
+ {
+ "type": "integer",
+ "minimum": 0
+ }
+ ]
+
}
}
}
From 64de36cdf27865eb342847e013d0c372405c939c Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Tue, 6 Oct 2020 15:16:45 +0200
Subject: [PATCH 05/13] Adds more DNS plugins
---
docker/docker-compose.dev.yml | 9 ++++
utils/certbot-dns-plugins.js | 85 +++++++++++++++++++++++++++++++++++
2 files changed, 94 insertions(+)
diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml
index 4321d86..24f2ee1 100644
--- a/docker/docker-compose.dev.yml
+++ b/docker/docker-compose.dev.yml
@@ -11,6 +11,8 @@ services:
- 3080:80
- 3081:81
- 3443:443
+ networks:
+ - nginx_proxy_manager
environment:
- NODE_ENV=development
- FORCE_COLOR=1
@@ -26,6 +28,8 @@ services:
db:
image: jc21/mariadb-aria
+ networks:
+ - nginx_proxy_manager
environment:
MYSQL_ROOT_PASSWORD: "npm"
MYSQL_DATABASE: "npm"
@@ -38,6 +42,8 @@ services:
image: 'swaggerapi/swagger-ui:latest'
ports:
- 3001:80
+ networks:
+ - nginx_proxy_manager
environment:
URL: "http://127.0.0.1:3081/api/schema"
PORT: '80'
@@ -48,3 +54,6 @@ volumes:
npm_data:
le_data:
db_data:
+
+networks:
+ nginx_proxy_manager:
diff --git a/utils/certbot-dns-plugins.js b/utils/certbot-dns-plugins.js
index ef533c1..a0a5c9a 100644
--- a/utils/certbot-dns-plugins.js
+++ b/utils/certbot-dns-plugins.js
@@ -38,6 +38,25 @@ dns_cloudxns_secret_key = 1122334455667788`,
full_plugin_name: "dns-cloudxns",
},
//####################################################//
+ corenetworks: {
+ display_name: "Core Networks",
+ package_name: "certbot-dns-corenetworks",
+ package_version: "0.1.4",
+ credentials: `certbot_dns_corenetworks:dns_corenetworks_username = asaHB12r
+certbot_dns_corenetworks:dns_corenetworks_password = secure_password`,
+ full_plugin_name: "certbot-dns-corenetworks:dns-corenetworks",
+ },
+ //####################################################//
+ cpanel: {
+ display_name: "cPanel",
+ package_name: "certbot-dns-cpanel",
+ package_version: "0.2.2",
+ credentials: `certbot_dns_cpanel:cpanel_url = https://cpanel.example.com:2083
+certbot_dns_cpanel:cpanel_username = user
+certbot_dns_cpanel:cpanel_password = hunter2`,
+ full_plugin_name: "certbot-dns-cpanel:cpanel",
+ },
+ //####################################################//
digitalocean: {
display_name: "DigitalOcean",
package_name: "certbot-dns-digitalocean",
@@ -46,6 +65,16 @@ dns_cloudxns_secret_key = 1122334455667788`,
full_plugin_name: "dns-digitalocean",
},
//####################################################//
+ directadmin: {
+ display_name: "DirectAdmin",
+ package_name: "certbot-dns-directadmin",
+ package_version: "0.0.20",
+ credentials: `directadmin_url = https://my.directadminserver.com:2222
+directadmin_username = username
+directadmin_password = aSuperStrongPassword`,
+ full_plugin_name: "certbot-dns-directadmin:directadmin",
+ },
+ //####################################################//
dnsimple: {
display_name: "DNSimple",
package_name: "certbot-dns-dnsimple",
@@ -63,6 +92,15 @@ dns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55`,
full_plugin_name: "dns-dnsmadeeasy",
},
//####################################################//
+ dnspod: {
+ display_name: "DNSPod",
+ package_name: "certbot-dns-dnspod",
+ package_version: "0.1.0",
+ credentials: `certbot_dns_dnspod:dns_dnspod_email = "DNSPOD-API-REQUIRES-A-VALID-EMAIL"
+certbot_dns_dnspod:dns_dnspod_api_token = "DNSPOD-API-TOKEN"`,
+ full_plugin_name: "certbot-dns-dnspod:dns-dnspod",
+ },
+ //####################################################//
google: {
display_name: "Google",
package_name: "certbot-dns-google",
@@ -82,6 +120,36 @@ dns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55`,
full_plugin_name: "certbot-dns-hetzner:dns-hetzner",
},
//####################################################//
+ inwx: {
+ display_name: "INWX",
+ package_name: "certbot-dns-inwx",
+ package_version: "2.1.2",
+ credentials: `certbot_dns_inwx:dns_inwx_url = https://api.domrobot.com/xmlrpc/
+certbot_dns_inwx:dns_inwx_username = your_username
+certbot_dns_inwx:dns_inwx_password = your_password
+certbot_dns_inwx:dns_inwx_shared_secret = your_shared_secret optional`,
+ full_plugin_name: "certbot-dns-inwx:dns-inwx",
+ },
+ //####################################################//
+ ispconfig: {
+ display_name: "ISPConfig",
+ package_name: "certbot-dns-ispconfig",
+ package_version: "0.2.0",
+ credentials: `certbot_dns_ispconfig:dns_ispconfig_username = myremoteuser
+certbot_dns_ispconfig:dns_ispconfig_password = verysecureremoteuserpassword
+certbot_dns_ispconfig:dns_ispconfig_endpoint = https://localhost:8080`,
+ full_plugin_name: "certbot-dns-ispconfig:dns-ispconfig",
+ },
+ //####################################################//
+ isset: {
+ display_name: "Isset",
+ package_name: "certbot-dns-isset",
+ package_version: "0.0.3",
+ credentials: `certbot_dns_isset:dns_isset_endpoint="https://customer.isset.net/api"
+certbot_dns_isset:dns_isset_token=""`,
+ full_plugin_name: "certbot-dns-isset:dns-isset",
+ },
+ //####################################################//
linode: {
display_name: "Linode",
package_name: "certbot-dns-linode",
@@ -137,6 +205,15 @@ dns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
full_plugin_name: "dns-ovh",
},
//####################################################//
+ powerdns: {
+ display_name: "PowerDNS",
+ package_name: "certbot-dns-powerdns",
+ package_version: "0.2.0",
+ credentials: `certbot_dns_powerdns:dns_powerdns_api_url = https://api.mypowerdns.example.org
+certbot_dns_powerdns:dns_powerdns_api_key = AbCbASsd!@34`,
+ full_plugin_name: "certbot-dns-powerdns:dns-powerdns",
+ },
+ //####################################################//
rfc2136: {
display_name: "RFC 2136",
package_name: "certbot-dns-rfc2136",
@@ -161,4 +238,12 @@ dns_rfc2136_algorithm = HMAC-SHA512`,
credentials: false,
full_plugin_name: "dns-route53",
},
+ //####################################################//
+ vultr: {
+ display_name: "Vultr",
+ package_name: "certbot-dns-vultr",
+ package_version: "1.0.3",
+ credentials: `certbot_dns_vultr:dns_vultr_key = YOUR_VULTR_API_KEY`,
+ full_plugin_name: "certbot-dns-vultr:dns-vultr",
+ },
};
From 4cbc1f5bbea2ac5dc1ad4b31639e2e2755c42e9d Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Tue, 6 Oct 2020 15:37:51 +0200
Subject: [PATCH 06/13] Minor refactoring
---
frontend/js/app/nginx/certificates/form.ejs | 2 +-
frontend/js/app/nginx/certificates/form.js | 12 ++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/frontend/js/app/nginx/certificates/form.ejs b/frontend/js/app/nginx/certificates/form.ejs
index 4c7a596..270ab71 100644
--- a/frontend/js/app/nginx/certificates/form.ejs
+++ b/frontend/js/app/nginx/certificates/form.ejs
@@ -12,7 +12,7 @@
<% if (provider === 'letsencrypt') { %>
diff --git a/frontend/js/app/nginx/certificates/form.js b/frontend/js/app/nginx/certificates/form.js
index 7db7a01..25ebeaf 100644
--- a/frontend/js/app/nginx/certificates/form.js
+++ b/frontend/js/app/nginx/certificates/form.js
@@ -18,7 +18,7 @@ module.exports = Mn.View.extend({
form: 'form',
loader_content: '.loader-content',
non_loader_content: '.non-loader-content',
- error_info: '#error-info',
+ le_error_info: '#le-error-info',
domain_names: 'input[name="domain_names"]',
buttons: '.modal-footer button',
cancel: 'button.cancel',
@@ -68,7 +68,7 @@ module.exports = Mn.View.extend({
'click @ui.save': function (e) {
e.preventDefault();
- this.ui.error_info.hide();
+ this.ui.le_error_info.hide();
if (!this.ui.form[0].checkValidity()) {
$(' ').hide().appendTo(this.ui.form).click().remove();
@@ -189,11 +189,11 @@ module.exports = Mn.View.extend({
.catch(err => {
try{
const error_message = JSON.parse(err.debug).debug.stack.join("\n");
- this.ui.error_info[0].innerHTML = ` ${err.message} ${error_message} `;
+ this.ui.le_error_info[0].innerHTML = ` ${err.message} ${error_message} `;
} catch(e) {
- this.ui.error_info[0].innerHTML = ` ${err.message} `;
+ this.ui.le_error_info[0].innerHTML = ` ${err.message} `;
}
- this.ui.error_info.show();
+ this.ui.le_error_info.show();
this.ui.le_error_info[0].scrollIntoView();
this.ui.loader_content.hide();
this.ui.non_loader_content.show();
@@ -250,7 +250,7 @@ module.exports = Mn.View.extend({
this.ui.dns_challenge_content.hide();
this.ui.credentials_file_content.hide();
this.ui.loader_content.hide();
- this.ui.error_info.hide();
+ this.ui.le_error_info.hide();
},
initialize: function (options) {
From 514b13fcc24fd07bcef6885bec40b9c169626597 Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Tue, 6 Oct 2020 16:12:12 +0200
Subject: [PATCH 07/13] Fixes build issues due to globally used file
---
backend/internal/certificate.js | 2 +-
docker/Dockerfile | 1 +
frontend/js/app/nginx/certificates/form.js | 2 +-
frontend/js/app/nginx/certificates/list/item.js | 2 +-
frontend/js/app/nginx/dead/form.js | 2 +-
frontend/js/app/nginx/proxy/form.js | 2 +-
frontend/js/app/nginx/redirection/form.js | 2 +-
{utils => global}/certbot-dns-plugins.js | 0
8 files changed, 7 insertions(+), 6 deletions(-)
rename {utils => global}/certbot-dns-plugins.js (100%)
diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js
index 1b6689b..fc11a31 100644
--- a/backend/internal/certificate.js
+++ b/backend/internal/certificate.js
@@ -13,7 +13,7 @@ const internalNginx = require('./nginx');
const internalHost = require('./host');
const certbot_command = '/usr/bin/certbot';
const le_config = '/etc/letsencrypt.ini';
-const dns_plugins = require('../../utils/certbot-dns-plugins')
+const dns_plugins = require('../../global/certbot-dns-plugins')
function omissions() {
return ['is_deleted'];
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 3c99751..acac5fa 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -34,6 +34,7 @@ EXPOSE 443
COPY docker/rootfs /
ADD backend /app
ADD frontend/dist /app/frontend
+COPY global /app/global
WORKDIR /app
RUN yarn install
diff --git a/frontend/js/app/nginx/certificates/form.js b/frontend/js/app/nginx/certificates/form.js
index 25ebeaf..df38159 100644
--- a/frontend/js/app/nginx/certificates/form.js
+++ b/frontend/js/app/nginx/certificates/form.js
@@ -4,7 +4,7 @@ const App = require('../../main');
const CertificateModel = require('../../../models/certificate');
const template = require('./form.ejs');
const i18n = require('../../i18n');
-const dns_providers = require('../../../../../utils/certbot-dns-plugins');
+const dns_providers = require('../../../../../global/certbot-dns-plugins');
require('jquery-serializejson');
require('selectize');
diff --git a/frontend/js/app/nginx/certificates/list/item.js b/frontend/js/app/nginx/certificates/list/item.js
index b5b2d85..c967fdb 100644
--- a/frontend/js/app/nginx/certificates/list/item.js
+++ b/frontend/js/app/nginx/certificates/list/item.js
@@ -2,7 +2,7 @@ const Mn = require('backbone.marionette');
const moment = require('moment');
const App = require('../../../main');
const template = require('./item.ejs');
-const dns_providers = require('../../../../../../utils/certbot-dns-plugins')
+const dns_providers = require('../../../../../../global/certbot-dns-plugins')
module.exports = Mn.View.extend({
template: template,
diff --git a/frontend/js/app/nginx/dead/form.js b/frontend/js/app/nginx/dead/form.js
index 0df24f7..a39038b 100644
--- a/frontend/js/app/nginx/dead/form.js
+++ b/frontend/js/app/nginx/dead/form.js
@@ -5,7 +5,7 @@ const template = require('./form.ejs');
const certListItemTemplate = require('../certificates-list-item.ejs');
const Helpers = require('../../../lib/helpers');
const i18n = require('../../i18n');
-const dns_providers = require('../../../../../utils/certbot-dns-plugins');
+const dns_providers = require('../../../../../global/certbot-dns-plugins');
require('jquery-serializejson');
require('selectize');
diff --git a/frontend/js/app/nginx/proxy/form.js b/frontend/js/app/nginx/proxy/form.js
index 3c17225..ec76987 100644
--- a/frontend/js/app/nginx/proxy/form.js
+++ b/frontend/js/app/nginx/proxy/form.js
@@ -8,7 +8,7 @@ const accessListItemTemplate = require('./access-list-item.ejs');
const CustomLocation = require('./location');
const Helpers = require('../../../lib/helpers');
const i18n = require('../../i18n');
-const dns_providers = require('../../../../../utils/certbot-dns-plugins');
+const dns_providers = require('../../../../../global/certbot-dns-plugins');
require('jquery-serializejson');
diff --git a/frontend/js/app/nginx/redirection/form.js b/frontend/js/app/nginx/redirection/form.js
index 5ca3b8d..6fa3693 100644
--- a/frontend/js/app/nginx/redirection/form.js
+++ b/frontend/js/app/nginx/redirection/form.js
@@ -5,7 +5,7 @@ const template = require('./form.ejs');
const certListItemTemplate = require('../certificates-list-item.ejs');
const Helpers = require('../../../lib/helpers');
const i18n = require('../../i18n');
-const dns_providers = require('../../../../../utils/certbot-dns-plugins');
+const dns_providers = require('../../../../../global/certbot-dns-plugins');
require('jquery-serializejson');
diff --git a/utils/certbot-dns-plugins.js b/global/certbot-dns-plugins.js
similarity index 100%
rename from utils/certbot-dns-plugins.js
rename to global/certbot-dns-plugins.js
From 95208a50a742a40f4aba51b8d73433f7afd35327 Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Thu, 8 Oct 2020 13:21:17 +0200
Subject: [PATCH 08/13] Increases timeouts in front- and backend
---
Jenkinsfile | 1 +
backend/internal/certificate.js | 2 +-
backend/routes/api/nginx/certificates.js | 2 ++
docker/rootfs/etc/nginx/conf.d/dev.conf | 3 +++
docker/rootfs/etc/nginx/conf.d/production.conf | 3 +++
frontend/js/app/api.js | 3 ++-
frontend/js/app/nginx/certificates/form.js | 14 +++++++-------
scripts/frontend-build | 2 +-
8 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/Jenkinsfile b/Jenkinsfile
index f5ec652..74dc0a1 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -65,6 +65,7 @@ pipeline {
// See: https://github.com/yarnpkg/yarn/issues/3254
sh '''docker run --rm \\
-v "$(pwd)/backend:/app" \\
+ -v "$(pwd)/global:/app/global" \\
-w /app \\
node:latest \\
sh -c "yarn install && yarn eslint . && rm -rf node_modules"
diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js
index fc11a31..641b494 100644
--- a/backend/internal/certificate.js
+++ b/backend/internal/certificate.js
@@ -13,7 +13,7 @@ const internalNginx = require('./nginx');
const internalHost = require('./host');
const certbot_command = '/usr/bin/certbot';
const le_config = '/etc/letsencrypt.ini';
-const dns_plugins = require('../../global/certbot-dns-plugins')
+const dns_plugins = require('../global/certbot-dns-plugins');
function omissions() {
return ['is_deleted'];
diff --git a/backend/routes/api/nginx/certificates.js b/backend/routes/api/nginx/certificates.js
index 50d3913..553a0bb 100644
--- a/backend/routes/api/nginx/certificates.js
+++ b/backend/routes/api/nginx/certificates.js
@@ -58,6 +58,7 @@ router
.post((req, res, next) => {
apiValidator({$ref: 'endpoints/certificates#/links/1/schema'}, req.body)
.then((payload) => {
+ req.setTimeout(900000); // 15 minutes timeout
return internalCertificate.create(res.locals.access, payload);
})
.then((result) => {
@@ -197,6 +198,7 @@ router
* Renew certificate
*/
.post((req, res, next) => {
+ req.setTimeout(900000); // 15 minutes timeout
internalCertificate.renew(res.locals.access, {
id: parseInt(req.params.certificate_id, 10)
})
diff --git a/docker/rootfs/etc/nginx/conf.d/dev.conf b/docker/rootfs/etc/nginx/conf.d/dev.conf
index b70db17..edbdec8 100644
--- a/docker/rootfs/etc/nginx/conf.d/dev.conf
+++ b/docker/rootfs/etc/nginx/conf.d/dev.conf
@@ -17,6 +17,9 @@ server {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:3000/;
+
+ proxy_read_timeout 15m;
+ proxy_send_timeout 15m;
}
location / {
diff --git a/docker/rootfs/etc/nginx/conf.d/production.conf b/docker/rootfs/etc/nginx/conf.d/production.conf
index b632bce..877e51d 100644
--- a/docker/rootfs/etc/nginx/conf.d/production.conf
+++ b/docker/rootfs/etc/nginx/conf.d/production.conf
@@ -18,6 +18,9 @@ server {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:3000/;
+
+ proxy_read_timeout 15m;
+ proxy_send_timeout 15m;
}
location / {
diff --git a/frontend/js/app/api.js b/frontend/js/app/api.js
index 1d7b358..baa5cb1 100644
--- a/frontend/js/app/api.js
+++ b/frontend/js/app/api.js
@@ -586,7 +586,8 @@ module.exports = {
/**
* @param {Object} data
*/
- create: function (data, timeout = 180000) {
+ create: function (data) {
+ const timeout = 180000 + (data.meta.propagation_seconds ? Number(data.meta.propagation_seconds) * 1000 : 0);
return fetch('post', 'nginx/certificates', data, {timeout});
},
diff --git a/frontend/js/app/nginx/certificates/form.js b/frontend/js/app/nginx/certificates/form.js
index df38159..94b18a8 100644
--- a/frontend/js/app/nginx/certificates/form.js
+++ b/frontend/js/app/nginx/certificates/form.js
@@ -167,8 +167,7 @@ module.exports = Mn.View.extend({
}
})
.then(() => {
- const timeout = 180000 + (data.meta.propagation_seconds ? Number(data.meta.propagation_seconds) : 0);
- return App.Api.Nginx.Certificates.create(data, timeout);
+ return App.Api.Nginx.Certificates.create(data);
})
.then(result => {
view.model.set(result);
@@ -187,12 +186,13 @@ module.exports = Mn.View.extend({
});
})
.catch(err => {
- try{
- const error_message = JSON.parse(err.debug).debug.stack.join("\n");
- this.ui.le_error_info[0].innerHTML = ` ${err.message} ${error_message} `;
- } catch(e) {
- this.ui.le_error_info[0].innerHTML = ` ${err.message} `;
+ let more_info = '';
+ if(err.code === 500){
+ try{
+ more_info = JSON.parse(err.debug).debug.stack.join("\n");
+ } catch(e) {}
}
+ this.ui.le_error_info[0].innerHTML = `${err.message}${more_info !== '' ? ` ${more_info} `:''}`;
this.ui.le_error_info.show();
this.ui.le_error_info[0].scrollIntoView();
this.ui.loader_content.hide();
diff --git a/scripts/frontend-build b/scripts/frontend-build
index 506a334..45c6d59 100755
--- a/scripts/frontend-build
+++ b/scripts/frontend-build
@@ -10,7 +10,7 @@ if hash docker 2>/dev/null; then
docker pull "${DOCKER_IMAGE}"
cd "${DIR}/.."
echo -e "${BLUE}❯ ${CYAN}Building Frontend ...${RESET}"
- docker run --rm -e CI=true -v "$(pwd)/frontend:/app/frontend" -w /app/frontend "$DOCKER_IMAGE" sh -c "yarn install && yarn build && yarn build && chown -R $(id -u):$(id -g) /app/frontend"
+ docker run --rm -e CI=true -v "$(pwd)/frontend:/app/frontend" -v "$(pwd)/global:/app/global" -w /app/frontend "$DOCKER_IMAGE" sh -c "yarn install && yarn build && yarn build && chown -R $(id -u):$(id -g) /app/frontend"
echo -e "${BLUE}❯ ${GREEN}Building Frontend Complete${RESET}"
else
echo -e "${RED}❯ docker command is not available${RESET}"
From 867fe1322bdca87929f6e74196d24605f2b170e8 Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Thu, 8 Oct 2020 13:38:20 +0200
Subject: [PATCH 09/13] Unifies directory structure in dev and prod containers
---
backend/config/sqlite-test-db.json | 2 +-
docker/docker-compose.dev.yml | 4 +++-
docker/rootfs/etc/services.d/manager/run | 2 +-
scripts/test-dev | 2 +-
4 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/backend/config/sqlite-test-db.json b/backend/config/sqlite-test-db.json
index 2806121..ad54886 100644
--- a/backend/config/sqlite-test-db.json
+++ b/backend/config/sqlite-test-db.json
@@ -4,7 +4,7 @@
"knex": {
"client": "sqlite3",
"connection": {
- "filename": "/app/backend/config/mydb.sqlite"
+ "filename": "/app/config/mydb.sqlite"
},
"pool": {
"min": 0,
diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml
index 24f2ee1..5668dbd 100644
--- a/docker/docker-compose.dev.yml
+++ b/docker/docker-compose.dev.yml
@@ -21,7 +21,9 @@ services:
volumes:
- npm_data:/data
- le_data:/etc/letsencrypt
- - ..:/app
+ - ../backend:/app
+ - ../frontend:/app/frontend
+ - ../global:/app/global
depends_on:
- db
working_dir: /app
diff --git a/docker/rootfs/etc/services.d/manager/run b/docker/rootfs/etc/services.d/manager/run
index 3ea1a17..ba0fb05 100755
--- a/docker/rootfs/etc/services.d/manager/run
+++ b/docker/rootfs/etc/services.d/manager/run
@@ -5,7 +5,7 @@ mkdir -p /data/letsencrypt-acme-challenge
cd /app || echo
if [ "$DEVELOPMENT" == "true" ]; then
- cd /app/backend || exit 1
+ cd /app || exit 1
yarn install
node --max_old_space_size=250 --abort_on_uncaught_exception node_modules/nodemon/bin/nodemon.js
else
diff --git a/scripts/test-dev b/scripts/test-dev
index eb5c5bd..f75527b 100755
--- a/scripts/test-dev
+++ b/scripts/test-dev
@@ -7,7 +7,7 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if hash docker-compose 2>/dev/null; then
cd "${DIR}/.."
echo -e "${BLUE}❯ ${CYAN}Testing Dev Stack ...${RESET}"
- docker-compose exec -T npm bash -c "cd /app/backend && task test"
+ docker-compose exec -T npm bash -c "cd /app && task test"
else
echo -e "${RED}❯ docker-compose command is not available${RESET}"
fi
From 3fec135fe5ef3cdfeb0090533ba737aa78fc329b Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Thu, 8 Oct 2020 14:23:21 +0200
Subject: [PATCH 10/13] Fixes ESlint formatting errors
---
backend/internal/certificate.js | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js
index 641b494..98e5274 100644
--- a/backend/internal/certificate.js
+++ b/backend/internal/certificate.js
@@ -782,15 +782,15 @@ const internalCertificate = {
requestLetsEncryptSslWithDnsChallenge: (certificate) => {
const dns_plugin = dns_plugins[certificate.meta.dns_provider];
- if(!dns_plugin){
- throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`)
+ if (!dns_plugin) {
+ throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`);
}
logger.info(`Requesting Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
- const credentials_loc = `/etc/letsencrypt/credentials-${certificate.id}`;
- const credentials_cmd = `echo '${certificate.meta.dns_provider_credentials.replace("'", "\'")}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'`;
- const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
+ const credentials_loc = '/etc/letsencrypt/credentials-' + certificate.id;
+ const credentials_cmd = 'echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'';
+ const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
const main_cmd =
certbot_command + ' certonly --non-interactive ' +
@@ -802,8 +802,8 @@ const internalCertificate = {
'--' + dns_plugin.full_plugin_name + '-credentials "' + credentials_loc + '"' +
(
certificate.meta.propagation_seconds !== undefined
- ? ' --' + dns_plugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
- : ''
+ ? ' --' + dns_plugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
+ : ''
) +
(le_staging ? ' --staging' : '');
@@ -904,15 +904,15 @@ const internalCertificate = {
renewLetsEncryptSslWithDnsChallenge: (certificate) => {
const dns_plugin = dns_plugins[certificate.meta.dns_provider];
- if(!dns_plugin){
- throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`)
+ if (!dns_plugin) {
+ throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`);
}
logger.info(`Renewing Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
- const credentials_loc = `/etc/letsencrypt/credentials-${certificate.id}`;
- const credentials_cmd = `echo '${certificate.meta.dns_provider_credentials.replace("'", "\'")}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'`;
- const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
+ const credentials_loc = '/etc/letsencrypt/credentials-' + certificate.id;
+ const credentials_cmd = 'echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'';
+ const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
const main_cmd =
certbot_command + ' renew --non-interactive ' +
From 07e78aec482125482da9f668669d2614872cf3b5 Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Thu, 8 Oct 2020 15:30:13 +0200
Subject: [PATCH 11/13] Adds error stack information in prod environment for
certificates
---
backend/app.js | 2 +-
frontend/js/app/nginx/certificates/form.js | 2 +-
frontend/js/app/nginx/dead/form.js | 2 +-
frontend/js/app/nginx/proxy/form.js | 2 +-
frontend/js/app/nginx/redirection/form.js | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/backend/app.js b/backend/app.js
index fc39e10..33ffacc 100644
--- a/backend/app.js
+++ b/backend/app.js
@@ -66,7 +66,7 @@ app.use(function (err, req, res, next) {
}
};
- if (process.env.NODE_ENV === 'development') {
+ if (process.env.NODE_ENV === 'development' || (req.baseUrl + req.path).includes('nginx/certificates')) {
payload.debug = {
stack: typeof err.stack !== 'undefined' && err.stack ? err.stack.split('\n') : null,
previous: err.previous
diff --git a/frontend/js/app/nginx/certificates/form.js b/frontend/js/app/nginx/certificates/form.js
index 94b18a8..677ba9a 100644
--- a/frontend/js/app/nginx/certificates/form.js
+++ b/frontend/js/app/nginx/certificates/form.js
@@ -187,7 +187,7 @@ module.exports = Mn.View.extend({
})
.catch(err => {
let more_info = '';
- if(err.code === 500){
+ if(err.code === 500 && err.debug){
try{
more_info = JSON.parse(err.debug).debug.stack.join("\n");
} catch(e) {}
diff --git a/frontend/js/app/nginx/dead/form.js b/frontend/js/app/nginx/dead/form.js
index a39038b..8f6774f 100644
--- a/frontend/js/app/nginx/dead/form.js
+++ b/frontend/js/app/nginx/dead/form.js
@@ -193,7 +193,7 @@ module.exports = Mn.View.extend({
})
.catch(err => {
let more_info = '';
- if(err.code === 500){
+ if(err.code === 500 && err.debug){
try{
more_info = JSON.parse(err.debug).debug.stack.join("\n");
} catch(e) {}
diff --git a/frontend/js/app/nginx/proxy/form.js b/frontend/js/app/nginx/proxy/form.js
index ec76987..8802b95 100644
--- a/frontend/js/app/nginx/proxy/form.js
+++ b/frontend/js/app/nginx/proxy/form.js
@@ -228,7 +228,7 @@ module.exports = Mn.View.extend({
})
.catch(err => {
let more_info = '';
- if(err.code === 500){
+ if(err.code === 500 && err.debug){
try{
more_info = JSON.parse(err.debug).debug.stack.join("\n");
} catch(e) {}
diff --git a/frontend/js/app/nginx/redirection/form.js b/frontend/js/app/nginx/redirection/form.js
index 6fa3693..1f81fee 100644
--- a/frontend/js/app/nginx/redirection/form.js
+++ b/frontend/js/app/nginx/redirection/form.js
@@ -195,7 +195,7 @@ module.exports = Mn.View.extend({
})
.catch(err => {
let more_info = '';
- if(err.code === 500){
+ if(err.code === 500 && err.debug){
try{
more_info = JSON.parse(err.debug).debug.stack.join("\n");
} catch(e) {}
From 049e4249570fe629b0ddf46ca2bccde82e48a392 Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Wed, 14 Oct 2020 09:20:52 +0200
Subject: [PATCH 12/13] Adds special case for Route53
---
backend/internal/certificate.js | 23 ++++++++++++++++++++---
global/certbot-dns-plugins.js | 4 +++-
2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js
index 98e5274..06b0990 100644
--- a/backend/internal/certificate.js
+++ b/backend/internal/certificate.js
@@ -792,20 +792,32 @@ const internalCertificate = {
const credentials_cmd = 'echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'';
const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
- const main_cmd =
+ // Whether the plugin has a -- -credentials argument
+ const has_config_arg = certificate.meta.dns_provider !== 'route53';
+
+ let main_cmd =
certbot_command + ' certonly --non-interactive ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--agree-tos ' +
'--email "' + certificate.meta.letsencrypt_email + '" ' +
'--domains "' + certificate.domain_names.join(',') + '" ' +
'--authenticator ' + dns_plugin.full_plugin_name + ' ' +
- '--' + dns_plugin.full_plugin_name + '-credentials "' + credentials_loc + '"' +
+ (
+ has_config_arg
+ ? '--' + dns_plugin.full_plugin_name + '-credentials "' + credentials_loc + '"'
+ : ''
+ ) +
(
certificate.meta.propagation_seconds !== undefined
? ' --' + dns_plugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
: ''
) +
(le_staging ? ' --staging' : '');
+
+ // Prepend the path to the credentials file as an environment variable
+ if (certificate.meta.dns_provider === 'route53') {
+ main_cmd = 'AWS_CONFIG_FILE=\'' + credentials_loc + '\' ' + main_cmd
+ }
const teardown_cmd = `rm '${credentials_loc}'`;
@@ -914,12 +926,17 @@ const internalCertificate = {
const credentials_cmd = 'echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'';
const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
- const main_cmd =
+ let main_cmd =
certbot_command + ' renew --non-interactive ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--disable-hook-validation' +
(le_staging ? ' --staging' : '');
+ // Prepend the path to the credentials file as an environment variable
+ if (certificate.meta.dns_provider === 'route53') {
+ main_cmd = 'AWS_CONFIG_FILE=\'' + credentials_loc + '\' ' + main_cmd
+ }
+
const teardown_cmd = `rm '${credentials_loc}'`;
if (debug_mode) {
diff --git a/global/certbot-dns-plugins.js b/global/certbot-dns-plugins.js
index a0a5c9a..724a339 100644
--- a/global/certbot-dns-plugins.js
+++ b/global/certbot-dns-plugins.js
@@ -235,7 +235,9 @@ dns_rfc2136_algorithm = HMAC-SHA512`,
display_name: "Route 53 (Amazon)",
package_name: "certbot-dns-route53",
package_version: "1.8.0",
- credentials: false,
+ credentials: `[default]
+aws_access_key_id=AKIAIOSFODNN7EXAMPLE
+aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,
full_plugin_name: "dns-route53",
},
//####################################################//
From ac9f05230981f13beb688e6ea19c61c45c91fea0 Mon Sep 17 00:00:00 2001
From: chaptergy <26956711+chaptergy@users.noreply.github.com>
Date: Wed, 14 Oct 2020 09:55:45 +0200
Subject: [PATCH 13/13] Fixes linting errors
---
backend/internal/certificate.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js
index 06b0990..613c837 100644
--- a/backend/internal/certificate.js
+++ b/backend/internal/certificate.js
@@ -814,10 +814,10 @@ const internalCertificate = {
) +
(le_staging ? ' --staging' : '');
- // Prepend the path to the credentials file as an environment variable
- if (certificate.meta.dns_provider === 'route53') {
- main_cmd = 'AWS_CONFIG_FILE=\'' + credentials_loc + '\' ' + main_cmd
- }
+ // Prepend the path to the credentials file as an environment variable
+ if (certificate.meta.dns_provider === 'route53') {
+ main_cmd = 'AWS_CONFIG_FILE=\'' + credentials_loc + '\' ' + main_cmd;
+ }
const teardown_cmd = `rm '${credentials_loc}'`;
@@ -934,7 +934,7 @@ const internalCertificate = {
// Prepend the path to the credentials file as an environment variable
if (certificate.meta.dns_provider === 'route53') {
- main_cmd = 'AWS_CONFIG_FILE=\'' + credentials_loc + '\' ' + main_cmd
+ main_cmd = 'AWS_CONFIG_FILE=\'' + credentials_loc + '\' ' + main_cmd;
}
const teardown_cmd = `rm '${credentials_loc}'`;
|