trivoallan/houba

GitHub: trivoallan/houba

houba 是一个容器镜像供应链准入工具,为组织引入的外部公共镜像提供来源打标、可选加固与全生命周期审计能力。

Stars: 0 | Forks: 0

# houba **您组织运行的外部容器镜像的单一前门。** 每个进入您 registry 的公共镜像都会经过 houba:它会被镜像——或者,当您声明了加固策略时,会使用内部 CA 证书和内部包镜像进行重建——并被打上**标准化的、可移植的来源证明**(OCI 注解加上签名的 SLSA / in-toto 证明)的标记。 其回报在严重的 CVE 爆发的清晨即可显现。因为每一个通过 houba 引入的镜像都带有一致的来源标记,*“我们的影响范围有多大,以及由谁负责?”* 在您现有的可观测性工具栈中变成了**一次查询**——而不是一张令人抓狂的表格。houba 生成该标记;您的工具(Datadog、PowerBI、Wiz 等)负责读取它。 houba **不是**一个镜像镜像工具。`skopeo sync` 和 Harbor replication 会逐字节复制镜像。houba 会为每个镜像*打上*可移植来源的标记——并对您选择重建的镜像进行*加固*。 [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) [![Python](https://img.shields.io/badge/python-3.12-blue.svg)](https://www.python.org) ## 工作原理 对于您引入的每个镜像,您需要声明一个小的 `MirrorPolicy`(源、tag 选择规则、可选的加固步骤)。然后,`houba reconcile` 会根据每个策略执行以下操作: 1. 列出源 registry 上的 tag(通过 `regctl`)。 2. 选择要导入的 tag —— 包括正则表达式的包含/排除过滤器、semver 排序、moving-tag 别名,以及针对移动摘要的 7 天稳定窗口。 3. 对于每个 tag:按原样对其进行**镜像**(`regctl copy`),或者——当策略声明了 `transform` 时——通过 BuildKit(`buildctl`)结合您的加固步骤(内部 CA、内部包镜像、时区等)对其进行**重建**。 4. 使用标准化的来源证明对结果进行**打标** —— OCI 标准注解加上 `io.houba.*` 转换谱系,以及(在配置时)签名的 SLSA / in-toto 证明。 5. 推送到您的 registry,更新 moving-tag 别名,并归档被替换的 tag。 6. 报告运行情况 —— 向 stdout 输出人类可读/JSON 格式的报告,向 stderr 输出结构化的事件日志 —— 并以反映最差策略结果的代码退出。 变更检测基于来源证明并且是幂等的:重新运行 `reconcile` 是一个空操作(no-op),除非源摘要发生了移动(过了稳定窗口)或者您更改了加固策略。 除了 `reconcile` 之外,CLI 还提供: - **`houba audit`** —— 覆盖范围差距报告:遍历 registry 并列出**未携带** houba 标记的镜像(`--fail-on-uncovered` 使其成为一个 CI 门禁)。这正是让前门变得*可验证*的原因。 - **`houba purge`** —— 参考收割机:硬删除标记为 `pending-deletion` 且经使用预言机确认未被使用的 tag(受 `HOUBA_PURGE_MIN_IDLE_DAYS` 限制;除非使用 `--apply`,否则为 dry-run)。 - **`houba attach --report `** —— 摄取上游扫描报告(例如 SARIF)并将其作为打标的 OCI referrer 附加到镜像上。 请参阅 [路线图](docs/roadmap.md) 了解已构建与计划中的内容,以及 [设计概述](docs/architecture/design.md) 了解其架构。 ### 作为部署运行 **参考部署**将 houba 作为 Kubernetes CronJob 运行(通过 git-sync 同步的策略、无 root 权限的 buildkitd、一个影响范围消费者)——相同的 `deploy/` 清单既可用于本地 kind 演示,也可用作生产蓝图。最快的体验方式: ``` make demo-lite # kind up, reconcile the busybox example, print blast radius ``` 请参阅 [docs/runbooks/reference-deployment.md](docs/runbooks/reference-deployment.md)。 ## 快速开始 ### 安装 `houba` 以 Docker 镜像的形式发布,其中捆绑了 `regctl`、BuildKit (`buildctl`) 以及 Python CLI 本身: ``` docker pull ghcr.io//houba:0.4 ``` (运行时镜像还捆绑了 `cosign`,用于可选的签名证明。) 或者使用 [uv](https://github.com/astral-sh/uv) 从源码运行: ``` git clone https://github.com//houba.git cd houba uv sync uv run houba --help ``` 从源码运行时,您需要在 `PATH` 中包含 `regctl`(如果使用重建路径,还需要 `buildctl`)。 ### 配置 `houba` 从环境变量(12-factor)中读取其配置。所有变量均使用 `HOUBA_*` 作为命名空间。 | 变量 | 必需 | 默认值 | 描述 | |---|---|---|---| | `HOUBA_REGISTRIES` | 是¹ | `{}` | 逻辑 registry 名称到 `RegistryConfig` 的 JSON 映射(源和目标 registry;见下文)。 | | `HOUBA_LABEL_PREFIX` | 否 | `io.houba` | houba 自身来源注解的前缀(为空 ⇒ 无 houba 标签)。 | | `HOUBA_BUILD_PLATFORM` | 否 | `linux/amd64` | 重建路径的平台(单平台)。 | | `HOUBA_MAX_CONCURRENCY` | 否 | `4` | 每次运行的最大并行 tag 操作数(`1` = 顺序执行)。可通过 `--concurrency` / `-j` 覆盖。 | | `HOUBA_WORK_DIR` | 否 | `/tmp/houba-work` | 用于构建上下文的临时目录。 | | `HOUBA_TRANSFORM_CA_CERTS` | 否 | `{}` | 名称到 CA 源的 JSON 映射,由 `injectCA` 转换解析。 | | `HOUBA_TRANSFORM_PACKAGE_MIRRORS` | 否 | `{}` | 名称到包镜像源的 JSON 映射,由 `rewritePackageSources` 解析。 | | `HOUBA_ATTEST_SIGNER` | 否 | `""` | `""` (关闭) / `keyless` / `kms` / `key` —— 在重建路径上启用签名的 SLSA 证明。`kms`/`key` 还需要 `HOUBA_ATTEST_KEY_REF`;keyless 使用 `HOUBA_ATTEST_FULCIO_URL` / `_REKOR_URL`。 | | `HOUBA_PURGE_MIN_IDLE_DAYS` | 否 | _未设置_ | `houba purge` 在清理已标记的 tag 之前要求的空闲窗口期(运行 `purge` 必需)。 | | `HOUBA_LOG_FORMAT` | 否 | `text` | `text` 或 `json`。 | | `HOUBA_LOG_LEVEL` | 否 | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR`。 | | `HOUBA_DRY_RUN_TAGS` | 否 | `false` | 跳过镜像复制 / 推送。 | | `HOUBA_DRY_RUN_DELETIONS` | 否 | `false` | 跳过删除操作。 | ¹ 默认为空,但必须至少配置一个 registry 才能协调任何内容。 **`RegistryConfig` 字段**(`HOUBA_REGISTRIES` 中的每个条目): | 字段 | 必需 | 描述 | |---|---|---| | `host` | 是 | registry 主机,例如 `harbor.example.com` 或 `localhost:5001`。 | | `username` | 否 | registry 用户名(必须与 `password` 一起设置)。 | | `password` | 否 | registry 密码(必须与 `username` 一起设置)。 | | `tls_verify` | 否 | 对于纯 HTTP 的 registry 设置为 `false`(默认为 `true`);houba 会自动运行 `regctl registry set … --tls disabled`。 | | `ca_cert` | 否 | `regctl` 在为此 registry 进行 TLS 连接时应信任的 CA PEM 文件的路径(位于内部 CA 之后的 registry)。 | ### 尝试一下 可运行的 `MirrorPolicy` 演示位于 [`docs/examples/`](docs/examples/README.md):将几个 busybox tag 镜像到本地 registry 并派生 moving-tag 别名,按 semver 选择 redis,或者将 Debian 重建为按时区区分的变体。每一个 `reconcile` 都是**计划后执行**的——请先使用 `--dry-run` 查看计划。 ## 架构 `houba` 遵循六边形架构(端口与适配器): ``` houba/ ├── domain/ pure logic — mirror_policy, selection, aliases, semver, expand, policy_merge, │ variants, reconcile, collision, sharding, stamp, attestation, coverage, │ lifecycle, purge, scan/, transforms/ ├── ports/ typing.Protocol interfaces — registry, image_builder, attestor, │ usage_oracle, reporter, clock ├── adapters/ concrete I/O — regctl_cli, buildkit_cli, cosign_cli, command_usage, │ structlog_reporter, system_clock ├── use_cases/ orchestration — loader, reconcile, purge, attach, audit, report └── cli/ Typer entry points — reconcile, purge, attach, audit, version ``` **黄金法则** - `domain/` 永远不导入 I/O(没有 `httpx`,没有 `subprocess`,没有 `os.environ`,没有时钟)。 - `use_cases/` 通过注入接收端口;它们永远不导入适配器。 - `cli/` 解析参数并将异常映射到退出代码;其他所有操作均被委派。 - 环境变量仅在 `houba/config.py` 内部读取。 当前的适配器均通过 `subprocess`(`regctl`, `buildctl`)或使用标准库向外调用—— 没有 HTTP 客户端。这使得业务逻辑可以通过内存中的模拟对象(`tests/fakes/*`)实现 100% 的单元测试覆盖率,并且适配器可以使用 fake-bin shell 脚本进行隔离的集成测试。 完整的全貌——以及 C4 模型——位于 [`docs/architecture/`](docs/architecture/design.md) 中。 ## 开发 ``` uv sync # install deps uv run pytest # full suite uv run pytest tests/unit/domain --cov=houba.domain --cov-fail-under=90 uv run ruff check . && uv run ruff format --check . uv run mypy houba docker build -t houba:dev . # build the runtime image ``` CI 中强制执行的覆盖率门禁:**全局 ≥ 80%**,**`houba.domain` ≥ 90%**。 ## 许可证 Apache License 2.0 —— 详见 [LICENSE](LICENSE)。 版权所有 2026 Tristan Rivoallan 及其贡献者。
标签:DevSecOps, Python, 上游代理, 子域名突变, 安全合规, 容器镜像, 无后门, 网络代理, 请求拦截, 软件物料清单(SBOM), 逆向工具