From b01817bc7ffa68fb07d69472fb9acfa1f9860c84 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Sun, 13 Oct 2024 21:54:58 +1000 Subject: [PATCH 001/137] Adds squid to dev/CI stacks - for testing forwarded ip address later --- docker/dev/squid.conf | 92 +++++++++++++++++++++++++++++++++++ docker/docker-compose.ci.yml | 13 +++++ docker/docker-compose.dev.yml | 17 ++++++- test/cypress/config/ci.js | 4 +- test/cypress/config/dev.js | 4 +- test/package.json | 4 +- 6 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 docker/dev/squid.conf diff --git a/docker/dev/squid.conf b/docker/dev/squid.conf new file mode 100644 index 000000000..cdd749f58 --- /dev/null +++ b/docker/dev/squid.conf @@ -0,0 +1,92 @@ +# WELCOME TO SQUID 6.6 +# ---------------------------- +# +# This is the documentation for the Squid configuration file. +# This documentation can also be found online at: +# http://www.squid-cache.org/Doc/config/ +# +# You may wish to look at the Squid home page and wiki for the +# FAQ and other documentation: +# http://www.squid-cache.org/ +# https://wiki.squid-cache.org/SquidFaq +# https://wiki.squid-cache.org/ConfigExamples +# + +# Example rule allowing access from your local networks. +# Adapt to list your (internal) IP networks from where browsing +# should be allowed +acl localnet src 0.0.0.1-0.255.255.255 # RFC 1122 "this" network (LAN) +acl localnet src 10.0.0.0/8 # RFC 1918 local private network (LAN) +acl localnet src 100.64.0.0/10 # RFC 6598 shared address space (CGN) +acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines +acl localnet src 172.0.0.0/8 +acl localnet src 192.168.0.0/16 # RFC 1918 local private network (LAN) +acl localnet src fc00::/7 # RFC 4193 local private network range +acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines + +acl SSL_ports port 443 +acl Safe_ports port 80 # http +acl Safe_ports port 81 +acl Safe_ports port 443 # https + +# +# Recommended minimum Access Permission configuration: +# +# Deny requests to certain unsafe ports +http_access deny !Safe_ports + +# Deny CONNECT to other than secure SSL ports +http_access deny CONNECT !SSL_ports + +# Only allow cachemgr access from localhost +http_access allow localhost manager +http_access deny manager + +# This default configuration only allows localhost requests because a more +# permissive Squid installation could introduce new attack vectors into the +# network by proxying external TCP connections to unprotected services. +http_access allow localhost + +# The two deny rules below are unnecessary in this default configuration +# because they are followed by a "deny all" rule. However, they may become +# critically important when you start allowing external requests below them. + +# Protect web applications running on the same server as Squid. They often +# assume that only local users can access them at "localhost" ports. +http_access deny to_localhost + +# Protect cloud servers that provide local users with sensitive info about +# their server via certain well-known link-local (a.k.a. APIPA) addresses. +http_access deny to_linklocal + +# +# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS +# +include /etc/squid/conf.d/*.conf + +# For example, to allow access from your local networks, you may uncomment the +# following rule (and/or add rules that match your definition of "local"): +# http_access allow localnet + +# And finally deny all other access to this proxy +http_access deny all + +# Squid normally listens to port 3128 +http_port 3128 + +# Leave coredumps in the first cache dir +coredump_dir /var/spool/squid + +# +# Add any of your own refresh_pattern entries above these. +# +refresh_pattern ^ftp: 1440 20% 10080 +refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 +refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims +refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims +refresh_pattern \/InRelease$ 0 0% 0 refresh-ims +refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims +# example pattern for deb packages +#refresh_pattern (\.deb|\.udeb)$ 129600 100% 129600 +refresh_pattern . 0 20% 4320 + diff --git a/docker/docker-compose.ci.yml b/docker/docker-compose.ci.yml index b4a448063..391b41233 100644 --- a/docker/docker-compose.ci.yml +++ b/docker/docker-compose.ci.yml @@ -22,6 +22,7 @@ services: networks: fulltest: aliases: + - npm - website1.example.com - website2.example.com - website3.example.com @@ -92,13 +93,25 @@ services: dockerfile: test/cypress/Dockerfile environment: CYPRESS_baseUrl: 'http://fullstack:81' + HTTP_PROXY: 'http://squid:3128' + HTTPS_PROXY: 'http://squid:3128' volumes: - 'cypress_logs:/results' - './dev/resolv.conf:/etc/resolv.conf:ro' + - '/etc/localtime:/etc/localtime:ro' command: cypress run --browser chrome --config-file=cypress/config/ci.js networks: - fulltest + squid: + image: ubuntu/squid + volumes: + - './dev/squid.conf:/etc/squid/squid.conf:ro' + - './dev/resolv.conf:/etc/resolv.conf:ro' + - '/etc/localtime:/etc/localtime:ro' + networks: + - fulltest + volumes: cypress_logs: npm_data_ci: diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index 8092a33e4..4cdb1e916 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -12,7 +12,11 @@ services: - 3081:81 - 3443:443 networks: - - nginx_proxy_manager + nginx_proxy_manager: + aliases: + - website1.example.com + - website2.example.com + - website3.example.com environment: PUID: 1000 PGID: 1000 @@ -65,6 +69,17 @@ services: depends_on: - npm + squid: + image: ubuntu/squid + container_name: npm_squid + volumes: + - './dev/squid.conf:/etc/squid/squid.conf:ro' + - '/etc/localtime:/etc/localtime:ro' + networks: + - nginx_proxy_manager + ports: + - 8128:3128 + volumes: npm_data: name: npm_core_data diff --git a/test/cypress/config/ci.js b/test/cypress/config/ci.js index 2b50db1e8..63c9d8c81 100644 --- a/test/cypress/config/ci.js +++ b/test/cypress/config/ci.js @@ -15,8 +15,8 @@ module.exports = defineConfig({ return require("../plugins/index.js")(on, config); }, env: { - swaggerBase: '{{baseUrl}}/api/schema', + swaggerBase: 'http://npm:81/api/schema', }, - baseUrl: 'http://localhost:1234', + baseUrl: 'http://npm:81', } }); diff --git a/test/cypress/config/dev.js b/test/cypress/config/dev.js index 90ae943bc..f3c9f6d28 100644 --- a/test/cypress/config/dev.js +++ b/test/cypress/config/dev.js @@ -15,8 +15,8 @@ module.exports = defineConfig({ return require("../plugins/index.js")(on, config); }, env: { - swaggerBase: '{{baseUrl}}/api/schema', + swaggerBase: 'http://npm:81/api/schema', }, - baseUrl: 'http://localhost:1234', + baseUrl: 'http://npm:81', } }); diff --git a/test/package.json b/test/package.json index 7032efe68..99215363a 100644 --- a/test/package.json +++ b/test/package.json @@ -19,8 +19,8 @@ "mocha-junit-reporter": "^2.2.1" }, "scripts": { - "cypress": "cypress open --config-file=cypress/config/dev.js --config baseUrl=${BASE_URL:-http://127.0.0.1:3081}", - "cypress:headless": "cypress run --config-file=cypress/config/dev.js --config baseUrl=${BASE_URL:-http://127.0.0.1:3081}" + "cypress": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress open --config-file=cypress/config/dev.js", + "cypress:headless": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress run --config-file=cypress/config/dev.js" }, "author": "", "license": "ISC" From f2bb8f2b3d0bd64b2c58a4a45e9e1a8ac10e336e Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Sun, 13 Oct 2024 22:04:07 +1000 Subject: [PATCH 002/137] Squid ci fixes --- docker/docker-compose.ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docker/docker-compose.ci.yml b/docker/docker-compose.ci.yml index 391b41233..5d5b0dded 100644 --- a/docker/docker-compose.ci.yml +++ b/docker/docker-compose.ci.yml @@ -92,9 +92,8 @@ services: context: ../ dockerfile: test/cypress/Dockerfile environment: - CYPRESS_baseUrl: 'http://fullstack:81' - HTTP_PROXY: 'http://squid:3128' - HTTPS_PROXY: 'http://squid:3128' + HTTP_PROXY: 'squid:3128' + HTTPS_PROXY: 'squid:3128' volumes: - 'cypress_logs:/results' - './dev/resolv.conf:/etc/resolv.conf:ro' From 81b89185f2af1d40406d1ae2507e0f24e9a2f294 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Sun, 13 Oct 2024 22:15:18 +1000 Subject: [PATCH 003/137] Squid ci fixes --- docker/docker-compose.ci.yml | 1 - test/cypress/config/ci.js | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/docker/docker-compose.ci.yml b/docker/docker-compose.ci.yml index 5d5b0dded..e13e8bf26 100644 --- a/docker/docker-compose.ci.yml +++ b/docker/docker-compose.ci.yml @@ -22,7 +22,6 @@ services: networks: fulltest: aliases: - - npm - website1.example.com - website2.example.com - website3.example.com diff --git a/test/cypress/config/ci.js b/test/cypress/config/ci.js index 63c9d8c81..873330dc7 100644 --- a/test/cypress/config/ci.js +++ b/test/cypress/config/ci.js @@ -15,8 +15,8 @@ module.exports = defineConfig({ return require("../plugins/index.js")(on, config); }, env: { - swaggerBase: 'http://npm:81/api/schema', + swaggerBase: 'http://fullstack:81/api/schema', }, - baseUrl: 'http://npm:81', + baseUrl: 'http://fullstack:81', } }); From 7322d35bd734d3694c111a4883e834435bb4b00d Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Mon, 14 Oct 2024 07:21:04 +1000 Subject: [PATCH 004/137] Fix CI --- Jenkinsfile | 9 +-------- scripts/ci/fulltest-cypress | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ae631f935..757579468 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -204,20 +204,13 @@ pipeline { always { sh 'echo Reverting ownership' sh 'docker run --rm -v "$(pwd):/data" jc21/ci-tools chown -R "$(id -u):$(id -g)" /data' - } - success { - juxtapose event: 'success' - sh 'figlet "SUCCESS"' + printResult(true) } failure { archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true) - juxtapose event: 'failure' - sh 'figlet "FAILURE"' } unstable { archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true) - juxtapose event: 'unstable' - sh 'figlet "UNSTABLE"' } } } diff --git a/scripts/ci/fulltest-cypress b/scripts/ci/fulltest-cypress index 7e4469fec..9101189c2 100755 --- a/scripts/ci/fulltest-cypress +++ b/scripts/ci/fulltest-cypress @@ -65,7 +65,7 @@ rm -rf "${LOCAL_RESOLVE}" printf "nameserver %s\noptions ndots:0" "${DNSROUTER_IP}" > "${LOCAL_RESOLVE}" # bring up all remaining containers, except cypress! -docker-compose up -d --remove-orphans stepca +docker-compose up -d --remove-orphans stepca squid docker-compose pull db-mysql || true # ok to fail docker-compose up -d --remove-orphans --pull=never fullstack From e5aa880ec41c5a46f49c515a11240b4a0dd5a716 Mon Sep 17 00:00:00 2001 From: Dusan Cervenka Date: Tue, 15 Oct 2024 01:58:15 +0200 Subject: [PATCH 005/137] fixed wedos password description Signed-off-by: Dusan Cervenka --- global/certbot-dns-plugins.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global/certbot-dns-plugins.json b/global/certbot-dns-plugins.json index bc3cfa7a7..6729842e8 100644 --- a/global/certbot-dns-plugins.json +++ b/global/certbot-dns-plugins.json @@ -492,7 +492,7 @@ "package_name": "certbot-dns-wedos", "version": "~=2.2", "dependencies": "", - "credentials": "dns_wedos_user = \ndns_wedos_auth = ", + "credentials": "dns_wedos_user = \ndns_wedos_auth = ", "full_plugin_name": "dns-wedos" }, "edgedns": { From 351ba8dacd55f70bf0797212bfa4f9650b92a8b1 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Mon, 14 Oct 2024 22:48:36 +1000 Subject: [PATCH 006/137] More tests for certificates, fixed schema problems --- backend/internal/certificate.js | 11 +++-- .../schema/components/certificate-object.json | 28 ++++++++--- .../certificates/certID/upload/post.json | 19 ++++++++ test/cypress/e2e/api/Certificates.cy.js | 47 +++++++++++++++++++ test/package.json | 2 +- test/yarn.lock | 8 ++-- 6 files changed, 98 insertions(+), 17 deletions(-) diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index 9bdfe695c..68dd55e88 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -3,27 +3,28 @@ const fs = require('fs'); const https = require('https'); const tempWrite = require('temp-write'); const moment = require('moment'); +const archiver = require('archiver'); +const path = require('path'); +const { isArray } = require('lodash'); const logger = require('../logger').ssl; const config = require('../lib/config'); const error = require('../lib/error'); const utils = require('../lib/utils'); +const certbot = require('../lib/certbot'); const certificateModel = require('../models/certificate'); const tokenModel = require('../models/token'); const dnsPlugins = require('../global/certbot-dns-plugins.json'); const internalAuditLog = require('./audit-log'); const internalNginx = require('./nginx'); const internalHost = require('./host'); -const certbot = require('../lib/certbot'); -const archiver = require('archiver'); -const path = require('path'); -const { isArray } = require('lodash'); + const letsencryptStaging = config.useLetsencryptStaging(); const letsencryptConfig = '/etc/letsencrypt.ini'; const certbotCommand = 'certbot'; function omissions() { - return ['is_deleted']; + return ['is_deleted', 'owner.is_deleted']; } const internalCertificate = { diff --git a/backend/schema/components/certificate-object.json b/backend/schema/components/certificate-object.json index 04cd89801..a4e8e1fce 100644 --- a/backend/schema/components/certificate-object.json +++ b/backend/schema/components/certificate-object.json @@ -24,13 +24,23 @@ "description": "Nice Name for the custom certificate" }, "domain_names": { - "$ref": "../common.json#/properties/domain_names" + "description": "Domain Names separated by a comma", + "type": "array", + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$" + } }, "expires_on": { "description": "Date and time of expiration", "readOnly": true, "type": "string" }, + "owner": { + "$ref": "./user-object.json" + }, "meta": { "type": "object", "additionalProperties": false, @@ -51,12 +61,16 @@ "type": "string" }, "propagation_seconds": { - "anyOf": [ - { - "type": "integer", - "minimum": 0 - } - ] + "type": "integer", + "minimum": 0 + }, + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 } } } diff --git a/backend/schema/paths/nginx/certificates/certID/upload/post.json b/backend/schema/paths/nginx/certificates/certID/upload/post.json index e9274856a..f38b8102a 100644 --- a/backend/schema/paths/nginx/certificates/certID/upload/post.json +++ b/backend/schema/paths/nginx/certificates/certID/upload/post.json @@ -55,6 +55,25 @@ "certificate_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1n9j9C5Bes1nd\nqACDckERauxXVNKCnUlUM1buGBx1xc+j2e2Ar23wUJJuWBY18VfT8yqfqVDktO2w\nrbmvZvLuPmXePOKbIKS+XXh+2NG9L5bDG9rwGFCRXnbQj+GWCdMfzx14+CR1IHge\nYz6Cv/Si2/LJPCh/CoBfM4hUQJON3lxAWrWBpdbZnKYMrxuPBRfW9OuzTbCVXToQ\noxRAHiOR9081Xn1WeoKr7kVBIa5UphlvWXa12w1YmUwJu7YndnJGIavLWeNCVc7Z\nEo+nS8Wr/4QWicatIWZXpVaEOPhRoeplQDxNWg5b/Q26rYoVd7PrCmRs7sVcH79X\nzGONeH1PAgMBAAECggEAANb3Wtwl07pCjRrMvc7WbC0xYIn82yu8/g2qtjkYUJcU\nia5lQbYN7RGCS85Oc/tkq48xQEG5JQWNH8b918jDEMTrFab0aUEyYcru1q9L8PL6\nYHaNgZSrMrDcHcS8h0QOXNRJT5jeGkiHJaTR0irvB526tqF3knbK9yW22KTfycUe\na0Z9voKn5xRk1DCbHi/nk2EpT7xnjeQeLFaTIRXbS68omkr4YGhwWm5OizoyEGZu\nW0Zum5BkQyMr6kor3wdxOTG97ske2rcyvvHi+ErnwL0xBv0qY0Dhe8DpuXpDezqw\no72yY8h31Fu84i7sAj24YuE5Df8DozItFXQpkgbQ6QKBgQDPrufhvIFm2S/MzBdW\nH8JxY7CJlJPyxOvc1NIl9RczQGAQR90kx52cgIcuIGEG6/wJ/xnGfMmW40F0DnQ+\nN+oLgB9SFxeLkRb7s9Z/8N3uIN8JJFYcerEOiRQeN2BXEEWJ7bUThNtsVrAcKoUh\nELsDmnHW/3V+GKwhd0vpk842+wKBgQDf4PGLG9PTE5tlAoyHFodJRd2RhTJQkwsU\nMDNjLJ+KecLv+Nl+QiJhoflG1ccqtSFlBSCG067CDQ5LV0xm3mLJ7pfJoMgjcq31\nqjEmX4Ls91GuVOPtbwst3yFKjsHaSoKB5fBvWRcKFpBUezM7Qcw2JP3+dQT+bQIq\ncMTkRWDSvQKBgQDOdCQFDjxg/lR7NQOZ1PaZe61aBz5P3pxNqa7ClvMaOsuEQ7w9\nvMYcdtRq8TsjA2JImbSI0TIg8gb2FQxPcYwTJKl+FICOeIwtaSg5hTtJZpnxX5LO\nutTaC0DZjNkTk5RdOdWA8tihyUdGqKoxJY2TVmwGe2rUEDjFB++J4inkEwKBgB6V\ng0nmtkxanFrzOzFlMXwgEEHF+Xaqb9QFNa/xs6XeNnREAapO7JV75Cr6H2hFMFe1\nmJjyqCgYUoCWX3iaHtLJRnEkBtNY4kzyQB6m46LtsnnnXO/dwKA2oDyoPfFNRoDq\nYatEd3JIXNU9s2T/+x7WdOBjKhh72dTkbPFmTPDdAoGAU6rlPBevqOFdObYxdPq8\nEQWu44xqky3Mf5sBpOwtu6rqCYuziLiN7K4sjN5GD5mb1cEU+oS92ZiNcUQ7MFXk\n8yTYZ7U0VcXyAcpYreWwE8thmb0BohJBr+Mp3wLTx32x0HKdO6vpUa0d35LUTUmM\nRrKmPK/msHKK/sVHiL+NFqo=\n-----END PRIVATE KEY-----\n" } } + }, + "schema": { + "type": "object", + "additionalProperties": false, + "required": ["certificate", "certificate_key"], + "properties": { + "certificate": { + "type": "string", + "minLength": 1 + }, + "certificate_key": { + "type": "string", + "minLength": 1 + }, + "intermediate_certificate": { + "type": "string", + "minLength": 1 + } + } } } } diff --git a/test/cypress/e2e/api/Certificates.cy.js b/test/cypress/e2e/api/Certificates.cy.js index 043680f3e..687d09e57 100644 --- a/test/cypress/e2e/api/Certificates.cy.js +++ b/test/cypress/e2e/api/Certificates.cy.js @@ -2,6 +2,7 @@ describe('Certificates endpoints', () => { let token; + let certID; before(() => { cy.getToken().then((tok) => { @@ -24,6 +25,52 @@ describe('Certificates endpoints', () => { }); }); + it('Custom certificate lifecycle', function() { + cy.task('backendApiPost', { + token: token, + path: '/api/nginx/certificates', + data: { + provider: "other", + nice_name: "Test Certificate", + }, + }).then((data) => { + cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data); + expect(data).to.have.property('id'); + certID = data.id; + + cy.task('backendApiPostFiles', { + token: token, + path: `/api/nginx/certificates/${certID}/upload`, + files: { + certificate: 'test.example.com.pem', + certificate_key: 'test.example.com-key.pem', + }, + }).then((data) => { + cy.validateSwaggerSchema('post', 201, '/nginx/certificates/upload', data); + expect(data).to.have.property('certificate'); + expect(data).to.have.property('certificate_key'); + + cy.task('backendApiDelete', { + token: token, + path: `/api/nginx/certificates/${certID}` + }).then((data) => { + cy.validateSwaggerSchema('delete', 200, '/nginx/certificates/{certID}', data); + expect(data).to.be.equal(true); + }); + }); + }); + }); + + it('Should be able to get all certs', function() { + cy.task('backendApiGet', { + token: token, + path: '/api/nginx/certificates?expand=owner' + }).then((data) => { + cy.validateSwaggerSchema('get', 200, '/nginx/certificates', data); + expect(data.length).to.be.greaterThan(0); + }); + }); + it('Request Certificate - CVE-2024-46256/CVE-2024-46257', function() { cy.task('backendApiPost', { token: token, diff --git a/test/package.json b/test/package.json index 99215363a..a1c68908a 100644 --- a/test/package.json +++ b/test/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "dependencies": { - "@jc21/cypress-swagger-validation": "^0.2.7", + "@jc21/cypress-swagger-validation": "^0.2.8", "axios": "^1.7.7", "cypress": "^13.15.0", "cypress-multi-reporters": "^1.6.4", diff --git a/test/yarn.lock b/test/yarn.lock index b12b42477..38d85e0a8 100644 --- a/test/yarn.lock +++ b/test/yarn.lock @@ -167,10 +167,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== -"@jc21/cypress-swagger-validation@^0.2.7": - version "0.2.7" - resolved "https://registry.yarnpkg.com/@jc21/cypress-swagger-validation/-/cypress-swagger-validation-0.2.7.tgz#64642b12d98b884df8c30b72852162941285d2af" - integrity sha512-4EQ0gfigRwVVl3DnVYbR48/EKGnn7oH5YYdMzf6zqypO+bqYvDHu9kgk/WqkGlT/aauGQ7e0YGMo8ZvR7mL0Ng== +"@jc21/cypress-swagger-validation@^0.2.8": + version "0.2.8" + resolved "https://registry.yarnpkg.com/@jc21/cypress-swagger-validation/-/cypress-swagger-validation-0.2.8.tgz#8ab059bd41e3ee100a1998a1484b9e5a2e9a4224" + integrity sha512-9fiZIHj3//bJjC5YUMOc42RnoEUeeokVn6xtMnP52XIZ/ryWQ9PIyFdlOAH8q/LW/uPxozJo2+hdB6ou4iurag== dependencies: "@apidevtools/swagger-parser" "^10.1.0" ajv "^8.17.1" From f48e1b46a8979b58d05c953f0893f140717c5fb1 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Tue, 15 Oct 2024 23:54:39 +1000 Subject: [PATCH 007/137] Updated swagger cypress package, which works with proxies --- Jenkinsfile | 10 +++++++ docker/docker-compose.dev.yml | 4 +-- test/cypress/config/ci.js | 2 +- test/cypress/config/dev.js | 22 --------------- test/cypress/e2e/api/Certificates.cy.js | 34 ++++++++++++----------- test/cypress/e2e/api/Health.cy.js | 4 +-- test/cypress/e2e/api/Hosts.cy.js | 2 +- test/cypress/e2e/api/Users.cy.js | 2 +- test/cypress/plugins/backendApi/client.js | 2 +- test/cypress/plugins/index.js | 2 +- test/package.json | 6 ++-- test/yarn.lock | 31 ++++++++------------- 12 files changed, 52 insertions(+), 69 deletions(-) delete mode 100644 test/cypress/config/dev.js diff --git a/Jenkinsfile b/Jenkinsfile index 757579468..9b29ee970 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -127,6 +127,11 @@ pipeline { junit 'test/results/junit/*' sh 'docker-compose down --remove-orphans --volumes -t 30 || true' } + unstable { + dir(path: 'testing/results') { + archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml') + } + } } } stage('Test Mysql') { @@ -155,6 +160,11 @@ pipeline { junit 'test/results/junit/*' sh 'docker-compose down --remove-orphans --volumes -t 30 || true' } + unstable { + dir(path: 'testing/results') { + archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml') + } + } } } stage('MultiArch Build') { diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index 4cdb1e916..e7f9bcbaa 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -1,7 +1,7 @@ # WARNING: This is a DEVELOPMENT docker-compose file, it should not be used for production. services: - npm: + fullstack: image: nginxproxymanager:dev container_name: npm_core build: @@ -67,7 +67,7 @@ services: URL: "http://npm:81/api/schema" PORT: '80' depends_on: - - npm + - fullstack squid: image: ubuntu/squid diff --git a/test/cypress/config/ci.js b/test/cypress/config/ci.js index 873330dc7..dc968dbd3 100644 --- a/test/cypress/config/ci.js +++ b/test/cypress/config/ci.js @@ -15,7 +15,7 @@ module.exports = defineConfig({ return require("../plugins/index.js")(on, config); }, env: { - swaggerBase: 'http://fullstack:81/api/schema', + swaggerBase: '{{baseUrl}}/api/schema?ts=' + Date.now(), }, baseUrl: 'http://fullstack:81', } diff --git a/test/cypress/config/dev.js b/test/cypress/config/dev.js deleted file mode 100644 index f3c9f6d28..000000000 --- a/test/cypress/config/dev.js +++ /dev/null @@ -1,22 +0,0 @@ -const { defineConfig } = require('cypress'); - -module.exports = defineConfig({ - requestTimeout: 30000, - defaultCommandTimeout: 20000, - reporter: 'cypress-multi-reporters', - reporterOptions: { - configFile: 'multi-reporter.json' - }, - video: false, - videosFolder: 'results/videos', - screenshotsFolder: 'results/screenshots', - e2e: { - setupNodeEvents(on, config) { - return require("../plugins/index.js")(on, config); - }, - env: { - swaggerBase: 'http://npm:81/api/schema', - }, - baseUrl: 'http://npm:81', - } -}); diff --git a/test/cypress/e2e/api/Certificates.cy.js b/test/cypress/e2e/api/Certificates.cy.js index 687d09e57..1e8a6fed4 100644 --- a/test/cypress/e2e/api/Certificates.cy.js +++ b/test/cypress/e2e/api/Certificates.cy.js @@ -1,4 +1,4 @@ -/// +/// describe('Certificates endpoints', () => { let token; @@ -26,6 +26,7 @@ describe('Certificates endpoints', () => { }); it('Custom certificate lifecycle', function() { + // Create custom cert cy.task('backendApiPost', { token: token, path: '/api/nginx/certificates', @@ -38,6 +39,7 @@ describe('Certificates endpoints', () => { expect(data).to.have.property('id'); certID = data.id; + // Upload files cy.task('backendApiPostFiles', { token: token, path: `/api/nginx/certificates/${certID}/upload`, @@ -46,31 +48,31 @@ describe('Certificates endpoints', () => { certificate_key: 'test.example.com-key.pem', }, }).then((data) => { - cy.validateSwaggerSchema('post', 201, '/nginx/certificates/upload', data); + cy.validateSwaggerSchema('post', 200, '/nginx/certificates/{certID}/upload', data); expect(data).to.have.property('certificate'); expect(data).to.have.property('certificate_key'); - cy.task('backendApiDelete', { + // Get all certs + cy.task('backendApiGet', { token: token, - path: `/api/nginx/certificates/${certID}` + path: '/api/nginx/certificates?expand=owner' }).then((data) => { - cy.validateSwaggerSchema('delete', 200, '/nginx/certificates/{certID}', data); - expect(data).to.be.equal(true); + cy.validateSwaggerSchema('get', 200, '/nginx/certificates', data); + expect(data.length).to.be.greaterThan(0); + + // Delete cert + cy.task('backendApiDelete', { + token: token, + path: `/api/nginx/certificates/${certID}` + }).then((data) => { + cy.validateSwaggerSchema('delete', 200, '/nginx/certificates/{certID}', data); + expect(data).to.be.equal(true); + }); }); }); }); }); - it('Should be able to get all certs', function() { - cy.task('backendApiGet', { - token: token, - path: '/api/nginx/certificates?expand=owner' - }).then((data) => { - cy.validateSwaggerSchema('get', 200, '/nginx/certificates', data); - expect(data.length).to.be.greaterThan(0); - }); - }); - it('Request Certificate - CVE-2024-46256/CVE-2024-46257', function() { cy.task('backendApiPost', { token: token, diff --git a/test/cypress/e2e/api/Health.cy.js b/test/cypress/e2e/api/Health.cy.js index f765c99b9..49881e97b 100644 --- a/test/cypress/e2e/api/Health.cy.js +++ b/test/cypress/e2e/api/Health.cy.js @@ -1,4 +1,4 @@ -/// +/// describe('Basic API checks', () => { it('Should return a valid health payload', function () { @@ -12,7 +12,7 @@ describe('Basic API checks', () => { it('Should return a valid schema payload', function () { cy.task('backendApiGet', { - path: '/api/schema', + path: '/api/schema?ts=' + Date.now(), }).then((data) => { expect(data.openapi).to.be.equal('3.1.0'); }); diff --git a/test/cypress/e2e/api/Hosts.cy.js b/test/cypress/e2e/api/Hosts.cy.js index 62b9581bb..75d732c7c 100644 --- a/test/cypress/e2e/api/Hosts.cy.js +++ b/test/cypress/e2e/api/Hosts.cy.js @@ -1,4 +1,4 @@ -/// +/// describe('Hosts endpoints', () => { let token; diff --git a/test/cypress/e2e/api/Users.cy.js b/test/cypress/e2e/api/Users.cy.js index 43303d431..06b183176 100644 --- a/test/cypress/e2e/api/Users.cy.js +++ b/test/cypress/e2e/api/Users.cy.js @@ -1,4 +1,4 @@ -/// +/// describe('Users endpoints', () => { let token; diff --git a/test/cypress/plugins/backendApi/client.js b/test/cypress/plugins/backendApi/client.js index e7c0c439d..ba28e3ae1 100644 --- a/test/cypress/plugins/backendApi/client.js +++ b/test/cypress/plugins/backendApi/client.js @@ -80,7 +80,7 @@ BackendApi.prototype._handleError = function(err, resolve, reject, returnOnError * @returns {Promise} */ BackendApi.prototype.request = function (method, path, returnOnError, data) { - logger(method.toUpperCase(), this.config.baseUrl + path); + logger(method.toUpperCase(), path); const options = this._prepareOptions(returnOnError); return new Promise((resolve, reject) => { diff --git a/test/cypress/plugins/index.js b/test/cypress/plugins/index.js index 8cf6eef6c..2f3e3c5af 100644 --- a/test/cypress/plugins/index.js +++ b/test/cypress/plugins/index.js @@ -1,4 +1,4 @@ -const {SwaggerValidation} = require('@jc21/cypress-swagger-validation'); +const { SwaggerValidation } = require('@jc21/cypress-swagger-validation'); module.exports = (on, config) => { // Replace swaggerBase config var wildcard diff --git a/test/package.json b/test/package.json index a1c68908a..b52ecfbd7 100644 --- a/test/package.json +++ b/test/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "dependencies": { - "@jc21/cypress-swagger-validation": "^0.2.8", + "@jc21/cypress-swagger-validation": "^0.3.1", "axios": "^1.7.7", "cypress": "^13.15.0", "cypress-multi-reporters": "^1.6.4", @@ -19,8 +19,8 @@ "mocha-junit-reporter": "^2.2.1" }, "scripts": { - "cypress": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress open --config-file=cypress/config/dev.js", - "cypress:headless": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress run --config-file=cypress/config/dev.js" + "cypress": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress open --config-file=cypress/config/ci.js", + "cypress:headless": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress run --config-file=cypress/config/ci.js" }, "author": "", "license": "ISC" diff --git a/test/yarn.lock b/test/yarn.lock index 38d85e0a8..4fa9e51f9 100644 --- a/test/yarn.lock +++ b/test/yarn.lock @@ -11,14 +11,13 @@ call-me-maybe "^1.0.1" js-yaml "^3.13.1" -"@apidevtools/json-schema-ref-parser@9.0.9": - version "9.0.9" - resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b" - integrity sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w== +"@apidevtools/json-schema-ref-parser@^11.7.2": + version "11.7.2" + resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz#cdf3e0aded21492364a70e193b45b7cf4177f031" + integrity sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA== dependencies: "@jsdevtools/ono" "^7.1.3" - "@types/json-schema" "^7.0.6" - call-me-maybe "^1.0.1" + "@types/json-schema" "^7.0.15" js-yaml "^4.1.0" "@apidevtools/openapi-schemas@^2.1.0": @@ -167,15 +166,16 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== -"@jc21/cypress-swagger-validation@^0.2.8": - version "0.2.8" - resolved "https://registry.yarnpkg.com/@jc21/cypress-swagger-validation/-/cypress-swagger-validation-0.2.8.tgz#8ab059bd41e3ee100a1998a1484b9e5a2e9a4224" - integrity sha512-9fiZIHj3//bJjC5YUMOc42RnoEUeeokVn6xtMnP52XIZ/ryWQ9PIyFdlOAH8q/LW/uPxozJo2+hdB6ou4iurag== +"@jc21/cypress-swagger-validation@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@jc21/cypress-swagger-validation/-/cypress-swagger-validation-0.3.1.tgz#1cdd49850a20f876ed62149623f99988264751be" + integrity sha512-Vdt1gLfj8p0tJhA42Cfn43XBbsKocNfVCEVSwkn7RmZgWUyRKjqhBBRTVa9cKZTozyg8Co/yhBMsNyjmHFVXtQ== dependencies: + "@apidevtools/json-schema-ref-parser" "^11.7.2" "@apidevtools/swagger-parser" "^10.1.0" ajv "^8.17.1" + axios "^1.7.7" json-schema "^0.4.0" - json-schema-ref-parser "^9.0.9" jsonpath "^1.1.1" lodash "^4.17.21" openapi-types "^12.1.3" @@ -196,7 +196,7 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== -"@types/json-schema@^7.0.15", "@types/json-schema@^7.0.6": +"@types/json-schema@^7.0.15": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -1468,13 +1468,6 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-schema-ref-parser@^9.0.9: - version "9.0.9" - resolved "https://registry.yarnpkg.com/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#66ea538e7450b12af342fa3d5b8458bc1e1e013f" - integrity sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q== - dependencies: - "@apidevtools/json-schema-ref-parser" "9.0.9" - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" From 929ac3bd7cbe4f11e7ec49744c251cf9dc0aadad Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Wed, 16 Oct 2024 11:06:29 +1000 Subject: [PATCH 008/137] Adds env var to set certbot acme server this is required for test suite to use dns certbot request without talking to live or staging letsencrypt servers or production level dns providers. This is a backwards port from the v3 branch and opens the door for a full certificate cypress test --- backend/internal/certificate.js | 4 +- backend/lib/config.js | 10 ++++ docker/Dockerfile | 4 ++ docker/dev/Dockerfile | 24 +++++---- docker/docker-compose.ci.yml | 3 ++ docker/docker-compose.dev.yml | 86 +++++++++++++++++++++++++++++++++ scripts/.common.sh | 10 ++++ scripts/cypress-dev | 13 +++++ scripts/start-dev | 37 +++++++++++++- 9 files changed, 180 insertions(+), 11 deletions(-) create mode 100755 scripts/cypress-dev diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index 68dd55e88..aea741c7d 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -20,6 +20,7 @@ const internalHost = require('./host'); const letsencryptStaging = config.useLetsencryptStaging(); +const letsencryptServer = config.useLetsencryptServer(); const letsencryptConfig = '/etc/letsencrypt.ini'; const certbotCommand = 'certbot'; @@ -838,7 +839,8 @@ const internalCertificate = { '--email "' + certificate.meta.letsencrypt_email + '" ' + '--preferred-challenges "dns,http" ' + '--domains "' + certificate.domain_names.join(',') + '" ' + - (letsencryptStaging ? '--staging' : ''); + (letsencryptStaging ? '--staging' : '') + + (letsencryptServer !== null ? `--server '${letsencryptServer}'` : ''); logger.info('Command:', cmd); diff --git a/backend/lib/config.js b/backend/lib/config.js index b42f9e3ca..f7fbdca6f 100644 --- a/backend/lib/config.js +++ b/backend/lib/config.js @@ -180,5 +180,15 @@ module.exports = { */ useLetsencryptStaging: function () { return !!process.env.LE_STAGING; + }, + + /** + * @returns {string|null} + */ + useLetsencryptServer: function () { + if (process.env.LE_SERVER) { + return process.env.LE_SERVER; + } + return null; } }; diff --git a/docker/Dockerfile b/docker/Dockerfile index 799ee2a63..0603e2ded 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -3,6 +3,8 @@ # This file assumes that the frontend has been built using ./scripts/frontend-build +FROM nginxproxymanager/testca AS testca +FROM letsencrypt/pebble AS pebbleca FROM nginxproxymanager/nginx-full:certbot-node ARG TARGETPLATFORM @@ -45,6 +47,8 @@ RUN yarn install \ # add late to limit cache-busting by modifications COPY docker/rootfs / +COPY --from=pebbleca /test/certs/pebble.minica.pem /etc/ssl/certs/pebble.minica.pem +COPY --from=testca /home/step/certs/root_ca.crt /etc/ssl/certs/NginxProxyManager.crt # Remove frontend service not required for prod, dev nginx config as well RUN rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/frontend /etc/nginx/conf.d/dev.conf \ diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile index 3c21849cd..bb4ac6d44 100644 --- a/docker/dev/Dockerfile +++ b/docker/dev/Dockerfile @@ -1,7 +1,10 @@ +FROM nginxproxymanager/testca AS testca +FROM letsencrypt/pebble AS pebbleca FROM nginxproxymanager/nginx-full:certbot-node LABEL maintainer="Jamie Curnow " -# See: https://github.com/just-containers/s6-overlay/blob/master/README.md +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + ENV SUPPRESS_NO_CONFIG_WARNING=1 \ S6_BEHAVIOUR_IF_STAGE2_FAILS=1 \ S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \ @@ -17,17 +20,20 @@ RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \ && rm -rf /var/lib/apt/lists/* # Task -RUN cd /usr \ - && curl -sL https://taskfile.dev/install.sh | sh \ - && cd /root +WORKDIR /usr +RUN curl -sL https://taskfile.dev/install.sh | sh +WORKDIR /root COPY rootfs / -RUN rm -f /etc/nginx/conf.d/production.conf -RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager - -# s6 overlay COPY scripts/install-s6 /tmp/install-s6 -RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6 +RUN rm -f /etc/nginx/conf.d/production.conf \ + && chmod 644 /etc/logrotate.d/nginx-proxy-manager \ + && /tmp/install-s6 "${TARGETPLATFORM}" \ + && rm -f /tmp/install-s6 + +# Certs for testing purposes +COPY --from=pebbleca /test/certs/pebble.minica.pem /etc/ssl/certs/pebble.minica.pem +COPY --from=testca /home/step/certs/root_ca.crt /etc/ssl/certs/NginxProxyManager.crt EXPOSE 80 81 443 ENTRYPOINT [ "/init" ] diff --git a/docker/docker-compose.ci.yml b/docker/docker-compose.ci.yml index e13e8bf26..bb68858f9 100644 --- a/docker/docker-compose.ci.yml +++ b/docker/docker-compose.ci.yml @@ -9,6 +9,9 @@ services: environment: DEBUG: 'true' FORCE_COLOR: 1 + # Required for DNS Certificate provisioning in CI + LE_SERVER: 'https://ca.internal/acme/acme/directory' + REQUESTS_CA_BUNDLE: '/etc/ssl/certs/NginxProxyManager.crt' volumes: - 'npm_data_ci:/data' - 'npm_le_ci:/etc/letsencrypt' diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index e7f9bcbaa..2bfa2b798 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -33,12 +33,20 @@ services: DB_MYSQL_NAME: 'npm' # DB_SQLITE_FILE: "/data/database.sqlite" # DISABLE_IPV6: "true" + # Required for DNS Certificate provisioning testing: + LE_SERVER: 'https://ca.internal/acme/acme/directory' + REQUESTS_CA_BUNDLE: '/etc/ssl/certs/NginxProxyManager.crt' volumes: - npm_data:/data - le_data:/etc/letsencrypt + - './dev/resolv.conf:/etc/resolv.conf:ro' - ../backend:/app - ../frontend:/app/frontend - ../global:/app/global + healthcheck: + test: ["CMD", "/usr/bin/check-health"] + interval: 10s + timeout: 3s depends_on: - db working_dir: /app @@ -58,6 +66,23 @@ services: volumes: - db_data:/var/lib/mysql + stepca: + image: jc21/testca + volumes: + - './dev/resolv.conf:/etc/resolv.conf:ro' + - '/etc/localtime:/etc/localtime:ro' + networks: + nginx_proxy_manager: + aliases: + - ca.internal + + dnsrouter: + image: jc21/dnsrouter + volumes: + - ./dev/dnsrouter-config.json.tmp:/dnsrouter-config.json:ro + networks: + - nginx_proxy_manager + swagger: image: swaggerapi/swagger-ui:latest container_name: npm_swagger @@ -74,12 +99,71 @@ services: container_name: npm_squid volumes: - './dev/squid.conf:/etc/squid/squid.conf:ro' + - './dev/resolv.conf:/etc/resolv.conf:ro' - '/etc/localtime:/etc/localtime:ro' networks: - nginx_proxy_manager ports: - 8128:3128 + pdns: + image: pschiffe/pdns-mysql + volumes: + - '/etc/localtime:/etc/localtime:ro' + environment: + PDNS_master: 'yes' + PDNS_api: 'yes' + PDNS_api_key: 'npm' + PDNS_webserver: 'yes' + PDNS_webserver_address: '0.0.0.0' + PDNS_webserver_password: 'npm' + PDNS_webserver-allow-from: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8' + PDNS_version_string: 'anonymous' + PDNS_default_ttl: 1500 + PDNS_allow_axfr_ips: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8' + PDNS_gmysql_host: pdns-db + PDNS_gmysql_port: 3306 + PDNS_gmysql_user: pdns + PDNS_gmysql_password: pdns + PDNS_gmysql_dbname: pdns + depends_on: + - pdns-db + networks: + nginx_proxy_manager: + aliases: + - ns1.pdns + - ns2.pdns + + pdns-db: + image: mariadb + environment: + MYSQL_ROOT_PASSWORD: 'pdns' + MYSQL_DATABASE: 'pdns' + MYSQL_USER: 'pdns' + MYSQL_PASSWORD: 'pdns' + volumes: + - 'pdns_mysql:/var/lib/mysql' + - '/etc/localtime:/etc/localtime:ro' + - './dev/pdns-db.sql:/docker-entrypoint-initdb.d/01_init.sql:ro' + networks: + - nginx_proxy_manager + + cypress: + image: "npm_dev_cypress" + build: + context: ../ + dockerfile: test/cypress/Dockerfile + environment: + HTTP_PROXY: 'squid:3128' + HTTPS_PROXY: 'squid:3128' + volumes: + - '../test/results:/results' + - './dev/resolv.conf:/etc/resolv.conf:ro' + - '/etc/localtime:/etc/localtime:ro' + command: cypress run --browser chrome --config-file=cypress/config/ci.js + networks: + - nginx_proxy_manager + volumes: npm_data: name: npm_core_data @@ -87,6 +171,8 @@ volumes: name: npm_le_data db_data: name: npm_db_data + pdns_mysql: + name: npm_pdns_mysql networks: nginx_proxy_manager: diff --git a/scripts/.common.sh b/scripts/.common.sh index 3cea09167..4111db3b5 100644 --- a/scripts/.common.sh +++ b/scripts/.common.sh @@ -15,3 +15,13 @@ COMPOSE_PROJECT_NAME="npmdev" COMPOSE_FILE="docker/docker-compose.dev.yml" export COMPOSE_FILE COMPOSE_PROJECT_NAME + +# $1: container_name +get_container_ip () { + local container_name=$1 + local container + local ip + container=$(docker-compose ps --all -q "${container_name}" | tail -n1) + ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$container") + echo "$ip" +} diff --git a/scripts/cypress-dev b/scripts/cypress-dev new file mode 100755 index 000000000..a0c64ad96 --- /dev/null +++ b/scripts/cypress-dev @@ -0,0 +1,13 @@ +#!/bin/bash -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +. "$DIR/.common.sh" + +# Ensure docker-compose exists +if hash docker-compose 2>/dev/null; then + cd "${DIR}/.." + rm -rf "$DIR/../test/results" + docker-compose up --build cypress +else + echo -e "${RED}❯ docker-compose command is not available${RESET}" +fi diff --git a/scripts/start-dev b/scripts/start-dev index f064a4bdf..9da6ed450 100755 --- a/scripts/start-dev +++ b/scripts/start-dev @@ -7,8 +7,43 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if hash docker-compose 2>/dev/null; then cd "${DIR}/.." echo -e "${BLUE}❯ ${CYAN}Starting Dev Stack ...${RESET}" + echo -e "${BLUE}❯ $(docker-compose config)${RESET}" - docker-compose up -d --remove-orphans --force-recreate --build + # Bring up a stack, in steps so we can inject IPs everywhere + docker-compose up -d pdns pdns-db + PDNS_IP=$(get_container_ip "pdns") + echo -e "${BLUE}❯ ${YELLOW}PDNS IP is ${PDNS_IP}${RESET}" + + # adjust the dnsrouter config + LOCAL_DNSROUTER_CONFIG="$DIR/../docker/dev/dnsrouter-config.json" + rm -rf "$LOCAL_DNSROUTER_CONFIG.tmp" + # IMPORTANT: changes to dnsrouter-config.json will affect this line: + jq --arg a "$PDNS_IP" '.servers[0].upstreams[1].upstream = $a' "$LOCAL_DNSROUTER_CONFIG" > "$LOCAL_DNSROUTER_CONFIG.tmp" + + docker-compose up -d dnsrouter + DNSROUTER_IP=$(get_container_ip "dnsrouter") + echo -e "${BLUE}❯ ${YELLOW}DNS Router IP is ${DNSROUTER_IP}" + + if [ "${DNSROUTER_IP:-}" = "" ]; then + echo -e "${RED}❯ ERROR: DNS Router IP is not set${RESET}" + exit 1 + fi + + # mount the resolver + LOCAL_RESOLVE="$DIR/../docker/dev/resolv.conf" + rm -rf "${LOCAL_RESOLVE}" + printf "nameserver %s\noptions ndots:0" "${DNSROUTER_IP}" > "${LOCAL_RESOLVE}" + + # bring up all remaining containers, except cypress! + docker-compose up -d --remove-orphans stepca squid + docker-compose pull db + docker-compose up -d --remove-orphans --pull=never fullstack + docker-compose up -d --remove-orphans swagger + + # docker-compose up -d --remove-orphans --force-recreate --build + + # wait for main container to be healthy + bash "$DIR/wait-healthy" "$(docker-compose ps --all -q fullstack)" 120 echo "" echo -e "${CYAN}Admin UI: http://127.0.0.1:3081${RESET}" From 5bdc05878f60a92de4d90a325d8724d0fb521248 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Wed, 16 Oct 2024 11:22:24 +1000 Subject: [PATCH 009/137] Fix issues with certbot command when using LE_SERVER --- backend/internal/certificate.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index aea741c7d..901128d98 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -839,8 +839,8 @@ const internalCertificate = { '--email "' + certificate.meta.letsencrypt_email + '" ' + '--preferred-challenges "dns,http" ' + '--domains "' + certificate.domain_names.join(',') + '" ' + - (letsencryptStaging ? '--staging' : '') + - (letsencryptServer !== null ? `--server '${letsencryptServer}'` : ''); + (letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') + + (letsencryptStaging && letsencryptServer === null ? '--staging ' : ''); logger.info('Command:', cmd); From fe2d8895d68b6f9f96ea0fdba6e34e63a16e24c9 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Wed, 16 Oct 2024 14:53:57 +1000 Subject: [PATCH 010/137] Cypress test for http and dns cert provision --- backend/internal/certificate.js | 69 ++++++++++--------- .../schema/components/certificate-object.json | 27 ++++---- test/cypress/e2e/api/FullCertProvision.cy.js | 61 ++++++++++++++++ test/cypress/plugins/backendApi/client.js | 2 +- 4 files changed, 114 insertions(+), 45 deletions(-) create mode 100644 test/cypress/e2e/api/FullCertProvision.cy.js diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index 901128d98..34b8fdf5a 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -209,6 +209,7 @@ const internalCertificate = { .patchAndFetchById(certificate.id, { expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss') }) + .then(utils.omitRow(omissions())) .then((saved_row) => { // Add cert data for audit log saved_row.meta = _.assign({}, saved_row.meta, { @@ -732,29 +733,29 @@ const internalCertificate = { return utils.exec('openssl x509 -in ' + certificate_file + ' -subject -noout') .then((result) => { + // Examples: + // subject=CN = *.jc21.com // subject=CN = something.example.com const regex = /(?:subject=)?[^=]+=\s+(\S+)/gim; const match = regex.exec(result); - - if (typeof match[1] === 'undefined') { - throw new error.ValidationError('Could not determine subject from certificate: ' + result); + if (match && typeof match[1] !== 'undefined') { + certData['cn'] = match[1]; } - - certData['cn'] = match[1]; }) .then(() => { return utils.exec('openssl x509 -in ' + certificate_file + ' -issuer -noout'); }) + .then((result) => { + // Examples: // issuer=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 + // issuer=C = US, O = Let's Encrypt, CN = E5 + // issuer=O = NginxProxyManager, CN = NginxProxyManager Intermediate CA","O = NginxProxyManager, CN = NginxProxyManager Intermediate CA const regex = /^(?:issuer=)?(.*)$/gim; const match = regex.exec(result); - - if (typeof match[1] === 'undefined') { - throw new error.ValidationError('Could not determine issuer from certificate: ' + result); + if (match && typeof match[1] !== 'undefined') { + certData['issuer'] = match[1]; } - - certData['issuer'] = match[1]; }) .then(() => { return utils.exec('openssl x509 -in ' + certificate_file + ' -dates -noout'); @@ -829,16 +830,16 @@ const internalCertificate = { requestLetsEncryptSsl: (certificate) => { logger.info('Requesting Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); - const cmd = certbotCommand + ' certonly ' + - '--config "' + letsencryptConfig + '" ' + + const cmd = `${certbotCommand} certonly ` + + `--config '${letsencryptConfig}' ` + '--work-dir "/tmp/letsencrypt-lib" ' + '--logs-dir "/tmp/letsencrypt-log" ' + - '--cert-name "npm-' + certificate.id + '" ' + + `--cert-name "npm-${certificate.id}" ` + '--agree-tos ' + '--authenticator webroot ' + - '--email "' + certificate.meta.letsencrypt_email + '" ' + + `--email '${certificate.meta.letsencrypt_email}' ` + '--preferred-challenges "dns,http" ' + - '--domains "' + certificate.domain_names.join(',') + '" ' + + `--domains "${certificate.domain_names.join(',')}" ` + (letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') + (letsencryptStaging && letsencryptServer === null ? '--staging ' : ''); @@ -871,25 +872,26 @@ const internalCertificate = { const hasConfigArg = certificate.meta.dns_provider !== 'route53'; let mainCmd = certbotCommand + ' certonly ' + - '--config "' + letsencryptConfig + '" ' + + `--config '${letsencryptConfig}' ` + '--work-dir "/tmp/letsencrypt-lib" ' + '--logs-dir "/tmp/letsencrypt-log" ' + - '--cert-name "npm-' + certificate.id + '" ' + + `--cert-name 'npm-${certificate.id}' ` + '--agree-tos ' + - '--email "' + certificate.meta.letsencrypt_email + '" ' + - '--domains "' + certificate.domain_names.join(',') + '" ' + - '--authenticator ' + dnsPlugin.full_plugin_name + ' ' + + `--email '${certificate.meta.letsencrypt_email}' ` + + `--domains '${certificate.domain_names.join(',')}' ` + + `--authenticator '${dnsPlugin.full_plugin_name}' ` + ( hasConfigArg - ? '--' + dnsPlugin.full_plugin_name + '-credentials "' + credentialsLocation + '"' + ? `--${dnsPlugin.full_plugin_name}-credentials '${credentialsLocation}' ` : '' ) + ( certificate.meta.propagation_seconds !== undefined - ? ' --' + dnsPlugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds + ? `--${dnsPlugin.full_plugin_name}-propagation-seconds '${certificate.meta.propagation_seconds}' ` : '' ) + - (letsencryptStaging ? ' --staging' : ''); + (letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') + + (letsencryptStaging && letsencryptServer === null ? '--staging ' : ''); // Prepend the path to the credentials file as an environment variable if (certificate.meta.dns_provider === 'route53') { @@ -966,14 +968,15 @@ const internalCertificate = { logger.info('Renewing Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); const cmd = certbotCommand + ' renew --force-renewal ' + - '--config "' + letsencryptConfig + '" ' + + `--config '${letsencryptConfig}' ` + '--work-dir "/tmp/letsencrypt-lib" ' + '--logs-dir "/tmp/letsencrypt-log" ' + - '--cert-name "npm-' + certificate.id + '" ' + + `--cert-name 'npm-${certificate.id}' ` + '--preferred-challenges "dns,http" ' + '--no-random-sleep-on-renew ' + '--disable-hook-validation ' + - (letsencryptStaging ? '--staging' : ''); + (letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') + + (letsencryptStaging && letsencryptServer === null ? '--staging ' : ''); logger.info('Command:', cmd); @@ -998,13 +1001,14 @@ const internalCertificate = { logger.info(`Renewing Let'sEncrypt certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`); let mainCmd = certbotCommand + ' renew --force-renewal ' + - '--config "' + letsencryptConfig + '" ' + + `--config "${letsencryptConfig}" ` + '--work-dir "/tmp/letsencrypt-lib" ' + '--logs-dir "/tmp/letsencrypt-log" ' + - '--cert-name "npm-' + certificate.id + '" ' + + `--cert-name 'npm-${certificate.id}' ` + '--disable-hook-validation ' + '--no-random-sleep-on-renew ' + - (letsencryptStaging ? ' --staging' : ''); + (letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') + + (letsencryptStaging && letsencryptServer === null ? '--staging ' : ''); // Prepend the path to the credentials file as an environment variable if (certificate.meta.dns_provider === 'route53') { @@ -1030,12 +1034,13 @@ const internalCertificate = { logger.info('Revoking Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); const mainCmd = certbotCommand + ' revoke ' + - '--config "' + letsencryptConfig + '" ' + + `--config '${letsencryptConfig}' ` + '--work-dir "/tmp/letsencrypt-lib" ' + '--logs-dir "/tmp/letsencrypt-log" ' + - '--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' + + `--cert-path '/etc/letsencrypt/live/npm-${certificate.id}/fullchain.pem' ` + '--delete-after-revoke ' + - (letsencryptStaging ? '--staging' : ''); + (letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') + + (letsencryptStaging && letsencryptServer === null ? '--staging ' : ''); // Don't fail command if file does not exist const delete_credentialsCmd = `rm -f '/etc/letsencrypt/credentials/credentials-${certificate.id}' || true`; diff --git a/backend/schema/components/certificate-object.json b/backend/schema/components/certificate-object.json index a4e8e1fce..b75dcf61d 100644 --- a/backend/schema/components/certificate-object.json +++ b/backend/schema/components/certificate-object.json @@ -45,11 +45,13 @@ "type": "object", "additionalProperties": false, "properties": { - "letsencrypt_email": { - "type": "string" + "certificate": { + "type": "string", + "minLength": 1 }, - "letsencrypt_agree": { - "type": "boolean" + "certificate_key": { + "type": "string", + "minLength": 1 }, "dns_challenge": { "type": "boolean" @@ -60,17 +62,18 @@ "dns_provider_credentials": { "type": "string" }, + "letsencrypt_agree": { + "type": "boolean" + }, + "letsencrypt_certificate": { + "type": "object" + }, + "letsencrypt_email": { + "type": "string" + }, "propagation_seconds": { "type": "integer", "minimum": 0 - }, - "certificate": { - "type": "string", - "minLength": 1 - }, - "certificate_key": { - "type": "string", - "minLength": 1 } } } diff --git a/test/cypress/e2e/api/FullCertProvision.cy.js b/test/cypress/e2e/api/FullCertProvision.cy.js new file mode 100644 index 000000000..93cacce9e --- /dev/null +++ b/test/cypress/e2e/api/FullCertProvision.cy.js @@ -0,0 +1,61 @@ +/// + +describe('Full Certificate Provisions', () => { + let token; + + before(() => { + cy.getToken().then((tok) => { + token = tok; + }); + }); + + it.only('Should be able to create new http certificate', function() { + cy.task('backendApiPost', { + token: token, + path: '/api/nginx/certificates', + data: { + domain_names: [ + 'website1.example.com' + ], + meta: { + letsencrypt_email: 'admin@example.com', + letsencrypt_agree: true, + dns_challenge: false + }, + provider: 'letsencrypt' + } + }).then((data) => { + cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data); + expect(data).to.have.property('id'); + expect(data.id).to.be.greaterThan(0); + expect(data.provider).to.be.equal('letsencrypt'); + }); + }); + + it('Should be able to create new DNS certificate with Powerdns', function() { + cy.task('backendApiPost', { + token: token, + path: '/api/certificates', + data: { + domain_names: [ + 'website2.example.com' + ], + meta: { + letsencrypt_email: "admin@example.com", + dns_challenge: true, + dns_provider: 'powerdns', + dns_provider_credentials: 'dns_powerdns_api_url = http://ns1.pdns:8081\r\ndns_powerdns_api_key = npm', + letsencrypt_agree: true + }, + provider: 'letsencrypt' + } + }).then((data) => { + cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data); + expect(data).to.have.property('id'); + expect(data.id).to.be.greaterThan(0); + expect(data.provider).to.be.equal('letsencrypt'); + expect(data.meta.dns_provider).to.be.equal('powerdns'); + }); + }); + +}); diff --git a/test/cypress/plugins/backendApi/client.js b/test/cypress/plugins/backendApi/client.js index ba28e3ae1..c10653e41 100644 --- a/test/cypress/plugins/backendApi/client.js +++ b/test/cypress/plugins/backendApi/client.js @@ -7,7 +7,7 @@ const BackendApi = function(config, token) { this.axios = axios.create({ baseURL: config.baseUrl, - timeout: 5000, + timeout: 60000, }); }; From d96a3987c0d6c679059af47bec33f8d94f7e4d78 Mon Sep 17 00:00:00 2001 From: Nephiel Date: Wed, 16 Oct 2024 19:04:50 +0000 Subject: [PATCH 011/137] Fix forward_scheme validation in Redirection Host Should solve error `data/forward_scheme must be equal to one of the allowed values` when configuring a Redirection Host with scheme set to `auto`. #4074 --- backend/schema/components/redirection-host-object.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/schema/components/redirection-host-object.json b/backend/schema/components/redirection-host-object.json index cc4dbdd2f..e7a495fd3 100644 --- a/backend/schema/components/redirection-host-object.json +++ b/backend/schema/components/redirection-host-object.json @@ -28,7 +28,7 @@ }, "forward_scheme": { "type": "string", - "enum": ["http", "https"] + "enum": ["auto", "http", "https"] }, "forward_domain_name": { "description": "Domain Name", From fa2c814fcb76b6a11b979dc23a817853a459644d Mon Sep 17 00:00:00 2001 From: Nephiel Date: Wed, 16 Oct 2024 19:09:14 +0000 Subject: [PATCH 012/137] Fix schema validation in Default Site Should solve error `data/value must match exactly one schema in oneOf` when setting the Default Site to 404 or 444. #4074 --- backend/schema/components/setting-object.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/schema/components/setting-object.json b/backend/schema/components/setting-object.json index e08777264..65ec2a08e 100644 --- a/backend/schema/components/setting-object.json +++ b/backend/schema/components/setting-object.json @@ -25,7 +25,7 @@ "value": { "description": "Value in almost any form", "example": "congratulations", - "oneOf": [ + "anyOf": [ { "type": "string", "minLength": 1 From edbed1af90ab86658a9fc4a17ef571797484edcc Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Thu, 17 Oct 2024 08:48:47 +1000 Subject: [PATCH 013/137] Adds tests for settings endpoints and reenables dns cert test and fixes problems with schema --- backend/internal/nginx.js | 4 +- .../schema/components/proxy-host-object.json | 10 +- backend/schema/components/setting-object.json | 5 +- .../paths/nginx/dead-hosts/hostID/put.json | 4 +- .../schema/paths/nginx/dead-hosts/post.json | 4 +- .../paths/nginx/proxy-hosts/hostID/put.json | 4 +- .../schema/paths/nginx/proxy-hosts/post.json | 4 +- .../nginx/redirection-hosts/hostID/put.json | 4 +- .../paths/nginx/redirection-hosts/post.json | 4 +- .../paths/nginx/streams/streamID/put.json | 4 +- .../schema/paths/settings/settingID/put.json | 18 ++- test/cypress/e2e/api/FullCertProvision.cy.js | 7 +- .../e2e/api/{Hosts.cy.js => ProxyHosts.cy.js} | 2 +- test/cypress/e2e/api/Settings.cy.js | 124 ++++++++++++++++++ test/cypress/plugins/backendApi/client.js | 2 +- 15 files changed, 160 insertions(+), 40 deletions(-) rename test/cypress/e2e/api/{Hosts.cy.js => ProxyHosts.cy.js} (96%) create mode 100644 test/cypress/e2e/api/Settings.cy.js diff --git a/backend/internal/nginx.js b/backend/internal/nginx.js index 77933e733..5f802c004 100644 --- a/backend/internal/nginx.js +++ b/backend/internal/nginx.js @@ -181,7 +181,9 @@ const internalNginx = { * @param {Object} host * @returns {Promise} */ - generateConfig: (host_type, host) => { + generateConfig: (host_type, host_row) => { + // Prevent modifying the original object: + let host = JSON.parse(JSON.stringify(host_row)); const nice_host_type = internalNginx.getFileFriendlyHostType(host_type); if (config.debug()) { diff --git a/backend/schema/components/proxy-host-object.json b/backend/schema/components/proxy-host-object.json index a64a58c8f..5098802b1 100644 --- a/backend/schema/components/proxy-host-object.json +++ b/backend/schema/components/proxy-host-object.json @@ -23,9 +23,7 @@ "locations", "hsts_enabled", "hsts_subdomains", - "certificate", - "use_default_location", - "ipv6" + "certificate" ], "additionalProperties": false, "properties": { @@ -151,12 +149,6 @@ "$ref": "./access-list-object.json" } ] - }, - "use_default_location": { - "type": "boolean" - }, - "ipv6": { - "type": "boolean" } } } diff --git a/backend/schema/components/setting-object.json b/backend/schema/components/setting-object.json index 65ec2a08e..b9c6a1039 100644 --- a/backend/schema/components/setting-object.json +++ b/backend/schema/components/setting-object.json @@ -46,7 +46,10 @@ }, "meta": { "description": "Extra metadata", - "example": {}, + "example": { + "redirect": "http://example.com", + "html": "

404

" + }, "type": "object" } } diff --git a/backend/schema/paths/nginx/dead-hosts/hostID/put.json b/backend/schema/paths/nginx/dead-hosts/hostID/put.json index 6a0a57e3a..f9505ed48 100644 --- a/backend/schema/paths/nginx/dead-hosts/hostID/put.json +++ b/backend/schema/paths/nginx/dead-hosts/hostID/put.json @@ -94,9 +94,7 @@ "avatar": "", "roles": ["admin"] }, - "certificate": null, - "use_default_location": true, - "ipv6": true + "certificate": null } } }, diff --git a/backend/schema/paths/nginx/dead-hosts/post.json b/backend/schema/paths/nginx/dead-hosts/post.json index 593135065..c8bbb6932 100644 --- a/backend/schema/paths/nginx/dead-hosts/post.json +++ b/backend/schema/paths/nginx/dead-hosts/post.json @@ -79,9 +79,7 @@ "nickname": "Admin", "avatar": "", "roles": ["admin"] - }, - "use_default_location": true, - "ipv6": true + } } } }, diff --git a/backend/schema/paths/nginx/proxy-hosts/hostID/put.json b/backend/schema/paths/nginx/proxy-hosts/hostID/put.json index af73905dc..5cab6e752 100644 --- a/backend/schema/paths/nginx/proxy-hosts/hostID/put.json +++ b/backend/schema/paths/nginx/proxy-hosts/hostID/put.json @@ -129,9 +129,7 @@ "roles": ["admin"] }, "certificate": null, - "access_list": null, - "use_default_location": true, - "ipv6": true + "access_list": null } } }, diff --git a/backend/schema/paths/nginx/proxy-hosts/post.json b/backend/schema/paths/nginx/proxy-hosts/post.json index 13f641610..85455fb6b 100644 --- a/backend/schema/paths/nginx/proxy-hosts/post.json +++ b/backend/schema/paths/nginx/proxy-hosts/post.json @@ -114,9 +114,7 @@ "avatar": "//www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?default=mm", "roles": ["admin"] }, - "access_list": null, - "use_default_location": true, - "ipv6": true + "access_list": null } } }, diff --git a/backend/schema/paths/nginx/redirection-hosts/hostID/put.json b/backend/schema/paths/nginx/redirection-hosts/hostID/put.json index 870f16fcd..fd97cbfa8 100644 --- a/backend/schema/paths/nginx/redirection-hosts/hostID/put.json +++ b/backend/schema/paths/nginx/redirection-hosts/hostID/put.json @@ -114,9 +114,7 @@ "avatar": "", "roles": ["admin"] }, - "certificate": null, - "use_default_location": true, - "ipv6": true + "certificate": null } } }, diff --git a/backend/schema/paths/nginx/redirection-hosts/post.json b/backend/schema/paths/nginx/redirection-hosts/post.json index 3a9a05fec..5bfde2c38 100644 --- a/backend/schema/paths/nginx/redirection-hosts/post.json +++ b/backend/schema/paths/nginx/redirection-hosts/post.json @@ -99,9 +99,7 @@ "nickname": "Admin", "avatar": "", "roles": ["admin"] - }, - "use_default_location": true, - "ipv6": true + } } } }, diff --git a/backend/schema/paths/nginx/streams/streamID/put.json b/backend/schema/paths/nginx/streams/streamID/put.json index f3ef54d47..fbfdc901b 100644 --- a/backend/schema/paths/nginx/streams/streamID/put.json +++ b/backend/schema/paths/nginx/streams/streamID/put.json @@ -129,9 +129,7 @@ "roles": ["admin"] }, "certificate": null, - "access_list": null, - "use_default_location": true, - "ipv6": true + "access_list": null } } }, diff --git a/backend/schema/paths/settings/settingID/put.json b/backend/schema/paths/settings/settingID/put.json index 5888ec056..4ca624293 100644 --- a/backend/schema/paths/settings/settingID/put.json +++ b/backend/schema/paths/settings/settingID/put.json @@ -13,7 +13,8 @@ "name": "settingID", "schema": { "type": "string", - "minLength": 1 + "minLength": 1, + "enum": ["default-site"] }, "required": true, "description": "Setting ID", @@ -31,10 +32,21 @@ "minProperties": 1, "properties": { "value": { - "$ref": "../../../components/setting-object.json#/properties/value" + "type": "string", + "minLength": 1, + "enum": ["congratulations", "404", "444", "redirect", "html"] }, "meta": { - "$ref": "../../../components/setting-object.json#/properties/meta" + "type": "object", + "additionalProperties": false, + "properties": { + "redirect": { + "type": "string" + }, + "html": { + "type": "string" + } + } } } } diff --git a/test/cypress/e2e/api/FullCertProvision.cy.js b/test/cypress/e2e/api/FullCertProvision.cy.js index 93cacce9e..5ca5692cd 100644 --- a/test/cypress/e2e/api/FullCertProvision.cy.js +++ b/test/cypress/e2e/api/FullCertProvision.cy.js @@ -9,7 +9,7 @@ describe('Full Certificate Provisions', () => { }); }); - it.only('Should be able to create new http certificate', function() { + it('Should be able to create new http certificate', function() { cy.task('backendApiPost', { token: token, path: '/api/nginx/certificates', @@ -35,7 +35,7 @@ describe('Full Certificate Provisions', () => { it('Should be able to create new DNS certificate with Powerdns', function() { cy.task('backendApiPost', { token: token, - path: '/api/certificates', + path: '/api/nginx/certificates', data: { domain_names: [ 'website2.example.com' @@ -45,7 +45,8 @@ describe('Full Certificate Provisions', () => { dns_challenge: true, dns_provider: 'powerdns', dns_provider_credentials: 'dns_powerdns_api_url = http://ns1.pdns:8081\r\ndns_powerdns_api_key = npm', - letsencrypt_agree: true + letsencrypt_agree: true, + propagation_seconds: 5, }, provider: 'letsencrypt' } diff --git a/test/cypress/e2e/api/Hosts.cy.js b/test/cypress/e2e/api/ProxyHosts.cy.js similarity index 96% rename from test/cypress/e2e/api/Hosts.cy.js rename to test/cypress/e2e/api/ProxyHosts.cy.js index 75d732c7c..5bc645800 100644 --- a/test/cypress/e2e/api/Hosts.cy.js +++ b/test/cypress/e2e/api/ProxyHosts.cy.js @@ -1,6 +1,6 @@ /// -describe('Hosts endpoints', () => { +describe('Proxy Hosts endpoints', () => { let token; before(() => { diff --git a/test/cypress/e2e/api/Settings.cy.js b/test/cypress/e2e/api/Settings.cy.js new file mode 100644 index 000000000..6942760c7 --- /dev/null +++ b/test/cypress/e2e/api/Settings.cy.js @@ -0,0 +1,124 @@ +/// + +describe('Settings endpoints', () => { + let token; + + before(() => { + cy.getToken().then((tok) => { + token = tok; + }); + }); + + it('Get all settings', function() { + cy.task('backendApiGet', { + token: token, + path: '/api/settings', + }).then((data) => { + cy.validateSwaggerSchema('get', 200, '/settings', data); + expect(data.length).to.be.greaterThan(0); + }); + }); + + it('Get default-site setting', function() { + cy.task('backendApiGet', { + token: token, + path: '/api/settings/default-site', + }).then((data) => { + cy.validateSwaggerSchema('get', 200, '/settings/{settingID}', data); + expect(data).to.have.property('id'); + expect(data.id).to.be.equal('default-site'); + }); + }); + + it('Default Site congratulations', function() { + cy.task('backendApiPut', { + token: token, + path: '/api/settings/default-site', + data: { + value: 'congratulations', + }, + }).then((data) => { + cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data); + expect(data).to.have.property('id'); + expect(data.id).to.be.equal('default-site'); + expect(data).to.have.property('value'); + expect(data.value).to.be.equal('congratulations'); + }); + }); + + it('Default Site 404', function() { + cy.task('backendApiPut', { + token: token, + path: '/api/settings/default-site', + data: { + value: '404', + }, + }).then((data) => { + cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data); + expect(data).to.have.property('id'); + expect(data.id).to.be.equal('default-site'); + expect(data).to.have.property('value'); + expect(data.value).to.be.equal('404'); + }); + }); + + it('Default Site 444', function() { + cy.task('backendApiPut', { + token: token, + path: '/api/settings/default-site', + data: { + value: '444', + }, + }).then((data) => { + cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data); + expect(data).to.have.property('id'); + expect(data.id).to.be.equal('default-site'); + expect(data).to.have.property('value'); + expect(data.value).to.be.equal('444'); + }); + }); + + it('Default Site redirect', function() { + cy.task('backendApiPut', { + token: token, + path: '/api/settings/default-site', + data: { + value: 'redirect', + meta: { + redirect: 'https://www.google.com', + }, + }, + }).then((data) => { + cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data); + expect(data).to.have.property('id'); + expect(data.id).to.be.equal('default-site'); + expect(data).to.have.property('value'); + expect(data.value).to.be.equal('redirect'); + expect(data).to.have.property('meta'); + expect(data.meta).to.have.property('redirect'); + expect(data.meta.redirect).to.be.equal('https://www.google.com'); + }); + }); + + it('Default Site html', function() { + cy.task('backendApiPut', { + token: token, + path: '/api/settings/default-site', + data: { + value: 'html', + meta: { + html: '

hello world

' + }, + }, + }).then((data) => { + cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data); + expect(data).to.have.property('id'); + expect(data.id).to.be.equal('default-site'); + expect(data).to.have.property('value'); + expect(data.value).to.be.equal('html'); + expect(data).to.have.property('meta'); + expect(data.meta).to.have.property('html'); + expect(data.meta.html).to.be.equal('

hello world

'); + }); + }); +}); diff --git a/test/cypress/plugins/backendApi/client.js b/test/cypress/plugins/backendApi/client.js index c10653e41..6f5f7661e 100644 --- a/test/cypress/plugins/backendApi/client.js +++ b/test/cypress/plugins/backendApi/client.js @@ -7,7 +7,7 @@ const BackendApi = function(config, token) { this.axios = axios.create({ baseURL: config.baseUrl, - timeout: 60000, + timeout: 90000, }); }; From 2f9e062718d0d66fcff0e240ac47533bb1fcbda4 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Thu, 17 Oct 2024 09:05:25 +1000 Subject: [PATCH 014/137] bump version --- .version | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.version b/.version index d8b698973..3cf561c0b 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.12.0 +2.12.1 diff --git a/README.md b/README.md index 2d1b8da5b..9ac6a6c85 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@



- + From d499e2bfef7c79981ad46fa5946e743d7380eb65 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Thu, 17 Oct 2024 10:00:12 +1000 Subject: [PATCH 015/137] Push PR and github branch builds to separate docker image --- Jenkinsfile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 9b29ee970..302e05b27 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -43,7 +43,7 @@ pipeline { steps { script { // Defaults to the Branch name, which is applies to all branches AND pr's - buildxPushTags = "-t docker.io/jc21/${IMAGE}:github-${BRANCH_LOWER}" + buildxPushTags = "-t docker.io/nginxproxymanager/${IMAGE}-dev:${BRANCH_LOWER}" } } } @@ -203,7 +203,13 @@ pipeline { } steps { script { - npmGithubPrComment("Docker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${IMAGE}) as `jc21/${IMAGE}:github-${BRANCH_LOWER}`\n\n**Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes.", true) + npmGithubPrComment("""Docker Image for build ${BUILD_NUMBER} is available on +[DockerHub](https://cloud.docker.com/repository/docker/nginxproxymanager/${IMAGE}-dev) +as `nginxproxymanager/${IMAGE}-dev:${BRANCH_LOWER}` + +**Note:** ensure you backup your NPM instance before testing this image! Especially if there are database changes +**Note:** this is a different docker image namespace than the official image +""", true) } } } From 96c58b203ee80690a1af1ce8f4ea28a50285eca9 Mon Sep 17 00:00:00 2001 From: Guiorgy Date: Thu, 17 Oct 2024 15:34:04 +0400 Subject: [PATCH 016/137] normalize indentations in certbot-dns-plugins.json --- global/certbot-dns-plugins.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/global/certbot-dns-plugins.json b/global/certbot-dns-plugins.json index 6729842e8..dee7b8611 100644 --- a/global/certbot-dns-plugins.json +++ b/global/certbot-dns-plugins.json @@ -7,7 +7,7 @@ "credentials": "dns_acmedns_api_url = http://acmedns-server/\ndns_acmedns_registration_file = /data/acme-registration.json", "full_plugin_name": "dns-acmedns" }, - "active24":{ + "active24":{ "name": "Active24", "package_name": "certbot-dns-active24", "version": "~=1.5.1", @@ -424,13 +424,13 @@ "full_plugin_name": "dns-rfc2136" }, "rockenstein": { - "name": "rockenstein AG", - "package_name": "certbot-dns-rockenstein", - "version": "~=1.0.0", - "dependencies": "", - "credentials": "dns_rockenstein_token=", - "full_plugin_name": "dns-rockenstein" - }, + "name": "rockenstein AG", + "package_name": "certbot-dns-rockenstein", + "version": "~=1.0.0", + "dependencies": "", + "credentials": "dns_rockenstein_token=", + "full_plugin_name": "dns-rockenstein" + }, "route53": { "name": "Route 53 (Amazon)", "package_name": "certbot-dns-route53", From d92421d098d26eee73d4d80a4a075efe058257de Mon Sep 17 00:00:00 2001 From: "T. Todua" <7117978+ttodua@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:33:32 +0400 Subject: [PATCH 017/137] doc(site) - default credentials change --- docs/src/setup/index.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/src/setup/index.md b/docs/src/setup/index.md index 9b1505bed..bffcf6d56 100644 --- a/docs/src/setup/index.md +++ b/docs/src/setup/index.md @@ -137,5 +137,13 @@ Email: admin@example.com Password: changeme ``` -Immediately after logging in with this default user you will be asked to modify your details and change your password. +Immediately after logging in with this default user you will be asked to modify your details and change your password. You can set pre-defined initial credentials in docker-compose: + + +``` + environment: + INITIAL_ADMIN_EMAIL: my@example.com + INITIAL_ADMIN_PASSWORD: mypassword1 +``` + From 68a9baf206fb722b10d829633cb41b22b22e1c3d Mon Sep 17 00:00:00 2001 From: "T. Todua" <7117978+ttodua@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:35:15 +0400 Subject: [PATCH 018/137] minor --- docs/src/setup/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/setup/index.md b/docs/src/setup/index.md index bffcf6d56..ee8e9903d 100644 --- a/docs/src/setup/index.md +++ b/docs/src/setup/index.md @@ -137,7 +137,7 @@ Email: admin@example.com Password: changeme ``` -Immediately after logging in with this default user you will be asked to modify your details and change your password. You can set pre-defined initial credentials in docker-compose: +Immediately after logging in with this default user you will be asked to modify your details and change your password. You can change defaults with: ``` From d7e0558a35a50a3f117e129ceec698b3ee15aefb Mon Sep 17 00:00:00 2001 From: Sergey 'dreik' Kolesnik Date: Thu, 24 Oct 2024 01:30:14 +0300 Subject: [PATCH 019/137] http2 directive to reduce warns in logs --- backend/templates/_listen.conf | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/templates/_listen.conf b/backend/templates/_listen.conf index ad1c96ba0..34a808e6a 100644 --- a/backend/templates/_listen.conf +++ b/backend/templates/_listen.conf @@ -5,11 +5,16 @@ #listen [::]:80; {% endif %} {% if certificate -%} - listen 443 ssl{% if http2_support == 1 or http2_support == true %} http2{% endif %}; + listen 443 ssl; {% if ipv6 -%} - listen [::]:443 ssl{% if http2_support == 1 or http2_support == true %} http2{% endif %}; + listen [::]:443 ssl; {% else -%} #listen [::]:443; {% endif %} {% endif %} server_name {{ domain_names | join: " " }}; +{% if http2_support == 1 or http2_support == true %} + http2 on; +{% else -%} + http2 off; +{% endif %} \ No newline at end of file From dad8d0ca00d0d366d46d1bbe85b7c73255cde756 Mon Sep 17 00:00:00 2001 From: Chris Maffey Date: Thu, 24 Oct 2024 14:04:17 +1300 Subject: [PATCH 020/137] Update _access.conf the pass_auth and satisfy_any properties and now boolean true/false, they do not == 1 so the switching in this template breaks --- backend/templates/_access.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/templates/_access.conf b/backend/templates/_access.conf index 447006c0c..f59263775 100644 --- a/backend/templates/_access.conf +++ b/backend/templates/_access.conf @@ -4,7 +4,7 @@ auth_basic "Authorization required"; auth_basic_user_file /data/access/{{ access_list_id }}; - {% if access_list.pass_auth == 0 %} + {% if access_list.pass_auth == 0 or access_list.pass_auth == true %} proxy_set_header Authorization ""; {% endif %} @@ -17,7 +17,7 @@ deny all; # Access checks must... - {% if access_list.satisfy_any == 1 %} + {% if access_list.satisfy_any == 1 or access_list.satisfy_any == true %} satisfy any; {% else %} satisfy all; From 2e9a4f1aed06231f2ce1582fa75d603f10779fa6 Mon Sep 17 00:00:00 2001 From: Chris Maffey Date: Thu, 24 Oct 2024 17:29:16 +1300 Subject: [PATCH 021/137] Update put.json Password can be left blank for updates. Otherwise you have to reenter the password every time you save the auth list --- backend/schema/paths/nginx/access-lists/listID/put.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/schema/paths/nginx/access-lists/listID/put.json b/backend/schema/paths/nginx/access-lists/listID/put.json index 3a69f8567..7f887dad6 100644 --- a/backend/schema/paths/nginx/access-lists/listID/put.json +++ b/backend/schema/paths/nginx/access-lists/listID/put.json @@ -49,8 +49,7 @@ "minLength": 1 }, "password": { - "type": "string", - "minLength": 1 + "type": "string" } } } From 1c1cee383674669adeb10b2b290699943992e411 Mon Sep 17 00:00:00 2001 From: Emil <651107+prospo@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:25:09 +0000 Subject: [PATCH 022/137] feat: Add leaseweb to certbot-dns-plugins --- global/certbot-dns-plugins.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/global/certbot-dns-plugins.json b/global/certbot-dns-plugins.json index dee7b8611..075877744 100644 --- a/global/certbot-dns-plugins.json +++ b/global/certbot-dns-plugins.json @@ -303,6 +303,14 @@ "credentials": "dns_joker_username = \ndns_joker_password = \ndns_joker_domain = ", "full_plugin_name": "dns-joker" }, + "leaseweb": { + "name": "LeaseWeb", + "package_name": "certbot-dns-leaseweb", + "version": "~=1.0.1", + "dependencies": "", + "credentials": "dns_leaseweb_api_token = 01234556789", + "full_plugin_name": "dns-leaseweb" + }, "linode": { "name": "Linode", "package_name": "certbot-dns-linode", From e9d4f5b827564fcb90883a77710779192495f260 Mon Sep 17 00:00:00 2001 From: mitossoft-rd <106842163+mitossoft-rd@users.noreply.github.com> Date: Mon, 28 Oct 2024 02:59:23 +0300 Subject: [PATCH 023/137] Remove variable usage from proxy_pass directive to fix resolution issues By using a static URL, the backend server can be accessed reliably, avoiding the common 404 errors or "no resolver defined" issues seen when variables are used. --- backend/templates/_location.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/templates/_location.conf b/backend/templates/_location.conf index fcc7d1210..04a4b18f3 100644 --- a/backend/templates/_location.conf +++ b/backend/templates/_location.conf @@ -11,7 +11,7 @@ set $proxy_server "{{ forward_host }}"; set $proxy_port {{ forward_port }}; - proxy_pass $proxy_forward_scheme://$proxy_server:$proxy_port{{ forward_path }}; + proxy_pass {{ forward_scheme }}:{{ forward_host }}:{{ forward_port }}{{ forward_path }}; {% include "_access.conf" %} {% include "_assets.conf" %} From a55de386e74cb21cf35a60251bf1e920c9aca062 Mon Sep 17 00:00:00 2001 From: mitossoft-rd <106842163+mitossoft-rd@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:15:08 +0300 Subject: [PATCH 024/137] Fix URL format --- backend/templates/_location.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/templates/_location.conf b/backend/templates/_location.conf index 04a4b18f3..ba9ea6953 100644 --- a/backend/templates/_location.conf +++ b/backend/templates/_location.conf @@ -11,7 +11,7 @@ set $proxy_server "{{ forward_host }}"; set $proxy_port {{ forward_port }}; - proxy_pass {{ forward_scheme }}:{{ forward_host }}:{{ forward_port }}{{ forward_path }}; + proxy_pass {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }}; {% include "_access.conf" %} {% include "_assets.conf" %} From f7d3ca0b07a51578350575f53799529905758d83 Mon Sep 17 00:00:00 2001 From: mitossoft-rd <106842163+mitossoft-rd@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:18:54 +0300 Subject: [PATCH 025/137] Cleaning unused variable. --- backend/templates/_location.conf | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backend/templates/_location.conf b/backend/templates/_location.conf index ba9ea6953..a2ecb166d 100644 --- a/backend/templates/_location.conf +++ b/backend/templates/_location.conf @@ -7,10 +7,6 @@ proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr; - set $proxy_forward_scheme {{ forward_scheme }}; - set $proxy_server "{{ forward_host }}"; - set $proxy_port {{ forward_port }}; - proxy_pass {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }}; {% include "_access.conf" %} From 62c94f309921084bfae123e5e360d42ec9413c76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 02:19:58 +0000 Subject: [PATCH 026/137] Bump elliptic from 6.5.7 to 6.6.0 in /frontend Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.7 to 6.6.0. - [Commits](https://github.com/indutny/elliptic/compare/v6.5.7...v6.6.0) --- updated-dependencies: - dependency-name: elliptic dependency-type: indirect ... Signed-off-by: dependabot[bot] --- frontend/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/yarn.lock b/frontend/yarn.lock index c37fc95df..02655441f 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -2648,9 +2648,9 @@ electron-to-chromium@^1.3.47: integrity sha512-67V62Z4CFOiAtox+o+tosGfVk0QX4DJgH609tjT8QymbJZVAI/jWnAthnr8c5hnRNziIRwkc9EMQYejiVz3/9Q== elliptic@^6.5.3, elliptic@^6.5.4: - version "6.5.7" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" - integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== + version "6.6.0" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.0.tgz#5919ec723286c1edf28685aa89261d4761afa210" + integrity sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA== dependencies: bn.js "^4.11.9" brorand "^1.1.0" From d6791f4e38e386f9b430a6bdb3d8853c3dff68f3 Mon Sep 17 00:00:00 2001 From: Jonas Riedel Date: Thu, 31 Oct 2024 11:25:38 +0100 Subject: [PATCH 027/137] docs(setup): Remove deprecated version from docker-compose.yml --- docs/src/advanced-config/index.md | 3 --- docs/src/setup/index.md | 2 -- 2 files changed, 5 deletions(-) diff --git a/docs/src/advanced-config/index.md b/docs/src/advanced-config/index.md index efeaefec3..c9b42bcc7 100644 --- a/docs/src/advanced-config/index.md +++ b/docs/src/advanced-config/index.md @@ -50,7 +50,6 @@ networks: Let's look at a Portainer example: ```yml -version: '3.8' services: portainer: @@ -92,8 +91,6 @@ This image supports the use of Docker secrets to import from files and keep sens You can set any environment variable from a file by appending `__FILE` (double-underscore FILE) to the environmental variable name. ```yml -version: '3.8' - secrets: # Secrets are single-line text files where the sole content is the secret # Paths in this example assume that secrets are kept in local folder called ".secrets" diff --git a/docs/src/setup/index.md b/docs/src/setup/index.md index ee8e9903d..0b5d69da8 100644 --- a/docs/src/setup/index.md +++ b/docs/src/setup/index.md @@ -9,7 +9,6 @@ outline: deep Create a `docker-compose.yml` file: ```yml -version: '3.8' services: app: image: 'jc21/nginx-proxy-manager:latest' @@ -55,7 +54,6 @@ are going to use. Here is an example of what your `docker-compose.yml` will look like when using a MariaDB container: ```yml -version: '3.8' services: app: image: 'jc21/nginx-proxy-manager:latest' From a0b26b9e9842414ea8ab5c500fb467832397f9d7 Mon Sep 17 00:00:00 2001 From: irexyc Date: Mon, 4 Nov 2024 20:01:39 +0800 Subject: [PATCH 028/137] Add woff2 format to assets.conf for Cache Assets --- docker/rootfs/etc/nginx/conf.d/include/assets.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/rootfs/etc/nginx/conf.d/include/assets.conf b/docker/rootfs/etc/nginx/conf.d/include/assets.conf index b7037343d..5a90beb8a 100644 --- a/docker/rootfs/etc/nginx/conf.d/include/assets.conf +++ b/docker/rootfs/etc/nginx/conf.d/include/assets.conf @@ -1,4 +1,4 @@ -location ~* ^.*\.(css|js|jpe?g|gif|png|webp|woff|eot|ttf|svg|ico|css\.map|js\.map)$ { +location ~* ^.*\.(css|js|jpe?g|gif|png|webp|woff|woff2|eot|ttf|svg|ico|css\.map|js\.map)$ { if_modified_since off; # use the public cache From c17175213717c40fda3a92a2988403d38494e5d9 Mon Sep 17 00:00:00 2001 From: Medan-rfz Date: Fri, 8 Nov 2024 02:29:38 +0400 Subject: [PATCH 029/137] Added certbot plugin for Beget DNS service --- global/certbot-dns-plugins.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/global/certbot-dns-plugins.json b/global/certbot-dns-plugins.json index 075877744..39b94316f 100644 --- a/global/certbot-dns-plugins.json +++ b/global/certbot-dns-plugins.json @@ -31,6 +31,14 @@ "credentials": "# This plugin supported API authentication using either Service Principals or utilizing a Managed Identity assigned to the virtual machine.\n# Regardless which authentication method used, the identity will need the “DNS Zone Contributor” role assigned to it.\n# As multiple Azure DNS Zones in multiple resource groups can exist, the config file needs a mapping of zone to resource group ID. Multiple zones -> ID mappings can be listed by using the key dns_azure_zoneX where X is a unique number. At least 1 zone mapping is required.\n\n# Using a service principal (option 1)\ndns_azure_sp_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5\ndns_azure_sp_client_secret = E-xqXU83Y-jzTI6xe9fs2YC~mck3ZzUih9\ndns_azure_tenant_id = ed1090f3-ab18-4b12-816c-599af8a88cf7\n\n# Using used assigned MSI (option 2)\n# dns_azure_msi_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5\n\n# Using system assigned MSI (option 3)\n# dns_azure_msi_system_assigned = true\n\n# Zones (at least one always required)\ndns_azure_zone1 = example.com:/subscriptions/c135abce-d87d-48df-936c-15596c6968a5/resourceGroups/dns1\ndns_azure_zone2 = example.org:/subscriptions/99800903-fb14-4992-9aff-12eaf2744622/resourceGroups/dns2", "full_plugin_name": "dns-azure" }, + "beget": { + "name":"Beget", + "package_name": "certbot-dns-beget", + "version": "~=1.7.0.dev3", + "dependencies": "", + "credentials": "# Beget API credentials used by Certbot\ndns_beget_login = login\ndns_beget_password = passwd", + "full_plugin_name": "dns-beget" + }, "bunny": { "name": "bunny.net", "package_name": "certbot-dns-bunny", From 595a742c400c8909dea1eb04f4ef4a5ed7b49c48 Mon Sep 17 00:00:00 2001 From: Medan-rfz Date: Sun, 10 Nov 2024 15:09:41 +0400 Subject: [PATCH 030/137] Change beget plugin --- global/certbot-dns-plugins.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/global/certbot-dns-plugins.json b/global/certbot-dns-plugins.json index 39b94316f..5ef597307 100644 --- a/global/certbot-dns-plugins.json +++ b/global/certbot-dns-plugins.json @@ -33,11 +33,11 @@ }, "beget": { "name":"Beget", - "package_name": "certbot-dns-beget", - "version": "~=1.7.0.dev3", + "package_name": "certbot-beget-plugin", + "version": "~=1.0.0.dev3", "dependencies": "", - "credentials": "# Beget API credentials used by Certbot\ndns_beget_login = login\ndns_beget_password = passwd", - "full_plugin_name": "dns-beget" + "credentials": "# Beget API credentials used by Certbot\ndns_beget_username = username\ndns_beget_password = password", + "full_plugin_name": "beget-plugin" }, "bunny": { "name": "bunny.net", From 10b9a49274b18f6c3a7ff8b6aa2a9c5bccf48112 Mon Sep 17 00:00:00 2001 From: Medan-rfz Date: Sun, 10 Nov 2024 16:16:45 +0400 Subject: [PATCH 031/137] Update version 'certbot-beget-plugin' --- global/certbot-dns-plugins.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global/certbot-dns-plugins.json b/global/certbot-dns-plugins.json index 5ef597307..e8063a50d 100644 --- a/global/certbot-dns-plugins.json +++ b/global/certbot-dns-plugins.json @@ -34,7 +34,7 @@ "beget": { "name":"Beget", "package_name": "certbot-beget-plugin", - "version": "~=1.0.0.dev3", + "version": "~=1.0.0.dev4", "dependencies": "", "credentials": "# Beget API credentials used by Certbot\ndns_beget_username = username\ndns_beget_password = password", "full_plugin_name": "beget-plugin" From 4c893796713d7cd55eca811728a137d63bb953bd Mon Sep 17 00:00:00 2001 From: Medan-rfz Date: Sun, 10 Nov 2024 18:31:07 +0400 Subject: [PATCH 032/137] Update version 'certbot-beget-plugin' --- global/certbot-dns-plugins.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/global/certbot-dns-plugins.json b/global/certbot-dns-plugins.json index e8063a50d..5e6cca757 100644 --- a/global/certbot-dns-plugins.json +++ b/global/certbot-dns-plugins.json @@ -34,9 +34,9 @@ "beget": { "name":"Beget", "package_name": "certbot-beget-plugin", - "version": "~=1.0.0.dev4", + "version": "~=1.0.0.dev8", "dependencies": "", - "credentials": "# Beget API credentials used by Certbot\ndns_beget_username = username\ndns_beget_password = password", + "credentials": "# Beget API credentials used by Certbot\beget_plugin_username = username\beget_plugin_password = password", "full_plugin_name": "beget-plugin" }, "bunny": { From a56342c76a37eefa86e74cd46e9eea89ff94e2d5 Mon Sep 17 00:00:00 2001 From: Medan-rfz Date: Sun, 10 Nov 2024 19:23:28 +0400 Subject: [PATCH 033/137] Fix credentials --- global/certbot-dns-plugins.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global/certbot-dns-plugins.json b/global/certbot-dns-plugins.json index 5e6cca757..b5d00ab8d 100644 --- a/global/certbot-dns-plugins.json +++ b/global/certbot-dns-plugins.json @@ -36,7 +36,7 @@ "package_name": "certbot-beget-plugin", "version": "~=1.0.0.dev8", "dependencies": "", - "credentials": "# Beget API credentials used by Certbot\beget_plugin_username = username\beget_plugin_password = password", + "credentials": "# Beget API credentials used by Certbot\nbeget_plugin_username = username\beget_plugin_password = password", "full_plugin_name": "beget-plugin" }, "bunny": { From 2cee211fb03b139748800c2403c674f837f74ed6 Mon Sep 17 00:00:00 2001 From: hatharry Date: Wed, 13 Nov 2024 16:31:59 +1300 Subject: [PATCH 034/137] add First Domains plugin --- global/certbot-dns-plugins.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/global/certbot-dns-plugins.json b/global/certbot-dns-plugins.json index 075877744..68d1265c3 100644 --- a/global/certbot-dns-plugins.json +++ b/global/certbot-dns-plugins.json @@ -191,6 +191,14 @@ "credentials": "dns_eurodns_applicationId = myuser\ndns_eurodns_apiKey = mysecretpassword\ndns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy", "full_plugin_name": "dns-eurodns" }, + "firstdomains": { + "name": "First Domains", + "package_name": "certbot-dns-firstdomains", + "version": ">=1.0", + "dependencies": "", + "credentials": "dns_firstdomains_username = myremoteuser\ndns_firstdomains_password = verysecureremoteuserpassword", + "full_plugin_name": "dns-firstdomains" + }, "freedns": { "name": "FreeDNS", "package_name": "certbot-dns-freedns", From 87998a03ced6ef6dc2f3f9b31310c2bef562ac36 Mon Sep 17 00:00:00 2001 From: Jasper Stubbe Date: Thu, 14 Nov 2024 11:39:48 -0800 Subject: [PATCH 035/137] Fix bootloop if stream is used for http/https port --- backend/schema/components/stream-object.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/schema/components/stream-object.json b/backend/schema/components/stream-object.json index 516c7f891..e17749940 100644 --- a/backend/schema/components/stream-object.json +++ b/backend/schema/components/stream-object.json @@ -19,7 +19,9 @@ "incoming_port": { "type": "integer", "minimum": 1, - "maximum": 65535 + "maximum": 65535, + "if": {"properties": {"tcp_forwarding": {"const": true}}}, + "then": {"not": {"oneOf": [{"const": 80}, {"const": 443}]}} }, "forwarding_host": { "anyOf": [ From 20646e7bb543503dcc53bd5a074cdddc5e101880 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 21:19:05 +0000 Subject: [PATCH 036/137] Bump @eslint/plugin-kit from 0.2.0 to 0.2.3 in /test Bumps [@eslint/plugin-kit](https://github.com/eslint/rewrite) from 0.2.0 to 0.2.3. - [Release notes](https://github.com/eslint/rewrite/releases) - [Changelog](https://github.com/eslint/rewrite/blob/main/release-please-config.json) - [Commits](https://github.com/eslint/rewrite/compare/core-v0.2.0...plugin-kit-v0.2.3) --- updated-dependencies: - dependency-name: "@eslint/plugin-kit" dependency-type: indirect ... Signed-off-by: dependabot[bot] --- test/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/yarn.lock b/test/yarn.lock index 4fa9e51f9..909d269d4 100644 --- a/test/yarn.lock +++ b/test/yarn.lock @@ -132,9 +132,9 @@ integrity sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ== "@eslint/plugin-kit@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz#8712dccae365d24e9eeecb7b346f85e750ba343d" - integrity sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig== + version "0.2.3" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz#812980a6a41ecf3a8341719f92a6d1e784a2e0e8" + integrity sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA== dependencies: levn "^0.4.1" From 126d3d44ca9cc1a07af65b96af65e1b8257cd29c Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Sun, 17 Nov 2024 10:44:29 +0000 Subject: [PATCH 037/137] Bump certbot-dns-porkbun --- global/certbot-dns-plugins.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/global/certbot-dns-plugins.json b/global/certbot-dns-plugins.json index 075877744..6a48c33a6 100644 --- a/global/certbot-dns-plugins.json +++ b/global/certbot-dns-plugins.json @@ -7,7 +7,7 @@ "credentials": "dns_acmedns_api_url = http://acmedns-server/\ndns_acmedns_registration_file = /data/acme-registration.json", "full_plugin_name": "dns-acmedns" }, - "active24":{ + "active24": { "name": "Active24", "package_name": "certbot-dns-active24", "version": "~=1.5.1", @@ -402,7 +402,7 @@ "porkbun": { "name": "Porkbun", "package_name": "certbot-dns-porkbun", - "version": "~=0.2", + "version": "~=0.9", "dependencies": "", "credentials": "dns_porkbun_key=your-porkbun-api-key\ndns_porkbun_secret=your-porkbun-api-secret", "full_plugin_name": "dns-porkbun" @@ -495,7 +495,7 @@ "credentials": "dns_websupport_identifier = \ndns_websupport_secret_key = ", "full_plugin_name": "dns-websupport" }, - "wedos":{ + "wedos": { "name": "Wedos", "package_name": "certbot-dns-wedos", "version": "~=2.2", @@ -511,4 +511,4 @@ "credentials": "edgedns_client_secret = as3d1asd5d1a32sdfsdfs2d1asd5=\nedgedns_host = sdflskjdf-dfsdfsdf-sdfsdfsdf.luna.akamaiapis.net\nedgedns_access_token = kjdsi3-34rfsdfsdf-234234fsdfsdf\nedgedns_client_token = dkfjdf-342fsdfsd-23fsdfsdfsdf", "full_plugin_name": "edgedns" } -} +} \ No newline at end of file From 640a1eeb68053bafed9a80525d339642de90e0d3 Mon Sep 17 00:00:00 2001 From: tametsi <93092155+tametsi@users.noreply.github.com> Date: Fri, 22 Nov 2024 10:30:58 +0100 Subject: [PATCH 038/137] Return generic auth error to prevent user enumeration attacks On invalid user/password error the error message "Invalid email or password" is returned. Thereby, no information about the existence of the user is given. --- backend/internal/token.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/internal/token.js b/backend/internal/token.js index ed9a45f82..0e6dec5e3 100644 --- a/backend/internal/token.js +++ b/backend/internal/token.js @@ -5,6 +5,8 @@ const authModel = require('../models/auth'); const helpers = require('../lib/helpers'); const TokenModel = require('../models/token'); +const ERROR_MESSAGE_INVALID_AUTH = 'Invalid email or password'; + module.exports = { /** @@ -69,15 +71,15 @@ module.exports = { }; }); } else { - throw new error.AuthError('Invalid password'); + throw new error.AuthError(ERROR_MESSAGE_INVALID_AUTH); } }); } else { - throw new error.AuthError('No password auth for user'); + throw new error.AuthError(ERROR_MESSAGE_INVALID_AUTH); } }); } else { - throw new error.AuthError('No relevant user found'); + throw new error.AuthError(ERROR_MESSAGE_INVALID_AUTH); } }); }, From 2075f98cadaf8eb33c97fbd422321a6f60b96f8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Nov 2024 03:36:44 +0000 Subject: [PATCH 039/137] Bump cross-spawn from 7.0.3 to 7.0.6 in /backend Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6. - [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md) - [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6) --- updated-dependencies: - dependency-name: cross-spawn dependency-type: indirect ... Signed-off-by: dependabot[bot] --- backend/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/yarn.lock b/backend/yarn.lock index 5441a511c..55723d375 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -830,9 +830,9 @@ crc32-stream@^4.0.2: readable-stream "^3.4.0" cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" From 151160a8346696cfd4a2aa73b3999439f9f7761a Mon Sep 17 00:00:00 2001 From: Muescha <184316+muescha@users.noreply.github.com> Date: Sun, 24 Nov 2024 20:10:17 +0100 Subject: [PATCH 040/137] Update index.md: add link to Proxmox VE Helper-Scripts Update index.md: add link to Proxmox VE Helper-Scripts --- docs/src/third-party/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/third-party/index.md b/docs/src/third-party/index.md index c36f54a8f..cd54b45b9 100644 --- a/docs/src/third-party/index.md +++ b/docs/src/third-party/index.md @@ -12,6 +12,7 @@ Known integrations: - [HomeAssistant Hass.io plugin](https://github.com/hassio-addons/addon-nginx-proxy-manager) - [UnRaid / Synology](https://github.com/jlesage/docker-nginx-proxy-manager) - [Proxmox Scripts](https://github.com/ej52/proxmox-scripts/tree/main/apps/nginx-proxy-manager) +- [Proxmox VE Helper-Scripts](https://community-scripts.github.io/ProxmoxVE/scripts?id=nginxproxymanager) - [nginxproxymanagerGraf](https://github.com/ma-karai/nginxproxymanagerGraf) From 93ea17a9bb782cdd65434dd172483f364fa4765f Mon Sep 17 00:00:00 2001 From: Remco Kersten Date: Mon, 25 Nov 2024 20:37:49 +0100 Subject: [PATCH 041/137] Fix entries of a deleted user break the UI --- frontend/js/app/nginx/access/list/item.ejs | 4 ++-- frontend/js/app/nginx/certificates/list/item.ejs | 4 ++-- frontend/js/app/nginx/dead/list/item.ejs | 4 ++-- frontend/js/app/nginx/proxy/list/item.ejs | 4 ++-- frontend/js/app/nginx/redirection/list/item.ejs | 4 ++-- frontend/js/app/nginx/stream/list/item.ejs | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/frontend/js/app/nginx/access/list/item.ejs b/frontend/js/app/nginx/access/list/item.ejs index 2ee37a50a..fe043c98e 100644 --- a/frontend/js/app/nginx/access/list/item.ejs +++ b/frontend/js/app/nginx/access/list/item.ejs @@ -1,6 +1,6 @@ -

- +
+
diff --git a/frontend/js/app/nginx/certificates/list/item.ejs b/frontend/js/app/nginx/certificates/list/item.ejs index 20d6f2396..9a0d6b27d 100644 --- a/frontend/js/app/nginx/certificates/list/item.ejs +++ b/frontend/js/app/nginx/certificates/list/item.ejs @@ -1,6 +1,6 @@ -
- +
+
diff --git a/frontend/js/app/nginx/dead/list/item.ejs b/frontend/js/app/nginx/dead/list/item.ejs index d447bd1e3..dede3b639 100644 --- a/frontend/js/app/nginx/dead/list/item.ejs +++ b/frontend/js/app/nginx/dead/list/item.ejs @@ -1,6 +1,6 @@ -
- +
+
diff --git a/frontend/js/app/nginx/proxy/list/item.ejs b/frontend/js/app/nginx/proxy/list/item.ejs index a59368048..3eeaa6d26 100644 --- a/frontend/js/app/nginx/proxy/list/item.ejs +++ b/frontend/js/app/nginx/proxy/list/item.ejs @@ -1,6 +1,6 @@ -
- +
+
diff --git a/frontend/js/app/nginx/redirection/list/item.ejs b/frontend/js/app/nginx/redirection/list/item.ejs index 4f25d973e..dff186fdf 100644 --- a/frontend/js/app/nginx/redirection/list/item.ejs +++ b/frontend/js/app/nginx/redirection/list/item.ejs @@ -1,6 +1,6 @@ -
- +
+
diff --git a/frontend/js/app/nginx/stream/list/item.ejs b/frontend/js/app/nginx/stream/list/item.ejs index a8ff83d4c..2b4cb626b 100644 --- a/frontend/js/app/nginx/stream/list/item.ejs +++ b/frontend/js/app/nginx/stream/list/item.ejs @@ -1,6 +1,6 @@ -
- +
+
From 81c9038929a75f72574add9bf3baaa80171f11bf Mon Sep 17 00:00:00 2001 From: Julian Gassner Date: Wed, 27 Nov 2024 18:27:11 +0100 Subject: [PATCH 042/137] Refactor user form structure --- frontend/js/app/user/form.ejs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/frontend/js/app/user/form.ejs b/frontend/js/app/user/form.ejs index aeb268f7c..9ba84438a 100644 --- a/frontend/js/app/user/form.ejs +++ b/frontend/js/app/user/form.ejs @@ -1,10 +1,10 @@ -<% } %> +<% } %> \ No newline at end of file diff --git a/frontend/js/app/nginx/certificates/list/item.js b/frontend/js/app/nginx/certificates/list/item.js index 7fa1c6814..b9a927adc 100644 --- a/frontend/js/app/nginx/certificates/list/item.js +++ b/frontend/js/app/nginx/certificates/list/item.js @@ -44,14 +44,24 @@ module.exports = Mn.View.extend({ }, }, - templateContext: { - canManage: App.Cache.User.canManage('certificates'), - isExpired: function () { - return moment(this.expires_on).isBefore(moment()); - }, - dns_providers: dns_providers + templateContext: function () { + return { + canManage: App.Cache.User.canManage('certificates'), + isExpired: function () { + return moment(this.expires_on).isBefore(moment()); + }, + dns_providers: dns_providers, + active_domain_names: function () { + const { proxy_hosts = [], redirect_hosts = [], dead_hosts = [] } = this; + return [...proxy_hosts, ...redirect_hosts, ...dead_hosts].reduce((acc, host) => { + acc.push(...(host.domain_names || [])); + return acc; + }, []); + } + }; }, + initialize: function () { this.listenTo(this.model, 'change', this.render); } diff --git a/frontend/js/app/nginx/certificates/list/main.ejs b/frontend/js/app/nginx/certificates/list/main.ejs index aa49a27fb..329b58434 100644 --- a/frontend/js/app/nginx/certificates/list/main.ejs +++ b/frontend/js/app/nginx/certificates/list/main.ejs @@ -3,6 +3,7 @@ <%- i18n('str', 'name') %> <%- i18n('all-hosts', 'cert-provider') %> <%- i18n('str', 'expires') %> + <%- i18n('str', 'status') %> <% if (canManage) { %>   <% } %> diff --git a/frontend/js/app/nginx/certificates/main.js b/frontend/js/app/nginx/certificates/main.js index 89562768b..3f9f022eb 100644 --- a/frontend/js/app/nginx/certificates/main.js +++ b/frontend/js/app/nginx/certificates/main.js @@ -74,7 +74,7 @@ module.exports = Mn.View.extend({ e.preventDefault(); let query = this.ui.query.val(); - this.fetch(['owner'], query) + this.fetch(['owner','proxy_hosts', 'dead_hosts', 'redirection_hosts'], query) .then(response => this.showData(response)) .catch(err => { this.showError(err); @@ -89,7 +89,7 @@ module.exports = Mn.View.extend({ onRender: function () { let view = this; - view.fetch(['owner']) + view.fetch(['owner','proxy_hosts', 'dead_hosts', 'redirection_hosts']) .then(response => { if (!view.isDestroyed()) { if (response && response.length) { diff --git a/frontend/js/app/user/form.ejs b/frontend/js/app/user/form.ejs index aeb268f7c..9ba84438a 100644 --- a/frontend/js/app/user/form.ejs +++ b/frontend/js/app/user/form.ejs @@ -1,10 +1,10 @@ -