From 1df270f10e4184fcccadca550ccf9e3e4b180fc5 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 18:48:26 +0000 Subject: [PATCH 1/3] Implement Let's Encrypt IP certificate support - Add `acme-client` dependency to `src/shadowbox`. - Implement `CertificateManager` to automate ACME HTTP-01 challenges on port 80. - Integrate `CertificateManager` into `main.ts` for zero-downtime certificate renewal via `setSecureContext`. - Update `install_server.sh` to ensure write permissions for certificate updates. - Update Node.js engine requirement to `>=18.0.0` for `crypto.X509Certificate` support. --- package-lock.json | 955 ++++++++++++++++-- package.json | 2 +- .../install_scripts/install_server.sh | 2 + src/shadowbox/package.json | 10 +- src/shadowbox/server/certificate_manager.ts | 204 ++++ src/shadowbox/server/main.ts | 16 + 6 files changed, 1111 insertions(+), 78 deletions(-) create mode 100644 src/shadowbox/server/certificate_manager.ts diff --git a/package-lock.json b/package-lock.json index f38ece7c3..569a04312 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,7 @@ "webpack-cli": "^5.1.4" }, "engines": { - "node": "18.x.x" + "node": ">=18.0.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -759,6 +759,154 @@ "node": ">= 8" } }, + "node_modules/@peculiar/asn1-cms": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.6.0.tgz", + "integrity": "sha512-2uZqP+ggSncESeUF/9Su8rWqGclEfEiz1SyU02WX5fUONFfkjzS2Z/F1Li0ofSmf4JqYXIOdCAZqIXAIBAT1OA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "@peculiar/asn1-x509-attr": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-csr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.6.0.tgz", + "integrity": "sha512-BeWIu5VpTIhfRysfEp73SGbwjjoLL/JWXhJ/9mo4vXnz3tRGm+NGm3KNcRzQ9VMVqwYS2RHlolz21svzRXIHPQ==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.6.0.tgz", + "integrity": "sha512-FF3LMGq6SfAOwUG2sKpPXblibn6XnEIKa+SryvUl5Pik+WR9rmRA3OCiwz8R3lVXnYnyRkSZsSLdml8H3UiOcw==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pfx": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.6.0.tgz", + "integrity": "sha512-rtUvtf+tyKGgokHHmZzeUojRZJYPxoD/jaN1+VAB4kKR7tXrnDCA/RAWXAIhMJJC+7W27IIRGe9djvxKgsldCQ==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.6.0", + "@peculiar/asn1-pkcs8": "^2.6.0", + "@peculiar/asn1-rsa": "^2.6.0", + "@peculiar/asn1-schema": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs8": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.6.0.tgz", + "integrity": "sha512-KyQ4D8G/NrS7Fw3XCJrngxmjwO/3htnA0lL9gDICvEQ+GJ+EPFqldcJQTwPIdvx98Tua+WjkdKHSC0/Km7T+lA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs9": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.6.0.tgz", + "integrity": "sha512-b78OQ6OciW0aqZxdzliXGYHASeCvvw5caqidbpQRYW2mBtXIX2WhofNXTEe7NyxTb0P6J62kAAWLwn0HuMF1Fw==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.6.0", + "@peculiar/asn1-pfx": "^2.6.0", + "@peculiar/asn1-pkcs8": "^2.6.0", + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "@peculiar/asn1-x509-attr": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.6.0.tgz", + "integrity": "sha512-Nu4C19tsrTsCp9fDrH+sdcOKoVfdfoQQ7S3VqjJU6vedR7tY3RLkQ5oguOIB3zFW33USDUuYZnPEQYySlgha4w==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.6.0.tgz", + "integrity": "sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg==", + "license": "MIT", + "dependencies": { + "asn1js": "^3.0.6", + "pvtsutils": "^1.3.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.6.0.tgz", + "integrity": "sha512-uzYbPEpoQiBoTq0/+jZtpM6Gq6zADBx+JNFP3yqRgziWBxQ/Dt/HcuvRfm9zJTPdRcBqPNdaRHTVwpyiq6iNMA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.6.0", + "asn1js": "^3.0.6", + "pvtsutils": "^1.3.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509-attr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.6.0.tgz", + "integrity": "sha512-MuIAXFX3/dc8gmoZBkwJWxUWOSvG4MMDntXhrOZpJVMkYX+MYc/rUAU2uJOved9iJEoiUx7//3D8oG83a78UJA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/x509": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.2.tgz", + "integrity": "sha512-r2w1Hg6pODDs0zfAKHkSS5HLkOLSeburtcgwvlLLWWCixw+MmW3U6kD5ddyvc2Y2YdbGuVwCF2S2ASoU1cFAag==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.6.0", + "@peculiar/asn1-csr": "^2.6.0", + "@peculiar/asn1-ecc": "^2.6.0", + "@peculiar/asn1-pkcs9": "^2.6.0", + "@peculiar/asn1-rsa": "^2.6.0", + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "pvtsutils": "^1.3.6", + "reflect-metadata": "^0.2.2", + "tslib": "^2.8.1", + "tsyringe": "^4.10.0" + }, + "engines": { + "node": ">=22.0.0" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -784,6 +932,17 @@ "node": ">= 10" } }, + "node_modules/@types/acme-client": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/acme-client/-/acme-client-3.0.0.tgz", + "integrity": "sha512-IPEjIL9mNrpgPql8sh/69aJOWwJVhZSKoYImOX4OoTb/oZT5+vYHg8kANKyFKxZCAZAjne5FmGhS83IiS/eA4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "axios": "*" + } + }, "node_modules/@types/body-parser": { "version": "1.19.1", "dev": true, @@ -880,7 +1039,9 @@ } }, "node_modules/@types/jasmine": { - "version": "3.10.1", + "version": "3.10.18", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.10.18.tgz", + "integrity": "sha512-jOk52a1Kz+1oU5fNWwAcNe64/GsE7r/Q6ronwDox0D3ETo/cr4ICMQyeXrj7G6FPW1n8YjRoAZA2F0XBr6GicQ==", "dev": true, "license": "MIT" }, @@ -911,19 +1072,30 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/mkdirp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz", + "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "16.11.34", "dev": true, "license": "MIT" }, "node_modules/@types/node-fetch": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", - "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", - "form-data": "^3.0.0" + "form-data": "^4.0.4" } }, "node_modules/@types/qs": { @@ -1053,6 +1225,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.0.tgz", "integrity": "sha512-fNcDm3wSwVM8QYL4HKVBggdIPAy9Q41vcvC/GtDobw3c4ndVT3K6cqudUmjHPw8EAp4ufax0o58/xvWaP2FmTg==", "dev": true, + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.7.0", "@typescript-eslint/types": "7.7.0", @@ -1491,11 +1664,51 @@ "node": ">= 0.6" } }, + "node_modules/acme-client": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/acme-client/-/acme-client-5.4.0.tgz", + "integrity": "sha512-mORqg60S8iML6XSmVjqjGHJkINrCGLMj2QvDmFzI9vIlv1RGlyjmw3nrzaINJjkNsYXC41XhhD5pfy7CtuGcbA==", + "license": "MIT", + "dependencies": { + "@peculiar/x509": "^1.11.0", + "asn1js": "^3.0.5", + "axios": "^1.7.2", + "debug": "^4.3.5", + "node-forge": "^1.3.1" + }, + "engines": { + "node": ">= 16" + } + }, + "node_modules/acme-client/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/acme-client/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1535,6 +1748,7 @@ "version": "6.12.6", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1707,6 +1921,20 @@ "safer-buffer": "~2.1.0" } }, + "node_modules/asn1js": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.7.tgz", + "integrity": "sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==", + "license": "BSD-3-Clause", + "dependencies": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/assert-plus": { "version": "1.0.0", "license": "MIT", @@ -1737,7 +1965,6 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "dev": true, "license": "MIT" }, "node_modules/atomic-sleep": { @@ -1748,6 +1975,17 @@ "node": ">=8.0.0" } }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "dev": true, @@ -1923,6 +2161,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001541", "electron-to-chromium": "^1.4.535", @@ -2002,6 +2241,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/caller-callsite": { "version": "2.0.0", "dev": true, @@ -2185,7 +2437,6 @@ }, "node_modules/combined-stream": { "version": "1.0.8", - "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -2536,7 +2787,6 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -2623,6 +2873,20 @@ "node": ">=0.10" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2809,12 +3073,57 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", "dev": true }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -2868,6 +3177,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -3142,6 +3452,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", "dev": true, + "peer": true, "dependencies": { "array-includes": "^3.1.4", "array.prototype.flat": "^1.2.5", @@ -3931,16 +4242,16 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", - "dev": true, + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -3979,12 +4290,15 @@ } }, "node_modules/form-data": { - "version": "3.0.1", - "dev": true, + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -4084,17 +4398,42 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.1", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stdin": { "version": "6.0.0", "dev": true, @@ -4234,6 +4573,18 @@ "node": ">=10" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4278,6 +4629,7 @@ }, "node_modules/has": { "version": "1.0.3", + "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.1" @@ -4316,9 +4668,10 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -4327,11 +4680,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -4345,6 +4699,18 @@ "dev": true, "license": "MIT" }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hpack.js": { "version": "2.1.6", "license": "MIT", @@ -4971,19 +5337,23 @@ } }, "node_modules/jasmine": { - "version": "3.10.0", + "version": "3.99.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.99.0.tgz", + "integrity": "sha512-YIThBuHzaIIcjxeuLmPD40SjxkEcc8i//sGMDKCgkRMVgIwRJf5qyExtlJpQeh7pkeoBSOe6lQEdg+/9uKg9mw==", "dev": true, "license": "MIT", "dependencies": { "glob": "^7.1.6", - "jasmine-core": "~3.10.0" + "jasmine-core": "~3.99.0" }, "bin": { "jasmine": "bin/jasmine.js" } }, "node_modules/jasmine-core": { - "version": "3.10.1", + "version": "3.99.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz", + "integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==", "dev": true, "license": "MIT" }, @@ -5564,6 +5934,15 @@ "node": ">=10" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "license": "MIT", @@ -5665,7 +6044,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5681,7 +6059,6 @@ }, "node_modules/mkdirp": { "version": "0.5.6", - "dev": true, "license": "MIT", "dependencies": { "minimist": "^1.2.6" @@ -6392,6 +6769,7 @@ "version": "2.4.1", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -6569,7 +6947,6 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", - "dev": true, "license": "MIT" }, "node_modules/pump": { @@ -6708,6 +7085,24 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", + "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/q": { "version": "1.5.1", "dev": true, @@ -6891,6 +7286,12 @@ "node": ">= 12.13.0" } }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, "node_modules/regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -8191,6 +8592,30 @@ "node": ">=4" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsyringe": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", + "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", + "license": "MIT", + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/tsyringe/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, "node_modules/tweetnacl": { "version": "0.14.5", "license": "Unlicense" @@ -8242,6 +8667,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8293,6 +8719,13 @@ "through": "^2.3.8" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, "node_modules/unique-string": { "version": "2.0.0", "dev": true, @@ -8495,6 +8928,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", "dev": true, + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", @@ -8542,6 +8976,7 @@ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dev": true, + "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", @@ -9017,9 +9452,12 @@ "name": "outline-server", "license": "Apache", "dependencies": { + "acme-client": "^5.4.0", "ip-regex": "^4.1.0", "js-yaml": "^3.12.0", - "outline-shadowsocksconfig": "git+ssh://git@github.com/Jigsaw-Code/outline-shadowsocksconfig.git#add590ed57277653d02dd2031ae301500ae881e1", + "mkdirp": "^0.5.6", + "node-fetch": "^2.6.7", + "outline-shadowsocksconfig": "github:Jigsaw-Code/outline-shadowsocksconfig#v0.2.0", "prom-client": "^11.1.3", "randomstring": "^1.1.5", "restify": "^11.1.0", @@ -9028,12 +9466,17 @@ "uuid": "^3.1.0" }, "devDependencies": { + "@types/acme-client": "^3.0.0", + "@types/jasmine": "^3.10.18", "@types/js-yaml": "^3.11.2", - "@types/node": "^12", + "@types/mkdirp": "^1.0.2", + "@types/node": "^18.19.130", + "@types/node-fetch": "^2.6.13", "@types/randomstring": "^1.1.6", "@types/restify": "^8.4.2", "@types/restify-cors-middleware": "^1.0.1", "@types/tmp": "^0.2.1", + "jasmine": "^3.99.0", "tmp": "^0.2.1", "ts-loader": "^9.5.0", "webpack": "^5.88.2", @@ -9041,9 +9484,14 @@ } }, "src/shadowbox/node_modules/@types/node": { - "version": "12.20.51", + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } } }, "dependencies": { @@ -9562,6 +10010,140 @@ "fastq": "^1.6.0" } }, + "@peculiar/asn1-cms": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.6.0.tgz", + "integrity": "sha512-2uZqP+ggSncESeUF/9Su8rWqGclEfEiz1SyU02WX5fUONFfkjzS2Z/F1Li0ofSmf4JqYXIOdCAZqIXAIBAT1OA==", + "requires": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "@peculiar/asn1-x509-attr": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "@peculiar/asn1-csr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.6.0.tgz", + "integrity": "sha512-BeWIu5VpTIhfRysfEp73SGbwjjoLL/JWXhJ/9mo4vXnz3tRGm+NGm3KNcRzQ9VMVqwYS2RHlolz21svzRXIHPQ==", + "requires": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "@peculiar/asn1-ecc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.6.0.tgz", + "integrity": "sha512-FF3LMGq6SfAOwUG2sKpPXblibn6XnEIKa+SryvUl5Pik+WR9rmRA3OCiwz8R3lVXnYnyRkSZsSLdml8H3UiOcw==", + "requires": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "@peculiar/asn1-pfx": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.6.0.tgz", + "integrity": "sha512-rtUvtf+tyKGgokHHmZzeUojRZJYPxoD/jaN1+VAB4kKR7tXrnDCA/RAWXAIhMJJC+7W27IIRGe9djvxKgsldCQ==", + "requires": { + "@peculiar/asn1-cms": "^2.6.0", + "@peculiar/asn1-pkcs8": "^2.6.0", + "@peculiar/asn1-rsa": "^2.6.0", + "@peculiar/asn1-schema": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "@peculiar/asn1-pkcs8": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.6.0.tgz", + "integrity": "sha512-KyQ4D8G/NrS7Fw3XCJrngxmjwO/3htnA0lL9gDICvEQ+GJ+EPFqldcJQTwPIdvx98Tua+WjkdKHSC0/Km7T+lA==", + "requires": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "@peculiar/asn1-pkcs9": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.6.0.tgz", + "integrity": "sha512-b78OQ6OciW0aqZxdzliXGYHASeCvvw5caqidbpQRYW2mBtXIX2WhofNXTEe7NyxTb0P6J62kAAWLwn0HuMF1Fw==", + "requires": { + "@peculiar/asn1-cms": "^2.6.0", + "@peculiar/asn1-pfx": "^2.6.0", + "@peculiar/asn1-pkcs8": "^2.6.0", + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "@peculiar/asn1-x509-attr": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "@peculiar/asn1-rsa": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.6.0.tgz", + "integrity": "sha512-Nu4C19tsrTsCp9fDrH+sdcOKoVfdfoQQ7S3VqjJU6vedR7tY3RLkQ5oguOIB3zFW33USDUuYZnPEQYySlgha4w==", + "requires": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "@peculiar/asn1-schema": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.6.0.tgz", + "integrity": "sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg==", + "requires": { + "asn1js": "^3.0.6", + "pvtsutils": "^1.3.6", + "tslib": "^2.8.1" + } + }, + "@peculiar/asn1-x509": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.6.0.tgz", + "integrity": "sha512-uzYbPEpoQiBoTq0/+jZtpM6Gq6zADBx+JNFP3yqRgziWBxQ/Dt/HcuvRfm9zJTPdRcBqPNdaRHTVwpyiq6iNMA==", + "requires": { + "@peculiar/asn1-schema": "^2.6.0", + "asn1js": "^3.0.6", + "pvtsutils": "^1.3.6", + "tslib": "^2.8.1" + } + }, + "@peculiar/asn1-x509-attr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.6.0.tgz", + "integrity": "sha512-MuIAXFX3/dc8gmoZBkwJWxUWOSvG4MMDntXhrOZpJVMkYX+MYc/rUAU2uJOved9iJEoiUx7//3D8oG83a78UJA==", + "requires": { + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "asn1js": "^3.0.6", + "tslib": "^2.8.1" + } + }, + "@peculiar/x509": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.2.tgz", + "integrity": "sha512-r2w1Hg6pODDs0zfAKHkSS5HLkOLSeburtcgwvlLLWWCixw+MmW3U6kD5ddyvc2Y2YdbGuVwCF2S2ASoU1cFAag==", + "requires": { + "@peculiar/asn1-cms": "^2.6.0", + "@peculiar/asn1-csr": "^2.6.0", + "@peculiar/asn1-ecc": "^2.6.0", + "@peculiar/asn1-pkcs9": "^2.6.0", + "@peculiar/asn1-rsa": "^2.6.0", + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "pvtsutils": "^1.3.6", + "reflect-metadata": "^0.2.2", + "tslib": "^2.8.1", + "tsyringe": "^4.10.0" + } + }, "@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -9576,6 +10158,16 @@ "@tootallnate/once": { "version": "2.0.0" }, + "@types/acme-client": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/acme-client/-/acme-client-3.0.0.tgz", + "integrity": "sha512-IPEjIL9mNrpgPql8sh/69aJOWwJVhZSKoYImOX4OoTb/oZT5+vYHg8kANKyFKxZCAZAjne5FmGhS83IiS/eA4w==", + "dev": true, + "requires": { + "@types/node": "*", + "axios": "*" + } + }, "@types/body-parser": { "version": "1.19.1", "dev": true, @@ -9663,7 +10255,9 @@ } }, "@types/jasmine": { - "version": "3.10.1", + "version": "3.10.18", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.10.18.tgz", + "integrity": "sha512-jOk52a1Kz+1oU5fNWwAcNe64/GsE7r/Q6ronwDox0D3ETo/cr4ICMQyeXrj7G6FPW1n8YjRoAZA2F0XBr6GicQ==", "dev": true }, "@types/js-yaml": { @@ -9690,18 +10284,27 @@ "version": "3.0.5", "dev": true }, + "@types/mkdirp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz", + "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "16.11.34", "dev": true }, "@types/node-fetch": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", - "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", "dev": true, "requires": { "@types/node": "*", - "form-data": "^3.0.0" + "form-data": "^4.0.4" } }, "@types/qs": { @@ -9802,6 +10405,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.0.tgz", "integrity": "sha512-fNcDm3wSwVM8QYL4HKVBggdIPAy9Q41vcvC/GtDobw3c4ndVT3K6cqudUmjHPw8EAp4ufax0o58/xvWaP2FmTg==", "dev": true, + "peer": true, "requires": { "@typescript-eslint/scope-manager": "7.7.0", "@typescript-eslint/types": "7.7.0", @@ -10121,11 +10725,39 @@ "negotiator": "0.6.3" } }, + "acme-client": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/acme-client/-/acme-client-5.4.0.tgz", + "integrity": "sha512-mORqg60S8iML6XSmVjqjGHJkINrCGLMj2QvDmFzI9vIlv1RGlyjmw3nrzaINJjkNsYXC41XhhD5pfy7CtuGcbA==", + "requires": { + "@peculiar/x509": "^1.11.0", + "asn1js": "^3.0.5", + "axios": "^1.7.2", + "debug": "^4.3.5", + "node-forge": "^1.3.1" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true + "dev": true, + "peer": true }, "acorn-import-assertions": { "version": "1.9.0", @@ -10150,6 +10782,7 @@ "ajv": { "version": "6.12.6", "dev": true, + "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -10256,6 +10889,16 @@ "safer-buffer": "~2.1.0" } }, + "asn1js": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.7.tgz", + "integrity": "sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==", + "requires": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + } + }, "assert-plus": { "version": "1.0.0" }, @@ -10280,14 +10923,23 @@ } }, "asynckit": { - "version": "0.4.0", - "dev": true + "version": "0.4.0" }, "atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" }, + "axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "requires": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, "balanced-match": { "version": "1.0.2", "dev": true @@ -10400,6 +11052,7 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "dev": true, + "peer": true, "requires": { "caniuse-lite": "^1.0.30001541", "electron-to-chromium": "^1.4.535", @@ -10444,6 +11097,15 @@ "get-intrinsic": "^1.0.2" } }, + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, "caller-callsite": { "version": "2.0.0", "dev": true, @@ -10555,7 +11217,6 @@ }, "combined-stream": { "version": "1.0.8", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -10792,8 +11453,7 @@ } }, "delayed-stream": { - "version": "1.0.0", - "dev": true + "version": "1.0.0" }, "detect-node": { "version": "2.1.0" @@ -10856,6 +11516,16 @@ "nan": "^2.14.0" } }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } + }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -10991,12 +11661,41 @@ "unbox-primitive": "^1.0.2" } }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, "es-module-lexer": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", "dev": true }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, "es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -11034,6 +11733,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, + "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -11310,6 +12010,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", "dev": true, + "peer": true, "requires": { "array-includes": "^3.1.4", "array.prototype.flat": "^1.2.5", @@ -11777,10 +12478,9 @@ "dev": true }, "follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", - "dev": true + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==" }, "foreground-child": { "version": "3.1.1", @@ -11801,11 +12501,14 @@ } }, "form-data": { - "version": "3.0.1", - "dev": true, + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, @@ -11868,11 +12571,29 @@ "dev": true }, "get-intrinsic": { - "version": "1.1.1", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" } }, "get-stdin": { @@ -11966,6 +12687,11 @@ "node-forge": "^1.3.1" } }, + "gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + }, "graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -12003,6 +12729,7 @@ }, "has": { "version": "1.0.3", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -12027,21 +12754,30 @@ } }, "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" }, "has-tostringtag": { - "version": "1.0.0", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "requires": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" } }, "hash-stream-validation": { "version": "0.2.4", "dev": true }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, "hpack.js": { "version": "2.1.6", "requires": { @@ -12431,15 +13167,19 @@ } }, "jasmine": { - "version": "3.10.0", + "version": "3.99.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.99.0.tgz", + "integrity": "sha512-YIThBuHzaIIcjxeuLmPD40SjxkEcc8i//sGMDKCgkRMVgIwRJf5qyExtlJpQeh7pkeoBSOe6lQEdg+/9uKg9mw==", "dev": true, "requires": { "glob": "^7.1.6", - "jasmine-core": "~3.10.0" + "jasmine-core": "~3.99.0" } }, "jasmine-core": { - "version": "3.10.1", + "version": "3.99.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz", + "integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==", "dev": true }, "jest-worker": { @@ -12861,6 +13601,11 @@ "yallist": "^4.0.0" } }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, "media-typer": { "version": "0.3.0" }, @@ -12922,8 +13667,7 @@ "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "minipass": { "version": "5.0.0", @@ -12933,7 +13677,6 @@ }, "mkdirp": { "version": "0.5.6", - "dev": true, "requires": { "minimist": "^1.2.6" } @@ -13183,15 +13926,23 @@ "outline-server": { "version": "file:src/shadowbox", "requires": { + "@types/acme-client": "^3.0.0", + "@types/jasmine": "^3.10.18", "@types/js-yaml": "^3.11.2", - "@types/node": "^12", + "@types/mkdirp": "^1.0.2", + "@types/node": "^18.19.130", + "@types/node-fetch": "^2.6.13", "@types/randomstring": "^1.1.6", "@types/restify": "^8.4.2", "@types/restify-cors-middleware": "^1.0.1", "@types/tmp": "^0.2.1", + "acme-client": "^5.4.0", "ip-regex": "^4.1.0", + "jasmine": "^3.99.0", "js-yaml": "^3.12.0", - "outline-shadowsocksconfig": "git+ssh://git@github.com/Jigsaw-Code/outline-shadowsocksconfig.git#add590ed57277653d02dd2031ae301500ae881e1", + "mkdirp": "^0.5.6", + "node-fetch": "^2.6.7", + "outline-shadowsocksconfig": "github:Jigsaw-Code/outline-shadowsocksconfig#v0.2.0", "prom-client": "^11.1.3", "randomstring": "^1.1.5", "restify": "^11.1.0", @@ -13205,8 +13956,13 @@ }, "dependencies": { "@types/node": { - "version": "12.20.51", - "dev": true + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } } } }, @@ -13433,7 +14189,8 @@ }, "prettier": { "version": "2.4.1", - "dev": true + "dev": true, + "peer": true }, "pretty-quick": { "version": "3.1.1", @@ -13541,8 +14298,7 @@ } }, "proxy-from-env": { - "version": "1.1.0", - "dev": true + "version": "1.1.0" }, "pump": { "version": "3.0.0", @@ -13632,6 +14388,19 @@ } } }, + "pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "requires": { + "tslib": "^2.8.1" + } + }, + "pvutils": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", + "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==" + }, "q": { "version": "1.5.1", "dev": true @@ -13752,6 +14521,11 @@ "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==" }, + "reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==" + }, "regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -14746,6 +15520,26 @@ } } }, + "tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "tsyringe": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", + "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", + "requires": { + "tslib": "^1.9.3" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, "tweetnacl": { "version": "0.14.5" }, @@ -14780,7 +15574,8 @@ "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true + "dev": true, + "peer": true }, "ua-parser-js": { "version": "0.7.33", @@ -14808,6 +15603,12 @@ "through": "^2.3.8" } }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "unique-string": { "version": "2.0.0", "dev": true, @@ -14945,6 +15746,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", "dev": true, + "peer": true, "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", @@ -14977,6 +15779,7 @@ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dev": true, + "peer": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", diff --git a/package.json b/package.json index bbf324d93..32457c88b 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "postinstall": "go build github.com/go-task/task/v3/cmd/task" }, "engines": { - "node": "18.x.x" + "node": ">=18.0.0" }, "workspaces": [ "src/*" diff --git a/src/server_manager/install_scripts/install_server.sh b/src/server_manager/install_scripts/install_server.sh index 39ba2b0d4..3475793ce 100755 --- a/src/server_manager/install_scripts/install_server.sh +++ b/src/server_manager/install_scripts/install_server.sh @@ -237,6 +237,8 @@ function create_persisted_state_dir() { readonly STATE_DIR="${SHADOWBOX_DIR}/persisted-state" mkdir -p "${STATE_DIR}" chmod ug+rwx,g+s,o-rwx "${STATE_DIR}" + # Ensure the container has write access to the state directory for certificates + chmod -R ug+rwx "${STATE_DIR}" } # Generate a secret key for access to the Management API and store it in a tag. diff --git a/src/shadowbox/package.json b/src/shadowbox/package.json index 89a2ef5d5..532ab919a 100644 --- a/src/shadowbox/package.json +++ b/src/shadowbox/package.json @@ -9,8 +9,11 @@ "Using https:// for ShadowsocksConfig to avoid adding git in the Docker image" ], "dependencies": { + "acme-client": "^5.4.0", "ip-regex": "^4.1.0", "js-yaml": "^3.12.0", + "mkdirp": "^0.5.6", + "node-fetch": "^2.6.7", "outline-shadowsocksconfig": "github:Jigsaw-Code/outline-shadowsocksconfig#v0.2.0", "prom-client": "^11.1.3", "randomstring": "^1.1.5", @@ -20,12 +23,17 @@ "uuid": "^3.1.0" }, "devDependencies": { + "@types/acme-client": "^3.0.0", + "@types/jasmine": "^3.10.18", "@types/js-yaml": "^3.11.2", - "@types/node": "^12", + "@types/mkdirp": "^1.0.2", + "@types/node": "^18.19.130", + "@types/node-fetch": "^2.6.13", "@types/randomstring": "^1.1.6", "@types/restify": "^8.4.2", "@types/restify-cors-middleware": "^1.0.1", "@types/tmp": "^0.2.1", + "jasmine": "^3.99.0", "tmp": "^0.2.1", "ts-loader": "^9.5.0", "webpack": "^5.88.2", diff --git a/src/shadowbox/server/certificate_manager.ts b/src/shadowbox/server/certificate_manager.ts new file mode 100644 index 000000000..94d496db5 --- /dev/null +++ b/src/shadowbox/server/certificate_manager.ts @@ -0,0 +1,204 @@ +// Copyright 2024 The Outline Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import * as acme from 'acme-client'; +import * as crypto from 'crypto'; +import * as fs from 'fs'; +import * as http from 'http'; +import * as path from 'path'; +import * as tls from 'tls'; +import * as logging from '../infrastructure/logging'; + +// Renew if expiring within 30 days +const RENEW_THRESHOLD_DAYS = 30; +const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours + +export class CertificateManager { + private client: acme.Client; + private accountKeyPath: string; + + constructor( + private readonly hostname: string, + private readonly certFile: string, + private readonly keyFile: string, + private readonly stateDir: string, + private readonly onUpdate: (context: tls.SecureContext) => void + ) { + this.accountKeyPath = path.join(this.stateDir, 'acme-account.key'); + } + + async start() { + try { + await this.initClient(); + await this.checkAndRenew(); + } catch (e) { + logging.error(`CertificateManager initialization failed: ${e}`); + } + + setInterval(() => { + this.checkAndRenew().catch((e) => { + logging.error(`Scheduled certificate renewal failed: ${e}`); + }); + }, CHECK_INTERVAL_MS); + } + + private async initClient() { + let accountKey: Buffer; + if (fs.existsSync(this.accountKeyPath)) { + logging.info(`Loading ACME account key from ${this.accountKeyPath}`); + accountKey = fs.readFileSync(this.accountKeyPath); + } else { + logging.info('Generating new ACME account key...'); + accountKey = await acme.crypto.createPrivateKey(); + fs.writeFileSync(this.accountKeyPath, accountKey); + } + + this.client = new acme.Client({ + directoryUrl: acme.directory.letsencrypt.production, + accountKey: accountKey, + }); + } + + private async checkAndRenew() { + logging.info('Checking certificate status...'); + if (this.shouldRenew()) { + logging.info('Certificate requires renewal/issuance.'); + await this.renew(); + } else { + logging.info('Certificate is valid and does not need renewal.'); + } + } + + private shouldRenew(): boolean { + if (!fs.existsSync(this.certFile)) { + logging.warn('Certificate file not found.'); + return true; + } + + try { + const certBuffer = fs.readFileSync(this.certFile); + const cert = new crypto.X509Certificate(certBuffer); + + // Check if self-signed + if (cert.issuer === cert.subject) { + logging.info('Current certificate is self-signed.'); + return true; + } + + // Check expiry + const validTo = new Date(cert.validTo); + const now = new Date(); + const daysRemaining = (validTo.getTime() - now.getTime()) / (1000 * 60 * 60 * 24); + + if (daysRemaining < RENEW_THRESHOLD_DAYS) { + logging.info(`Certificate expires in ${daysRemaining.toFixed(1)} days.`); + return true; + } + + return false; + } catch (e) { + logging.error(`Error parsing certificate: ${e}`); + return true; + } + } + + private async renew() { + logging.info(`Attempting to obtain certificate for ${this.hostname}`); + + // Create a challenge server + const challengeMap = new Map(); + const challengeServer = http.createServer((req, res) => { + if (req.url && req.url.startsWith('/.well-known/acme-challenge/')) { + const token = req.url.split('/').pop(); + if (token && challengeMap.has(token)) { + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.write(challengeMap.get(token)); + res.end(); + return; + } + } + res.writeHead(404); + res.end(); + }); + + try { + // Start server on port 80 + await new Promise((resolve, reject) => { + challengeServer.listen(80, '0.0.0.0', () => { + logging.info('ACME challenge server listening on port 80'); + resolve(); + }); + challengeServer.on('error', reject); + }); + + // Order certificate + /* eslint-disable @typescript-eslint/no-explicit-any */ + const order = await this.client.createOrder({ + identifiers: [{ type: 'ip', value: this.hostname }], + } as any); + /* eslint-enable @typescript-eslint/no-explicit-any */ + + const authorizations = await this.client.getAuthorizations(order); + const authz = authorizations[0]; + const challenge = authz.challenges.find((c) => c.type === 'http-01'); + + if (!challenge) { + throw new Error('No http-01 challenge found'); + } + + const keyAuthorization = await this.client.getChallengeKeyAuthorization(challenge); + + // Set up the challenge response + challengeMap.set(challenge.token, keyAuthorization); + + // Verify challenge + await this.client.completeChallenge(challenge); + await this.client.waitForValidStatus(challenge); + + // Finalize and download + const [key, csr] = await acme.crypto.createCsr({ + commonName: this.hostname, + // IP certificates usually don't need SANs if CN is IP, or maybe they do? + // Let's Encrypt for IP requires the IP in SANs. + altNames: [this.hostname], + }); + + const finalize = await this.client.finalizeOrder(order, csr); + const cert = await this.client.getCertificate(finalize); + + // Save to disk + logging.info('Certificate obtained successfully. Saving...'); + fs.writeFileSync(this.certFile, cert); + fs.writeFileSync(this.keyFile, key); + + // Update running server + const context = tls.createSecureContext({ + cert: cert, + key: key, + }); + this.onUpdate(context); + logging.info('Server security context updated.'); + + } catch (e) { + logging.error(`ACME renewal failed: ${e}`); + if (e.code === 'EADDRINUSE') { + logging.error('Port 80 is in use. Cannot perform HTTP-01 challenge.'); + } + throw e; + } finally { + challengeServer.close(); + logging.info('ACME challenge server closed.'); + } + } +} diff --git a/src/shadowbox/server/main.ts b/src/shadowbox/server/main.ts index 533f9f439..0d36da043 100644 --- a/src/shadowbox/server/main.ts +++ b/src/shadowbox/server/main.ts @@ -33,6 +33,8 @@ import {bindService, ShadowsocksManagerService} from './manager_service'; import {OutlineShadowsocksServer} from './outline_shadowsocks_server'; import {AccessKeyConfigJson, ServerAccessKeyRepository} from './server_access_key'; import * as server_config from './server_config'; +import {CertificateManager} from './certificate_manager'; +import * as tls from 'tls'; import { OutlineSharedMetricsPublisher, PrometheusUsageMetrics, @@ -238,6 +240,20 @@ async function main() { key: fs.readFileSync(privateKeyFilename), }); + const certificateManager = new CertificateManager( + proxyHostname, + certificateFilename, + privateKeyFilename, + process.env.SB_STATE_DIR || DEFAULT_STATE_DIR, + (context: tls.SecureContext) => { + // Access the underlying node server to update the secure context + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (apiServer.server as any).setSecureContext(context); + } + ); + // Do not await this, so the server starts even if certificate generation takes time or fails + certificateManager.start(); + // Pre-routing handlers const cors = corsMiddleware({ origins: ['*'], From 2ea358013b2823000041a1205effe001d50b2598 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 21:40:49 +0000 Subject: [PATCH 2/3] Implement Let's Encrypt IP certificate support with factory pattern - Refactor `CertificateManager` to use a factory function (`createCertificateManager`) for dependency injection of the ACME client. - Update `main.ts` to use the factory and initialize certificate management asynchronously. - Remove unused dependencies (`node-fetch`, `mkdirp`) from `src/shadowbox`. - Ensure correct ACME client usage (v5 API). - Update `install_server.sh` to grant write permissions to the persisted state directory for certificate updates. - Update Node.js engine requirement to `>=18.0.0` for `crypto.X509Certificate` support. --- package-lock.json | 33 ++---------- src/shadowbox/package.json | 4 -- src/shadowbox/server/certificate_manager.ts | 58 +++++++++++---------- src/shadowbox/server/main.ts | 11 ++-- 4 files changed, 42 insertions(+), 64 deletions(-) diff --git a/package-lock.json b/package-lock.json index 569a04312..e4f06353a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1072,16 +1072,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/mkdirp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz", - "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/node": { "version": "16.11.34", "dev": true, @@ -6044,6 +6034,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6059,6 +6050,7 @@ }, "node_modules/mkdirp": { "version": "0.5.6", + "dev": true, "license": "MIT", "dependencies": { "minimist": "^1.2.6" @@ -9455,8 +9447,6 @@ "acme-client": "^5.4.0", "ip-regex": "^4.1.0", "js-yaml": "^3.12.0", - "mkdirp": "^0.5.6", - "node-fetch": "^2.6.7", "outline-shadowsocksconfig": "github:Jigsaw-Code/outline-shadowsocksconfig#v0.2.0", "prom-client": "^11.1.3", "randomstring": "^1.1.5", @@ -9469,9 +9459,7 @@ "@types/acme-client": "^3.0.0", "@types/jasmine": "^3.10.18", "@types/js-yaml": "^3.11.2", - "@types/mkdirp": "^1.0.2", "@types/node": "^18.19.130", - "@types/node-fetch": "^2.6.13", "@types/randomstring": "^1.1.6", "@types/restify": "^8.4.2", "@types/restify-cors-middleware": "^1.0.1", @@ -10284,15 +10272,6 @@ "version": "3.0.5", "dev": true }, - "@types/mkdirp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz", - "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/node": { "version": "16.11.34", "dev": true @@ -13667,7 +13646,8 @@ "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true }, "minipass": { "version": "5.0.0", @@ -13677,6 +13657,7 @@ }, "mkdirp": { "version": "0.5.6", + "dev": true, "requires": { "minimist": "^1.2.6" } @@ -13929,9 +13910,7 @@ "@types/acme-client": "^3.0.0", "@types/jasmine": "^3.10.18", "@types/js-yaml": "^3.11.2", - "@types/mkdirp": "^1.0.2", "@types/node": "^18.19.130", - "@types/node-fetch": "^2.6.13", "@types/randomstring": "^1.1.6", "@types/restify": "^8.4.2", "@types/restify-cors-middleware": "^1.0.1", @@ -13940,8 +13919,6 @@ "ip-regex": "^4.1.0", "jasmine": "^3.99.0", "js-yaml": "^3.12.0", - "mkdirp": "^0.5.6", - "node-fetch": "^2.6.7", "outline-shadowsocksconfig": "github:Jigsaw-Code/outline-shadowsocksconfig#v0.2.0", "prom-client": "^11.1.3", "randomstring": "^1.1.5", diff --git a/src/shadowbox/package.json b/src/shadowbox/package.json index 532ab919a..ff07f68d1 100644 --- a/src/shadowbox/package.json +++ b/src/shadowbox/package.json @@ -12,8 +12,6 @@ "acme-client": "^5.4.0", "ip-regex": "^4.1.0", "js-yaml": "^3.12.0", - "mkdirp": "^0.5.6", - "node-fetch": "^2.6.7", "outline-shadowsocksconfig": "github:Jigsaw-Code/outline-shadowsocksconfig#v0.2.0", "prom-client": "^11.1.3", "randomstring": "^1.1.5", @@ -26,9 +24,7 @@ "@types/acme-client": "^3.0.0", "@types/jasmine": "^3.10.18", "@types/js-yaml": "^3.11.2", - "@types/mkdirp": "^1.0.2", "@types/node": "^18.19.130", - "@types/node-fetch": "^2.6.13", "@types/randomstring": "^1.1.6", "@types/restify": "^8.4.2", "@types/restify-cors-middleware": "^1.0.1", diff --git a/src/shadowbox/server/certificate_manager.ts b/src/shadowbox/server/certificate_manager.ts index 94d496db5..65f3a59ba 100644 --- a/src/shadowbox/server/certificate_manager.ts +++ b/src/shadowbox/server/certificate_manager.ts @@ -24,26 +24,47 @@ import * as logging from '../infrastructure/logging'; const RENEW_THRESHOLD_DAYS = 30; const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours -export class CertificateManager { - private client: acme.Client; - private accountKeyPath: string; +export async function createCertificateManager( + hostname: string, + certFile: string, + keyFile: string, + stateDir: string, + onUpdate: (context: tls.SecureContext) => void +): Promise { + const accountKeyPath = path.join(stateDir, 'acme-account.key'); + let accountKey: Buffer; + + if (fs.existsSync(accountKeyPath)) { + logging.info(`Loading ACME account key from ${accountKeyPath}`); + accountKey = fs.readFileSync(accountKeyPath); + } else { + logging.info('Generating new ACME account key...'); + accountKey = await acme.crypto.createPrivateKey(); + fs.writeFileSync(accountKeyPath, accountKey); + } + const client = new acme.Client({ + directoryUrl: acme.directory.letsencrypt.production, + accountKey: accountKey, + }); + + return new CertificateManager(hostname, certFile, keyFile, onUpdate, client); +} + +export class CertificateManager { constructor( private readonly hostname: string, private readonly certFile: string, private readonly keyFile: string, - private readonly stateDir: string, - private readonly onUpdate: (context: tls.SecureContext) => void - ) { - this.accountKeyPath = path.join(this.stateDir, 'acme-account.key'); - } + private readonly onUpdate: (context: tls.SecureContext) => void, + private readonly client: acme.Client + ) {} async start() { try { - await this.initClient(); await this.checkAndRenew(); } catch (e) { - logging.error(`CertificateManager initialization failed: ${e}`); + logging.error(`CertificateManager initial check failed: ${e}`); } setInterval(() => { @@ -53,23 +74,6 @@ export class CertificateManager { }, CHECK_INTERVAL_MS); } - private async initClient() { - let accountKey: Buffer; - if (fs.existsSync(this.accountKeyPath)) { - logging.info(`Loading ACME account key from ${this.accountKeyPath}`); - accountKey = fs.readFileSync(this.accountKeyPath); - } else { - logging.info('Generating new ACME account key...'); - accountKey = await acme.crypto.createPrivateKey(); - fs.writeFileSync(this.accountKeyPath, accountKey); - } - - this.client = new acme.Client({ - directoryUrl: acme.directory.letsencrypt.production, - accountKey: accountKey, - }); - } - private async checkAndRenew() { logging.info('Checking certificate status...'); if (this.shouldRenew()) { diff --git a/src/shadowbox/server/main.ts b/src/shadowbox/server/main.ts index 0d36da043..0ca3ceb8d 100644 --- a/src/shadowbox/server/main.ts +++ b/src/shadowbox/server/main.ts @@ -33,7 +33,7 @@ import {bindService, ShadowsocksManagerService} from './manager_service'; import {OutlineShadowsocksServer} from './outline_shadowsocks_server'; import {AccessKeyConfigJson, ServerAccessKeyRepository} from './server_access_key'; import * as server_config from './server_config'; -import {CertificateManager} from './certificate_manager'; +import {createCertificateManager} from './certificate_manager'; import * as tls from 'tls'; import { OutlineSharedMetricsPublisher, @@ -240,7 +240,8 @@ async function main() { key: fs.readFileSync(privateKeyFilename), }); - const certificateManager = new CertificateManager( + // Do not await this, so the server starts even if certificate generation takes time or fails + createCertificateManager( proxyHostname, certificateFilename, privateKeyFilename, @@ -250,9 +251,9 @@ async function main() { // eslint-disable-next-line @typescript-eslint/no-explicit-any (apiServer.server as any).setSecureContext(context); } - ); - // Do not await this, so the server starts even if certificate generation takes time or fails - certificateManager.start(); + ).then((certificateManager) => { + certificateManager.start(); + }); // Pre-routing handlers const cors = corsMiddleware({ From daf88dae61eabbf2e048a4a1d22e01d806dd0d61 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 22:27:36 +0000 Subject: [PATCH 3/3] Implement Let's Encrypt IP certificate support with async/await - Refactor `CertificateManager` to use a factory function (`createCertificateManager`) for dependency injection of the ACME client. - Update `main.ts` to use `async/await` within an IIFE for cleaner initialization of the certificate manager, handling errors gracefully without blocking startup. - Remove unused dependencies (`node-fetch`, `mkdirp`) from `src/shadowbox`. - Ensure correct ACME client usage (v5 API). - Update `install_server.sh` to grant write permissions to the persisted state directory for certificate updates. - Update Node.js engine requirement to `>=18.0.0` for `crypto.X509Certificate` support. --- src/shadowbox/server/main.ts | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/shadowbox/server/main.ts b/src/shadowbox/server/main.ts index 0ca3ceb8d..5c359d812 100644 --- a/src/shadowbox/server/main.ts +++ b/src/shadowbox/server/main.ts @@ -241,19 +241,24 @@ async function main() { }); // Do not await this, so the server starts even if certificate generation takes time or fails - createCertificateManager( - proxyHostname, - certificateFilename, - privateKeyFilename, - process.env.SB_STATE_DIR || DEFAULT_STATE_DIR, - (context: tls.SecureContext) => { - // Access the underlying node server to update the secure context - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (apiServer.server as any).setSecureContext(context); + (async () => { + try { + const certificateManager = await createCertificateManager( + proxyHostname, + certificateFilename, + privateKeyFilename, + process.env.SB_STATE_DIR || DEFAULT_STATE_DIR, + (context: tls.SecureContext) => { + // Access the underlying node server to update the secure context + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (apiServer.server as any).setSecureContext(context); + } + ); + await certificateManager.start(); + } catch (error) { + logging.error(`Failed to initialize CertificateManager: ${error}`); } - ).then((certificateManager) => { - certificateManager.start(); - }); + })(); // Pre-routing handlers const cors = corsMiddleware({