test(e2e): windows.mjs 补 L2 status/collect/verify 三条(T05)
字段与 manifest system.audit.l2 的 returns_schema(四 action 属性并集) 逐字对齐:status 全字段断言(platform/supported/auditpol/ legacy_policy_disabled/cmdline_logging/sysmon_installed/file/file_exists); collect 断 since/limit 回显、written<=collected、信任边界 note 必返; verify 断 ok/checked。 collect 对非提权环境(读 Security 日志需管理员)skip 容错 —— 与 winget 缺失同一哲学,不把「环境没条件」伪装成「功能坏了」。 Mac 上不跑 windows.mjs:node --check + 静态自证(参数名/能力名/字段 与 manifest returns_schema 逐字对齐),不假跑。e2e 总数 33 → 50。
This commit is contained in:
1 parent
6152a68b4a
commit
654d694ff6
1 file changed
+52
@@ -223,6 +223,58 @@ async function main() {
|
||||
assert.equal(r.status, 'failed');
|
||||
assert.equal(r.error.name, 'E_CAPABILITY_DISABLED');
|
||||
});
|
||||
|
||||
// ---------- v2.1.0 L2 系统级审计(T05,Windows 真机)----------
|
||||
// 字段与 packages/protocol/src/capabilities/manifest/system.ts 的
|
||||
// system.audit.l2 returns_schema(四种 action 的属性并集)逐字对齐:
|
||||
// status → platform/supported/auditpol/legacy_policy_disabled/
|
||||
// cmdline_logging/sysmon_installed/file/file_exists(/note)
|
||||
// collect → collected/written/since/limit/file(/note)
|
||||
// verify → ok/checked(/broken_at)
|
||||
// 信任边界(不夸大):本地 audit-l2.log 只是归一化副本,防篡改依赖转发出机。
|
||||
await test('v2.1.0 L2 status:Windows 审计策略状态(returns_schema 全字段)', async () => {
|
||||
const c = await connect();
|
||||
const r = await c.invoke('system.audit.l2', { action: 'status' }, 90_000);
|
||||
c.close();
|
||||
assert.equal(r.status, 'ok', `L2 status 失败: ${JSON.stringify(r.error)}`);
|
||||
assert.equal(r.data.platform, 'windows', 'platform 必须回 windows');
|
||||
assert.equal(r.data.supported, true, 'Windows 上必须 supported=true');
|
||||
assert.equal(typeof r.data.auditpol, 'string', 'auditpol 原始输出应为字符串');
|
||||
assert.equal(typeof r.data.legacy_policy_disabled, 'boolean', 'SCENoApplyLegacyAuditPolicy 判定应为布尔');
|
||||
assert.equal(typeof r.data.cmdline_logging, 'boolean', '命令行记录开关应为布尔');
|
||||
assert.equal(typeof r.data.sysmon_installed, 'boolean', 'Sysmon 检测结果应为布尔');
|
||||
assert.equal(typeof r.data.file, 'string', 'L2 副本路径应为字符串');
|
||||
assert.equal(typeof r.data.file_exists, 'boolean', 'file_exists 应为布尔');
|
||||
});
|
||||
|
||||
await test('v2.1.0 L2 collect:拉取 Security 事件归一化落盘(since/limit 回显)', async () => {
|
||||
const c = await connect();
|
||||
const since = Date.now() - 60 * 60 * 1000; // 近 1 小时:缩小扫描窗口,CI 上更快
|
||||
const r = await c.invoke('system.audit.l2', { action: 'collect', since, limit: 100 }, 120_000);
|
||||
c.close();
|
||||
// 读 Security 日志需要管理员;非提权环境明确跳过(与 winget 缺失同一容错哲学,
|
||||
// 不把「环境没条件」伪装成「功能坏了」)
|
||||
if (r.status === 'failed' && r.error?.name === 'E_EXECUTION_FAILED') return 'skip';
|
||||
assert.equal(r.status, 'ok', `L2 collect 失败: ${JSON.stringify(r.error)}`);
|
||||
assert.equal(r.data.since, since, 'since 必须原样回显(默认 24h 的参数契约)');
|
||||
assert.equal(r.data.limit, 100, 'limit 必须原样回显');
|
||||
assert.ok(Number.isInteger(r.data.collected) && r.data.collected >= 0, 'collected 应为非负整数');
|
||||
assert.ok(
|
||||
Number.isInteger(r.data.written) && r.data.written >= 0 && r.data.written <= r.data.collected,
|
||||
'written 应为非负整数且不超过 collected',
|
||||
);
|
||||
assert.equal(typeof r.data.file, 'string', '落盘路径应为字符串');
|
||||
assert.equal(typeof r.data.note, 'string', '信任边界提示必须随 collect 返回(不得假装本地副本不可篡改)');
|
||||
});
|
||||
|
||||
await test('v2.1.0 L2 verify:归一化链完整性校验(空链亦为 ok)', async () => {
|
||||
const c = await connect();
|
||||
const r = await c.invoke('system.audit.l2', { action: 'verify' }, 60_000);
|
||||
c.close();
|
||||
assert.equal(r.status, 'ok', `L2 verify 失败: ${JSON.stringify(r.error)}`);
|
||||
assert.equal(r.data.ok, true, `L2 链应完整${r.data.ok ? '' : `: ${JSON.stringify(r.data.broken_at)}`}`);
|
||||
assert.ok(Number.isInteger(r.data.checked) && r.data.checked >= 0, 'checked 应为非负整数');
|
||||
});
|
||||
} finally {
|
||||
agent.kill();
|
||||
await new Promise((r) => setTimeout(r, 300));
|
||||
|
||||
Reference in new issue
Block a user