diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f0f02e7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,23 @@ +# Source control metadata +.git + +# Local configuration and credential material +.env +.env.* +configs/local.yaml +deploy/.control-plane-tls/ +*.crt +*.key +*.pem + +# Local build, test, and tooling outputs +.playwright-mcp/ +temp/ +bin/ +dist/ +coverage/ +*.out +*.test +*.prof +*.exe +.tmp-proto/ diff --git a/deploy/compose_test.go b/deploy/compose_test.go index a135180..4af8e32 100644 --- a/deploy/compose_test.go +++ b/deploy/compose_test.go @@ -265,6 +265,29 @@ func TestDeploymentEntrypointsExistInSource(t *testing.T) { } } +func TestDockerBuildContextExcludesLocalSecretsAndArtifacts(t *testing.T) { + payload, err := os.ReadFile("../.dockerignore") + if err != nil { + t.Fatalf("read .dockerignore: %v", err) + } + rules := make(map[string]struct{}) + for _, raw := range strings.Split(string(payload), "\n") { + rule := strings.TrimSpace(raw) + if rule == "" || strings.HasPrefix(rule, "#") { + continue + } + rules[rule] = struct{}{} + } + for _, required := range []string{ + ".git", ".env", ".env.*", "*.key", "*.pem", "*.crt", + "deploy/.control-plane-tls/", "bin/", "dist/", "coverage/", ".tmp-proto/", + } { + if _, exists := rules[required]; !exists { + t.Errorf(".dockerignore does not exclude %q", required) + } + } +} + func TestKubernetesBaseLeavesControlPlaneClientsForMTLSOverlay(t *testing.T) { payload, err := os.ReadFile("kubernetes/base/kustomization.yaml") if err != nil { diff --git a/docs/requirements/completion-audit.md b/docs/requirements/completion-audit.md index 37c2bd1..4fba5ff 100644 --- a/docs/requirements/completion-audit.md +++ b/docs/requirements/completion-audit.md @@ -118,7 +118,8 @@ SPIFFE URI 解析器:X.509-SVID 叶证书必须且只能包含一个 URI SAN 仓库审计会拒绝生产源和部署清单中的 `TODO`、`TBD`、`FIXME` 与私钥材料;原有 OpenAPI、 Queue、配置、指标和部署契约分别锁定一次性 Extract、队列容量、库存/累计获取边界及 -低基数标签。开发示例、环境变量引用和 CI fixture 不被视为生产 Secret 或未实现占位。 +低基数标签。根 `.dockerignore` 还会从镜像构建上下文排除本地控制面证书、私钥、环境文件和 +构建产物。开发示例、环境变量引用和 CI fixture 不被视为生产 Secret 或未实现占位。 ## 3. 后续实现范围 diff --git a/docs/security/security-model.md b/docs/security/security-model.md index f8eb3fb..ad27b31 100644 --- a/docs/security/security-model.md +++ b/docs/security/security-model.md @@ -48,6 +48,8 @@ CGNAT、协议转换保留段和已知云元数据端点属于硬拒绝项。私 ## 4. Secret 处理 - 配置只保存环境变量或文件引用,不在日志中输出解析后的值。 +- Docker 镜像构建上下文通过根目录 `.dockerignore` 排除本地环境文件、控制面证书/私钥、 + 凭据文件、Git 元数据和测试/构建产物;运行时证书只能通过受控挂载提供。 - Proxy 唯一键包含 username 与 credentialVersion,不包含密码或 SecretRef 内容。 - Provider Parser 将静态/响应密码写入 `credentials.Store`,Proxy Snapshot 只携带 SecretRef 与 credentialVersion;Gateway 通过统一 Resolver 按版本读取。 diff --git a/findings.md b/findings.md index 13adaf0..8bfbcca 100644 --- a/findings.md +++ b/findings.md @@ -268,3 +268,9 @@ Routing 自上而下匹配,首条命中停止;支持 Gateway 与 Extract 两 `@redocly/cli@2.25.4` 对两份 OpenAPI 3.1 文档执行标准验证,避免只依赖自定义遍历器。 - 标准最小规则集中的 Tag 描述已提升为错误;Distribution、Health、Status、Audit、Upstreams、 Routing 和 Configuration 标签均有面向 API 使用者的稳定说明。 + +## Docker 构建上下文审计(2026-08-07) + +- Dockerfile 构建阶段需要 `COPY . .`,因此根 `.dockerignore` 是隔离本地工作区与镜像上下文的 + 必要边界。它显式排除 Git 元数据、环境文件、本地配置、控制面证书/私钥、PEM/CRT/KEY 文件及 + 构建和测试产物;部署测试会在清单被删除或放宽时失败。 diff --git a/progress.md b/progress.md index cceff45..25db441 100644 --- a/progress.md +++ b/progress.md @@ -2,6 +2,8 @@ ## 2026-08-07 +- Docker 构建上下文现由根 `.dockerignore` 保护:本地控制面证书/私钥、环境文件、凭据文件、 + Git 元数据和构建产物不会被 `COPY . .` 发送到镜像构建器;部署测试固定该清单。 - OpenAPI 标准验证已固定为 `@redocly/cli@2.25.4`:`verify-openapi.ps1` 对两份 OpenAPI 3.1 文档运行最小规则集,并将 Tag 描述提升为错误;本地统一校验与 GitHub Actions 均执行该门禁。 - 运行验证环境探测:Windows Go 为 `CGO_ENABLED=0`,系统没有可用 C 编译器;WSL 仅安装