Files
safetynet/apps/server/index.mjs
T

35 lines
2.9 KiB
JavaScript
Raw Normal View History

2026-10-13 10:33:31 +02:00
import { resolve } from 'node:path';
import { createApp } from './app.mjs';
import { openStore } from './store.mjs';
import { startTelemetry } from './telemetry.mjs';
import { startSIEM } from './siem.mjs';
import {startAuditRetention} from './audit-retention.mjs';
const env=process.env;
const publicUrl=(env.PUBLIC_URL||'http://127.0.0.1:4310').replace(/\/$/,'');
const u=new URL(publicUrl);
if(u.protocol!=='https:' && !['127.0.0.1','localhost','[::1]'].includes(u.hostname))throw Error('Remote management requires HTTPS');
if(u.protocol==='http:'&&(!env.ADMIN_TOKEN||env.ADMIN_TOKEN.length<32))throw Error('Local development requires ADMIN_TOKEN of at least 32 characters');
if(u.protocol==='http:'&&env.HOST&&!['127.0.0.1','localhost','::1'].includes(env.HOST))throw Error('Development HTTP management must bind only to loopback');
if(u.protocol==='https:'&&(!env.OIDC_ISSUER||!env.OIDC_CLIENT_ID))throw Error('HTTPS management requires enterprise OIDC configuration; shared bootstrap administrator tokens are disabled');
const config={publicUrl,secure:u.protocol==='https:',adminToken:env.ADMIN_TOKEN,oidcIssuer:env.OIDC_ISSUER,oidcClientId:env.OIDC_CLIENT_ID,oidcClientSecret:env.OIDC_CLIENT_SECRET,oidcAdminGroup:env.OIDC_ADMIN_GROUP||'safetynet-admins',oidcGroupsClaim:env.OIDC_GROUPS_CLAIM||'groups',aiBaseUrl:env.AI_BASE_URL,aiKey:env.AI_API_KEY,aiModel:env.AI_MODEL,inspectorUrl:env.INSPECTOR_URL,inspectorToken:env.INSPECTOR_TOKEN};
const store=openStore(resolve(env.DATA_DIR||'data'));
config.evidenceKeyFile=env.EVIDENCE_KEY_FILE;
config.evidenceRetentionDays=Number(env.EVIDENCE_RETENTION_DAYS||30);
config.oidcDeviceGroup=env.OIDC_DEVICE_GROUP;
config.oidcOperatorGroup=env.OIDC_OPERATOR_GROUP;
config.oidcAuditorGroup=env.OIDC_AUDITOR_GROUP;
config.requireIndependentPolicyApproval=env.REQUIRE_INDEPENDENT_POLICY_APPROVAL==='true';
config.requirePQManagement=env.REQUIRE_PQ_MANAGEMENT_CHANNEL!=='false';
if(u.protocol==='https:'&&!config.requirePQManagement)throw Error('Remote deployment requires the protected management channel');
config.aiEndpointId=env.AI_ENDPOINT_ID||'default';
const telemetry=startTelemetry();
const siem=startSIEM(store,resolve(env.DATA_DIR||'data'));
config.siemStatus=()=>siem.status();
const retention=startAuditRetention(store,siem,{days:Number(env.AUDIT_RETENTION_DAYS||0)});
config.auditRetentionStatus=()=>retention.status();
const server=createApp(store,config).listen(Number(env.PORT||4310),env.HOST||'127.0.0.1',()=>console.log(`SafetyNet management: ${publicUrl}`));
const timer=setInterval(()=>{
for(const table of ['sessions','logins','tickets','enrollments'])store.db.prepare(`DELETE FROM ${table} WHERE expires<?`).run(Date.now());
},60000);timer.unref();
async function stop(){clearInterval(timer);retention.stop();siem.stop();server.close(async()=>{store.db.close();await telemetry?.shutdown();process.exit(0);});}
process.on('SIGINT',stop);process.on('SIGTERM',stop);