feat(ql3): prove security administration custody live

This commit is contained in:
whyour
2026-08-25 09:15:40 +08:00
parent 2eb8b29e51
commit c6b9e1504c
14 changed files with 2391 additions and 10 deletions
@@ -0,0 +1,121 @@
name: QingLong 3.0 Security Administration Kubernetes live evidence
on:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ql3-security-administration-live-${{ github.ref }}
cancel-in-progress: false
jobs:
security-administration-live:
name: Three-node Security Administration, PostgreSQL and PVC custody
runs-on: ubuntu-24.04
timeout-minutes: 90
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v6
with:
version: '8.3.1'
- uses: actions/setup-node@v6
with:
node-version: '24.18.0'
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Require enough ephemeral disk for three isolated K3s nodes
shell: bash
run: |
set -euo pipefail
available_kib="$(df -Pk / | awk 'NR == 2 { print $4 }')"
minimum_kib="$((25 * 1024 * 1024))"
if (( available_kib < minimum_kib )); then
echo "Security Administration live gate requires at least 25 GiB free; found ${available_kib} KiB" >&2
exit 1
fi
docker volume ls --quiet --filter dangling=true | sort > \
"${RUNNER_TEMP}/ql3-dangling-volumes.before"
docker system df
- name: Install workspace dependencies without lifecycle scripts
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Install verified kubectl v1.34.3
shell: bash
run: |
set -euo pipefail
curl --fail --location --silent --show-error \
--output "${RUNNER_TEMP}/kubectl" \
https://dl.k8s.io/release/v1.34.3/bin/linux/amd64/kubectl
curl --fail --location --silent --show-error \
--output "${RUNNER_TEMP}/kubectl.sha256" \
https://dl.k8s.io/release/v1.34.3/bin/linux/amd64/kubectl.sha256
test "$(cat "${RUNNER_TEMP}/kubectl.sha256")" = \
"$(sha256sum "${RUNNER_TEMP}/kubectl" | cut -d ' ' -f 1)"
chmod 0755 "${RUNNER_TEMP}/kubectl"
- name: Fetch checksum-locked CloudNativePG operator manifest
shell: bash
run: |
set -euo pipefail
curl --fail --location --silent --show-error \
--output "${RUNNER_TEMP}/cloudnative-pg.yaml" \
https://github.com/cloudnative-pg/cloudnative-pg/releases/download/v1.30.0/cnpg-1.30.0.yaml
echo "f8bede43fe4ee0d478c2355b204a36876b2ae4faac60f2a9452280b293da3b88 ${RUNNER_TEMP}/cloudnative-pg.yaml" | sha256sum --check
- name: Recheck static Security Administration and evidence contracts
run: |
pnpm audit:security-administration-kubernetes:ql3
node --test \
test/back/ql3SecurityAdministrationKubernetesLiveContract.test.cjs \
test/back/ql3SecurityAdministrationKubernetesLiveAudit.test.cjs
- name: Preload the digest-bound K3s distribution
run: docker pull rancher/k3s:v1.34.3-k3s1
- name: Prove Security Administration through K3s, PostgreSQL and PVC
env:
QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE: '1'
QL3_KUBECTL_BIN: ${{ runner.temp }}/kubectl
QL3_CNPG_OPERATOR_MANIFEST_FILE: ${{ runner.temp }}/cloudnative-pg.yaml
QL3_SECURITY_ADMINISTRATION_REPORT: ${{ runner.temp }}/ql3-security-administration/report.json
shell: bash
run: |
set -euo pipefail
umask 077
mkdir -m 0700 "$(dirname "${QL3_SECURITY_ADMINISTRATION_REPORT}")"
pnpm test:security-administration-kubernetes-live:ql3 \
"--report=${QL3_SECURITY_ADMINISTRATION_REPORT}"
- name: Re-audit content-free report and isolated cleanup
env:
QL3_SECURITY_ADMINISTRATION_REPORT: ${{ runner.temp }}/ql3-security-administration/report.json
shell: bash
run: |
set -euo pipefail
test "$(stat -c '%a' "${QL3_SECURITY_ADMINISTRATION_REPORT}")" = '600'
pnpm audit:security-administration-kubernetes-live:ql3 \
"--report=${QL3_SECURITY_ADMINISTRATION_REPORT}"
sha256sum "${QL3_SECURITY_ADMINISTRATION_REPORT}"
test -z "$(docker ps -aq --filter name=ql3-security-live-)"
test -z "$(docker network ls -q --filter name=ql3-security-live-)"
docker volume ls --quiet --filter dangling=true | sort > \
"${RUNNER_TEMP}/ql3-dangling-volumes.after"
diff --unified \
"${RUNNER_TEMP}/ql3-dangling-volumes.before" \
"${RUNNER_TEMP}/ql3-dangling-volumes.after"
docker system df
- name: Upload audited content-free Security Administration evidence
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ql3-security-administration-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/ql3-security-administration/report.json
if-no-files-found: error
retention-days: 14
compression-level: 9
overwrite: false
include-hidden-files: false
@@ -29,6 +29,7 @@ spec:
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
initContainers:
+2 -2
View File
@@ -11,7 +11,7 @@
最新增量证据(2026-08-25):
- D-406/ADR-0501进行中:静态部署契约已验收,live gate pending):Cluster Security Administration 现在有可选的一次性 Kubernetes Job,而不是要求每个部署者自行拼装。通用 PostgreSQL、CloudNativePG、credential delivery 与组合入口均显式 opt-in,不进入共享 operations;因此 Edge/Standalone 以及默认 Cluster 的 package、依赖、启动路径和常驻资源仍为零增量。Job 固定 non-root/read-only/drop-all、无 ServiceAccount token/RBAC、`backoffLimit=0`、300 秒 deadline、600 秒 TTL、每容器 25m/48 MiB request 和 250m/128 MiB limit;主命令仍只打开一个 admin PostgreSQL connection。新增 stager 保留 kubelet Secret symlink 兼容性,同时以 realpath confinement、`O_NOFOLLOW`、读前/读后 inode 复验和独立大小上限把四个输入复制成 memory-backed `0700/0600` 私有边界,失败时主容器不可启动issue/rotate 才选择 PVC delivery componenttoken 只进入唯一 `0600` no-replace 文件。6 个 stager/CLI 测试、4 个静态审计及四种 `kubectl kustomize` 渲染均通过18-package clean build/test 退出 0,当前 `cluster-admin``454 total / 451 pass / 3 conditional skip / 0 fail`backend 为 `1579 total / 1577 pass / 2 conditional skip / 0 fail`122-module Edge import、Cluster dependency、package boundary、deployment、deployment-lock 与 release-version 审计全部 compatible。本地 Admin 镜像 `sha256:5464f0bbf5aa1302c080b13c9f18aaa89ba418ab5d09a917f5b5b4937c0ede2f` 在 non-root/read-only、无网络/能力、128 MiB/0.25 CPU 下包含并运行固定 stager 入口。真实 K3s + PostgreSQL register/query/issue/replay/revoke、PVC custody、response-loss 与清理证据尚未执行,所以 D-406 不冒充完整生产 ceremony,也不关闭双人复核/break-glass、pepper rotation、audit retention/export/alert 或远程 UI/API 门禁
- D-406/ADR-0501已验收):Cluster Security Administration 现在有可选的一次性 Kubernetes Job,而不是要求每个部署者自行拼装。通用 PostgreSQL、CloudNativePG、credential delivery 与组合入口均显式 opt-in,不进入共享 operations;因此 Edge/Standalone 以及默认 Cluster 的 package、依赖、启动路径和常驻资源仍为零增量。Job 固定 non-root/read-only/drop-all、无 ServiceAccount token/RBAC、`backoffLimit=0`、300 秒 deadline、600 秒 TTL、每容器 25m/48 MiB request 和 250m/128 MiB limit;主命令仍只打开一个 admin PostgreSQL connection。stager 保留 kubelet Secret symlink 兼容性,同时以 realpath confinement、`O_NOFOLLOW`、读前/读后 inode 复验和独立大小上限把四个输入复制成 memory-backed `0700/0600` 私有边界,失败时主容器不可启动issue/rotate 才选择 PVC delivery componenttoken 只进入唯一 `0600` no-replace 文件。真实 arm64 live gate 已在 1 control-plane + 2 worker 的 K3s `v1.34.3+k3s1`、Flannel、CloudNativePG 1.30.0、3 个 PostgreSQL 18.4 实例、migration 71/control-core capability 70 上完成 register、audit query、issue、response-loss exact replay、rotate、revoke;证明 kubelet `0440` immutable Secret 投影可被私有化、`0444` 扩权会在主容器启动前失败、RWO PVC 跨 Job 保留 `0700/0600` no-replace 交付、Kubernetes API/公网 egress 与 Secret/Job RBAC 均被拒绝。全部管理 Job 继续以 UID/GID 10001 运行;仅 live local-path fixture 用一个无网络、无 API token、drop-all 的 root Job 把实现特有的 `02777 root:10001` PVC 根收紧为 `02770`,不能据此声称生产 CSI 加密或 custody 已验收。content-free `0600` 报告独立审计为 `compatible=true/findings=[]`SHA-256 为 `e5c24af77034e1a2efee062107176e218c11a9f9f0d6c8c7308fdc280b0a82cf`18-package clean build/test 退出 0,当前 `cluster-admin``456 total / 453 pass / 3 conditional skip / 0 fail`backend 为 `1590 total / 1588 pass / 2 conditional skip / 0 fail`。D-406 关闭单主机 K3s/CNPG/PVC 的产品命令与权限边界门,但不冒充生产 Kubernetes control-plane HA、跨主机 STONITH/DR、加密 CSI、外部 IdP、双人复核/break-glass、pepper rotation、audit retention/export/alert、并发 dispatch 或远程 UI/API。
- D-405/ADR-0500(已验收):Cluster Identity/API Credential/Security Audit 现在有首个受审产品入口。`ql3-security-admin` 由既有 `ql3-cluster-admin security` facade 到达同一安装内的固定 target,不新建单文件 package,也不进入常驻 `cluster-control`;每次只执行一个 exact-shape 的 identity register/enable/disable、credential issue/rotate/revoke 或最多 200 条的 keyset audit query,随后关闭单连接 admin PostgreSQL authority。命令使用独立 `ql3-security-administration+jwt` type、`security-administration` purpose、audience 与 generation/revocation ledger,拒绝其他管理面的 assertioncommand、assertion、keyset 与 pepper 均来自显式有界文件,不发现 home、ambient Kubernetes context 或默认 credential。issue/rotate token 只经私有目录内 `0600``fsync`、hard-link no-replace 文件交付,stdout 仅含 basename 与 SHA-256;精确重放的 `token=null` 不重新生成或发布 secret。默认 PostgreSQL `verify-full`,Pool 最大一个连接,无 listener、daemon、timer、watcher 或后台 retention。`cluster-admin` 完整回归为 `448 total / 445 pass / 3 conditional skip / 0 fail`,新增聚焦测试 19/19、产品 facade 4/4、backend product contract 4/418-package clean build/test 退出 0backend 为 `1575 total / 1573 pass / 2 conditional skip / 0 fail`。真实 arm64 Admin 镜像在 non-root、read-only、无网络/能力、128 MiB/0.25 CPU 下通过 12-command live contractPostgreSQL 18.6 arm64 physical HA timeline 1→2 的 147 gates 全部通过,报告 SHA-256 为 `8fbb606773080dae15de5e31db5726abb8700862b51e4616b5f3f50e0b8374f3`。package、Cluster dependency、122-module Edge import、部署、镜像与 service bridge 审计全部 compatibleEdge/Standalone package、依赖和常驻资源不变。本切片关闭 ADR-0050“只有 application service、没有受审产品入口”的缺口,但不冒充远程 HTTP/API/UI、双人复核/break-glass、pepper rotation、audit retention/export/alert 或完整 Kubernetes Job ceremony。
@@ -10078,7 +10078,7 @@ PR-8 的本机最新增量由 ADR-0075/0076/0077/0078/0079/0080/0081/0082/0083/0
ADR-0087 Owner package 更新同样适用于上段 PR-8 累计描述:现行产品 CLI 只能经 console facade 到达其内部 bootstrap/credential-recovery,三个历史 ceremony package 名都只表示旧切片;`ql3-owner-gc` 由 maintenance 直接提供,不再拥有独立 importer。
PR-8 的 cluster ADR-0049 未完成项由 ADR-0050/0051/0500/0501 继续收敛:Identity register/enable/disable、credential issue/rotate/revoke、mutation ledger、强 actor、同事务 audit、有界 audit query,以及常驻 `/api/v3` 的认证前 overload shield 已孵化完成;D-405 新增默认无 listener、一次只执行一个命令并关闭单连接 admin authority 的 `ql3-security-admin` 产品 CLIcredential token 只向私有 no-replace 文件交付。D-406 又补齐默认不安装、无 Kubernetes API authority 的一次性 Job、私密输入 stager、CloudNativePG 与 PVC delivery 静态契约;其真实 K3s + PostgreSQL/PVC live ceremony 仍是当前 Gate。远程 API/UI、管理入口独立 rate limit、双人复核或 break-glass、pepper rotation、audit retention/export/alert 也仍未完成不得把短生命周期 CLI、静态 Job、application service 或 process-local HTTP shield 的存在解释为 cluster-control 已获得管理 authority 或全局 quota。
PR-8 的 cluster ADR-0049 未完成项由 ADR-0050/0051/0500/0501 继续收敛:Identity register/enable/disable、credential issue/rotate/revoke、mutation ledger、强 actor、同事务 audit、有界 audit query,以及常驻 `/api/v3` 的认证前 overload shield 已孵化完成;D-405 新增默认无 listener、一次只执行一个命令并关闭单连接 admin authority 的 `ql3-security-admin` 产品 CLIcredential token 只向私有 no-replace 文件交付。D-406 又补齐默认不安装、无 Kubernetes API authority 的一次性 Job、私密输入 stager、CloudNativePG 与 PVC delivery 契约,并已由真实三节点 K3s、三实例 PostgreSQL 18.4、response-loss replay、PVC custody、网络/RBAC 拒绝与失败清理 live ceremony 验收。该单 Docker host fixture 仍不证明生产 control-plane HA、跨主机 STONITH/DR 或加密 CSI远程 API/UI、管理入口独立 rate limit、双人复核或 break-glass、pepper rotation、audit retention/export/alert 也仍未完成不得把短生命周期 CLI、一次性 Job、application service 或 process-local HTTP shield 的存在解释为 cluster-control 已获得管理 authority 或全局 quota。
未进入当前孵化切片的代码在通过对应 Gate 前必须保持不可达:不得仅因 schema、service 或 Primary 编排器已存在,就让旧 Controller、Scheduler、gRPC callback 或 Shell 脚本直接写入新状态表或调用新 Executor。已接入的 Shadow 观察只能通过默认关闭的 Feature Flag 和 origin owner 决策到达,不得调用 Executor、再次 spawn 或改变 Legacy 返回结果。manual `runSingle` 只增加 owner selection seam;默认没有 router。HTTP bootstrap 每次启动只读取一次 manifest,缺失、禁用、拒绝或非 primary 时保持 Legacy 且不加载重组件;显式 accepted manual primary 会在恢复门禁通过后安装唯一 owner,选中后禁止回退双跑。ADR-0445 已让 `ScheduleService.runTask` 的 subscription/system/script 在显式 origin flag 下只观察同一个 Legacy ChildProcesssystem crond 的 `scheduled_system`、once/boot/grpc 与这些来源的 Primary owner 切换仍须独立门禁。
@@ -60,10 +60,12 @@ Identity 变更、revoke 和 audit query 使用无 delivery 的 base。只有 `c
- stager 聚焦测试覆盖真实 kubelet symlink 布局、`0700/0600` 收紧、持久 delivery 目录复验、realpath 逃逸、world-readable material、目标不可覆盖和 CLI 无敏感回显。
- 部署审计冻结无 API token/RBAC、caller-driven/零重试/deadline/TTL、non-root/read-only/drop-all、资源上限、固定 CLI、内存私有输入、独立 admin credential、CloudNativePG egress、PVC delivery 和默认聚合不可达;失败注入覆盖权限扩大、非持久 delivery 与误入共享 aggregate。
- `kubectl kustomize` 已分别渲染 base、CloudNativePG、credential-delivery 和 CloudNativePG + delivery 四个入口。
- 18-package clean build/test 退出 0;当前 `cluster-admin` 为 454 total / 451 pass / 3 conditional skip / 0 failbackend 为 1579 total / 1577 pass / 2 conditional skip / 0 fail。Edge import 仍为 122 modulesCluster dependency、package boundary、deployment、deployment-lock source surface 与 release-version 审计均 compatible。
- 本地构建的 Cluster Admin 镜像 digest 为 `sha256:5464f0bbf5aa1302c080b13c9f18aaa89ba418ab5d09a917f5b5b4937c0ede2f`;新 stager 在 non-root、read-only rootfs、`network=none`、drop-all、no-new-privileges、32 PID、128 MiB 与 0.25 CPU 下完成独立 `--help` smoke,证明发布镜像包含该固定入口
- 真实 K3s Pod、PostgreSQL admin operation、PVC token custody、response loss 与清理演练尚未执行,因此不得把本 ADR 解释为 live ceremony 已验收
- 18-package clean build/test 退出 0;当前 `cluster-admin` 为 456 total / 453 pass / 3 conditional skip / 0 failbackend 为 1590 total / 1588 pass / 2 conditional skip / 0 fail。
- opt-in live gate 在本机 arm64 建立 1 control-plane + 2 worker 的 K3s `v1.34.3+k3s1`/Flannel、CloudNativePG 1.30.0 和 3 个 PostgreSQL 18.4 实例;migration 71 与 control-core capability 70 通过后,6 个串行产品 Job 完成 register、audit query、issue、exact replay、rotate 与 revoke,另一个 `0444` 输入 Job 按预期在 init 阶段失败且主容器未启动
- live gate 证明 immutable Secret 的真实 kubelet Atomic Writer 投影、memory-backed 私有 stage、PVC 跨 Job persistence/no-replace replay、不同 rotation material、TLS 与单连接最小权限;同时实测拒绝 Kubernetes API/公网 egress、Secret read/Job mutation RBAC,并在 finally 删除 Job、Secret、证据 Job、fixture root Job、PVC、K3s 容器、网络与卷
- 所有 Security Administration Job 继续以 UID/GID 10001 运行并使用 `fsGroupChangePolicy=OnRootMismatch`,避免后续只读证据 Pod 递归改写 `0700/0600` custody。K3s local-path 实现把新 PVC 根暴露为 `02777 root:10001`,live gate 因此先用一个专用、无网络、无 API token、drop-all 的 root fixture Job 精确收紧为 `02770`;该 fixture 例外不是产品管理 authority,也不证明生产 CSI 加密或权限模型。
- content-free 报告权限为 `0600`,独立审计结果为 `compatible=true/findings=[]`SHA-256 为 `e5c24af77034e1a2efee062107176e218c11a9f9f0d6c8c7308fdc280b0a82cf`。可手动触发的专用 CI workflow 固定 K3s/CNPG/PostgreSQL 供应链并重复同一 ceremony。
## 影响与剩余门禁
D-406 关闭“每个部署者都要从零编写一次性 Admin Job”的静态部署缺口,且 Edge/Standalone 和默认 Cluster 常驻资源保持不变。下一门是以临时 K3s + PostgreSQL 执行 register/query/issue/replay/revoke、证明 token 仅存在于 PVC no-replace 文件、Pod 无 API authority、失败清理和证据 content-free;之后仍有双人复核/break-glass、pepper rotation、audit retention/export/alert、并发 dispatch 和远程管理 UI/API。
D-406 关闭“每个部署者都要从零编写一次性 Admin Job”及其单主机 K3s/CNPG/PVC live 缺口,且 Edge/Standalone 和默认 Cluster 常驻资源保持不变。该 gate 不代表生产 Kubernetes control-plane HA、跨主机故障隔离/STONITH、灾备恢复、加密 CSI custody 或外部 IdP 已完成;之后仍有双人复核/break-glass、pepper rotation、audit retention/export/alert、并发 dispatch 和远程管理 UI/API。
@@ -149,8 +149,8 @@ kubectl logs job/ql3-security-administration -n qinglong3-system \
-c administrator
```
当前固定资源名只允许串行执行。收集 content-free 结果和(仅 issue/rotatePVC 中的 `0600` delivery 文件后,删除 Job 与本次 immutable input Secret;不得重用 assertion、把 token 复制到终端输出,或以 `kubectl apply` 修改旧 Job。真实 K3s + PostgreSQL live ceremony 尚未验收,生产启用前仍需完成 ADR-0501 的 live gate
当前固定资源名只允许串行执行。收集 content-free 结果和(仅 issue/rotatePVC 中的 `0600` delivery 文件后,删除 Job 与本次 immutable input Secret;不得重用 assertion、把 token 复制到终端输出,或以 `kubectl apply` 修改旧 Job。ADR-0501 已由三节点 K3s、三实例 CloudNativePG/PostgreSQL、真实 kubelet Secret 投影和 RWO PVC 完成一次端到端 live 验收;它验证的是应用契约与权限边界,不替代生产 control-plane HA、跨主机 STONITH/DR、加密 CSI 和外部 IdP 验收
## 当前边界
本入口没有远程 API/UI、双人复核或 break-glass、pepper rotation、audit retention/export/alert。可选 Job 已有受审静态部署契约,但不默认安装,真实 K3s + PostgreSQL/PVC ceremony 仍待验收admin database credential 始终不得进入常驻 Cluster Control。命令决策见 [ADR-0500](../adr/ADR-0500-short-lived-cluster-security-administration-command.md),部署决策见 [ADR-0501](../adr/ADR-0501-opt-in-kubernetes-security-administration-job.md)。
本入口没有远程 API/UI、双人复核或 break-glass、pepper rotation、audit retention/export/alert。可选 Job 的静态契约与单主机 K3s + PostgreSQL/PVC ceremony 已验收,但仍不默认安装,也不证明生产基础设施 HA/DR 或存储加密admin database credential 始终不得进入常驻 Cluster Control。命令决策见 [ADR-0500](../adr/ADR-0500-short-lived-cluster-security-administration-command.md),部署决策见 [ADR-0501](../adr/ADR-0501-opt-in-kubernetes-security-administration-job.md)。
+2
View File
@@ -93,6 +93,8 @@
"test:postgres-backup-prompt-output-recovery-live:ql3": "pnpm --filter @qinglong/ai build && pnpm --filter @qinglong/cluster-admin build && node scripts/ql3-postgres-prompt-output-recovery-live-contract.cjs",
"audit:cluster-deployment:ql3": "node scripts/ql3-cluster-deployment-audit.cjs",
"audit:security-administration-kubernetes:ql3": "node scripts/ql3-security-administration-kubernetes-audit.cjs",
"test:security-administration-kubernetes-live:ql3": "node scripts/ql3-security-administration-kubernetes-live-contract.cjs",
"audit:security-administration-kubernetes-live:ql3": "node scripts/ql3-security-administration-kubernetes-live-audit.cjs",
"audit:cluster-copilot-console:ql3": "node scripts/ql3-cluster-copilot-console-audit.cjs",
"audit:cluster-copilot-console-distribution:ql3": "node scripts/ql3-cluster-copilot-console-distribution-audit.cjs",
"evidence:cluster-admin-release-workstation:ql3": "node scripts/ql3-cluster-admin-release-workstation-ceremony.cjs",
@@ -119,13 +119,23 @@ function sameFileState(
);
}
export function isClusterAdministrationProjectedSourceDirectoryAuthority(
status: Readonly<{ mode: number; uid: number }>,
): boolean {
const permissions = status.mode & 0o1777;
return (
(permissions & 0o002) === 0 ||
(status.uid === 0 && permissions === 0o1777)
);
}
function verifySourceDirectory(sourceDirectory: string): string {
const status = lstatSync(sourceDirectory, { throwIfNoEntry: false });
if (
status === undefined ||
!status.isDirectory() ||
status.isSymbolicLink() ||
(status.mode & 0o002) !== 0
!isClusterAdministrationProjectedSourceDirectoryAuthority(status)
) {
throw new ClusterAdministrationKubernetesInputStageError(
'projected source directory authority is invalid',
@@ -245,7 +255,7 @@ function verifyWritableParent(parent: string, label: string): void {
status === undefined ||
!status.isDirectory() ||
status.isSymbolicLink() ||
(status.mode & 0o002) !== 0
!isClusterAdministrationProjectedSourceDirectoryAuthority(status)
) {
throw new ClusterAdministrationKubernetesInputStageError(
`${label} parent authority is invalid`,
@@ -290,6 +300,7 @@ function createPrivateDirectory(directory: string, label: string): void {
}
function prepareDeliveryDirectory(directory: string): void {
verifyWritableParent(dirname(directory), 'delivery directory');
const existing = lstatSync(directory, { throwIfNoEntry: false });
if (existing === undefined) {
createPrivateDirectory(directory, 'delivery directory');
@@ -17,6 +17,7 @@ const { afterEach, test } = require('node:test');
const {
ClusterAdministrationKubernetesInputStageError,
isClusterAdministrationProjectedSourceDirectoryAuthority,
stageClusterAdministrationKubernetesInputs,
} = require('../dist/security-administration/clusterAdministrationKubernetesInputStage.js');
@@ -87,6 +88,44 @@ test('copies a Kubernetes projected Secret into a private immutable input bounda
assert.equal(JSON.stringify(result).includes('A'.repeat(43)), false);
});
test('accepts only the exact root-owned sticky Kubernetes mount authority', () => {
assert.equal(
isClusterAdministrationProjectedSourceDirectoryAuthority({
mode: 0o41777,
uid: 0,
}),
true,
);
assert.equal(
isClusterAdministrationProjectedSourceDirectoryAuthority({
mode: 0o43777,
uid: 0,
}),
true,
);
assert.equal(
isClusterAdministrationProjectedSourceDirectoryAuthority({
mode: 0o40777,
uid: 0,
}),
false,
);
assert.equal(
isClusterAdministrationProjectedSourceDirectoryAuthority({
mode: 0o41777,
uid: 10001,
}),
false,
);
assert.equal(
isClusterAdministrationProjectedSourceDirectoryAuthority({
mode: 0o40755,
uid: 10001,
}),
true,
);
});
test('prepares a private persistent delivery directory without weakening it', () => {
const fixture = projectedInput();
@@ -109,6 +148,26 @@ test('prepares a private persistent delivery directory without weakening it', ()
assert.equal(mode(fixture.deliveryDirectory), 0o700);
});
test('rejects a precreated private delivery directory under an unsafe parent', () => {
const fixture = projectedInput();
const unsafeParent = join(fixture.root, 'unsafe-delivery-parent');
mkdirSync(unsafeParent, { mode: 0o777 });
chmodSync(unsafeParent, 0o777);
const deliveryDirectory = join(unsafeParent, 'private');
mkdirSync(deliveryDirectory, { mode: 0o700 });
assert.throws(
() =>
stageClusterAdministrationKubernetesInputs({
sourceDirectory: fixture.sourceDirectory,
targetDirectory: fixture.targetDirectory,
deliveryDirectory,
}),
/delivery directory parent authority is invalid/,
);
assert.equal(mode(deliveryDirectory), 0o700);
});
test('rejects a projected input symlink that escapes the Secret authority', () => {
const fixture = projectedInput();
const external = join(fixture.root, 'external-command.json');
@@ -123,6 +123,7 @@ function auditSecurityAdministrationKubernetes(options = {}) {
pod?.securityContext?.runAsUser !== 10001 ||
pod?.securityContext?.runAsGroup !== 10001 ||
pod?.securityContext?.fsGroup !== 10001 ||
pod?.securityContext?.fsGroupChangePolicy !== 'OnRootMismatch' ||
pod?.securityContext?.seccompProfile?.type !== 'RuntimeDefault'
) {
findings.push(
@@ -0,0 +1,460 @@
#!/usr/bin/env node
'use strict';
const fs = require('node:fs');
const path = require('node:path');
const FIXTURE =
'qinglong/security-administration-kubernetes-live-contract@v1';
const LIMITATIONS = Object.freeze([
'three privileged K3s Docker nodes are not production infrastructure or control-plane HA evidence',
'the strong-User assertion is issued by a local deterministic ceremony rather than a production external IdP',
'CloudNativePG inside one Docker host is not infrastructure STONITH or disaster-recovery evidence',
'the local-path ReadWriteOnce volume is not encrypted production CSI custody evidence',
'a dedicated root storage-fixture Job constrains the local-path volume root before every non-root administration Job',
]);
const BANNED_KEYS = new Set([
'assertion',
'authorization',
'bearer',
'connectionstring',
'dsn',
'keyset',
'kubeconfig',
'password',
'pepper',
'privatekey',
'secret',
'tlskey',
'token',
]);
function finding(code, detail) {
return Object.freeze({ code, detail });
}
function exactKeys(value, expected) {
return (
value !== null &&
typeof value === 'object' &&
!Array.isArray(value) &&
JSON.stringify(Object.keys(value).sort()) ===
JSON.stringify([...expected].sort())
);
}
function allTrue(value, keys) {
return exactKeys(value, keys) && keys.every((key) => value[key] === true);
}
function isSha256(value) {
return typeof value === 'string' && /^sha256:[a-f0-9]{64}$/.test(value);
}
function isIsoTime(value) {
return (
typeof value === 'string' &&
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?Z$/.test(
value,
) &&
Number.isFinite(Date.parse(value))
);
}
function containsSensitiveMaterial(value, key = '') {
if (BANNED_KEYS.has(key.toLowerCase())) return true;
if (typeof value === 'string') {
return (
/postgres(?:ql)?:\/\/[^/\s]+:[^@\s]+@/i.test(value) ||
/\bql3c_[A-Za-z0-9_-]{16,}\b/.test(value) ||
/\beyJ[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\b/.test(
value,
) ||
/-----BEGIN (?:CERTIFICATE|(?:RSA |EC |OPENSSH )?PRIVATE KEY)-----/.test(
value,
)
);
}
if (Array.isArray(value)) {
return value.some((entry) => containsSensitiveMaterial(entry));
}
if (value && typeof value === 'object') {
return Object.entries(value).some(([childKey, child]) =>
containsSensitiveMaterial(child, childKey),
);
}
return false;
}
function validKubernetesVersion(value) {
const match =
typeof value === 'string'
? /^v1\.([0-9]{2,3})\.([0-9]+)(?:[-+][0-9A-Za-z](?:[0-9A-Za-z.-]{0,62}[0-9A-Za-z])?)?$/.exec(
value,
)
: null;
return Boolean(match && Number(match[1]) >= 32);
}
function validateSecurityAdministrationKubernetesLiveReport(report) {
const findings = [];
if (
!exactKeys(report, [
'schemaVersion',
'fixture',
'observedAt',
'platform',
'database',
'ceremony',
'inputBoundary',
'deliveryCustody',
'isolation',
'durability',
'cleanup',
'gates',
'limitations',
]) ||
report?.schemaVersion !== 1 ||
report?.fixture !== FIXTURE ||
!isIsoTime(report?.observedAt)
) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_REPORT_SHAPE',
'the report must use the exact versioned live-contract envelope',
),
);
}
if (containsSensitiveMaterial(report)) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_MATERIAL_EXPOSURE',
'the report must not contain credentials, assertions, database authority, kubeconfig or private key material',
),
);
}
const platform = report?.platform;
if (
!exactKeys(platform, [
'distribution',
'kubernetesVersion',
'architecture',
'kubernetesImageId',
'administrationImageId',
'cniName',
'cniDistributionBinding',
'controlPlaneNodes',
'workerNodes',
'readyNodes',
]) ||
platform?.distribution !== 'k3s' ||
!validKubernetesVersion(platform?.kubernetesVersion) ||
!['amd64', 'arm64'].includes(platform?.architecture) ||
!isSha256(platform?.kubernetesImageId) ||
!isSha256(platform?.administrationImageId) ||
platform?.cniName !== 'flannel' ||
platform?.cniDistributionBinding !== 'rancher/k3s:v1.34.3-k3s1' ||
platform?.controlPlaneNodes !== 1 ||
platform?.workerNodes !== 2 ||
platform?.readyNodes !== 3
) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_PLATFORM',
'the fixture must bind three real K3s nodes, Flannel and exact local runtime images',
),
);
}
const database = report?.database;
if (
!exactKeys(database, [
'operator',
'operatorVersion',
'postgresVersionNumber',
'postgresImageId',
'instances',
'readyInstances',
'administrationRole',
'roleConnectionLimit',
'commandConnectionLimit',
'migrationCount',
'controlCoreCapability',
'tlsVerified',
'leastPrivilege',
]) ||
database?.operator !== 'cloudnative-pg' ||
database?.operatorVersion !== '1.30.0' ||
database?.postgresVersionNumber !== 180004 ||
!isSha256(database?.postgresImageId) ||
database?.instances !== 3 ||
database?.readyInstances !== 3 ||
database?.administrationRole !== 'ql3_admin' ||
database?.roleConnectionLimit !== 4 ||
database?.commandConnectionLimit !== 1 ||
database?.migrationCount !== 71 ||
database?.controlCoreCapability !== 70 ||
database?.tlsVerified !== true ||
database?.leastPrivilege !== true
) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_DATABASE',
'three TLS CloudNativePG instances must expose only the reviewed one-connection administration authority',
),
);
}
const ceremony = report?.ceremony;
if (
!exactKeys(ceremony, [
'operations',
'completedJobs',
'failedJobs',
'callerDriven',
'backoffLimit',
'activeDeadlineSeconds',
'ttlSecondsAfterFinished',
'serviceAccount',
'serviceAccountTokenMounted',
'rbacGranted',
'responseLossReplayObserved',
'sensitiveMaterialReported',
]) ||
JSON.stringify(ceremony?.operations) !==
JSON.stringify([
'identity.register',
'audit.list',
'credential.issue',
'credential.issue.replay',
'credential.rotate',
'credential.revoke',
]) ||
ceremony?.completedJobs !== 6 ||
ceremony?.failedJobs !== 1 ||
ceremony?.callerDriven !== true ||
ceremony?.backoffLimit !== 0 ||
ceremony?.activeDeadlineSeconds !== 300 ||
ceremony?.ttlSecondsAfterFinished !== 600 ||
ceremony?.serviceAccount !== 'ql3-security-administration' ||
ceremony?.serviceAccountTokenMounted !== false ||
ceremony?.rbacGranted !== false ||
ceremony?.responseLossReplayObserved !== true ||
ceremony?.sensitiveMaterialReported !== false
) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_CEREMONY',
'six serial caller-created commands plus one failed input stage must use the exact tokenless Job contract',
),
);
}
if (
!allTrue(report?.inputBoundary, [
'immutableSecret',
'projectedMode0440',
'memoryBackedPrivateStage',
'targetDirectoryMode0700',
'targetFilesMode0600',
'kubeletAtomicWriterProjectionAccepted',
'worldReadableProjectionRejected',
'mainContainerNotStartedAfterStageFailure',
])
) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_INPUT_BOUNDARY',
'the real kubelet projection must stage privately and reject widened source permissions before the main container starts',
),
);
}
const delivery = report?.deliveryCustody;
if (
!exactKeys(delivery, [
'persistentVolumeClaim',
'accessMode',
'fixtureRootProvisioned',
'fixtureRootMode',
'fixtureProvisionerRanAsRoot',
'privateDirectoryMode',
'fileMode',
'fileCount',
'issueDigest',
'rotationDigest',
'distinctRotationMaterial',
'persistentAcrossJobs',
'noReplaceReplayPreserved',
'deliverySchemaValidated',
'bearerFormatValidatedInPod',
'sensitiveMaterialReported',
]) ||
delivery?.persistentVolumeClaim !== true ||
delivery?.accessMode !== 'ReadWriteOnce' ||
delivery?.fixtureRootProvisioned !== true ||
delivery?.fixtureRootMode !== '2770' ||
delivery?.fixtureProvisionerRanAsRoot !== true ||
delivery?.privateDirectoryMode !== '0700' ||
delivery?.fileMode !== '0600' ||
delivery?.fileCount !== 2 ||
!isSha256(delivery?.issueDigest) ||
!isSha256(delivery?.rotationDigest) ||
delivery?.issueDigest === delivery?.rotationDigest ||
![
'distinctRotationMaterial',
'persistentAcrossJobs',
'noReplaceReplayPreserved',
'deliverySchemaValidated',
'bearerFormatValidatedInPod',
].every((key) => delivery?.[key] === true) ||
delivery?.sensitiveMaterialReported !== false
) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_DELIVERY',
'issue and rotation material must remain distinct, private, persistent and no-replace on the caller-owned RWO volume',
),
);
}
if (
!allTrue(report?.isolation, [
'dnsAndDatabaseEgressAllowed',
'kubernetesApiEgressDenied',
'publicInternetEgressDenied',
'secretReadRbacDenied',
'jobMutationRbacDenied',
])
) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_ISOLATION',
'Flannel and RBAC evidence must allow only DNS/PostgreSQL and deny ambient Kubernetes or public authority',
),
);
}
const durability = report?.durability;
if (
!exactKeys(durability, [
'identityVersion',
'identityStatus',
'credentialVersion',
'credentialState',
'identityMutationCount',
'credentialMutationCount',
'issueMutationCount',
'credentialVersionCount',
'allowedAuditCount',
]) ||
durability?.identityVersion !== 1 ||
durability?.identityStatus !== 'active' ||
durability?.credentialVersion !== 3 ||
durability?.credentialState !== 'revoked' ||
durability?.identityMutationCount !== 1 ||
durability?.credentialMutationCount !== 3 ||
durability?.issueMutationCount !== 1 ||
durability?.credentialVersionCount !== 3 ||
durability?.allowedAuditCount !== 4
) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_DURABILITY',
'the database must retain one identity mutation and exactly three credential generations without replay duplication',
),
);
}
if (
!allTrue(report?.cleanup, [
'jobsDeleted',
'inputSecretsDeleted',
'evidenceJobsDeleted',
'storageProvisionJobDeleted',
'deliveryVolumeClaimDeleted',
])
) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_CLEANUP',
'all caller-created Jobs, inputs, evidence Pods and the fixture delivery claim must be removed',
),
);
}
if (
!allTrue(report?.gates, [
'realThreeNodeKubernetes',
'realCloudNativePg',
'realKubeletSecretProjection',
'realAdministrationProductCommands',
'realPersistentCredentialCustody',
'responseLossReplay',
'failedInputStageClosed',
'leastPrivilege',
'contentFreeEvidence',
'passed',
])
) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_GATES',
'every real ceremony gate must be explicitly and truthfully closed',
),
);
}
if (JSON.stringify(report?.limitations) !== JSON.stringify(LIMITATIONS)) {
findings.push(
finding(
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_LIMITATIONS',
'the report must retain the exact non-production fixture limitations',
),
);
}
return Object.freeze({
schemaVersion: 1,
fixture: FIXTURE,
findings: Object.freeze(findings),
compatible: findings.length === 0,
});
}
function reportPath(argv) {
if (
argv.length !== 1 ||
!argv[0].startsWith('--report=') ||
!path.isAbsolute(argv[0].slice('--report='.length))
) {
throw new Error(
'usage: ql3-security-administration-kubernetes-live-audit --report=/absolute/report.json',
);
}
return argv[0].slice('--report='.length);
}
if (require.main === module) {
try {
const report = JSON.parse(fs.readFileSync(reportPath(process.argv.slice(2))));
const result = validateSecurityAdministrationKubernetesLiveReport(report);
process.stdout.write(`${JSON.stringify(result)}\n`);
if (!result.compatible) process.exitCode = 1;
} catch (error) {
process.stderr.write(
`security administration Kubernetes live audit failed: ${
error instanceof Error ? error.message : String(error)
}\n`,
);
process.exitCode = 2;
}
}
module.exports = {
FIXTURE,
LIMITATIONS,
validateSecurityAdministrationKubernetesLiveReport,
};
File diff suppressed because it is too large Load Diff
@@ -48,6 +48,26 @@ test('rejects Kubernetes API token authority in the administration Job', () => {
);
});
test('rejects recursive fsGroup rewrites of persistent credential custody', () => {
const report = auditSecurityAdministrationKubernetes({
root: ROOT,
readFile: intercept(
'deploy/kubernetes/ql3-cluster/operations/security-administration/base/job.yaml',
(value) => value.replace(
'fsGroupChangePolicy: OnRootMismatch',
'fsGroupChangePolicy: Always',
),
),
});
assert.equal(report.compatible, false);
assert.ok(
report.findings.some(
({ code }) => code === 'QL3_SECURITY_ADMIN_KUBERNETES_JOB_BOUNDARY_INVALID',
),
);
});
test('rejects a non-persistent credential delivery boundary', () => {
const report = auditSecurityAdministrationKubernetes({
root: ROOT,
@@ -0,0 +1,175 @@
const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
FIXTURE,
LIMITATIONS,
validateSecurityAdministrationKubernetesLiveReport,
} = require('../../scripts/ql3-security-administration-kubernetes-live-audit.cjs');
const digest = (value) => `sha256:${value.repeat(64)}`;
function report() {
return {
schemaVersion: 1,
fixture: FIXTURE,
observedAt: '2026-08-25T04:00:00.000Z',
platform: {
distribution: 'k3s',
kubernetesVersion: 'v1.34.3+k3s1',
architecture: 'amd64',
kubernetesImageId: digest('1'),
administrationImageId: digest('2'),
cniName: 'flannel',
cniDistributionBinding: 'rancher/k3s:v1.34.3-k3s1',
controlPlaneNodes: 1,
workerNodes: 2,
readyNodes: 3,
},
database: {
operator: 'cloudnative-pg',
operatorVersion: '1.30.0',
postgresVersionNumber: 180004,
postgresImageId: digest('3'),
instances: 3,
readyInstances: 3,
administrationRole: 'ql3_admin',
roleConnectionLimit: 4,
commandConnectionLimit: 1,
migrationCount: 71,
controlCoreCapability: 70,
tlsVerified: true,
leastPrivilege: true,
},
ceremony: {
operations: [
'identity.register',
'audit.list',
'credential.issue',
'credential.issue.replay',
'credential.rotate',
'credential.revoke',
],
completedJobs: 6,
failedJobs: 1,
callerDriven: true,
backoffLimit: 0,
activeDeadlineSeconds: 300,
ttlSecondsAfterFinished: 600,
serviceAccount: 'ql3-security-administration',
serviceAccountTokenMounted: false,
rbacGranted: false,
responseLossReplayObserved: true,
sensitiveMaterialReported: false,
},
inputBoundary: {
immutableSecret: true,
projectedMode0440: true,
memoryBackedPrivateStage: true,
targetDirectoryMode0700: true,
targetFilesMode0600: true,
kubeletAtomicWriterProjectionAccepted: true,
worldReadableProjectionRejected: true,
mainContainerNotStartedAfterStageFailure: true,
},
deliveryCustody: {
persistentVolumeClaim: true,
accessMode: 'ReadWriteOnce',
fixtureRootProvisioned: true,
fixtureRootMode: '2770',
fixtureProvisionerRanAsRoot: true,
privateDirectoryMode: '0700',
fileMode: '0600',
fileCount: 2,
issueDigest: digest('4'),
rotationDigest: digest('5'),
distinctRotationMaterial: true,
persistentAcrossJobs: true,
noReplaceReplayPreserved: true,
deliverySchemaValidated: true,
bearerFormatValidatedInPod: true,
sensitiveMaterialReported: false,
},
isolation: {
dnsAndDatabaseEgressAllowed: true,
kubernetesApiEgressDenied: true,
publicInternetEgressDenied: true,
secretReadRbacDenied: true,
jobMutationRbacDenied: true,
},
durability: {
identityVersion: 1,
identityStatus: 'active',
credentialVersion: 3,
credentialState: 'revoked',
identityMutationCount: 1,
credentialMutationCount: 3,
issueMutationCount: 1,
credentialVersionCount: 3,
allowedAuditCount: 4,
},
cleanup: {
jobsDeleted: true,
inputSecretsDeleted: true,
evidenceJobsDeleted: true,
storageProvisionJobDeleted: true,
deliveryVolumeClaimDeleted: true,
},
gates: {
realThreeNodeKubernetes: true,
realCloudNativePg: true,
realKubeletSecretProjection: true,
realAdministrationProductCommands: true,
realPersistentCredentialCustody: true,
responseLossReplay: true,
failedInputStageClosed: true,
leastPrivilege: true,
contentFreeEvidence: true,
passed: true,
},
limitations: [...LIMITATIONS],
};
}
test('accepts the exact content-free Security Administration live report', () => {
const result = validateSecurityAdministrationKubernetesLiveReport(report());
assert.equal(result.compatible, true);
assert.deepEqual(result.findings, []);
});
test('rejects widened authority, false custody and replay duplication', () => {
const candidate = report();
candidate.ceremony.serviceAccountTokenMounted = true;
candidate.deliveryCustody.noReplaceReplayPreserved = false;
candidate.durability.issueMutationCount = 2;
candidate.gates.passed = false;
const codes = validateSecurityAdministrationKubernetesLiveReport(
candidate,
).findings.map((finding) => finding.code);
assert.ok(
codes.includes('QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_CEREMONY'),
);
assert.ok(
codes.includes('QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_DELIVERY'),
);
assert.ok(
codes.includes('QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_DURABILITY'),
);
assert.ok(codes.includes('QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_GATES'));
});
test('rejects any credential or assertion material in evidence', () => {
const candidate = report();
candidate.deliveryCustody.proof = {
token: 'ql3c_example_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
};
const result = validateSecurityAdministrationKubernetesLiveReport(candidate);
assert.equal(result.compatible, false);
assert.ok(
result.findings.some(
(finding) =>
finding.code ===
'QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE_MATERIAL_EXPOSURE',
),
);
});
@@ -0,0 +1,140 @@
const assert = require('node:assert/strict');
const { spawnSync } = require('node:child_process');
const fs = require('node:fs');
const path = require('node:path');
const { test } = require('node:test');
const {
auditListCommand,
credentialIssueCommand,
credentialRevokeCommand,
credentialRotateCommand,
custodyEvidenceSource,
deliveryVolumeProvisionSource,
identity,
identityRegisterCommand,
inputAuthorityEvidenceSource,
} = require('../../scripts/ql3-security-administration-kubernetes-live-contract.cjs');
const values = Object.freeze({
subject: Object.freeze({ type: 'api_app', id: 'd406-test-client' }),
credentialId: 'd406-test-client',
identityMutationId: '10000000-0000-4000-8000-000000000001',
issueMutationId: '10000000-0000-4000-8000-000000000002',
rotateMutationId: '10000000-0000-4000-8000-000000000003',
revokeMutationId: '10000000-0000-4000-8000-000000000004',
registerRequestId: 'd406-register-test',
issueRequestId: 'd406-issue-test',
rotateRequestId: 'd406-rotate-test',
revokeRequestId: 'd406-revoke-test',
notBeforeAtMs: 2_000_000_000_000,
expiresAtMs: 2_000_003_600_000,
});
test('requires a private report path before any Docker or Kubernetes mutation', () => {
const script = path.resolve(
__dirname,
'../../scripts/ql3-security-administration-kubernetes-live-contract.cjs',
);
const result = spawnSync(process.execPath, [script], {
encoding: 'utf8',
env: {
...process.env,
QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE: '1',
},
});
assert.equal(result.status, 1);
assert.match(result.stderr, /--report=\/absolute\/private-report\.json/);
assert.doesNotMatch(result.stderr, /Docker\/Kubernetes/);
});
test('builds the exact register, audit, issue, rotate and revoke commands', () => {
assert.deepEqual(identityRegisterCommand(values), {
schemaVersion: 1,
operation: 'identity.register',
request: {
mutationId: values.identityMutationId,
requestId: values.registerRequestId,
expectedCurrentVersion: 0,
subject: values.subject,
},
});
assert.deepEqual(auditListCommand(), {
schemaVersion: 1,
operation: 'audit.list',
request: { limit: 25, filter: { outcome: 'allowed' } },
});
assert.equal(credentialIssueCommand(values).request.expectedCurrentVersion, 0);
assert.equal(credentialRotateCommand(values).request.expectedCurrentVersion, 1);
assert.equal(credentialRevokeCommand(values).request.expectedCurrentVersion, 2);
assert.equal('notBeforeAtMs' in credentialRevokeCommand(values).request, false);
});
test('binds the live assertion to the isolated Security Administration purpose', () => {
const key = identity.reviewedKey('security-administration-unit-key');
const document = identity.keyset(1, [key]);
assert.equal(document.audience, 'qinglong3-security-administration');
const assertion = identity.assertion(key, 'unit-test');
const header = JSON.parse(Buffer.from(assertion.split('.')[0], 'base64url'));
const payload = JSON.parse(Buffer.from(assertion.split('.')[1], 'base64url'));
assert.equal(header.typ, 'ql3-security-administration+jwt');
assert.equal(payload.ql3_purpose, 'security-administration');
assert.equal(payload.sub, 'security-owner');
assert.equal(payload.acr, 'urn:ql3:mfa');
assert.deepEqual(payload.amr, ['pwd', 'otp']);
});
test('keeps the in-Pod custody verifier content-free and fail-closed', () => {
const source = custodyEvidenceSource();
assert.match(source, /bytes\.fill\(0\)/);
assert.match(source, /kubernetesApiConnected/);
assert.match(source, /publicInternetConnected/);
assert.match(source, /status\.nlink!==1/);
assert.doesNotMatch(source, /value\.token[,}]/);
assert.doesNotMatch(source, /console\.log/);
});
test('inspects projected input authority without reading private material', () => {
const source = inputAuthorityEvidenceSource();
assert.match(source, /lstatSync/);
assert.match(source, /realpathSync/);
assert.match(source, /confined/);
assert.doesNotMatch(source, /readFile/);
assert.doesNotMatch(source, /createReadStream/);
});
test('constrains only the exact local-path fixture root without network authority', () => {
const source = deliveryVolumeProvisionSource();
assert.match(source, /before\.mode!==['"]2777['"]/);
assert.match(source, /chmodSync\(root,0o2770\)/);
assert.match(source, /after\.mode!==['"]2770['"]/);
assert.doesNotMatch(source, /child_process/);
assert.doesNotMatch(source, /net|fetch|http/);
});
test('live runner remains opt-in, reviewed, cleanup-bound and log-free', () => {
const source = fs.readFileSync(
path.resolve(
__dirname,
'../../scripts/ql3-security-administration-kubernetes-live-contract.cjs',
),
'utf8',
);
assert.match(
source,
/QL3_SECURITY_ADMINISTRATION_KUBERNETES_LIVE !== '1'/,
);
assert.match(source, /reviewedOperatorManifest\(operatorManifestFile\)/);
assert.match(source, /validateSecurityAdministrationKubernetesLiveReport/);
assert.match(source, /projectedMode: 0o444/);
assert.match(source, /credential\.issue\.replay/);
assert.match(source, /FallbackToLogsOnError/);
assert.match(source, /failureMessage: 'rejected'/);
assert.match(
source,
/deploy\/kubernetes\/ql3-cluster\/base\/service-account\.yaml/,
);
assert.match(source, /persistentvolumeclaim\/\$\{DELIVERY_CLAIM\}/);
assert.match(source, /await fixture\.cleanup\(\)/);
assert.doesNotMatch(source, /kubectl\([^)]*logs/);
});