fix(gateway): resolve connecting-to-backend stall with native Node.js edge proxy, activate 9/9 online services, integrate raw TCP Redis mesh, and update documentation
This commit is contained in:
@@ -11,7 +11,7 @@ async function main() {
|
||||
timestamp message source severity
|
||||
}
|
||||
}`,
|
||||
variables: { appId: '3d5666fe-95db-4e73-b6b2-dd0e41fca7f6', max: 50 }
|
||||
variables: { appId: '8fb7c350-8475-4512-805d-f14fb42ef422', max: 50 }
|
||||
})
|
||||
});
|
||||
console.log('AppLogs result:\n', JSON.stringify(await res.json(), null, 2));
|
||||
|
||||
@@ -8,7 +8,7 @@ async function main() {
|
||||
body: JSON.stringify({
|
||||
query: `query {
|
||||
ghaymah_cloud_row_event(
|
||||
where: { app_id: { _eq: "3d5666fe-95db-4e73-b6b2-dd0e41fca7f6" } },
|
||||
where: { app_id: { _eq: "07131052-d08b-4053-8942-1b36a4d89818" } },
|
||||
order_by: { event_date: desc },
|
||||
limit: 5
|
||||
) {
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
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>([^<]+)<\/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);
|
||||
@@ -0,0 +1,179 @@
|
||||
const fs = require('fs');
|
||||
const crypto = require('crypto');
|
||||
const zlib = require('zlib');
|
||||
const { getAuth } = require('./auth_manager');
|
||||
|
||||
const RESOURCE_ID = '07131052-d08b-4053-8942-1b36a4d89818';
|
||||
const APP_NAME = 'soc-gateway-live';
|
||||
const PROJECT_ID = '5be77e31-3ac2-48f5-b97d-735e8b2ad45f';
|
||||
const DOMAIN = 'soc-gateway-live-7c2ca9361c37.hosted.ghaymah.systems';
|
||||
|
||||
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 main() {
|
||||
const { token, userId } = await getAuth();
|
||||
console.log(`Upgrading soc-gateway-live (${RESOURCE_ID})...`);
|
||||
|
||||
console.log('\n=== Step 1: Packaging Node.js Gateway & Resilient SOC Dashboard ===');
|
||||
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 | New SHA256:', sha256);
|
||||
|
||||
console.log('\n=== Step 2: Uploading Artifact to S3 Proxy ===');
|
||||
const uploadUrl = `https://s3-nhost-proxy-83e02743fd61.hosted.ghaymah.systems/files/${userId}/${RESOURCE_ID}.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: Triggering Resource Update in Ghaymah ===');
|
||||
const values = {
|
||||
name: APP_NAME,
|
||||
projectId: PROJECT_ID,
|
||||
resourceTier: 't1',
|
||||
container: {
|
||||
image: `registry.ghaymah.systems/${userId}/${RESOURCE_ID}: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 updateRes = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
query: `mutation UpdateApp($id: uuid!, $values: json!) {
|
||||
update_ghaymah_cloud_resources_by_pk(
|
||||
pk_columns: { id: $id },
|
||||
_set: { values: $values }
|
||||
) {
|
||||
id status message
|
||||
}
|
||||
}`,
|
||||
variables: {
|
||||
id: RESOURCE_ID,
|
||||
values: values
|
||||
}
|
||||
})
|
||||
});
|
||||
const updateData = await updateRes.json();
|
||||
console.log('Update response:', JSON.stringify(updateData, null, 2));
|
||||
|
||||
console.log('\n=== Step 4: Monitoring Build & Deployment Status ===');
|
||||
let finalStatus = null;
|
||||
for (let i = 1; i <= 30; i++) {
|
||||
await new Promise(r => setTimeout(r, 3000));
|
||||
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: RESOURCE_ID }
|
||||
})
|
||||
});
|
||||
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') {
|
||||
finalStatus = 'synced';
|
||||
console.log('\n>>> SUCCESS! RESOURCE SYNCED! <<<');
|
||||
break;
|
||||
}
|
||||
if (status === 'failed') {
|
||||
finalStatus = 'failed';
|
||||
console.log('Build failed:', msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n=== Step 5: Testing Live Public Endpoints at https://${DOMAIN}/ ===`);
|
||||
try {
|
||||
const res = await fetch(`https://${DOMAIN}/`);
|
||||
console.log('GET / Status:', res.status);
|
||||
const body = await res.text();
|
||||
console.log('Title:', body.match(/<title>([^<]+)<\/title>/)?.[1]);
|
||||
|
||||
const hRes = await fetch(`https://${DOMAIN}/health`);
|
||||
console.log('GET /health Status:', hRes.status);
|
||||
console.log('GET /health Body:', await hRes.json());
|
||||
|
||||
const pRes = await fetch(`https://${DOMAIN}/proxy/soc-siem/health`);
|
||||
console.log('GET /proxy/soc-siem/health Status:', pRes.status);
|
||||
console.log('GET /proxy/soc-siem/health Body:', await pRes.json());
|
||||
} catch (e) {
|
||||
console.error('Fetch test error:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
Reference in New Issue
Block a user