diff --git a/.agents/skills/unidesk-cicd/SKILL.md b/.agents/skills/unidesk-cicd/SKILL.md index d64d57ca..cb3cbbd5 100644 --- a/.agents/skills/unidesk-cicd/SKILL.md +++ b/.agents/skills/unidesk-cicd/SKILL.md @@ -370,6 +370,7 @@ bun scripts/cli.ts hwlab nodes control-plane legacy-cicd --help - registry 大流量不得经过 WireGuard/Flannel,也不得使用 CDN 或公共镜像站; - bcrypt hash 必须以 Compose-safe 字面量写入 Secret source,且 public-edge 用脱敏 material fingerprint 驱动凭据变更后的 recreate; + 候选校验不得用会保留引号的 `docker run --env-file` 改变 Secret 语义; - 验收统一走 `platform-infra k3s-cluster registry-smoke`,不手工 patch Caddy 或 containerd。 - worker 安装使用短启动并由 control-plane Node Ready 轮询收口,禁止让 `trans`/SSH 长挂等待 systemd notify。 - worker 加入集群不改变 PaC consumer 的 source commit authority,也不授权人工 PipelineRun、Argo sync 或业务 rollout。 diff --git a/docs/reference/platform-infra.md b/docs/reference/platform-infra.md index 62541598..4bfdcabc 100644 --- a/docs/reference/platform-infra.md +++ b/docs/reference/platform-infra.md @@ -203,7 +203,9 @@ - Basic Auth 只消费 SecretRef 中的用户名与 bcrypt hash,不把值写入 Git、计划输出或 Caddyfile; - bcrypt hash 在 Compose `env_file` 中必须使用单引号字面量,防止 `$` 被 Compose 插值;compose 只携带 Secret material 的 SHA-256 标记, - 使规范化或轮换触发受控 recreate,禁止手工重启容器; + 使规范化或轮换触发受控 recreate;候选 Caddy 校验必须 source Secret + 后仅按 key 继承环境,禁止用语义不同的 `docker run --env-file`,也禁止 + 手工重启容器; - 可信 TLS 由 public-edge 管理,镜像层不得经过 CDN 代理。 - worker containerd 归集群 CLI 管理: - 既有 `127.0.0.1:5000/...` 镜像引用保持不变; diff --git a/scripts/src/platform-infra-public-edge.ts b/scripts/src/platform-infra-public-edge.ts index 59af999f..9c170ce0 100644 --- a/scripts/src/platform-infra-public-edge.ts +++ b/scripts/src/platform-infra-public-edge.ts @@ -770,7 +770,10 @@ export function applyScript( const dnsItems = sites.map((site) => shQuote(`${site.hostname}|${site.expectedA}`)).join(" "); const probeItems = sites.map((site) => shQuote(`${site.hostname}|${site.healthPath}|${site.healthExpectedStatuses?.join(",") ?? "2xx3xx"}`)).join(" "); const authFiles = [...new Set(sites.flatMap((site) => site.accessPolicy === undefined ? [] : [site.accessPolicy.basicAuth.sourceRef]))]; - const caddyEnvArgs = authFiles.map((path) => `--env-file ${shQuote(path)}`).join(" "); + const authEnvKeys = [...new Set(sites.flatMap((site) => site.accessPolicy === undefined + ? [] + : [site.accessPolicy.basicAuth.usernameKey, site.accessPolicy.basicAuth.passwordHashKey]))]; + const caddyEnvArgs = authEnvKeys.map((key) => `-e ${shQuote(key)}`).join(" "); return `set -u mkdir -p "$(dirname ${shQuote(target.runtime.lockPath)})" exec 9>${shQuote(target.runtime.lockPath)} @@ -788,6 +791,9 @@ current_caddy="$tmp/Caddyfile.current" current_caddy_source="empty" mkdir -p ${shQuote(target.runtime.workDir)} ${shQuote(target.runtime.dataDir)} ${shQuote(target.runtime.configDir)} "$(dirname ${shQuote(target.runtime.statePath)})" ${authFiles.map((path) => `[ -s ${shQuote(path)} ] || { printf '%s\\n' '{"ok":false,"mutation":false,"error":"public-edge-auth-source-missing","sourceRef":${JSON.stringify(path)},"valuesPrinted":false}'; exit 1; }`).join("\n")} +set -a +${authFiles.map((path) => `. ${shQuote(path)}`).join("\n")} +set +a printf '%s' ${shQuote(ancestry)} | base64 -d >"$ancestry_file" printf '%s' ${shQuote(caddyfile)} | base64 -d >"$desired_caddy" printf '%s' ${shQuote(compose)} | base64 -d >"$compose_candidate"