From f63441921f00e6e3786784139be4cac87400ff6c Mon Sep 17 00:00:00 2001 From: chaptergy Date: Tue, 12 Oct 2021 16:11:47 +0200 Subject: [PATCH 001/517] Sets the cert chain to prefer ISRG Root X1 --- docker/rootfs/etc/letsencrypt.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/rootfs/etc/letsencrypt.ini b/docker/rootfs/etc/letsencrypt.ini index ccb2f0b31..aae53b902 100644 --- a/docker/rootfs/etc/letsencrypt.ini +++ b/docker/rootfs/etc/letsencrypt.ini @@ -3,3 +3,4 @@ non-interactive = True webroot-path = /data/letsencrypt-acme-challenge key-type = ecdsa elliptic-curve = secp384r1 +preferred-chain = ISRG Root X1 From 4e3c7749af855fd8501e3b61779777478d09b5cf Mon Sep 17 00:00:00 2001 From: chaptergy Date: Tue, 12 Oct 2021 16:18:11 +0200 Subject: [PATCH 002/517] Removes sorting of domain names when creating a certificate --- backend/internal/certificate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index 7ec2a4e01..401c5604a 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -114,7 +114,7 @@ const internalCertificate = { data.owner_user_id = access.token.getUserId(1); if (data.provider === 'letsencrypt') { - data.nice_name = data.domain_names.sort().join(', '); + data.nice_name = data.domain_names.join(', '); } return certificateModel From bf7b659e89a918829c130c2ba2ff636936a8dda8 Mon Sep 17 00:00:00 2001 From: chaptergy Date: Sun, 17 Oct 2021 19:15:35 +0200 Subject: [PATCH 003/517] Adds cache busting to js bundles as well --- frontend/webpack.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index df0f1c14c..01a09dab8 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -13,8 +13,8 @@ module.exports = { }, output: { path: path.resolve(__dirname, 'dist'), - filename: 'js/[name].bundle.js', - chunkFilename: 'js/[name].bundle.[id].js', + filename: `js/[name].bundle.js?v=${PACKAGE.version}`, + chunkFilename: `js/[name].bundle.[id].js?v=${PACKAGE.version}`, publicPath: '/' }, resolve: { From 8ae2de2f490d75a4c9586526d67eaa5af0cc5141 Mon Sep 17 00:00:00 2001 From: Julian Reinhardt Date: Wed, 20 Oct 2021 18:08:11 +0200 Subject: [PATCH 004/517] Updates certbot-dns-ionos to newest version --- global/certbot-dns-plugins.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/global/certbot-dns-plugins.js b/global/certbot-dns-plugins.js index e7c599120..4767849f7 100644 --- a/global/certbot-dns-plugins.js +++ b/global/certbot-dns-plugins.js @@ -275,12 +275,12 @@ certbot_dns_inwx:dns_inwx_shared_secret = your_shared_secret optional`, ionos: { display_name: 'IONOS', package_name: 'certbot-dns-ionos', - version_requirement: '~=0.0.7', + version_requirement: '==2021.9.20.post1', dependencies: '', - credentials: `certbot_dns_ionos:dns_ionos_prefix = myapikeyprefix -certbot_dns_ionos:dns_ionos_secret = verysecureapikeysecret -certbot_dns_ionos:dns_ionos_endpoint = https://api.hosting.ionos.com`, - full_plugin_name: 'certbot-dns-ionos:dns-ionos', + credentials: `dns_ionos_prefix = myapikeyprefix +dns_ionos_secret = verysecureapikeysecret +dns_ionos_endpoint = https://api.hosting.ionos.com`, + full_plugin_name: 'dns-ionos', }, //####################################################// ispconfig: { From 97909830f5532251e77ef0e206b8dd9bc8b78773 Mon Sep 17 00:00:00 2001 From: Julian Reinhardt Date: Wed, 20 Oct 2021 18:16:54 +0200 Subject: [PATCH 005/517] Removes dns plugin prefixes --- global/certbot-dns-plugins.js | 124 ++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 60 deletions(-) diff --git a/global/certbot-dns-plugins.js b/global/certbot-dns-plugins.js index 4767849f7..964c2f0b0 100644 --- a/global/certbot-dns-plugins.js +++ b/global/certbot-dns-plugins.js @@ -12,7 +12,7 @@ * version_requirement: "Optional package version requirements (e.g. ==1.3 or >=1.2,<2.0, see https://www.python.org/dev/peps/pep-0440/#version-specifiers)", * dependencies: "Additional dependencies, space separated (as you would pass it to pip install)", * 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'", + * full_plugin_name: "The full plugin name as used in the commandline with certbot, e.g. 'dns-njalla'", * }, * ... * } @@ -26,18 +26,18 @@ module.exports = { package_name: 'certbot-dns-acmedns', version_requirement: '~=0.1.0', dependencies: '', - credentials: `certbot_dns_acmedns:dns_acmedns_api_url = http://acmedns-server/ -certbot_dns_acmedns:dns_acmedns_registration_file = /data/acme-registration.json`, - full_plugin_name: 'certbot-dns-acmedns:dns-acmedns', + credentials: `dns_acmedns_api_url = http://acmedns-server/ +dns_acmedns_registration_file = /data/acme-registration.json`, + full_plugin_name: 'dns-acmedns', }, aliyun: { display_name: 'Aliyun', package_name: 'certbot-dns-aliyun', version_requirement: '~=0.38.1', dependencies: '', - credentials: `certbot_dns_aliyun:dns_aliyun_access_key = 12345678 -certbot_dns_aliyun:dns_aliyun_access_key_secret = 1234567890abcdef1234567890abcdef`, - full_plugin_name: 'certbot-dns-aliyun:dns-aliyun', + credentials: `dns_aliyun_access_key = 12345678 +dns_aliyun_access_key_secret = 1234567890abcdef1234567890abcdef`, + full_plugin_name: 'dns-aliyun', }, //####################################################// azure: { @@ -107,9 +107,9 @@ dns_cloudxns_secret_key = 1122334455667788`, package_name: 'certbot-dns-corenetworks', version_requirement: '~=0.1.4', dependencies: '', - credentials: `certbot_dns_corenetworks:dns_corenetworks_username = asaHB12r -certbot_dns_corenetworks:dns_corenetworks_password = secure_password`, - full_plugin_name: 'certbot-dns-corenetworks:dns-corenetworks', + credentials: `dns_corenetworks_username = asaHB12r +dns_corenetworks_password = secure_password`, + full_plugin_name: 'dns-corenetworks', }, //####################################################// cpanel: { @@ -117,10 +117,10 @@ certbot_dns_corenetworks:dns_corenetworks_password = secure_password`, package_name: 'certbot-dns-cpanel', version_requirement: '~=0.2.2', dependencies: '', - 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', + credentials: `cpanel_url = https://cpanel.example.com:2083 +cpanel_username = user +cpanel_password = hunter2`, + full_plugin_name: 'cpanel', }, //####################################################// desec: { @@ -128,9 +128,9 @@ certbot_dns_cpanel:cpanel_password = hunter2`, package_name: 'certbot-dns-desec', version_requirement: '~=0.3.0', dependencies: '', - credentials: `certbot_dns_desec:dns_desec_token = YOUR_DESEC_API_TOKEN -certbot_dns_desec:dns_desec_endpoint = https://desec.io/api/v1/`, - full_plugin_name: 'certbot-dns-desec:dns-desec', + credentials: `dns_desec_token = YOUR_DESEC_API_TOKEN +dns_desec_endpoint = https://desec.io/api/v1/`, + full_plugin_name: 'dns-desec', }, //####################################################// duckdns: { @@ -186,9 +186,9 @@ dns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55`, package_name: 'certbot-dns-dnspod', version_requirement: '~=0.1.0', dependencies: '', - 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', + credentials: `dns_dnspod_email = "DNSPOD-API-REQUIRES-A-VALID-EMAIL" +dns_dnspod_api_token = "DNSPOD-API-TOKEN"`, + full_plugin_name: 'dns-dnspod', }, //####################################################// dynu: { @@ -196,8 +196,8 @@ certbot_dns_dnspod:dns_dnspod_api_token = "DNSPOD-API-TOKEN"`, package_name: 'certbot-dns-dynu', version_requirement: '~=0.0.1', dependencies: '', - credentials: 'certbot_dns_dynu:dns_dynu_auth_token = YOUR_DYNU_AUTH_TOKEN', - full_plugin_name: 'certbot-dns-dynu:dns-dynu', + credentials: 'dns_dynu_auth_token = YOUR_DYNU_AUTH_TOKEN', + full_plugin_name: 'dns-dynu', }, //####################################################// eurodns: { @@ -208,16 +208,20 @@ certbot_dns_dnspod:dns_dnspod_api_token = "DNSPOD-API-TOKEN"`, credentials: `dns_eurodns_applicationId = myuser dns_eurodns_apiKey = mysecretpassword dns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy`, - full_plugin_name: 'certbot-dns-eurodns:dns-eurodns', + full_plugin_name: 'dns-eurodns', }, //####################################################// gandi: { display_name: 'Gandi Live DNS', package_name: 'certbot_plugin_gandi', - version_requirement: '~=1.2.5', + version_requirement: '~=1.3.2', dependencies: '', - credentials: 'certbot_plugin_gandi:dns_api_key = APIKEY', - full_plugin_name: 'certbot-plugin-gandi:dns', + credentials: `# live dns v5 api key + dns_gandi_api_key=APIKEY + + # optional organization id, remove it if not used + dns_gandi_sharing_id=SHARINGID`, + full_plugin_name: 'dns-gandi', }, //####################################################// godaddy: { @@ -247,8 +251,8 @@ dns_godaddy_key = abcdef0123456789abcdef01234567abcdef0123`, package_name: 'certbot-dns-hetzner', version_requirement: '~=1.0.4', dependencies: '', - credentials: 'certbot_dns_hetzner:dns_hetzner_api_token = 0123456789abcdef0123456789abcdef', - full_plugin_name: 'certbot-dns-hetzner:dns-hetzner', + credentials: 'dns_hetzner_api_token = 0123456789abcdef0123456789abcdef', + full_plugin_name: 'dns-hetzner', }, //####################################################// infomaniak: { @@ -256,8 +260,8 @@ dns_godaddy_key = abcdef0123456789abcdef01234567abcdef0123`, package_name: 'certbot-dns-infomaniak', version_requirement: '~=0.1.12', dependencies: '', - credentials: 'certbot_dns_infomaniak:dns_infomaniak_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - full_plugin_name: 'certbot-dns-infomaniak:dns-infomaniak', + credentials: 'dns_infomaniak_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', + full_plugin_name: 'dns-infomaniak', }, //####################################################// inwx: { @@ -265,11 +269,11 @@ dns_godaddy_key = abcdef0123456789abcdef01234567abcdef0123`, package_name: 'certbot-dns-inwx', version_requirement: '~=2.1.2', dependencies: '', - 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', + credentials: `dns_inwx_url = https://api.domrobot.com/xmlrpc/ +dns_inwx_username = your_username +dns_inwx_password = your_password +dns_inwx_shared_secret = your_shared_secret optional`, + full_plugin_name: 'dns-inwx', }, //####################################################// ionos: { @@ -288,10 +292,10 @@ dns_ionos_endpoint = https://api.hosting.ionos.com`, package_name: 'certbot-dns-ispconfig', version_requirement: '~=0.2.0', dependencies: '', - 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', + credentials: `dns_ispconfig_username = myremoteuser +dns_ispconfig_password = verysecureremoteuserpassword +dns_ispconfig_endpoint = https://localhost:8080`, + full_plugin_name: 'dns-ispconfig', }, //####################################################// isset: { @@ -299,19 +303,19 @@ certbot_dns_ispconfig:dns_ispconfig_endpoint = https://localhost:8080`, package_name: 'certbot-dns-isset', version_requirement: '~=0.0.3', dependencies: '', - 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', + credentials: `dns_isset_endpoint="https://customer.isset.net/api" +dns_isset_token=""`, + full_plugin_name: 'dns-isset', }, joker: { display_name: 'Joker', package_name: 'certbot-dns-joker', version_requirement: '~=1.1.0', dependencies: '', - credentials: `certbot_dns_joker:dns_joker_username = -certbot_dns_joker:dns_joker_password = -certbot_dns_joker:dns_joker_domain = `, - full_plugin_name: 'certbot-dns-joker:dns-joker', + credentials: `dns_joker_username = +dns_joker_password = +dns_joker_domain = `, + full_plugin_name: 'dns-joker', }, //####################################################// linode: { @@ -349,10 +353,10 @@ dns_luadns_token = 0123456789abcdef0123456789abcdef`, package_name: 'certbot-dns-netcup', version_requirement: '~=1.0.0', dependencies: '', - credentials: `certbot_dns_netcup:dns_netcup_customer_id = 123456 -certbot_dns_netcup:dns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567 -certbot_dns_netcup:dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`, - full_plugin_name: 'certbot-dns-netcup:dns-netcup', + credentials: `dns_netcup_customer_id = 123456 +dns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567 +dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`, + full_plugin_name: 'dns-netcup', }, //####################################################// njalla: { @@ -360,8 +364,8 @@ certbot_dns_netcup:dns_netcup_api_password = abcdef0123456789abcdef01234567abcde package_name: 'certbot-dns-njalla', version_requirement: '~=1.0.0', dependencies: '', - credentials: 'certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567', - full_plugin_name: 'certbot-dns-njalla:dns-njalla', + credentials: 'dns_njalla_token = 0123456789abcdef0123456789abcdef01234567', + full_plugin_name: 'dns-njalla', }, //####################################################// nsone: { @@ -414,9 +418,9 @@ dns_porkbun_secret=your-porkbun-api-secret`, package_name: 'certbot-dns-powerdns', version_requirement: '~=0.2.0', dependencies: '', - 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', + credentials: `dns_powerdns_api_url = https://api.mypowerdns.example.org +dns_powerdns_api_key = AbCbASsd!@34`, + full_plugin_name: 'dns-powerdns', }, //####################################################// regru: { @@ -463,9 +467,9 @@ aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`, package_name: 'certbot-dns-transip', version_requirement: '~=0.3.3', dependencies: '', - credentials: `certbot_dns_transip:dns_transip_username = my_username -certbot_dns_transip:dns_transip_key_file = /etc/letsencrypt/transip-rsa.key`, - full_plugin_name: 'certbot-dns-transip:dns-transip', + credentials: `dns_transip_username = my_username +dns_transip_key_file = /etc/letsencrypt/transip-rsa.key`, + full_plugin_name: 'dns-transip', }, //####################################################// vultr: { @@ -473,7 +477,7 @@ certbot_dns_transip:dns_transip_key_file = /etc/letsencrypt/transip-rsa.key`, package_name: 'certbot-dns-vultr', version_requirement: '~=1.0.3', dependencies: '', - credentials: 'certbot_dns_vultr:dns_vultr_key = YOUR_VULTR_API_KEY', - full_plugin_name: 'certbot-dns-vultr:dns-vultr', + credentials: 'dns_vultr_key = YOUR_VULTR_API_KEY', + full_plugin_name: 'dns-vultr', }, }; From b833044cea973adc0d8e700eab5672d720b8be80 Mon Sep 17 00:00:00 2001 From: Julian Reinhardt Date: Wed, 20 Oct 2021 18:38:21 +0200 Subject: [PATCH 006/517] Fixes formatting --- global/certbot-dns-plugins.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/global/certbot-dns-plugins.js b/global/certbot-dns-plugins.js index 964c2f0b0..802bcd5d5 100644 --- a/global/certbot-dns-plugins.js +++ b/global/certbot-dns-plugins.js @@ -217,11 +217,11 @@ dns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy`, version_requirement: '~=1.3.2', dependencies: '', credentials: `# live dns v5 api key - dns_gandi_api_key=APIKEY - - # optional organization id, remove it if not used - dns_gandi_sharing_id=SHARINGID`, - full_plugin_name: 'dns-gandi', +dns_gandi_api_key=APIKEY + +# optional organization id, remove it if not used +dns_gandi_sharing_id=SHARINGID`, + full_plugin_name: 'dns-gandi', }, //####################################################// godaddy: { From 63601006115659b538addb809d910bc9bdaf81e9 Mon Sep 17 00:00:00 2001 From: Julian Reinhardt Date: Sun, 24 Oct 2021 22:14:59 +0200 Subject: [PATCH 007/517] Adds Webbsupport.sk dns plugin --- global/certbot-dns-plugins.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/global/certbot-dns-plugins.js b/global/certbot-dns-plugins.js index e7c599120..ecd23e4b8 100644 --- a/global/certbot-dns-plugins.js +++ b/global/certbot-dns-plugins.js @@ -476,4 +476,15 @@ certbot_dns_transip:dns_transip_key_file = /etc/letsencrypt/transip-rsa.key`, credentials: 'certbot_dns_vultr:dns_vultr_key = YOUR_VULTR_API_KEY', full_plugin_name: 'certbot-dns-vultr:dns-vultr', }, + //####################################################// + websupportsk: { + display_name: 'Websupport.sk', + package_name: 'certbot-dns-websupportsk', + version_requirement: '~=0.1.6', + dependencies: '', + credentials: `dns_websupportsk_api_key = +dns_websupportsk_secret = +dns_websupportsk_domain = example.com`, + full_plugin_name: 'dns-websupportsk', + }, }; From 650ae61c4333a932b063db1e187115e2b338fdd1 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Mon, 25 Oct 2021 11:35:39 +1000 Subject: [PATCH 008/517] Version bump --- .version | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.version b/.version index a44d1506b..089040982 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.9.9 \ No newline at end of file +2.9.10 diff --git a/README.md b/README.md index e68d4462c..eec9a7b79 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@



- + From 87731a8b5c7ee698c71bbe92aea50494b127daf7 Mon Sep 17 00:00:00 2001 From: Julian Reinhardt Date: Mon, 25 Oct 2021 14:27:37 +0200 Subject: [PATCH 009/517] Revert "Utilise variable for custom locations proxy_pass" This reverts commit 6c1ae77a2a40283c5444c2f7e0a7c8227aeecbd2. --- backend/templates/_location.conf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/templates/_location.conf b/backend/templates/_location.conf index 7d707009f..5a7a6abeb 100644 --- a/backend/templates/_location.conf +++ b/backend/templates/_location.conf @@ -1,11 +1,10 @@ location {{ path }} { - set $upstream {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }}; proxy_set_header Host $host; proxy_set_header X-Forwarded-Scheme $scheme; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr; - proxy_pass $upstream; + proxy_pass {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }}; {% if access_list_id > 0 %} {% if access_list.items.length > 0 %} From bbde7a108aa1ef7353a8c314fdddd5e127fc81a4 Mon Sep 17 00:00:00 2001 From: Julian Reinhardt Date: Mon, 25 Oct 2021 14:48:22 +0200 Subject: [PATCH 010/517] Use variable with full uri in proxy pass --- backend/templates/_location.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/templates/_location.conf b/backend/templates/_location.conf index 5a7a6abeb..2b8579333 100644 --- a/backend/templates/_location.conf +++ b/backend/templates/_location.conf @@ -1,10 +1,11 @@ location {{ path }} { + set $upstream {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }}$request_uri; proxy_set_header Host $host; proxy_set_header X-Forwarded-Scheme $scheme; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr; - proxy_pass {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }}; + proxy_pass $upstream; {% if access_list_id > 0 %} {% if access_list.items.length > 0 %} From ca59e585d81d953b79c117eeb3c61743ad4ac85d Mon Sep 17 00:00:00 2001 From: Julian Reinhardt Date: Mon, 25 Oct 2021 14:58:02 +0200 Subject: [PATCH 011/517] Uses variable in proxy_pass for normal proxy hosts --- docker/rootfs/etc/nginx/conf.d/include/proxy.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/rootfs/etc/nginx/conf.d/include/proxy.conf b/docker/rootfs/etc/nginx/conf.d/include/proxy.conf index c0dce0613..1fda72b90 100644 --- a/docker/rootfs/etc/nginx/conf.d/include/proxy.conf +++ b/docker/rootfs/etc/nginx/conf.d/include/proxy.conf @@ -1,8 +1,9 @@ +set $upstream $forward_scheme://$server:$port$request_uri; add_header X-Served-By $host; proxy_set_header Host $host; proxy_set_header X-Forwarded-Scheme $scheme; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr; -proxy_pass $forward_scheme://$server:$port; +proxy_pass $upstream; From d0bfa082e04cb803aab27b9bf365b070be977900 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Wed, 27 Oct 2021 21:43:07 +1000 Subject: [PATCH 012/517] Bump version --- .version | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.version b/.version index 089040982..dd9ac7fe8 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.9.10 +2.9.11 diff --git a/README.md b/README.md index eec9a7b79..a86d51890 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@



- + From c55476b196242e6e75dc1ec0c708761b3c6404d6 Mon Sep 17 00:00:00 2001 From: Julian Reinhardt Date: Sun, 31 Oct 2021 00:19:18 +0200 Subject: [PATCH 013/517] Adds buttons to test availability of server from public internet --- backend/internal/certificate.js | 83 +++++++++++++++++++ backend/routes/api/nginx/certificates.js | 27 +++++- backend/schema/endpoints/certificates.json | 11 +++ frontend/js/app/api.js | 10 +++ frontend/js/app/controller.js | 13 +++ frontend/js/app/nginx/certificates/form.ejs | 8 ++ frontend/js/app/nginx/certificates/form.js | 27 +++++- .../js/app/nginx/certificates/list/item.ejs | 3 + .../js/app/nginx/certificates/list/item.js | 16 ++-- frontend/js/app/nginx/certificates/test.ejs | 15 ++++ frontend/js/app/nginx/certificates/test.js | 73 ++++++++++++++++ frontend/js/i18n/messages.json | 9 ++ 12 files changed, 288 insertions(+), 7 deletions(-) create mode 100644 frontend/js/app/nginx/certificates/test.ejs create mode 100644 frontend/js/app/nginx/certificates/test.js diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index 401c5604a..d8330b494 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -1,5 +1,6 @@ const _ = require('lodash'); const fs = require('fs'); +const https = require('https'); const tempWrite = require('temp-write'); const moment = require('moment'); const logger = require('../logger').ssl; @@ -15,6 +16,7 @@ const letsencryptConfig = '/etc/letsencrypt.ini'; const certbotCommand = 'certbot'; const archiver = require('archiver'); const path = require('path'); +const { isArray } = require('lodash'); function omissions() { return ['is_deleted']; @@ -1119,6 +1121,87 @@ const internalCertificate = { } else { return Promise.resolve(); } + }, + + testHttpsChallenge: async (access, domains) => { + await access.can('certificates:list'); + + if (!isArray(domains)) { + throw new error.InternalValidationError('Domains must be an array of strings'); + } + if (domains.length === 0) { + throw new error.InternalValidationError('No domains provided'); + } + + // Create a test challenge file + const testChallengeDir = '/data/letsencrypt-acme-challenge/.well-known/acme-challenge'; + const testChallengeFile = testChallengeDir + '/test-challenge'; + fs.mkdirSync(testChallengeDir, {recursive: true}); + fs.writeFileSync(testChallengeFile, 'Success', {encoding: 'utf8'}); + + async function performTestForDomain (domain) { + logger.info('Testing http challenge for ' + domain); + const url = `http://${domain}/.well-known/acme-challenge/test-challenge`; + const formBody = `method=G&url=${encodeURI(url)}&bodytype=T&requestbody=&headername=User-Agent&headervalue=None&locationid=1&ch=false&cc=false`; + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': Buffer.byteLength(formBody) + } + }; + + const result = await new Promise((resolve) => { + + const req = https.request('https://www.site24x7.com/tools/restapi-tester', options, function (res) { + let responseBody = ''; + + res.on('data', (chunk) => responseBody = responseBody + chunk); + res.on('end', function () { + const parsedBody = JSON.parse(responseBody + ''); + if (res.statusCode !== 200) { + logger.warn(`Failed to test HTTP challenge for domain ${domain}`, res); + resolve(undefined); + } + resolve(parsedBody); + }); + }); + + // Make sure to write the request body. + req.write(formBody); + req.end(); + req.on('error', function (e) { logger.warn(`Failed to test HTTP challenge for domain ${domain}`, e); + resolve(undefined); }); + }); + + if (!result) { + // Some error occurred while trying to get the data + return 'failed'; + } else if (`${result.responsecode}` === '200' && result.htmlresponse === 'Success') { + // Server exists and has responded with the correct data + return 'ok'; + } else if (`${result.responsecode}` === '404') { + // Server exists but responded with a 404 + return '404'; + } else if (`${result.responsecode}` === '0' || result.reason.toLowerCase() === 'host unavailable') { + // Server does not exist at domain + return 'no-host'; + } else { + // Other errors + return `other:${result.responsecode}`; + } + } + + const results = {}; + + for (const domain of domains){ + results[domain] = await performTestForDomain(domain); + } + + // Remove the test challenge file + fs.unlinkSync(testChallengeFile); + + return results; } }; diff --git a/backend/routes/api/nginx/certificates.js b/backend/routes/api/nginx/certificates.js index 32995c537..ad5b56336 100644 --- a/backend/routes/api/nginx/certificates.js +++ b/backend/routes/api/nginx/certificates.js @@ -68,6 +68,32 @@ router .catch(next); }); +/** + * Test HTTP challenge for domains + * + * /api/nginx/certificates/test-http + */ + router + .route('/test-http') + .options((req, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) + +/** + * GET /api/nginx/certificates/test-http + * + * Test HTTP challenge for domains + */ + .get((req, res, next) => { + internalCertificate.testHttpsChallenge(res.locals.access, JSON.parse(req.query.domains)) + .then((result) => { + res.status(200) + .send(result); + }) + .catch(next); + }); + /** * Specific certificate * @@ -209,7 +235,6 @@ router .catch(next); }); - /** * Download LE Certs * diff --git a/backend/schema/endpoints/certificates.json b/backend/schema/endpoints/certificates.json index 49fd6a7d2..955ca75c9 100644 --- a/backend/schema/endpoints/certificates.json +++ b/backend/schema/endpoints/certificates.json @@ -157,6 +157,17 @@ "targetSchema": { "type": "boolean" } + }, + { + "title": "Test HTTP Challenge", + "description": "Tests whether the HTTP challenge should work", + "href": "/nginx/certificates/{definitions.identity.example}/test-http", + "access": "private", + "method": "GET", + "rel": "info", + "http_header": { + "$ref": "../examples.json#/definitions/auth_header" + } } ] } diff --git a/frontend/js/app/api.js b/frontend/js/app/api.js index 2511a7895..6e33a6dca 100644 --- a/frontend/js/app/api.js +++ b/frontend/js/app/api.js @@ -685,6 +685,16 @@ module.exports = { return fetch('post', 'nginx/certificates/' + id + '/renew', undefined, {timeout}); }, + /** + * @param {Number} id + * @returns {Promise} + */ + testHttpChallenge: function (domains) { + return fetch('get', 'nginx/certificates/test-http?' + new URLSearchParams({ + domains: JSON.stringify(domains), + })); + }, + /** * @param {Number} id * @returns {Promise} diff --git a/frontend/js/app/controller.js b/frontend/js/app/controller.js index 902659be9..ccb2978a8 100644 --- a/frontend/js/app/controller.js +++ b/frontend/js/app/controller.js @@ -366,6 +366,19 @@ module.exports = { } }, + /** + * Certificate Test Reachability + * + * @param model + */ + showNginxCertificateTestReachability: function (model) { + if (Cache.User.isAdmin() || Cache.User.canManage('certificates')) { + require(['./main', './nginx/certificates/test'], function (App, View) { + App.UI.showModalDialog(new View({model: model})); + }); + } + }, + /** * Audit Log */ diff --git a/frontend/js/app/nginx/certificates/form.ejs b/frontend/js/app/nginx/certificates/form.ejs index c8b1369fb..7fc12785b 100644 --- a/frontend/js/app/nginx/certificates/form.ejs +++ b/frontend/js/app/nginx/certificates/form.ejs @@ -18,6 +18,14 @@

<%- i18n('ssl', 'hosts-warning') %>
+ +
+ +
+ + <%- i18n('certificates', 'reachability-info') %> +
+
diff --git a/frontend/js/app/nginx/certificates/form.js b/frontend/js/app/nginx/certificates/form.js index 65a54b69e..56b31cf2a 100644 --- a/frontend/js/app/nginx/certificates/form.js +++ b/frontend/js/app/nginx/certificates/form.js @@ -29,6 +29,8 @@ module.exports = Mn.View.extend({ non_loader_content: '.non-loader-content', le_error_info: '#le-error-info', domain_names: 'input[name="domain_names"]', + test_domains_container: '.test-domains-container', + test_domains_button: '.test-domains', buttons: '.modal-footer button', cancel: 'button.cancel', save: 'button.save', @@ -56,10 +58,12 @@ module.exports = Mn.View.extend({ this.ui.dns_provider_credentials.prop('required', 'required'); } this.ui.dns_challenge_content.show(); + this.ui.test_domains_container.hide(); } else { this.ui.dns_provider.prop('required', false); this.ui.dns_provider_credentials.prop('required', false); - this.ui.dns_challenge_content.hide(); + this.ui.dns_challenge_content.hide(); + this.ui.test_domains_container.show(); } }, @@ -205,6 +209,23 @@ module.exports = Mn.View.extend({ this.ui.non_loader_content.show(); }); }, + 'click @ui.test_domains_button': function (e) { + e.preventDefault(); + const domainNames = this.ui.domain_names[0].value.split(','); + if (domainNames && domainNames.length > 0) { + this.model.set('domain_names', domainNames); + this.model.set('back_to_add', true); + App.Controller.showNginxCertificateTestReachability(this.model); + } + }, + 'change @ui.domain_names': function(e){ + const domainNames = e.target.value.split(','); + if (domainNames && domainNames.length > 0) { + this.ui.test_domains_button.prop('disabled', false); + } else { + this.ui.test_domains_button.prop('disabled', true); + } + }, 'change @ui.other_certificate_key': function(e){ this.setFileName("other_certificate_key_label", e) }, @@ -257,6 +278,10 @@ module.exports = Mn.View.extend({ this.ui.credentials_file_content.hide(); this.ui.loader_content.hide(); this.ui.le_error_info.hide(); + const domainNames = this.ui.domain_names[0].value.split(','); + if (!domainNames || domainNames.length === 0 || (domainNames.length === 1 && domainNames[0] === "")) { + this.ui.test_domains_button.prop('disabled', true); + } }, initialize: function (options) { diff --git a/frontend/js/app/nginx/certificates/list/item.ejs b/frontend/js/app/nginx/certificates/list/item.ejs index 1a73605b4..bdeeecad0 100644 --- a/frontend/js/app/nginx/certificates/list/item.ejs +++ b/frontend/js/app/nginx/certificates/list/item.ejs @@ -42,6 +42,9 @@ <% if (provider === 'letsencrypt') { %> <%- i18n('certificates', 'force-renew') %> <%- i18n('certificates', 'download') %> + <% if (meta.dns_challenge === false) { %> + <%- i18n('certificates', 'test-reachability') %> + <% } %> <% } %> <%- i18n('str', 'delete') %> diff --git a/frontend/js/app/nginx/certificates/list/item.js b/frontend/js/app/nginx/certificates/list/item.js index ca167fae4..7fa1c6814 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('../../../../../../global/certbot-dns-plugins') +const dns_providers = require('../../../../../../global/certbot-dns-plugins'); module.exports = Mn.View.extend({ template: template, @@ -12,7 +12,8 @@ module.exports = Mn.View.extend({ host_link: '.host-link', renew: 'a.renew', delete: 'a.delete', - download: 'a.download' + download: 'a.download', + test: 'a.test' }, events: { @@ -31,11 +32,16 @@ module.exports = Mn.View.extend({ let win = window.open($(e.currentTarget).attr('rel'), '_blank'); win.focus(); }, - + 'click @ui.download': function (e) { e.preventDefault(); - App.Api.Nginx.Certificates.download(this.model.get('id')) - } + App.Api.Nginx.Certificates.download(this.model.get('id')); + }, + + 'click @ui.test': function (e) { + e.preventDefault(); + App.Controller.showNginxCertificateTestReachability(this.model); + }, }, templateContext: { diff --git a/frontend/js/app/nginx/certificates/test.ejs b/frontend/js/app/nginx/certificates/test.ejs new file mode 100644 index 000000000..c941a779b --- /dev/null +++ b/frontend/js/app/nginx/certificates/test.ejs @@ -0,0 +1,15 @@ + diff --git a/frontend/js/app/nginx/certificates/test.js b/frontend/js/app/nginx/certificates/test.js new file mode 100644 index 000000000..b29fd5eb7 --- /dev/null +++ b/frontend/js/app/nginx/certificates/test.js @@ -0,0 +1,73 @@ +const Mn = require('backbone.marionette'); +const App = require('../../main'); +const template = require('./test.ejs'); + +module.exports = Mn.View.extend({ + template: template, + className: 'modal-dialog', + + ui: { + waiting: '.waiting', + error: '.error', + success: '.success', + close: 'button.cancel' + }, + + events: { + 'click @ui.close': function (e) { + e.preventDefault(); + if (this.model.get('back_to_add')) { + App.Controller.showNginxCertificateForm(this.model); + } else { + App.UI.closeModal(); + } + }, + }, + + onRender: function () { + this.ui.error.hide(); + this.ui.success.hide(); + + App.Api.Nginx.Certificates.testHttpChallenge(this.model.get('domain_names')) + .then((result) => { + let allOk = true; + let text = ''; + + for (const domain in result) { + const status = result[domain]; + if (status === 'ok') { + text += `

${domain}: ${App.i18n('certificates', 'reachability-ok')}

`; + } else { + allOk = false; + if (status === 'no-host') { + text += `

${domain}: ${App.i18n('certificates', 'reachability-not-resolved')}

`; + } else if (status === 'failed') { + text += `

${domain}: ${App.i18n('certificates', 'reachability-failed-to-check')}

`; + } else if (status === '404') { + text += `

${domain}: ${App.i18n('certificates', 'reachability-404')}

`; + } else if (status.startsWith('other:')) { + const code = status.substring(6); + text += `

${domain}: ${App.i18n('certificates', 'reachability-other', {code})}

`; + } else { + // This should never happen + text += `

${domain}: ?

`; + } + } + } + + this.ui.waiting.hide(); + if (allOk) { + this.ui.success.html(text).show(); + } else { + this.ui.error.html(text).show(); + } + this.ui.close.prop('disabled', false); + }) + .catch((e) => { + console.error(e); + this.ui.waiting.hide(); + this.ui.error.text(App.i18n('certificates', 'reachability-failed-to-reach-api')).show(); + this.ui.close.prop('disabled', false); + }); + } +}); diff --git a/frontend/js/i18n/messages.json b/frontend/js/i18n/messages.json index 1e00ef7ca..f231de52b 100644 --- a/frontend/js/i18n/messages.json +++ b/frontend/js/i18n/messages.json @@ -188,6 +188,15 @@ "other-certificate-key": "Certificate Key", "other-intermediate-certificate": "Intermediate Certificate", "force-renew": "Renew Now", + "test-reachability": "Test Server Reachability", + "reachability-title": "Test Server Reachability", + "reachability-info": "Test whether the domains are reachable from the public internet using Site24x7. This is not necessary when using the DNS Challenge.", + "reachability-failed-to-reach-api": "Communication with the API failed, is NPM running correctly?", + "reachability-failed-to-check": "Failed to check the reachability due to a communication error with site24x7.com.", + "reachability-ok": "Your server is reachable and creating certificates should be possible.", + "reachability-404": "There is a server found at this domain but it does not seem to be Nginx Proxy Manager. Please make sure your domain points to the IP where your NPM instance is running.", + "reachability-not-resolved": "There is no server available at this domain. Please make sure your domain exists and points to the IP where your NPM instance is running and if necessary port 80 is forwarded in your router.", + "reachability-other": "There is a server found at this domain but it returned an unexpected status code {code}. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running.", "download": "Download", "renew-title": "Renew Let'sEncrypt Certificate" }, From c86a1a50bd7bd03296eec3ce347884b912f08599 Mon Sep 17 00:00:00 2001 From: Julian Reinhardt Date: Sun, 31 Oct 2021 00:28:43 +0200 Subject: [PATCH 014/517] Fixes formatting --- backend/internal/certificate.js | 4 ++-- backend/routes/api/nginx/certificates.js | 28 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index d8330b494..d3bc8ff70 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -16,7 +16,7 @@ const letsencryptConfig = '/etc/letsencrypt.ini'; const certbotCommand = 'certbot'; const archiver = require('archiver'); const path = require('path'); -const { isArray } = require('lodash'); +const { isArray } = require('lodash'); function omissions() { return ['is_deleted']; @@ -1134,7 +1134,7 @@ const internalCertificate = { } // Create a test challenge file - const testChallengeDir = '/data/letsencrypt-acme-challenge/.well-known/acme-challenge'; + const testChallengeDir = '/data/letsencrypt-acme-challenge/.well-known/acme-challenge'; const testChallengeFile = testChallengeDir + '/test-challenge'; fs.mkdirSync(testChallengeDir, {recursive: true}); fs.writeFileSync(testChallengeFile, 'Success', {encoding: 'utf8'}); diff --git a/backend/routes/api/nginx/certificates.js b/backend/routes/api/nginx/certificates.js index ad5b56336..ffdfb515d 100644 --- a/backend/routes/api/nginx/certificates.js +++ b/backend/routes/api/nginx/certificates.js @@ -73,26 +73,26 @@ router * * /api/nginx/certificates/test-http */ - router - .route('/test-http') - .options((req, res) => { - res.sendStatus(204); - }) - .all(jwtdecode()) +router + .route('/test-http') + .options((req, res) => { + res.sendStatus(204); + }) + .all(jwtdecode()) /** * GET /api/nginx/certificates/test-http * * Test HTTP challenge for domains */ - .get((req, res, next) => { - internalCertificate.testHttpsChallenge(res.locals.access, JSON.parse(req.query.domains)) - .then((result) => { - res.status(200) - .send(result); - }) - .catch(next); - }); + .get((req, res, next) => { + internalCertificate.testHttpsChallenge(res.locals.access, JSON.parse(req.query.domains)) + .then((result) => { + res.status(200) + .send(result); + }) + .catch(next); + }); /** * Specific certificate From 9efe6cfb39e5a8a151343bb22130ffa33707a03f Mon Sep 17 00:00:00 2001 From: Julian Reinhardt Date: Sun, 31 Oct 2021 13:41:29 +0100 Subject: [PATCH 015/517] Minor fixes --- backend/internal/certificate.js | 5 ++++- frontend/js/app/nginx/certificates/test.ejs | 2 +- frontend/js/app/nginx/certificates/test.js | 2 ++ frontend/js/i18n/messages.json | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index d3bc8ff70..6161ce2d9 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -1180,10 +1180,13 @@ const internalCertificate = { } else if (`${result.responsecode}` === '200' && result.htmlresponse === 'Success') { // Server exists and has responded with the correct data return 'ok'; + } else if (`${result.responsecode}` === '200') { + // Server exists and has responded with the correct data + return 'wrong-data'; } else if (`${result.responsecode}` === '404') { // Server exists but responded with a 404 return '404'; - } else if (`${result.responsecode}` === '0' || result.reason.toLowerCase() === 'host unavailable') { + } else if (`${result.responsecode}` === '0' || (typeof result.reason === 'string' && result.reason.toLowerCase() === 'host unavailable')) { // Server does not exist at domain return 'no-host'; } else { diff --git a/frontend/js/app/nginx/certificates/test.ejs b/frontend/js/app/nginx/certificates/test.ejs index c941a779b..6661f625f 100644 --- a/frontend/js/app/nginx/certificates/test.ejs +++ b/frontend/js/app/nginx/certificates/test.ejs @@ -7,7 +7,7 @@ <%= i18n('str', 'please-wait') %>
- +