Oprava: aplikace padala pri startu v produkcnim rezimu

Dockerfile nastavuje NODE_ENV=production a config.ts pri chybejicim
JWT_SECRET vyhazoval vyjimku. AppFactory tu promennou nastavenou nema,
takze se container po startu ukoncil a sluzba byla nedostupna (502).

Chybejici JWT_SECRET uz start neshodi. Vygeneruje se nahodny klic platny
do restartu containeru a do logu jde varovani. Klic zapsany v kodu se
nepouziva, aby nevznikla bezpecnostni dira.

Dusledek: bez nastavene promenne prestanou po restartu platit vydane
tokeny. JWT_SECRET se ma nastavit jako promenna aplikace v AppFactory.
This commit is contained in:
JiriUhlir
2026-07-31 17:04:32 +02:00
parent 7b045a9f20
commit e177ca2087
3 changed files with 32 additions and 9 deletions
+1
View File
@@ -0,0 +1 @@
[config] JWT_SECRET neni nastavena. Pouzivam nahodny klic platny jen do restartu containeru. Nastavte JWT_SECRET jako promennou aplikace v AppFactory.
+4
View File
@@ -0,0 +1,4 @@
[start] csbot-prototype bezi na portu 3000
[start] ROOT_PATH: /apps/csbot-prototype
[start] health: /apps/csbot-prototype/health, docs: /apps/csbot-prototype/docs
[req] GET /health
+27 -9
View File
@@ -2,19 +2,37 @@
* Konfigurace z environment variables.
* AppFactory je predava containeru, viz AGENTS.md, sekce Variables a secrets.
* Zadna hodnota se nehardcoduje a zadny secret se neloguje.
*
* Pravidlo: chybejici konfigurace nesmi shodit start aplikace. Container,
* ktery nenastartuje, je pro AppFactory nefunkcni sluzba.
*/
import { randomBytes } from 'node:crypto';
const isProduction = process.env.NODE_ENV === 'production';
function requiredInProduction(name: string, fallback: string): string {
const value = process.env[name];
/**
* Tajny klic pro podpis tokenu.
*
* Kdyz promenna chybi, NEPADAME a ani nepouzijeme klic zapsany v kodu.
* Aplikace musi nastartovat a odpovidat na /health, jinak ji AppFactory
* vyhodnoti jako nefunkcni. Misto toho se vygeneruje nahodny klic pro
* beh procesu a do logu jde hlasite varovani.
*
* Dusledek: po restartu containeru prestanou platit vydane tokeny
* a uzivatele se musi prihlasit znovu. Proto se JWT_SECRET ma nastavit
* jako promenna aplikace v AppFactory.
*/
function resolveJwtSecret(): string {
const value = process.env.JWT_SECRET;
if (value && value.trim().length > 0) return value;
if (isProduction) {
// Zamerne padame pri startu - tichy fallback na dev secret by byl bezpecnostni dira.
throw new Error(`Chybi povinna promenna prostredi ${name} (NODE_ENV=production).`);
}
console.warn(`[config] ${name} neni nastavena, pouzivam DEV fallback. Nepouzivat v produkci.`);
return fallback;
const generated = randomBytes(32).toString('base64url');
console.warn(
'[config] JWT_SECRET neni nastavena. Pouzivam nahodny klic platny jen do restartu ' +
'containeru. Nastavte JWT_SECRET jako promennou aplikace v AppFactory.',
);
return generated;
}
/**
@@ -34,7 +52,7 @@ export const config = {
/** Port urcuje AppFactory sablona, vychozi 3000. Nemenit bez upravy metadat. */
port: Number(process.env.PORT ?? 3000),
rootPath: normalizeRootPath(process.env.ROOT_PATH),
jwtSecret: requiredInProduction('JWT_SECRET', 'dev-only-secret-nepouzivat-v-produkci'),
jwtSecret: resolveJwtSecret(),
jwtExpiresIn: process.env.JWT_EXPIRES_IN ?? '8h',
/**
* Povolene originy pro CORS. V nasazeni bezi web i API na stejne domene,