feat: exposition Traefik + provisioning auth (v0.21.0)
Backend exposé via Traefik+TLS (réseau traefik-public externe, labels, CHLOVA_DOMAIN) — surface unique. Script provision-auth (hash scrypt + TOTP otpauth + JWT). .env.example section API/UI. security.md : surface exposée Phase 4. Compose revalidé. Palier de risque : privilégié (exposition réseau) — non déployé ; auth requise pour activer l'API. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import { randomBytes } from "node:crypto";
|
||||
import { generateSecret } from "otplib";
|
||||
import { hashPassword } from "../src/api/auth.js";
|
||||
|
||||
/**
|
||||
* Génère les secrets d'auth de la surface exposée (Phase 4) à coller dans .env.
|
||||
* Usage : npm run provision-auth -- <user> <password>
|
||||
*
|
||||
* N'imprime que des valeurs à mettre dans le coffre/.env (jamais commitées).
|
||||
* Le secret TOTP est aussi affiché en otpauth:// pour l'ajouter à une app 2FA.
|
||||
*/
|
||||
const [, , user, password] = process.argv;
|
||||
if (!user || !password) {
|
||||
console.error("Usage : npm run provision-auth -- <user> <password>");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const totpSecret = generateSecret();
|
||||
const jwtSecret = randomBytes(48).toString("base64url");
|
||||
const otpauth = `otpauth://totp/CHLOVA:${encodeURIComponent(user)}?secret=${totpSecret}&issuer=CHLOVA`;
|
||||
|
||||
console.log("# --- À coller dans .env (NE JAMAIS committer) ---");
|
||||
console.log(`CHLOVA_ADMIN_USER=${user}`);
|
||||
console.log(`CHLOVA_ADMIN_PASSWORD_HASH=${hashPassword(password)}`);
|
||||
console.log(`CHLOVA_TOTP_SECRET=${totpSecret}`);
|
||||
console.log(`CHLOVA_JWT_SECRET=${jwtSecret}`);
|
||||
console.log("\n# Ajoute ce TOTP à ton app 2FA (Aegis, Google Authenticator…) :");
|
||||
console.log(otpauth);
|
||||
Reference in New Issue
Block a user