mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-09-04 14:45:41 +00:00
fix: harden deploy enforcement paths (#1030)
* fix: harden deploy enforcement paths * fix: update Docker toolchain to Go 1.26.3 * fix: repair Dockerfile tr argument split across lines * fix: bump protobufjs to clear npm audit high-severity advisories * fix(test): add execFile to child_process mock in compose-images test * fix: resolve merge conflicts with main * fix: resolve merge conflicts with main * fix: resolve merge conflicts with main
This commit is contained in:
@@ -16,6 +16,7 @@ import { fetchRemoteMeta, getSenchoVersion, isValidVersion } from '../services/C
|
||||
import { authMiddleware } from '../middleware/auth';
|
||||
import { requirePaid, requireAdmin, requireNodeProxy } from '../middleware/tierGates';
|
||||
import { scheduleLocalUpdate } from './license';
|
||||
import { runPolicyGate } from '../helpers/policyGate';
|
||||
import { captureLocalNodeFiles, captureRemoteNodeFiles, type SnapshotNodeData } from '../utils/snapshot-capture';
|
||||
import { getLatestVersion } from '../utils/version-check';
|
||||
import { isValidStackName } from '../utils/validation';
|
||||
@@ -1325,6 +1326,7 @@ fleetRouter.post('/snapshots/:id/restore', authMiddleware, async (req: Request,
|
||||
}
|
||||
|
||||
if (redeploy) {
|
||||
if (!(await runPolicyGate(req, res, stackName, node.id))) return;
|
||||
const composeService = ComposeService.getInstance(node.id);
|
||||
await composeService.deployStack(stackName);
|
||||
}
|
||||
@@ -1335,9 +1337,12 @@ fleetRouter.post('/snapshots/:id/restore', authMiddleware, async (req: Request,
|
||||
}
|
||||
|
||||
const baseUrl = node.api_url.replace(/\/$/, '');
|
||||
const proxyHeaders = LicenseService.getInstance().getProxyHeaders();
|
||||
const headers: Record<string, string> = {
|
||||
Authorization: `Bearer ${node.api_token}`,
|
||||
'Content-Type': 'application/json',
|
||||
[PROXY_TIER_HEADER]: proxyHeaders.tier,
|
||||
[PROXY_VARIANT_HEADER]: proxyHeaders.variant ?? '',
|
||||
};
|
||||
|
||||
for (const file of files) {
|
||||
@@ -1361,11 +1366,12 @@ fleetRouter.post('/snapshots/:id/restore', authMiddleware, async (req: Request,
|
||||
}
|
||||
|
||||
if (redeploy) {
|
||||
await fetch(`${baseUrl}/api/compose/${encodeURIComponent(stackName)}/up`, {
|
||||
const deployRes = await fetch(`${baseUrl}/api/stacks/${encodeURIComponent(stackName)}/deploy`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
signal: AbortSignal.timeout(30000),
|
||||
});
|
||||
if (!deployRes.ok) throw new Error('Failed to redeploy stack on remote node');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Router, type Request, type Response } from 'express';
|
||||
import path from 'path';
|
||||
import { GitSourceService } from '../services/GitSourceService';
|
||||
import { FileSystemService } from '../services/FileSystemService';
|
||||
import { DatabaseService } from '../services/DatabaseService';
|
||||
import { checkPermission, requirePermission } from '../middleware/permissions';
|
||||
import { invalidateNodeCaches } from '../helpers/cacheInvalidation';
|
||||
import { triggerPostDeployScan } from '../helpers/policyGate';
|
||||
@@ -199,10 +200,17 @@ stackGitSourceRouter.post('/:stackName/git-source/apply', async (req: Request, r
|
||||
res.status(400).json({ error: 'commitSha is required' });
|
||||
return;
|
||||
}
|
||||
const source = DatabaseService.getInstance().getGitSource(stackName);
|
||||
const willDeploy = typeof deploy === 'boolean' ? deploy : source?.auto_deploy_on_apply === true;
|
||||
if (willDeploy && !requirePermission(req, res, 'stack:deploy', 'stack', stackName)) return;
|
||||
const result = await GitSourceService.getInstance().apply(
|
||||
stackName,
|
||||
commitSha.trim(),
|
||||
{ deploy: typeof deploy === 'boolean' ? deploy : undefined },
|
||||
{
|
||||
deploy: typeof deploy === 'boolean' ? deploy : undefined,
|
||||
actor: req.user?.username ?? 'unknown',
|
||||
bypassPolicy: req.query.ignorePolicy === 'true' && req.user?.role === 'admin',
|
||||
},
|
||||
);
|
||||
invalidateNodeCaches(req.nodeId);
|
||||
const shortSha = commitSha.trim().slice(0, 7);
|
||||
|
||||
@@ -805,6 +805,7 @@ stacksRouter.post('/:stackName/rollback', async (req: Request, res: Response) =>
|
||||
}
|
||||
console.log(`[Stacks] Rollback initiated: ${sanitizeForLog(stackName)}`);
|
||||
await fsSvc.restoreStackFiles(stackName);
|
||||
if (!(await runPolicyGate(req, res, stackName, req.nodeId))) return;
|
||||
await ComposeService.getInstance(req.nodeId).deployStack(stackName, getTerminalWs(), false);
|
||||
invalidateNodeCaches(req.nodeId);
|
||||
console.log(`[Stacks] Rollback completed: ${sanitizeForLog(stackName)}`);
|
||||
|
||||
Reference in New Issue
Block a user