const fs = require('fs').promises; const pathModule = require('path'); const state = require('../../../infrastructure/state'); const ca = require('../../../security/certificate_authority'); const { createInterfaceForDomain } = require('../../../networking/virtual_interfaces'); const { logDebug, logError } = require('../../../infrastructure/logger'); const { broadcast } = require('../websocket'); const certsDir = process.env.CERTS_DIR || './certs'; async function handleCertsRoutes(req, res) { const urlPath = req.urlPath || new URL(req.url, `https://${req.headers.host}`).pathname; const method = req.method; const url = new URL(req.url, `https://${req.headers.host}`); if (method === 'GET' && urlPath === '/api/certs') { try { const certDomains = await fs.readdir(certsDir); const filteredDomains = []; for (const file of certDomains) { if ((await fs.stat(pathModule.join(certsDir, file))).isDirectory()) { filteredDomains.push(file); } } res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(filteredDomains)); } catch (err) { logError('Admin', `Failed to fetch certs: ${err.message}`); res.writeHead(500); res.end(JSON.stringify({ error: 'Failed to fetch certs' })); } return true; } if (method === 'GET' && urlPath.startsWith('/api/cert-details')) { const domain = url.searchParams.get('domain'); try { const certPath = pathModule.join(certsDir, domain, 'cert.pem'); const certContent = await fs.readFile(certPath, 'utf8'); res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end(certContent); } catch (err) { logError('Admin', `Failed to fetch cert details: ${err.message}`); res.writeHead(500); res.end('Failed to fetch cert details'); } return true; } if (method === 'POST' && urlPath === '/api/regenerate-ca') { try { ca.regenerateRootCA(); broadcast({ type: 'update-certs' }); res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('OK'); } catch (err) { logError('Admin', `Failed to regenerate CA: ${err.message}`); res.writeHead(500); res.end(err.message); } return true; } if (method === 'POST' && urlPath === '/api/install-ca') { try { ca.installRootCA(); res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('OK'); } catch (err) { logError('Admin', `Failed to install CA: ${err.message}`); res.writeHead(500); res.end(err.message); } return true; } if (method === 'POST' && urlPath === '/api/generate-cert') { let body = ''; req.on('data', chunk => { body += chunk; }); req.on('end', async () => { try { const data = JSON.parse(body); if (!state.domainToIPMap.has(data.domain)) { await createInterfaceForDomain(data.domain); logDebug('Admin', `Assigned IP to ${data.domain}: ${state.domainToIPMap.get(data.domain)}`); } const ip = state.domainToIPMap.get(data.domain); ca.getOrCreateDomainCert(data.domain, ip); broadcast({ type: 'update-certs' }); res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('OK'); } catch (err) { logError('Admin', `Failed to generate cert: ${err.message}`); res.writeHead(500); res.end(err.message); } }); return true; } if (method === 'POST' && urlPath === '/api/delete-cert') { let body = ''; req.on('data', chunk => { body += chunk; }); req.on('end', async () => { try { const data = JSON.parse(body); const domainDir = pathModule.join(certsDir, data.domain); await fs.rm(domainDir, { recursive: true, force: true }); broadcast({ type: 'update-certs' }); res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('OK'); } catch (err) { logError('Admin', `Failed to delete cert: ${err.message}`); res.writeHead(500); res.end(err.message); } }); return true; } if (method === 'POST' && urlPath === '/api/regenerate-cert') { let body = ''; req.on('data', chunk => { body += chunk; }); req.on('end', async () => { try { const data = JSON.parse(body); const domainDir = pathModule.join(certsDir, data.domain); await fs.rm(domainDir, { recursive: true, force: true }); if (!state.domainToIPMap.has(data.domain)) { await createInterfaceForDomain(data.domain); logDebug('Admin', `Assigned IP to ${data.domain}: ${state.domainToIPMap.get(data.domain)}`); } const ip = state.domainToIPMap.get(data.domain); ca.getOrCreateDomainCert(data.domain, ip); broadcast({ type: 'update-certs' }); res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('OK'); } catch (err) { logError('Admin', `Failed to regenerate cert: ${err.message}`); res.writeHead(500); res.end(err.message); } }); return true; } return false; } module.exports = { handleCertsRoutes };