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);