mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
fix(ci): make Vault live fixture capability-free
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
最新增量证据(2026-08-24):
|
最新增量证据(2026-08-24):
|
||||||
|
|
||||||
- D-404/ADR-0499(已验收):Cluster Worker 现在有可选的直接外部 Secret custody adapter,而不再只能依赖 Kubernetes Secret value projection。`vault-kv-v2` 位于既有 `@qinglong/cluster-control` Remote Execution 子域,只有显式选择 provider 的 Cluster 进程才动态加载;基础部署继续使用 `mounted-files`,Edge/Standalone 不新增 package、依赖、daemon、timer、watcher、连接池或常驻内存。adapter 只在 durable Run/Attempt/Lease/Worker Session/execution digest/SecretRef authority 通过后,用 `SHA-256(canonical SecretRef)` 路径读取 KV v2;只接受显式私有 CA 的 TLS 1.3、每次重新打开的短期 orphan/non-renewable service token 和唯一精确 policy,不跟随 redirect、不使用系统 CA 回退、不缓存值或 token。Kubernetes overlay 删除 value Secret projection,只挂载 CA 与 token;普通 Secret、opaque environment bundle 和总响应仍受原 16/96/256 KiB 边界约束,空 Secret 保持合法,异常 envelope、metadata、digest、token、TLS 或 Vault availability 均失败关闭且不回退。真实 arm64 Vault 1.21.4 gate 已完成 3-share/2-threshold init、两个普通 Secret 与一个 bundle、value/token 原子轮换、旧 accessor revoke、缺失 material、不可信 CA、seal/unseal 与同持久存储容器替换;`0600` content-free 报告 SHA-256 为 `df225509cb763009b610cb0aea2207e0b07b5e05a44cf8cf0dff1633c1624d52`,audit 为 `compatible=true/findings=[]`。Cluster Control 为 `279 total / 277 pass / 2 conditional skip / 0 fail`,backend 为 `1574 total / 1572 pass / 2 conditional skip / 0 fail`,18-package clean build/test 退出 0;package、Cluster dependency、122-module Edge import、部署和 14 档 Local artifact 审计全部 compatible,基础 Edge/Standalone 仍为 `2,669,390 / 2,669,468 bytes`、325 files、58 modules。共享 CI 新增原生 x64/arm64 live matrix。该 fixture 关闭 QingLong 直接 custody adapter/data-boundary 门,不冒充生产 Vault HA、KMS/HSM seal、审计设备或灾备证明;ADR-0491 现在只剩固定低性能物理 Edge 的真实空间、RSS/I/O、写放大、ENOSPC 与断电恢复门。
|
- D-404/ADR-0499(已验收):Cluster Worker 现在有可选的直接外部 Secret custody adapter,而不再只能依赖 Kubernetes Secret value projection。`vault-kv-v2` 位于既有 `@qinglong/cluster-control` Remote Execution 子域,只有显式选择 provider 的 Cluster 进程才动态加载;基础部署继续使用 `mounted-files`,Edge/Standalone 不新增 package、依赖、daemon、timer、watcher、连接池或常驻内存。adapter 只在 durable Run/Attempt/Lease/Worker Session/execution digest/SecretRef authority 通过后,用 `SHA-256(canonical SecretRef)` 路径读取 KV v2;只接受显式私有 CA 的 TLS 1.3、每次重新打开的短期 orphan/non-renewable service token 和唯一精确 policy,不跟随 redirect、不使用系统 CA 回退、不缓存值或 token。Kubernetes overlay 删除 value Secret projection,只挂载 CA 与 token;普通 Secret、opaque environment bundle 和总响应仍受原 16/96/256 KiB 边界约束,空 Secret 保持合法,异常 envelope、metadata、digest、token、TLS 或 Vault availability 均失败关闭且不回退。真实 arm64 Vault 1.21.4 gate 已完成 3-share/2-threshold init、两个普通 Secret 与一个 bundle、value/token 原子轮换、旧 accessor revoke、缺失 material、不可信 CA、seal/unseal 与同持久存储容器替换;capability-free `0600` content-free 报告 SHA-256 为 `281fe542e1bf6078132216b9701a28e76f36dcbccc95367997d8457773a9c210`,audit 为 `compatible=true/findings=[]`。live fixture 以非 root、read-only rootfs、`cap-drop=ALL`、零新增 capability、`no-new-privileges` 与 `memory-swappiness=0` 运行,并为原生 hosted runner 的 capability/lock 差异显式关闭 fixture mlock;生产 Vault host 的 swap/mlock 硬化不由该门冒充。Cluster Control 为 `279 total / 277 pass / 2 conditional skip / 0 fail`,backend 为 `1574 total / 1572 pass / 2 conditional skip / 0 fail`,18-package clean build/test 退出 0;package、Cluster dependency、122-module Edge import、部署和 14 档 Local artifact 审计全部 compatible,基础 Edge/Standalone 仍为 `2,669,390 / 2,669,468 bytes`、325 files、58 modules。共享 CI 新增原生 x64/arm64 live matrix。该 fixture 关闭 QingLong 直接 custody adapter/data-boundary 门,不冒充生产 Vault HA、KMS/HSM seal、审计设备或灾备证明;ADR-0491 现在只剩固定低性能物理 Edge 的真实空间、RSS/I/O、写放大、ENOSPC 与断电恢复门。
|
||||||
|
|
||||||
- D-397/ADR-0491(进行中):Secret/Config reconciliation 已先冻结行为保持边界,不能把“密文已保存”冒充“任务已迁移”。2.x `Envs`
|
- D-397/ADR-0491(进行中):Secret/Config reconciliation 已先冻结行为保持边界,不能把“密文已保存”冒充“任务已迁移”。2.x `Envs`
|
||||||
的 active 行必须按 `isPinned DESC、position DESC、createdAt ASC、id ASC` 重放旧顺序,同名值用 `&` 形成唯一 effective Secret;该
|
的 active 行必须按 `isPinned DESC、position DESC、createdAt ASC、id ASC` 重放旧顺序,同名值用 `&` 形成唯一 effective Secret;该
|
||||||
|
|||||||
@@ -95,7 +95,9 @@ path "auth/token/lookup-self" {
|
|||||||
- unseal 后恢复,Vault 容器在同一持久存储上替换后值仍可读取;
|
- unseal 后恢复,Vault 容器在同一持久存储上替换后值仍可读取;
|
||||||
- 私有 `0600` 报告不含 token、SecretRef、value、证书私钥或 Vault path。
|
- 私有 `0600` 报告不含 token、SecretRef、value、证书私钥或 Vault path。
|
||||||
|
|
||||||
最终本地报告 SHA-256 为 `df225509cb763009b610cb0aea2207e0b07b5e05a44cf8cf0dff1633c1624d52`,离线 audit 为 `compatible=true`、`findings=[]`。共享 CI 在原生 x64/arm64 runner 上分别构建 provider、审计 overlay、拉取同一 digest-pinned Vault image 并重跑完整 live contract;远程运行结果作为提交后的独立证据。
|
该单机 fixture 以当前非 root UID/GID、read-only rootfs、`cap-drop=ALL`、不增加 capability、`no-new-privileges` 和 `memory-swappiness=0` 运行。为兼容 capability/lock 策略不同的原生 Linux hosted runner,fixture 显式 `disable_mlock=true`;这只作用于临时测试 authority,不替代生产 Vault 主机的 swap 禁用或 mlock、HA seal 与审计硬化门禁。
|
||||||
|
|
||||||
|
最终 capability-free 本地报告 SHA-256 为 `281fe542e1bf6078132216b9701a28e76f36dcbccc95367997d8457773a9c210`,离线 audit 为 `compatible=true`、`findings=[]`。共享 CI 在原生 x64/arm64 runner 上分别构建 provider、审计 overlay、拉取同一 digest-pinned Vault image 并重跑完整 live contract;远程运行结果作为提交后的独立证据。
|
||||||
|
|
||||||
本地完整验证中,Cluster Control 为 `279 total / 277 pass / 2 conditional skip / 0 fail`,backend 为 `1574 total / 1572 pass / 2 conditional skip / 0 fail`,18-package clean build/test 退出 0。package boundary 保持 18 packages、`singleSourcePackages=[]`、`shallowSourcePackages=[]`;Cluster dependency、122-module Edge import、service-manager bridge、Cluster deployment、Local image、Vault overlay 和 14 档 Local artifact 均 compatible。基础 Edge/Standalone 制品仍为 `2,669,390 / 2,669,468 bytes`、325 files、58 loaded modules,不包含 Cluster Control 或 Vault adapter。
|
本地完整验证中,Cluster Control 为 `279 total / 277 pass / 2 conditional skip / 0 fail`,backend 为 `1574 total / 1572 pass / 2 conditional skip / 0 fail`,18-package clean build/test 退出 0。package boundary 保持 18 packages、`singleSourcePackages=[]`、`shallowSourcePackages=[]`;Cluster dependency、122-module Edge import、service-manager bridge、Cluster deployment、Local image、Vault overlay 和 14 档 Local artifact 均 compatible。基础 Edge/Standalone 制品仍为 `2,669,390 / 2,669,468 bytes`、325 files、58 loaded modules,不包含 Cluster Control 或 Vault adapter。
|
||||||
|
|
||||||
|
|||||||
@@ -302,8 +302,8 @@ function startVaultContainer(container, publish, directory, tls) {
|
|||||||
`${uid}:${gid}`,
|
`${uid}:${gid}`,
|
||||||
'--cap-drop',
|
'--cap-drop',
|
||||||
'ALL',
|
'ALL',
|
||||||
'--cap-add',
|
'--memory-swappiness',
|
||||||
'IPC_LOCK',
|
'0',
|
||||||
'--security-opt',
|
'--security-opt',
|
||||||
'no-new-privileges:true',
|
'no-new-privileges:true',
|
||||||
'--read-only',
|
'--read-only',
|
||||||
@@ -436,7 +436,7 @@ async function main() {
|
|||||||
'vault-server.hcl',
|
'vault-server.hcl',
|
||||||
[
|
[
|
||||||
'ui = false',
|
'ui = false',
|
||||||
'disable_mlock = false',
|
'disable_mlock = true',
|
||||||
'api_addr = "https://127.0.0.1:8200"',
|
'api_addr = "https://127.0.0.1:8200"',
|
||||||
'cluster_addr = "https://127.0.0.1:8201"',
|
'cluster_addr = "https://127.0.0.1:8201"',
|
||||||
'storage "file" {',
|
'storage "file" {',
|
||||||
@@ -760,7 +760,7 @@ async function main() {
|
|||||||
},
|
},
|
||||||
limitations: [
|
limitations: [
|
||||||
'single-host file storage is not Vault integrated-storage HA or an HSM seal quorum',
|
'single-host file storage is not Vault integrated-storage HA or an HSM seal quorum',
|
||||||
'the short-lived private CA and service tokens are live fixture authorities rather than enterprise PKI or workload identity',
|
'the capability-free live fixture disables mlock with zero container swappiness and does not prove production Vault host swap hardening',
|
||||||
'the live gate proves direct external custody resolution and rotation, not fixed physical Edge storage behavior',
|
'the live gate proves direct external custody resolution and rotation, not fixed physical Edge storage behavior',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('node:assert/strict');
|
const assert = require('node:assert/strict');
|
||||||
|
const fs = require('node:fs');
|
||||||
|
const path = require('node:path');
|
||||||
const { test } = require('node:test');
|
const { test } = require('node:test');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -10,6 +12,14 @@ const {
|
|||||||
validateVaultKvWorkerSecretLiveReport,
|
validateVaultKvWorkerSecretLiveReport,
|
||||||
} = require('../../scripts/ql3-vault-kv-worker-secret-live-audit.cjs');
|
} = require('../../scripts/ql3-vault-kv-worker-secret-live-audit.cjs');
|
||||||
|
|
||||||
|
const LIVE_CONTRACT = fs.readFileSync(
|
||||||
|
path.resolve(
|
||||||
|
__dirname,
|
||||||
|
'../../scripts/ql3-vault-kv-worker-secret-live-contract.cjs',
|
||||||
|
),
|
||||||
|
'utf8',
|
||||||
|
);
|
||||||
|
|
||||||
function fixture() {
|
function fixture() {
|
||||||
return {
|
return {
|
||||||
schemaVersion: 1,
|
schemaVersion: 1,
|
||||||
@@ -86,3 +96,10 @@ test('rejects sensitive material or widened report shape', () => {
|
|||||||
assert.ok(findings.includes('report envelope is invalid'));
|
assert.ok(findings.includes('report envelope is invalid'));
|
||||||
assert.match(findings.join('; '), /endpoint is forbidden/);
|
assert.match(findings.join('; '), /endpoint is forbidden/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('keeps the hosted-runner fixture capability-free and non-swappable', () => {
|
||||||
|
assert.match(LIVE_CONTRACT, /'--cap-drop',\n\s+'ALL'/);
|
||||||
|
assert.match(LIVE_CONTRACT, /'--memory-swappiness',\n\s+'0'/);
|
||||||
|
assert.match(LIVE_CONTRACT, /'disable_mlock = true'/);
|
||||||
|
assert.doesNotMatch(LIVE_CONTRACT, /'--cap-add'|'IPC_LOCK'/);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user