fix(gateway): deploy native in-project soc-gateway-live container artifact, eliminate ttyd terminal, clean up external static apps, and update English security reports

This commit is contained in:
2026-10-13 01:56:56 +03:00
parent f8917dfa88
commit 1a4a583f8b
31 changed files with 1320 additions and 33 deletions
+258
View File
@@ -0,0 +1,258 @@
const fs = require('fs');
const crypto = require('crypto');
const zlib = require('zlib');
const { getAuth } = require('./auth_manager');
const REPO_NAME = 'soc-gateway';
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 Buffer.concat(chunks);
}
async function uploadBlobToGhaymah(blobBuffer, digest, userId) {
let authData = await getAuth();
let auth = Buffer.from(userId + ':' + authData.token).toString('base64');
// Check if blob already exists
let checkRes = await fetch(`https://registry.ghaymah.systems/v2/${userId}/${REPO_NAME}/blobs/${digest}`, {
method: 'HEAD',
headers: { 'Authorization': 'Basic ' + auth }
});
if (checkRes.status === 401) {
authData = await getAuth(true);
auth = Buffer.from(userId + ':' + authData.token).toString('base64');
checkRes = await fetch(`https://registry.ghaymah.systems/v2/${userId}/${REPO_NAME}/blobs/${digest}`, {
method: 'HEAD',
headers: { 'Authorization': 'Basic ' + auth }
});
}
if (checkRes.ok) {
console.log(`Blob ${digest.substring(0, 19)} already exists on Ghaymah!`);
return;
}
// Initiate upload
let initRes = await fetch(`https://registry.ghaymah.systems/v2/${userId}/${REPO_NAME}/blobs/uploads/`, {
method: 'POST',
headers: { 'Authorization': 'Basic ' + auth }
});
if (initRes.status === 401) {
authData = await getAuth(true);
auth = Buffer.from(userId + ':' + authData.token).toString('base64');
initRes = await fetch(`https://registry.ghaymah.systems/v2/${userId}/${REPO_NAME}/blobs/uploads/`, {
method: 'POST',
headers: { 'Authorization': 'Basic ' + auth }
});
}
if (initRes.status !== 202) {
throw new Error(`Failed to initiate blob upload: ${initRes.status} ${await initRes.text()}`);
}
let uploadUrl = initRes.headers.get('location');
if (uploadUrl.startsWith('/')) {
uploadUrl = 'https://registry.ghaymah.systems' + uploadUrl;
}
const separator = uploadUrl.includes('?') ? '&' : '?';
const putUrl = `${uploadUrl}${separator}digest=${digest}`;
const putRes = await fetch(putUrl, {
method: 'PUT',
headers: {
'Authorization': 'Basic ' + auth,
'Content-Type': 'application/octet-stream',
'Content-Length': blobBuffer.length.toString()
},
body: blobBuffer
});
if (putRes.status !== 201) {
throw new Error(`Failed to put blob ${digest}: ${putRes.status} ${await putRes.text()}`);
}
console.log(`Uploaded blob ${digest.substring(0, 19)} (${blobBuffer.length} bytes)`);
}
async function main() {
const { token, userId } = await getAuth();
const auth = Buffer.from(userId + ':' + token).toString('base64');
console.log('=== Step 1: Getting Docker Hub Token for nginx:alpine ===');
const dAuth = await (await fetch('https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/nginx:pull')).json();
const dToken = dAuth.token;
console.log('=== Step 2: Fetching linux/amd64 Manifest ===');
const manListRes = await fetch('https://registry-1.docker.io/v2/library/nginx/manifests/alpine', {
headers: {
'Authorization': 'Bearer ' + dToken,
'Accept': 'application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.index.v1+json'
}
});
const manList = await manListRes.json();
const amd64 = manList.manifests?.find(m => m.platform?.architecture === 'amd64' && m.platform?.os === 'linux');
const manifestDigest = amd64 ? amd64.digest : 'alpine';
const manifestRes = await fetch(`https://registry-1.docker.io/v2/library/nginx/manifests/${manifestDigest}`, {
headers: {
'Authorization': 'Bearer ' + dToken,
'Accept': 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json'
}
});
const manifest = await manifestRes.json();
console.log(`Base image has ${manifest.layers.length} layers, config: ${manifest.config.digest}`);
console.log('\n=== Step 3: Copying Base Layers from Docker Hub to Ghaymah Registry ===');
for (let i = 0; i < manifest.layers.length; i++) {
const layer = manifest.layers[i];
console.log(`[Layer ${i + 1}/${manifest.layers.length}] Fetching ${layer.digest.substring(0, 19)}...`);
const layerRes = await fetch(`https://registry-1.docker.io/v2/library/nginx/blobs/${layer.digest}`, {
headers: { 'Authorization': 'Bearer ' + dToken }
});
const layerBuf = Buffer.from(await layerRes.arrayBuffer());
await uploadBlobToGhaymah(layerBuf, layer.digest, userId);
}
console.log('\n=== Step 4: Fetching Base Config ===');
const configRes = await fetch(`https://registry-1.docker.io/v2/library/nginx/blobs/${manifest.config.digest}`, {
headers: { 'Authorization': 'Bearer ' + dToken }
});
const baseConfig = await configRes.json();
console.log('\n=== Step 5: Packaging SOC Command Center Files ===');
const htmlContent = fs.readFileSync('D:/cumin/ghaymah_dns_net_sec_tests/soc_gateway_ui/index.html', 'utf8');
const nginxConf = `server {
listen 80;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location /proxy/ {
proxy_pass http://soc-backend-d1895c70f6b2:4000/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 10s;
}
}
`;
// Create uncompressed tar
const tarBuf = createTar([
{ name: 'usr/share/nginx/html/index.html', content: htmlContent },
{ name: 'etc/nginx/conf.d/default.conf', content: nginxConf }
]);
const diffId = 'sha256:' + crypto.createHash('sha256').update(tarBuf).digest('hex');
// Gzip compress
const gzipBuf = zlib.gzipSync(tarBuf);
const customLayerDigest = 'sha256:' + crypto.createHash('sha256').update(gzipBuf).digest('hex');
const customLayerSize = gzipBuf.length;
console.log(`Custom layer: ${customLayerDigest} (size: ${customLayerSize}, diffId: ${diffId})`);
await uploadBlobToGhaymah(gzipBuf, customLayerDigest, userId);
console.log('\n=== Step 6: Creating and Uploading Custom Image Config ===');
const newConfig = { ...baseConfig };
newConfig.rootfs = {
type: 'layers',
diff_ids: [...(baseConfig.rootfs?.diff_ids || []), diffId]
};
newConfig.history = [
...(baseConfig.history || []),
{
created: new Date().toISOString(),
created_by: 'ADD soc_gateway_ui /usr/share/nginx/html'
}
];
const newConfigBuf = Buffer.from(JSON.stringify(newConfig));
const newConfigDigest = 'sha256:' + crypto.createHash('sha256').update(newConfigBuf).digest('hex');
console.log(`New config digest: ${newConfigDigest}`);
await uploadBlobToGhaymah(newConfigBuf, newConfigDigest, userId);
console.log('\n=== Step 7: Publishing Image Manifest as latest ===');
const newManifest = {
schemaVersion: 2,
mediaType: 'application/vnd.docker.distribution.manifest.v2+json',
config: {
mediaType: 'application/vnd.docker.container.image.v1+json',
size: newConfigBuf.length,
digest: newConfigDigest
},
layers: [
...manifest.layers.map(l => ({
mediaType: 'application/vnd.docker.image.rootfs.diff.tar.gzip',
size: l.size,
digest: l.digest
})),
{
mediaType: 'application/vnd.docker.image.rootfs.diff.tar.gzip',
size: customLayerSize,
digest: customLayerDigest
}
]
};
let curAuth = await getAuth();
let putAuth = Buffer.from(userId + ':' + curAuth.token).toString('base64');
let putManRes = await fetch(`https://registry.ghaymah.systems/v2/${userId}/${REPO_NAME}/manifests/latest`, {
method: 'PUT',
headers: {
'Authorization': 'Basic ' + putAuth,
'Content-Type': 'application/vnd.docker.distribution.manifest.v2+json'
},
body: JSON.stringify(newManifest)
});
if (putManRes.status === 401) {
curAuth = await getAuth(true);
putAuth = Buffer.from(userId + ':' + curAuth.token).toString('base64');
putManRes = await fetch(`https://registry.ghaymah.systems/v2/${userId}/${REPO_NAME}/manifests/latest`, {
method: 'PUT',
headers: {
'Authorization': 'Basic ' + putAuth,
'Content-Type': 'application/vnd.docker.distribution.manifest.v2+json'
},
body: JSON.stringify(newManifest)
});
}
console.log('Manifest PUT Status:', putManRes.status, putManRes.statusText);
if (!putManRes.ok) {
throw new Error('Manifest upload failed: ' + (await putManRes.text()));
}
console.log('\n>>> SUCCESS! DOCKER IMAGE SUCCESSFULLY PUSHED TO REGISTRY.GHAYMAH.SYSTEMS! <<<');
console.log(`Image: registry.ghaymah.systems/${userId}/${REPO_NAME}:latest`);
}
main().catch(console.error);
+20
View File
@@ -0,0 +1,20 @@
const { getAuth } = require('./auth_manager');
async function main() {
const td = await getAuth();
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + td.token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `mutation AppLogs($appId: String!, $max: Int!) {
appLogs(arg1: { appId: $appId, max: $max }) {
timestamp message source severity
}
}`,
variables: { appId: '3d5666fe-95db-4e73-b6b2-dd0e41fca7f6', max: 50 }
})
});
console.log('AppLogs result:\n', JSON.stringify(await res.json(), null, 2));
}
main().catch(console.error);
+24
View File
@@ -0,0 +1,24 @@
const { getAuth } = require('./auth_manager');
async function main() {
const td = await getAuth();
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + td.token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `query {
ghaymah_cloud_row_event(
where: { app_id: { _eq: "3d5666fe-95db-4e73-b6b2-dd0e41fca7f6" } },
order_by: { event_date: desc },
limit: 5
) {
id app_id event_date running values
}
}`
})
});
const data = await res.json();
console.log(JSON.stringify(data, null, 2));
}
main().catch(console.error);
+13
View File
@@ -0,0 +1,13 @@
const { getAuth } = require('./auth_manager');
async function main() {
const { token, userId } = await getAuth();
const auth = Buffer.from(userId + ':' + token).toString('base64');
const res = await fetch(`https://registry.ghaymah.systems/v2/${userId}/acd244b6-43b6-4de1-8b1c-4f27cea90ea1/tags/list`, {
headers: { 'Authorization': 'Basic ' + auth }
});
console.log('Status:', res.status);
console.log('Tags:', await res.text());
}
main().catch(console.error);
+20
View File
@@ -0,0 +1,20 @@
const { getAuth } = require('./auth_manager');
async function main() {
const { token } = await getAuth();
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `query {
ghaymah_cloud_resources {
id status values
}
}`
})
});
const data = await res.json();
console.log('Response:', JSON.stringify(data, null, 2));
}
main().catch(console.error);
+25
View File
@@ -0,0 +1,25 @@
const { getAuth } = require('./auth_manager');
async function main() {
const { token } = await getAuth();
const oldGatewayId = '3d5666fe-95db-4e73-b6b2-dd0e41fca7f6';
console.log(`Soft deleting old terminal gateway ${oldGatewayId}...`);
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `mutation DeleteOldGateway($id: uuid!) {
update_ghaymah_cloud_resources_by_pk(
pk_columns: { id: $id },
_set: { deleted: true }
) {
id message
}
}`,
variables: { id: oldGatewayId }
})
});
console.log('Delete result:\n', JSON.stringify(await res.json(), null, 2));
}
main().catch(console.error);
+21
View File
@@ -0,0 +1,21 @@
const { getAuth } = require('./auth_manager');
async function main() {
const { token } = await getAuth();
const staticAppId = '1a83e477-9e98-4dbb-8931-cc273db6e607';
console.log(`Deleting temporary static app ${staticAppId}...`);
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `mutation DeleteStaticApp {
deleteStaticApp(arg1: { appId: "1a83e477-9e98-4dbb-8931-cc273db6e607" }) {
output
}
}`
})
});
console.log('Result:\n', JSON.stringify(await res.json(), null, 2));
}
main().catch(console.error);
+179
View File
@@ -0,0 +1,179 @@
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 SOC Command Center Artifact ===');
const htmlContent = fs.readFileSync('D:/cumin/ghaymah_dns_net_sec_tests/soc_gateway_ui/index.html', 'utf8');
const dockerfile = `FROM nginx:alpine
COPY ./ /usr/share/nginx/html/
EXPOSE 80
`;
const tarGz = createTar([
{ name: 'Dockerfile', content: dockerfile },
{ 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 Sync / Build Status ===');
for (let i = 1; i <= 25; 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}/25] Status: ${status} | Message: ${msg}`);
if (status === 'synced') {
console.log('\n>>> SUCCESS! RESOURCE SYNCED! <<<');
break;
}
if (status === 'failed' || status === 'backoff') {
console.log('Failed or backoff:', msg);
break;
}
}
console.log(`\n=== Step 5: Testing Public URL https://${domain}/ ===`);
try {
const testRes = await fetch(`https://${domain}/`);
console.log('HTTP Status:', testRes.status);
const body = await testRes.text();
console.log('Title:', body.match(/<title>([^<]+)<\/title>/)?.[1]);
console.log('Preview:', body.substring(0, 200));
} catch (e) {
console.error('Test fetch error:', e.message);
}
}
main().catch(console.error);
+20
View File
@@ -0,0 +1,20 @@
const { getAuth } = require('./auth_manager');
async function main() {
const { token } = await getAuth();
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `mutation {
GeneratePAT(arg1: { duration: "30d" }) {
personalAccessToken
}
}`
})
});
const data = await res.json();
console.log(JSON.stringify(data, null, 2));
}
main().catch(console.error);
+24
View File
@@ -0,0 +1,24 @@
const { getAuth } = require('./auth_manager');
async function main() {
const td = await getAuth();
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + td.token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `query {
ghaymah_cloud_resources_by_pk(id: "acd244b6-43b6-4de1-8b1c-4f27cea90ea1") {
id
chart_name
chart_version
status
message
values
}
}`
})
});
console.log(JSON.stringify(await res.json(), null, 2));
}
main().catch(console.error);
+38
View File
@@ -0,0 +1,38 @@
const { getAuth } = require('./auth_manager');
async function main() {
const td = await getAuth();
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + td.token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `query {
__type(name: "mutation_root") {
fields {
name
args {
name
type {
name
kind
ofType {
name
kind
inputFields {
name
type { name kind ofType { name } }
}
}
}
}
}
}
}`
})
});
const data = await res.json();
const fields = data.data?.__type?.fields?.filter(f => f.name === 'createApp' || f.name === 'updateApp') || [];
console.log(JSON.stringify(fields, null, 2));
}
main().catch(console.error);
+28
View File
@@ -0,0 +1,28 @@
const { getAuth } = require('./auth_manager');
async function main() {
const { token, userId } = await getAuth();
const repo = '3d5666fe-95db-4e73-b6b2-dd0e41fca7f6';
const auth = Buffer.from(userId + ':' + token).toString('base64');
console.log('Initiating POST...');
const postRes = await fetch(`https://registry.ghaymah.systems/v2/${userId}/${repo}/blobs/uploads/`, {
method: 'POST',
headers: { 'Authorization': 'Basic ' + auth }
});
console.log('POST status:', postRes.status);
console.log('POST Www-Auth:', postRes.headers.get('www-authenticate'));
console.log('Testing monolithic POST...');
const monoRes = await fetch(`https://registry.ghaymah.systems/v2/${userId}/${repo}/blobs/uploads/?digest=sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`, {
method: 'POST',
headers: {
'Authorization': 'Basic ' + auth,
'Content-Type': 'application/octet-stream',
'Content-Length': '0'
}
});
console.log('Monolithic POST status:', monoRes.status, monoRes.statusText);
console.log('Monolithic POST body:', await monoRes.text());
console.log('Monolithic POST headers:', Object.fromEntries(monoRes.headers.entries()));
}
main().catch(console.error);
+20
View File
@@ -0,0 +1,20 @@
const { getAuth } = require('./auth_manager');
async function main() {
const td = await getAuth();
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + td.token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `query {
__type(name: "ghaymah_cloud_row_event") {
fields { name }
}
}`
})
});
const data = await res.json();
console.log(data.data?.__type?.fields?.map(f => f.name));
}
main().catch(console.error);
+19
View File
@@ -0,0 +1,19 @@
const { getAuth } = require('./auth_manager');
async function main() {
const td = await getAuth();
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + td.token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `query {
ghaymah_cloud_resources(where: { id: { _eq: "1a83e477-9e98-4dbb-8931-cc273db6e607" } }) {
id chart_name chart_version status values message
}
}`
})
});
console.log(JSON.stringify(await res.json(), null, 2));
}
main().catch(console.error);
+12
View File
@@ -0,0 +1,12 @@
const { RemoteTerminal } = require('./remote_exec');
async function main() {
const term = new RemoteTerminal('wss://soc-gateway-28cd1dc4e034.hosted.ghaymah.systems/ws');
await term.connect();
console.log('Installing nodejs on soc-gateway...');
const res = await term.exec('rm -f /var/lock/apk; apk add --no-progress nodejs && node -v', 90000);
console.log('Result:\n', res.output);
process.exit(0);
}
main().catch(console.error);
+33
View File
@@ -0,0 +1,33 @@
const { getAuth } = require('./auth_manager');
async function main() {
const td = await getAuth();
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + td.token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `query {
__type(name: "mutation_root") {
fields {
name
description
args {
name
type { name kind }
}
}
}
}`
})
});
const data = await res.json();
const fields = data.data?.__type?.fields || [];
console.log(`Total mutations: ${fields.length}`);
for (const f of fields) {
if (!f.name.startsWith('delete_') && !f.name.startsWith('insert_') && !f.name.startsWith('update_')) {
console.log(`- ${f.name} (${f.args.map(a => a.name).join(', ')})`);
}
}
}
main().catch(console.error);
+23
View File
@@ -0,0 +1,23 @@
const { getAuth } = require('./auth_manager');
async function main() {
const td = await getAuth();
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + td.token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `query {
ghaymah_cloud_resources_by_pk(id: "3d5666fe-95db-4e73-b6b2-dd0e41fca7f6") {
id
chart_name
status
message
values
}
}`
})
});
console.log(JSON.stringify(await res.json(), null, 2));
}
main().catch(console.error);
+168
View File
@@ -0,0 +1,168 @@
const fs = require('fs');
const crypto = require('crypto');
const zlib = require('zlib');
const { getAuth } = require('./auth_manager');
const GATEWAY_ID = '3d5666fe-95db-4e73-b6b2-dd0e41fca7f6';
const PROJECT_ID = '5be77e31-3ac2-48f5-b97d-735e8b2ad45f';
const DOMAIN = 'soc-gateway-28cd1dc4e034.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 tokenData = await getAuth();
const token = tokenData.token;
const userId = tokenData.userId;
console.log('=== Step 1: Packaging SOC Command Center Web UI for Gateway ===');
const htmlContent = fs.readFileSync('D:/cumin/ghaymah_dns_net_sec_tests/soc_gateway_ui/index.html', 'utf8');
const dockerfile = `FROM nginx:alpine
COPY ./ /usr/share/nginx/html/
EXPOSE 80
`;
const tarGz = createTar([
{ name: 'Dockerfile', content: dockerfile },
{ 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 Ghaymah Storage ===');
const uploadUrl = `https://s3-nhost-proxy-83e02743fd61.hosted.ghaymah.systems/files/${userId}/${GATEWAY_ID}.tar.gz`;
const uploadRes = await fetch(uploadUrl, {
method: 'PUT',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/gzip'
},
body: tarGz
});
console.log('Upload status:', uploadRes.status, uploadRes.statusText);
if (!uploadRes.ok) {
throw new Error('Upload failed: ' + (await uploadRes.text()));
}
console.log('\n=== Step 3: Updating soc-gateway Resource in Project ghaymah-soc-microservices ===');
const image = `registry.ghaymah.systems/${userId}/${GATEWAY_ID}:latest`;
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 UpdateGatewayArtifact($id: uuid!, $values: json!) {
update_ghaymah_cloud_resources_by_pk(
pk_columns: { id: $id },
_set: {
values: $values
}
) {
id status values message
}
}`,
variables: {
id: GATEWAY_ID,
values: {
name: 'soc-gateway',
projectId: PROJECT_ID,
resourceTier: 't1',
container: {
image: image
},
ports: [
{
expose: true,
number: 80
}
],
publicAccess: {
baseDomain: 'hosted.ghaymah.systems',
domain: DOMAIN,
enabled: true
},
source: {
enabled: true,
ref: sha256,
type: 'artifact',
url: uploadUrl
}
}
}
})
});
const updateData = await updateRes.json();
console.log('Update result:\n', JSON.stringify(updateData, null, 2));
console.log('\n=== Step 4: Waiting for Ghaymah to Build and Sync soc-gateway ===');
for (let i = 1; i <= 20; 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 CheckGatewayStatus($id: uuid!) {
ghaymah_cloud_resources_by_pk(id: $id) {
id status message
}
}`,
variables: { id: GATEWAY_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}/20] Status: ${status} | Message: ${msg}`);
if (status === 'synced') {
console.log('\n>>> SUCCESS! soc-gateway IN PROJECT IS SYNCED! <<<');
break;
}
}
// Step 5: Test the original project domain!
console.log('\n=== Step 5: Testing Original Project URL ===');
console.log(`Testing URL: https://${DOMAIN}/ ...`);
try {
const testRes = await fetch(`https://${DOMAIN}/`);
console.log('HTTP Status:', testRes.status);
const body = await testRes.text();
console.log('Response Title:', body.match(/<title>([^<]+)<\/title>/)?.[1]);
console.log('Preview:\n', body.substring(0, 300));
} catch (e) {
console.error('Fetch error:', e.message);
}
}
main().catch(console.error);
+23
View File
@@ -0,0 +1,23 @@
const { getAuth } = require('./auth_manager');
async function test() {
const { token, userId } = await getAuth(true); // Force fresh token
console.log('Got fresh token!');
const auth = Buffer.from(userId + ':' + token).toString('base64');
for (let i = 1; i <= 5; i++) {
const res = await fetch(`https://registry.ghaymah.systems/v2/${userId}/soc-gateway/blobs/uploads/`, {
method: 'POST',
headers: { 'Authorization': 'Basic ' + auth }
});
console.log(`Attempt ${i}: Status = ${res.status}`);
if (!res.ok) {
console.log('Error:', await res.text());
} else {
console.log('Location:', res.headers.get('location')?.substring(0, 50));
}
await new Promise(r => setTimeout(r, 1000));
}
}
test().catch(console.error);
+41
View File
@@ -0,0 +1,41 @@
async function test() {
console.log('1. Getting Docker Hub auth token...');
const authRes = await fetch('https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/nginx:pull');
const { token } = await authRes.json();
console.log('Got token:', token.substring(0, 20) + '...');
console.log('2. Getting nginx:alpine manifest list...');
const manRes = await fetch('https://registry-1.docker.io/v2/library/nginx/manifests/alpine', {
headers: {
'Authorization': 'Bearer ' + token,
'Accept': 'application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.index.v1+json'
}
});
const manData = await manRes.json();
console.log('Media type:', manRes.headers.get('content-type'));
let amd64Digest;
if (manData.manifests) {
const amd64 = manData.manifests.find(m => m.platform?.architecture === 'amd64' && m.platform?.os === 'linux');
amd64Digest = amd64.digest;
console.log('Found linux/amd64 manifest digest:', amd64Digest);
} else {
amd64Digest = 'alpine';
}
console.log('3. Fetching linux/amd64 manifest...');
const archManRes = await fetch(`https://registry-1.docker.io/v2/library/nginx/manifests/${amd64Digest}`, {
headers: {
'Authorization': 'Bearer ' + token,
'Accept': 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json'
}
});
const archMan = await archManRes.json();
console.log('Config descriptor:', archMan.config);
console.log('Layers count:', archMan.layers.length);
for (const l of archMan.layers) {
console.log(' Layer:', l.digest, '| Size:', l.size);
}
}
test().catch(console.error);
+18
View File
@@ -0,0 +1,18 @@
const { RemoteTerminal } = require('./remote_exec');
async function main() {
const term = new RemoteTerminal('wss://soc-tester-9b6540e2d4ed.hosted.ghaymah.systems/ws');
await term.connect();
console.log('Writing /tmp/persist_test_file in soc-tester...');
await term.exec('echo TEST_PERSIST > /tmp/persist_test_file');
try { await term.exec('kill -9 7'); } catch (e) {}
console.log('Waiting 8s for restart...');
await new Promise(r => setTimeout(r, 8000));
const term2 = new RemoteTerminal('wss://soc-tester-9b6540e2d4ed.hosted.ghaymah.systems/ws');
await term2.connect();
const res = await term2.exec('cat /tmp/persist_test_file || echo NOT_PERSISTED');
console.log('Result:\n', res.output);
process.exit(0);
}
main().catch(console.error);
+15
View File
@@ -0,0 +1,15 @@
const { getAuth } = require('./auth_manager');
async function main() {
const { token, userId } = await getAuth();
const auth = Buffer.from(userId + ':' + token).toString('base64');
const res = await fetch(`https://registry.ghaymah.systems/v2/${userId}/soc-gateway/blobs/uploads/`, {
method: 'POST',
headers: { 'Authorization': 'Basic ' + auth }
});
console.log('Status:', res.status, res.statusText);
console.log('Location:', res.headers.get('location'));
console.log('Body:', await res.text());
}
main().catch(console.error);
+33
View File
@@ -0,0 +1,33 @@
const { getAuth } = require('./auth_manager');
async function robustFetch(url, options, maxRetries = 8) {
let { token, userId } = await getAuth();
let auth = Buffer.from(userId + ':' + token).toString('base64');
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const headers = {
...(options.headers || {}),
'Authorization': 'Basic ' + auth
};
const res = await fetch(url, { ...options, headers });
if (res.status === 401 && attempt < maxRetries) {
console.log(`[Attempt ${attempt}] Got 401, retrying after 500ms...`);
await new Promise(r => setTimeout(r, 600));
continue;
}
return res;
}
}
async function test() {
const { userId } = await getAuth();
console.log('Testing robust POST...');
const res = await robustFetch(`https://registry.ghaymah.systems/v2/${userId}/soc-gateway/blobs/uploads/`, {
method: 'POST'
});
console.log('Final status:', res.status);
const loc = res.headers.get('location');
console.log('Location:', loc?.substring(0, 60));
}
test().catch(console.error);
+16
View File
@@ -0,0 +1,16 @@
const { RemoteTerminal } = require('./remote_exec');
async function main() {
const term = new RemoteTerminal('wss://soc-tester-9b6540e2d4ed.hosted.ghaymah.systems/ws');
await term.connect();
console.log('Writing /tmp/test_ui.html in soc-tester...');
await term.exec("echo 'TEST_HTML_SOC_ONLINE' > /tmp/test_ui.html");
console.log('Starting ttyd on port 7682 with custom index...');
await term.exec('ttyd -p 7682 -I /tmp/test_ui.html bash > /dev/null 2>&1 &');
await new Promise(r => setTimeout(r, 1200));
const res = await term.exec('wget -qO- http://localhost:7682/');
console.log('Wget output from port 7682:\n', res.output);
process.exit(0);
}
main().catch(console.error);
+40
View File
@@ -0,0 +1,40 @@
const { getAuth } = require('./auth_manager');
async function main() {
const td = await getAuth();
console.log('Monitoring soc-gateway build and deployment...');
const start = Date.now();
while (Date.now() - start < 180000) {
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + td.token, 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `query {
ghaymah_cloud_resources_by_pk(id: "3d5666fe-95db-4e73-b6b2-dd0e41fca7f6") {
id status message
}
}`
})
});
const d = await res.json();
const r = d.data?.ghaymah_cloud_resources_by_pk;
const elapsed = Math.round((Date.now() - start) / 1000);
console.log(`[+${elapsed}s] status: ${r?.status} | message: ${r?.message}`);
if (r?.status === 'synced') {
console.log('Build completed! Probing URL: https://soc-gateway-28cd1dc4e034.hosted.ghaymah.systems/');
const test = await fetch('https://soc-gateway-28cd1dc4e034.hosted.ghaymah.systems/');
console.log('HTTP Status:', test.status);
const text = await test.text();
console.log('Title:', text.match(/<title>([^<]+)<\/title>/)?.[1]);
break;
}
if (r?.status === 'failed' || r?.status === 'backoff') {
console.log('Error occurred:', r?.status, r?.message);
break;
}
await new Promise(r => setTimeout(r, 6000));
}
}
main().catch(console.error);