const fs = require('fs'); const crypto = require('crypto'); const zlib = require('zlib'); const { getAuth } = require('./auth_manager'); const PROJECT_ID = '5be77e31-3ac2-48f5-b97d-735e8b2ad45f'; // ghaymah-soc-microservices const APP_NAME = 'soc-gateway-live'; function createTar(files) { const chunks = []; for (const file of files) { const name = file.name; const content = Buffer.isBuffer(file.content) ? file.content : Buffer.from(file.content, 'utf8'); const size = content.length; const header = Buffer.alloc(512); header.write(name, 0, 100, 'utf8'); header.write('0000644\0', 100, 8, 'utf8'); header.write('0000000\0', 108, 8, 'utf8'); header.write('0000000\0', 116, 8, 'utf8'); header.write(size.toString(8).padStart(11, '0') + '\0', 124, 12, 'utf8'); const mtime = Math.floor(Date.now() / 1000); header.write(mtime.toString(8).padStart(11, '0') + '\0', 136, 12, 'utf8'); header.write(' ', 148, 8, 'utf8'); header.write('0', 156, 1, 'utf8'); header.write('ustar\0', 257, 6, 'utf8'); header.write('00', 263, 2, 'utf8'); let sum = 0; for (let i = 0; i < 512; i++) sum += header[i]; header.write(sum.toString(8).padStart(6, '0') + '\0 ', 148, 8, 'utf8'); chunks.push(header); chunks.push(content); const remainder = size % 512; if (remainder > 0) chunks.push(Buffer.alloc(512 - remainder)); } chunks.push(Buffer.alloc(1024)); return zlib.gzipSync(Buffer.concat(chunks)); } async function genDomainHash(name, id) { const input = `${name}-${id}`; const data = new TextEncoder().encode(input); const hash = await crypto.subtle.digest('SHA-256', data); const hex = Array.from(new Uint8Array(hash)).map(b => b.toString(16).padStart(2, '0')).join(''); return hex.substring(0, 12); } async function main() { const { token, userId } = await getAuth(); const resourceId = crypto.randomUUID(); const domainHash = await genDomainHash(APP_NAME, resourceId); const domain = `${APP_NAME}-${domainHash}.hosted.ghaymah.systems`; console.log(`Generated new resource ID: ${resourceId}`); console.log(`Domain will be: https://${domain}/`); console.log('\n=== Step 1: Packaging Node.js SOC Gateway Artifact ==='); const serverContent = fs.readFileSync('D:/cumin/ghaymah_dns_net_sec_tests/soc_gateway_ui/server.js', 'utf8'); const htmlContent = fs.readFileSync('D:/cumin/ghaymah_dns_net_sec_tests/soc_gateway_ui/index.html', 'utf8'); const dockerfile = `FROM node:alpine WORKDIR /app COPY . . EXPOSE 80 ENV PORT=80 CMD ["node", "server.js"] `; const tarGz = createTar([ { name: 'Dockerfile', content: dockerfile }, { name: 'server.js', content: serverContent }, { name: 'index.html', content: htmlContent } ]); const sha256 = crypto.createHash('sha256').update(tarGz).digest('hex'); console.log('Tarball created! Size:', tarGz.length, 'bytes | SHA256:', sha256); console.log('\n=== Step 2: Uploading Artifact to S3 ==='); const uploadUrl = `https://s3-nhost-proxy-83e02743fd61.hosted.ghaymah.systems/files/${userId}/${resourceId}.tar.gz`; const upRes = await fetch(uploadUrl, { method: 'PUT', headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/gzip' }, body: tarGz }); console.log('Upload status:', upRes.status, upRes.statusText); if (!upRes.ok) { throw new Error('Upload failed: ' + (await upRes.text())); } console.log('\n=== Step 3: Inserting New Cloud Resource into ghaymah-soc-microservices ==='); const insertRes = await fetch('https://graphql.ghaymah.systems/v1/graphql', { method: 'POST', headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' }, body: JSON.stringify({ query: `mutation CreateApp($id: uuid!, $userId: uuid!, $chartName: String!, $chartVersion: String!, $values: json!) { insert_ghaymah_cloud_resources_one(object: { id: $id, user_id: $userId, chart_name: $chartName, chart_version: $chartVersion, values: $values }) { id status message } }`, variables: { id: resourceId, userId: userId, chartName: 'ghaymah-app', chartVersion: '0.1', values: { name: APP_NAME, projectId: PROJECT_ID, resourceTier: 't1', container: { image: `registry.ghaymah.systems/${userId}/${resourceId}:latest` }, ports: [{ number: 80, expose: true }], publicAccess: { baseDomain: 'hosted.ghaymah.systems', domain: domain, enabled: true }, source: { enabled: true, ref: sha256, type: 'artifact', url: uploadUrl } } } }) }); const insData = await insertRes.json(); console.log('Insert response:\n', JSON.stringify(insData, null, 2)); console.log('\n=== Step 4: Monitoring Build / Sync Status ==='); let isSynced = false; for (let i = 1; i <= 30; i++) { await new Promise(r => setTimeout(r, 4000)); const checkRes = await fetch('https://graphql.ghaymah.systems/v1/graphql', { method: 'POST', headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' }, body: JSON.stringify({ query: `query CheckStatus($id: uuid!) { ghaymah_cloud_resources_by_pk(id: $id) { id status message } }`, variables: { id: resourceId } }) }); const checkData = await checkRes.json(); const status = checkData.data?.ghaymah_cloud_resources_by_pk?.status; const msg = checkData.data?.ghaymah_cloud_resources_by_pk?.message; console.log(`[Attempt ${i}/30] Status: ${status} | Message: ${msg}`); if (status === 'synced') { isSynced = true; console.log('\n>>> SUCCESS! RESOURCE SYNCED! <<<'); break; } if (status === 'failed') { console.log('Build failed:', msg); break; } } if (!isSynced) { throw new Error('Deployment did not reach synced status in time'); } console.log(`\n=== Step 5: Testing Live Public Endpoints at https://${domain}/ ===`); const testRes = await fetch(`https://${domain}/`); console.log('HTTP GET / Status:', testRes.status); const body = await testRes.text(); console.log('Page Title:', body.match(/([^<]+)<\/title>/)?.[1]); const hRes = await fetch(`https://${domain}/health`); console.log('HTTP GET /health Status:', hRes.status); console.log('Health Data:', await hRes.json()); const pRes = await fetch(`https://${domain}/proxy/soc-siem/health`); console.log('HTTP GET /proxy/soc-siem/health Status:', pRes.status); console.log('SIEM Health:', await pRes.json()); const statRes = await fetch(`https://${domain}/proxy/soc-siem/stats`); console.log('HTTP GET /proxy/soc-siem/stats Status:', statRes.status); console.log('SIEM Stats:', await statRes.json()); // Delete previous inactive/static gateway resource 07131052-d08b-4053-8942-1b36a4d89818 console.log('\n=== Step 6: Cleaning Up Preceding Gateway Resource ==='); await fetch('https://graphql.ghaymah.systems/v1/graphql', { method: 'POST', headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' }, body: JSON.stringify({ query: `mutation DeleteOld($id: uuid!) { update_ghaymah_cloud_resources_by_pk( pk_columns: { id: $id }, _set: { deleted: true } ) { id deleted } }`, variables: { id: '07131052-d08b-4053-8942-1b36a4d89818' } }) }); console.log('Marked old 07131052 resource as deleted.'); console.log('\n=== DEPLOYMENT SUMMARY ==='); console.log('Resource ID:', resourceId); console.log('Public URL:', `https://${domain}/`); } main().catch(console.error);