Files
multiverse/xcom-ultra/xcu-iam-gatekeeper/server.js
T

468 lines
19 KiB
JavaScript

// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential.
require('dotenv').config();
const { WebSocketServer } = require('ws');
const http = require('http');
const jwt = require('jsonwebtoken');
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const { generateRegistrationOptions, verifyRegistrationResponse, generateAuthenticationOptions, verifyAuthenticationResponse } = require('@simplewebauthn/server');
const PORT = process.env.PORT || 4001;
const JWT_SECRET = process.env.JWT_SECRET;
if (!JWT_SECRET) { console.error('[3Z VIOLATION] JWT_SECRET env var MUST be set. Exiting.'); process.exit(1); }
const WEBAUTHN_RP_ID = process.env.WEBAUTHN_RP_ID || 'jumpa.id';
const WEBAUTHN_EXPECTED_ORIGIN = process.env.WEBAUTHN_EXPECTED_ORIGIN || 'https://jumpa.id';
const STATE_FILE = path.join(__dirname, 'iam_state.json');
// IAM Omni-Policy State
let iamState = {
identities: {
'AEGIS-SUPREME-974EFB44BE-X': {
role: 'supreme_admin',
tenant_id: 'SUPREME-MODE',
packages: ['phase-1-to-75', 'aegis-synthetica', 'ouroboros-protocol']
},
'AEGIS-TENANT-80AA3EEBE8-X': {
role: 'tenant',
tenant_id: 'JUMPA.ID ENTERPRISE',
packages: ['JUMPA.ID OMNI-ENGINE']
}
},
policies: {
'AEGIS-TENANT-80AA3EEBE8-X': {
name: 'JUMPA.ID ENTERPRISE',
mfa_mode: 'free', // 'free', 'strict', 'random'
supreme_allowed: {
biometric: true,
optical: true,
aegis: true
},
tenant_enabled: {
biometric: false,
optical: false,
aegis: true
}
}
}
};
const Redis = require('ioredis');
// Connect to Redis for live sync
const redisUrl = process.env.REDIS_URL || 'redis://127.0.0.1:6379';
const redis = new Redis(redisUrl);
redis.subscribe('AEGIS_IAM_STATE_CHANNEL', (err) => {
if (err) console.error('[IAM GATEKEEPER] Failed to subscribe to Redis:', err);
else console.log('[IAM GATEKEEPER] Subscribed to Redis channel AEGIS_IAM_STATE_CHANNEL');
});
redis.on('message', (channel, message) => {
if (channel === 'AEGIS_IAM_STATE_CHANNEL') {
try {
const newState = JSON.parse(message);
iamState = { ...iamState, ...newState };
console.log('[IAM GATEKEEPER] Synced state from Neural Relay (Redis)');
// Broadcast to connected WS clients
const broadcastData = JSON.stringify({ type: 'SYNC_IAM_POLICY', payload: iamState });
wss.clients.forEach(client => {
if (client.readyState === 1) client.send(broadcastData);
});
} catch (e) {
console.error('[IAM GATEKEEPER] Error parsing Redis message:', e);
}
}
});
const BILLING_MATRIX_URL = process.env.BILLING_MATRIX_URL || 'http://127.0.0.1:8082';
// Hydrate Policy from DuckDB / Billing Matrix
const hydrateState = async () => {
try {
const res = await fetch(`${BILLING_MATRIX_URL}/v1/iam/state`);
const loadedState = await res.json();
if (loadedState.identities && Object.keys(loadedState.identities).length > 0) {
iamState.identities = loadedState.identities;
iamState.policies = { ...iamState.policies, ...loadedState.policies };
console.log('[IAM GATEKEEPER] Successfully hydrated policies from DuckDB.');
} else {
console.log('[IAM GATEKEEPER] DuckDB state empty, using defaults. Seeding DB...');
saveStateToFile(); // Will actually post to DuckDB
}
} catch (err) {
console.error('[IAM GATEKEEPER] Failed to fetch state from DuckDB.', err.message);
}
};
hydrateState();
const saveStateToFile = () => {
fetch(`${BILLING_MATRIX_URL}/v1/iam/state`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(iamState)
}).catch(err => {
console.error('[IAM GATEKEEPER] Failed to save state to DuckDB.', err.message);
});
};
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain', 'Access-Control-Allow-Origin': '*' });
res.end('XCU IAM Aegis Gatekeeper + Policy Engine + Key Forge is Online.\n');
});
const wss = new WebSocketServer({ server });
let activeAuthSessions = {}; // { sessionId: { targetKeyId, sequence: [], currentIndex: 0, ws: websocket } }
wss.on('connection', (ws) => {
console.log('[IAM GATEKEEPER] Quantum Client Connected.');
// Send the current policy state and mapped keys immediately
ws.send(JSON.stringify({
type: 'SYNC_IAM_POLICY',
payload: iamState
}));
const opticalInterval = setInterval(() => {
if (ws.readyState === 1) {
ws.send(JSON.stringify({
type: 'OPTICAL_CHALLENGE',
payload: `XCU-OPT-${Math.random().toString(36).substr(2, 9).toUpperCase()}`
}));
}
}, 5000);
ws.on('message', async (message) => {
try {
const data = JSON.parse(message);
// ==========================================
// 1. POLICY MUTATION HUB (DevSecOps)
// ==========================================
if (data.type === 'UPDATE_IAM_POLICY') {
const { keyId, supreme_allowed, tenant_enabled, mfa_mode } = data.payload;
if (iamState.policies[keyId]) {
if (supreme_allowed) iamState.policies[keyId].supreme_allowed = supreme_allowed;
if (tenant_enabled) iamState.policies[keyId].tenant_enabled = tenant_enabled;
if (mfa_mode) iamState.policies[keyId].mfa_mode = mfa_mode;
saveStateToFile();
const broadcastData = JSON.stringify({ type: 'SYNC_IAM_POLICY', payload: iamState });
wss.clients.forEach(client => {
if (client.readyState === 1) client.send(broadcastData);
});
}
}
// ==========================================
// 2. AEGIS KEY FORGE (Zero-Database Credential Swap)
// ==========================================
if (data.type === 'REGENERATE_AEGIS_KEY') {
const { oldKeyId } = data.payload;
const identity = iamState.identities[oldKeyId];
if (identity) {
// Create new chaotic string
const newKeyString = `AEGIS-${identity.role === 'supreme_admin' ? 'SUPREME' : 'TENANT'}-${Math.random().toString(36).substr(2, 10).toUpperCase()}-X`;
// Move identity to new Key
iamState.identities[newKeyString] = identity;
delete iamState.identities[oldKeyId];
// If it's a tenant, move the policy as well
if (iamState.policies[oldKeyId]) {
iamState.policies[newKeyString] = iamState.policies[oldKeyId];
delete iamState.policies[oldKeyId];
}
saveStateToFile();
console.log(`[IAM FORGE] Key Rotated: ${oldKeyId} -> ${newKeyString}`);
// Send the new key back exclusively to the requester so they can download it
ws.send(JSON.stringify({
type: 'NEW_KEYCARD_GENERATED',
payload: { oldKeyId, newKeyString, role: identity.role }
}));
// Broadcast state to all
const broadcastData = JSON.stringify({ type: 'SYNC_IAM_POLICY', payload: iamState });
wss.clients.forEach(client => {
if (client.readyState === 1) client.send(broadcastData);
});
}
}
// ==========================================
// 2.5 WEBAUTHN HARDWARE BINDING (FASE 39)
// ==========================================
if (data.type === 'GENERATE_REGISTRATION_OPTIONS') {
const { targetKeyId } = data.payload;
const identity = iamState.identities[targetKeyId];
if (identity) {
const user = {
id: Buffer.from(targetKeyId).toString('base64url'),
name: targetKeyId,
displayName: identity.tenant_id
};
const options = await generateRegistrationOptions({
rpName: 'XCU Ultra Gatekeeper',
rpID: WEBAUTHN_RP_ID,
userID: user.id,
userName: user.name,
attestationType: 'none',
authenticatorSelection: {
residentKey: 'required',
userVerification: 'preferred',
}
});
iamState.identities[targetKeyId].currentChallenge = options.challenge;
ws.send(JSON.stringify({ type: 'REGISTRATION_OPTIONS', payload: options }));
}
}
if (data.type === 'VERIFY_REGISTRATION_RESPONSE') {
const { targetKeyId, response } = data.payload;
const identity = iamState.identities[targetKeyId];
if (identity && identity.currentChallenge) {
try {
const verification = await verifyRegistrationResponse({
response: response,
expectedChallenge: identity.currentChallenge,
expectedOrigin: WEBAUTHN_EXPECTED_ORIGIN,
expectedRPID: WEBAUTHN_RP_ID,
});
if (verification.verified) {
const { registrationInfo } = verification;
iamState.identities[targetKeyId].webAuthn = {
credentialID: Buffer.from(registrationInfo.credentialID).toString('base64url'),
credentialPublicKey: Buffer.from(registrationInfo.credentialPublicKey).toString('base64url'),
counter: registrationInfo.counter,
};
delete iamState.identities[targetKeyId].currentChallenge;
saveStateToFile();
ws.send(JSON.stringify({ type: 'REGISTRATION_SUCCESS', payload: 'Hardware Biometrik Berhasil Didaftarkan' }));
}
} catch (e) {
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: 'WebAuthn Registration Failed: ' + e.message }));
}
}
}
if (data.type === 'GENERATE_AUTHENTICATION_OPTIONS') {
const options = await generateAuthenticationOptions({
rpID: 'localhost',
userVerification: 'required',
});
// Save challenge globally for verification later (since we don't know who is logging in yet)
iamState.globalAuthChallenge = options.challenge;
ws.send(JSON.stringify({ type: 'AUTHENTICATION_OPTIONS', payload: options }));
}
// ==========================================
// 2.8 AIR-GAPPED MOBILE PAIRING (FASE 41)
// ==========================================
if (data.type === 'GENERATE_OPTICAL_PAIRING') {
const { targetKeyId } = data.payload;
if (iamState.identities[targetKeyId]) {
const secret = crypto.randomBytes(32).toString('hex');
iamState.identities[targetKeyId].pendingOpticalSecret = secret;
ws.send(JSON.stringify({
type: 'OPTICAL_PAIRING_QR',
payload: `PAIR|${targetKeyId}|${secret}`
}));
}
}
if (data.type === 'CONFIRM_OPTICAL_PAIRING') {
const { targetKeyId, secret } = data.payload;
const identity = iamState.identities[targetKeyId];
if (identity && identity.pendingOpticalSecret === secret) {
identity.opticalSecret = secret;
delete identity.pendingOpticalSecret;
saveStateToFile();
ws.send(JSON.stringify({ type: 'OPTICAL_PAIRING_SUCCESS', payload: 'Perangkat Kuantum Berhasil Dikawinkan.' }));
} else {
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: 'Gagal mengawinkan perangkat.' }));
}
}
// ==========================================
// 3. AEGIS AUTHENTICATION HUB (MFA ORCHESTRATOR)
// ==========================================
if (data.type === 'AEGIS_AUTH_REQUEST') {
const { authType, keyPayload, sessionId } = data.payload;
console.log(`[IAM GATEKEEPER] Auth Request: ${authType}`);
let targetKeyId = null;
if (authType === 'BIOMETRIC_PULSE') {
const response = keyPayload; // keyPayload is the credential response from browser
// Find which identity this credential belongs to
targetKeyId = Object.keys(iamState.identities).find(k =>
iamState.identities[k].webAuthn &&
iamState.identities[k].webAuthn.credentialID === response.id
);
if (targetKeyId && iamState.identities[targetKeyId].webAuthn) {
try {
const verification = await verifyAuthenticationResponse({
response: response,
expectedChallenge: iamState.globalAuthChallenge,
expectedOrigin: WEBAUTHN_EXPECTED_ORIGIN,
expectedRPID: WEBAUTHN_RP_ID,
authenticator: {
credentialID: Buffer.from(iamState.identities[targetKeyId].webAuthn.credentialID, 'base64url'),
credentialPublicKey: Buffer.from(iamState.identities[targetKeyId].webAuthn.credentialPublicKey, 'base64url'),
counter: iamState.identities[targetKeyId].webAuthn.counter,
}
});
if (verification.verified) {
const { authenticationInfo } = verification;
iamState.identities[targetKeyId].webAuthn.counter = authenticationInfo.newCounter;
saveStateToFile();
} else {
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: 'Tanda Tangan Biometrik Tidak Valid.' }));
return;
}
} catch (e) {
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: 'Gagal Memverifikasi Biometrik: ' + e.message }));
return;
}
} else {
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: 'Hardware Biometrik Belum Terdaftar.' }));
return;
}
} else if (authType === 'AEGIS_KEYCARD') {
targetKeyId = keyPayload;
} else if (authType === 'OPTICAL_SYNC') {
// keyPayload carries { targetKeyId, signature, challenge }
targetKeyId = keyPayload.targetKeyId;
const identity = iamState.identities[targetKeyId];
if (!identity || !identity.opticalSecret) {
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: 'Ponsel ini belum di-Pairing (Dikawinkan) di dalam Dasbor.' }));
return;
}
// Verify HMAC-SHA256 signature
const expectedSignature = crypto.createHmac('sha256', identity.opticalSecret)
.update(keyPayload.challenge)
.digest('hex');
if (keyPayload.signature !== expectedSignature) {
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: 'Tanda Tangan Kriptografi Ponsel DITOLAK!' }));
return;
}
}
if (targetKeyId && iamState.identities[targetKeyId]) {
const identity = iamState.identities[targetKeyId];
const policy = iamState.policies[targetKeyId];
const typeMap = { 'BIOMETRIC_PULSE': 'biometric', 'OPTICAL_SYNC': 'optical', 'AEGIS_KEYCARD': 'aegis' };
const methodKey = typeMap[authType];
// === STRICT POLICY ENFORCEMENT CHECK ===
if (identity.role === 'tenant' && policy) {
if (!policy.supreme_allowed[methodKey]) {
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: `ACCESS DENIED: Protokol [${methodKey}] telah dicabut secara absolut oleh Supreme Admin.` }));
return;
}
if (!policy.tenant_enabled[methodKey]) {
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: `ACCESS DENIED: Anda telah menonaktifkan protokol [${methodKey}] di Security Enclave Anda.` }));
return;
}
}
// === MFA ORCHESTRATION ===
if (identity.role === 'tenant' && policy) {
const mode = policy.mfa_mode || 'free';
const activeLayers = ['biometric', 'optical', 'aegis'].filter(k => policy.supreme_allowed[k] && policy.tenant_enabled[k]);
if (mode !== 'free' && activeLayers.length > 1) {
// Multi-Factor required
if (!sessionId) {
// Initialize new session
const newSessionId = `MFA-SESS-${Math.random().toString(36).substr(2, 9).toUpperCase()}`;
let sequence = [...activeLayers];
if (mode === 'random') {
sequence = sequence.sort(() => Math.random() - 0.5);
}
// If the first step in sequence is what they just submitted, advance. Otherwise, reject and tell them the sequence
if (sequence[0] === methodKey) {
activeAuthSessions[newSessionId] = { targetKeyId, sequence, currentIndex: 1, ws };
ws.send(JSON.stringify({
type: 'MFA_STEP_REQUIRED',
payload: { sessionId: newSessionId, nextStep: sequence[1], sequence, currentIndex: 1 }
}));
return;
} else {
ws.send(JSON.stringify({
type: 'MFA_SEQUENCE_STARTED',
payload: { sessionId: newSessionId, sequence, currentIndex: 0, message: `Kebijakan Multi-Lapis Aktif. Anda wajib mematuhi urutan: ${sequence.join(' -> ').toUpperCase()}` }
}));
return;
}
} else {
// Advance existing session
const session = activeAuthSessions[sessionId];
if (!session || session.targetKeyId !== targetKeyId) {
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: 'Sesi MFA tidak valid atau telah usang.' }));
return;
}
if (session.sequence[session.currentIndex] !== methodKey) {
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: `Pelanggaran Urutan! Langkah yang diharapkan: ${session.sequence[session.currentIndex].toUpperCase()}` }));
delete activeAuthSessions[sessionId];
return;
}
session.currentIndex++;
if (session.currentIndex < session.sequence.length) {
ws.send(JSON.stringify({
type: 'MFA_STEP_REQUIRED',
payload: { sessionId, nextStep: session.sequence[session.currentIndex], sequence: session.sequence, currentIndex: session.currentIndex }
}));
return;
}
// If finished, delete session and grant access
delete activeAuthSessions[sessionId];
}
}
}
// Issue JWT if single-layer, free mode, or MFA completed
console.log('[IAM GATEKEEPER] Auth Successful. Issuing JWT.');
const token = jwt.sign({
role: identity.role,
tenant_id: identity.tenant_id,
used_gb: Math.random() * 50,
quota_limit_gb: 500,
packages: identity.packages
}, JWT_SECRET, { expiresIn: '24h' });
ws.send(JSON.stringify({ type: 'AUTH_SUCCESS', payload: { token } }));
} else {
console.warn('[IAM GATEKEEPER] Auth Failed. Invalid Key.');
ws.send(JSON.stringify({ type: 'AUTH_FAILED', payload: 'Kriptografi Gagal Divalidasi. Kunci Fisik ini mungkin sudah Hangus (Revoked).' }));
}
}
} catch (err) {
console.error('[IAM GATEKEEPER] Payload parsing error:', err);
}
});
ws.on('close', () => {
clearInterval(opticalInterval);
});
});
server.listen(PORT, () => {
console.log(`[IAM GATEKEEPER] Listening on ws://localhost:${PORT}`);
});