diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b6e48dc1..b88b5b32 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,3 +5,13 @@ updates: schedule: interval: "weekly" rebase-strategy: "auto" + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + rebase-strategy: "auto" + - package-ecosystem: "npm" + directory: "/src/" + schedule: + interval: "weekly" + rebase-strategy: "auto" diff --git a/.github/workflows/deploy-development.yml b/.github/workflows/deploy-development.yml index da26f886..2f8f1e63 100644 --- a/.github/workflows/deploy-development.yml +++ b/.github/workflows/deploy-development.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: production + ref: master - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/deploy-nightly.yml b/.github/workflows/deploy-nightly.yml index eac5a29e..906d407b 100644 --- a/.github/workflows/deploy-nightly.yml +++ b/.github/workflows/deploy-nightly.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: production + ref: master - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/deploy-pr.yml b/.github/workflows/deploy-pr.yml index 8acd5e60..d32d818f 100644 --- a/.github/workflows/deploy-pr.yml +++ b/.github/workflows/deploy-pr.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: production + ref: master - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/npm-update-bot.yml b/.github/workflows/npm-update-bot.yml deleted file mode 100644 index b13de144..00000000 --- a/.github/workflows/npm-update-bot.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: NPM Update Bot 🤖 - -on: - push: - branches: [ "master" ] - schedule: - - cron: "0 0 * * 1" - -jobs: - npmupbot: - name: NPM Update Bot 🤖 - runs-on: ubuntu-latest - if: github.repository_owner == 'wg-easy' - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - repository: wg-easy/wg-easy - ref: master - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: 'lts/*' - check-latest: true - cache: 'npm' - - - name: Bot 🤖 "Updating NPM Packages..." - run: | - npm install -g --silent npm-check-updates - ncu -u - npm update - cd src - ncu -u - npm update - npm run buildcss - git config --global user.name 'NPM Update Bot' - git config --global user.email 'npmupbot@users.noreply.github.com' - git add . - git commit -am "npm: package updates" || true - git push diff --git a/How_to_generate_an_bcrypt_hash.md b/How_to_generate_an_bcrypt_hash.md index e77e3717..3e3bee9a 100644 --- a/How_to_generate_an_bcrypt_hash.md +++ b/How_to_generate_an_bcrypt_hash.md @@ -12,9 +12,15 @@ To generate a bcrypt password hash using docker, run the following command : ```sh -docker run ghcr.io/wg-easy/wg-easy wgpw YOUR_PASSWORD +docker run -it ghcr.io/wg-easy/wg-easy wgpw YOUR_PASSWORD PASSWORD_HASH='$2b$12$coPqCsPtcFO.Ab99xylBNOW4.Iu7OOA2/ZIboHN6/oyxca3MWo7fW' // literally YOUR_PASSWORD ``` +If a password is not provided, the tool will prompt you for one : +```sh +docker run -it ghcr.io/wg-easy/wg-easy wgpw +Enter your password: // hidden prompt, type in your password +PASSWORD_HASH='$2b$12$coPqCsPtcFO.Ab99xylBNOW4.Iu7OOA2/ZIboHN6/oyxca3MWo7fW' +``` **Important** : make sure to enclose your password in **single quotes** when you run `docker run` command : @@ -33,4 +39,4 @@ $2b$12$coPqCsPtcF - PASSWORD_HASH=$$2y$$10$$hBCoykrB95WSzuV4fafBzOHWKu9sbyVa34GJr8VV5R/pIelfEMYyG ``` -This hash is for the password 'foobar123', obtained using the command `docker run ghcr.io/wg-easy/wg-easy wgpw foobar123` and then inserted an additional `$` before each existing `$` symbal. +This hash is for the password 'foobar123', obtained using the command `docker run ghcr.io/wg-easy/wg-easy wgpw foobar123` and then inserted an additional `$` before each existing `$` symbol. diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index bd4a836d..d1b7cf66 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -13,5 +13,5 @@ services: - NET_ADMIN - SYS_MODULE environment: - # - PASSWORD=p + # - PASSWORD_HASH=p - WG_HOST=192.168.1.233 diff --git a/src/config.js b/src/config.js index 01f0ce20..72314ae1 100644 --- a/src/config.js +++ b/src/config.js @@ -5,6 +5,8 @@ const { release: { version } } = require('./package.json'); module.exports.RELEASE = version; module.exports.PORT = process.env.PORT || '51821'; module.exports.WEBUI_HOST = process.env.WEBUI_HOST || '0.0.0.0'; +/** This is only kept for migration purpose. DO NOT USE! */ +module.exports.PASSWORD = process.env.PASSWORD; module.exports.PASSWORD_HASH = process.env.PASSWORD_HASH; module.exports.MAX_AGE = parseInt(process.env.MAX_AGE, 10) * 1000 * 60 || 0; module.exports.WG_PATH = process.env.WG_PATH || '/etc/wireguard/'; diff --git a/src/lib/Server.js b/src/lib/Server.js index 17e5058b..08e7dc5e 100644 --- a/src/lib/Server.js +++ b/src/lib/Server.js @@ -29,6 +29,7 @@ const { PORT, WEBUI_HOST, RELEASE, + PASSWORD, PASSWORD_HASH, MAX_AGE, LANG, @@ -428,6 +429,10 @@ module.exports = class Server { }), ); + if (PASSWORD) { + throw new Error('DO NOT USE PASSWORD ENVIRONMENT VARIABLE. USE PASSWORD_HASH INSTEAD.\nSee https://github.com/wg-easy/wg-easy/blob/master/How_to_generate_an_bcrypt_hash.md'); + } + createServer(toNodeListener(app)).listen(PORT, WEBUI_HOST); debug(`Listening on http://${WEBUI_HOST}:${PORT}`); diff --git a/src/package-lock.json b/src/package-lock.json index 5e619198..f50190ac 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -12,13 +12,13 @@ "basic-auth": "^2.0.1", "bcryptjs": "^2.4.3", "crc-32": "^1.2.2", - "debug": "^4.3.6", + "debug": "^4.3.7", "express-session": "^1.18.0", "h3": "^1.12.0", "qrcode": "^1.5.4" }, "devDependencies": { - "@tailwindcss/forms": "^0.5.7", + "@tailwindcss/forms": "^0.5.9", "eslint-config-athom": "^3.1.3", "nodemon": "^3.1.4", "tailwindcss": "^3.4.10" @@ -454,17 +454,24 @@ "node": ">=14" } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, "node_modules/@tailwindcss/forms": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz", - "integrity": "sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.9.tgz", + "integrity": "sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==", "dev": true, "license": "MIT", "dependencies": { "mini-svg-data-uri": "^1.2.3" }, "peerDependencies": { - "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20" } }, "node_modules/@types/json-schema": { @@ -1346,12 +1353,11 @@ } }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "license": "MIT", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1789,9 +1795,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz", - "integrity": "sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.9.0.tgz", + "integrity": "sha512-McVbYmwA3NEKwRQY5g4aWMdcZE5xZxV8i8l7CqJSrameuGSQJtSWaL/LxTEzSKKaCcOhlpDR8XEfYXWPrdo/ZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1850,27 +1856,28 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", + "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", "dev": true, "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", "array.prototype.flat": "^1.3.2", "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", + "eslint-module-utils": "^2.9.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", "semver": "^6.3.1", "tsconfig-paths": "^3.15.0" }, @@ -3352,10 +3359,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "license": "MIT" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/mz": { "version": "2.7.0", @@ -3774,9 +3780,9 @@ "license": "MIT" }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true, "license": "ISC" }, @@ -3833,9 +3839,9 @@ } }, "node_modules/postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "version": "8.4.45", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz", + "integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==", "dev": true, "funding": [ { @@ -5190,9 +5196,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "dev": true, "license": "ISC", "bin": { diff --git a/src/package.json b/src/package.json index 007f08c2..618bdbb6 100644 --- a/src/package.json +++ b/src/package.json @@ -18,13 +18,13 @@ "basic-auth": "^2.0.1", "bcryptjs": "^2.4.3", "crc-32": "^1.2.2", - "debug": "^4.3.6", + "debug": "^4.3.7", "express-session": "^1.18.0", "h3": "^1.12.0", "qrcode": "^1.5.4" }, "devDependencies": { - "@tailwindcss/forms": "^0.5.7", + "@tailwindcss/forms": "^0.5.9", "eslint-config-athom": "^3.1.3", "nodemon": "^3.1.4", "tailwindcss": "^3.4.10" diff --git a/src/wgpw.mjs b/src/wgpw.mjs index 4062a73e..6ad6aede 100644 --- a/src/wgpw.mjs +++ b/src/wgpw.mjs @@ -2,6 +2,8 @@ // Import needed libraries import bcrypt from 'bcryptjs'; +import { Writable } from 'stream'; +import readline from 'readline'; // Function to generate hash const generateHash = async (password) => { @@ -31,12 +33,35 @@ const comparePassword = async (password, hash) => { } }; +const readStdinPassword = () => { + return new Promise((resolve) => { + process.stdout.write('Enter your password: '); + + const rl = readline.createInterface({ + input: process.stdin, + output: new Writable({ + write(_chunk, _encoding, callback) { + callback(); + }, + }), + terminal: true, + }); + + rl.question('', (answer) => { + rl.close(); + // Print a new line after password prompt + process.stdout.write('\n'); + resolve(answer); + }); + }); +}; + (async () => { try { // Retrieve command line arguments const args = process.argv.slice(2); // Ignore the first two arguments if (args.length > 2) { - throw new Error('Usage : wgpw YOUR_PASSWORD [HASH]'); + throw new Error('Usage : wgpw [YOUR_PASSWORD] [HASH]'); } const [password, hash] = args; @@ -44,6 +69,9 @@ const comparePassword = async (password, hash) => { await comparePassword(password, hash); } else if (password) { await generateHash(password); + } else { + const password = await readStdinPassword(); + await generateHash(password); } } catch (error) { // eslint-disable-next-line no-console