https://github.com/trivoallan/houba
The single front door for external container images: harden, stamp, and trace every image you run.
https://github.com/trivoallan/houba
cli container-images containers devsecops golden-images harbor image-hardening oci provenance python slsa supply-chain-security
Last synced: about 1 month ago
JSON representation
The single front door for external container images: harden, stamp, and trace every image you run.
- Host: GitHub
- URL: https://github.com/trivoallan/houba
- Owner: trivoallan
- License: apache-2.0
- Created: 2026-06-11T07:20:37.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-06-11T09:06:06.000Z (about 1 month ago)
- Last Synced: 2026-06-11T09:13:53.943Z (about 1 month ago)
- Topics: cli, container-images, containers, devsecops, golden-images, harbor, image-hardening, oci, provenance, python, slsa, supply-chain-security
- Language: Python
- Homepage: https://github.com/trivoallan/houba
- Size: 255 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Roadmap: docs/roadmap.md
Awesome Lists containing this project
README
# houba
**The single front door for the external container images your organization runs.**
> **Status — early development.** Foundations and I/O adapters are in place (`v0.2`); the derive-and-stamp engine and the provenance schema are the current focus ([roadmap](docs/roadmap.md)). Not yet production-ready.
Every public image that enters your registry passes through houba: it is rebuilt with your hardening policy — internal CA certificates, internal package mirrors — and stamped with **standardized, portable provenance** (OCI annotations + SLSA attestations).
The payoff lands the morning a critical CVE drops. Because every running image carries a consistent provenance stamp, *"what's our blast radius, and who owns it?"* becomes **one query** in the observability stack you already have — not a frantic spreadsheet. houba produces the stamp; your tools (Datadog, PowerBI, Wiz…) read it.
houba is **not** an image mirror. `skopeo sync` and Harbor replication copy images byte-for-byte. houba *transforms* them and makes them *traceable*.
[](LICENSE)
[](https://www.python.org)
---
## How it works
For each image you bring in, you declare a small policy (source, tag-selection rules, hardening steps). houba then:
1. Lists tags on the source registry (via `skopeo`).
2. Selects which tags to derive — regex include/exclude filters, semver ordering, a 7-day stability window for moving digests.
3. Rebuilds each selected image through your hardening policy (via `buildctl` / BuildKit): internal CA certificates, internal package mirrors, configurable steps.
4. Stamps the result with standardized provenance (OCI annotations today; SLSA attestations on the roadmap).
5. Pushes the derived image to your registry, optionally archiving superseded tags.
6. Notifies on success / failure (Teams webhook).
See the [roadmap](docs/roadmap.md) for what is built versus planned, and the [design overview](docs/design.md) for the architecture.
---
## Quick start
### Install
`houba` is published as a Docker image bundling skopeo, BuildKit (`buildctl`), git, and the Python CLI itself:
```bash
docker pull ghcr.io//houba:v0-rc
```
Or from source with [uv](https://github.com/astral-sh/uv):
```bash
git clone https://github.com//houba.git
cd houba
uv sync
uv run houba --help
```
You still need `skopeo`, `buildctl`, and `git` on `PATH` when running from source.
### Configuration
`houba` reads its configuration from environment variables (12-factor). All variables are namespaced `HOUBA_*`.
| Variable | Required | Default | Description |
|---|---|---|---|
| `HOUBA_HARBOR_URL` | yes | — | Base URL of the Harbor instance (e.g. `https://harbor.example.com`) |
| `HOUBA_HARBOR_USER` | yes | — | Harbor robot account (e.g. `robot$houba`) |
| `HOUBA_HARBOR_PASSWORD` | yes | — | Secret token for the robot account |
| `HOUBA_HARBOR_PROJECT_DEFAULT` | no | — | Default Harbor project when not specified per-product |
| `HOUBA_GITLAB_URL` | yes | — | Base URL of the GitLab instance |
| `HOUBA_GITLAB_TOKEN` | yes | — | Personal access token (read/write API) |
| `HOUBA_GITLAB_GROUP` | yes | — | GitLab group containing per-product repositories |
| `HOUBA_TEAMS_WEBHOOK_URL` | no | — | Disables notifications when absent |
| `HOUBA_LABEL_PREFIX` | no | `io.houba` | OCI label key prefix (e.g. `org.example.mirror`) |
| `HOUBA_LOG_FORMAT` | no | `text` | `text` or `json` |
| `HOUBA_LOG_LEVEL` | no | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |
| `HOUBA_DRY_RUN_TAGS` | no | `false` | Skip image pushes |
| `HOUBA_DRY_RUN_DELETIONS` | no | `false` | Skip deletions |
| `HOUBA_WORK_DIR` | no | `/tmp/houba-work` | Scratch directory for clones/builds |
### Capture production fixtures (development)
To capture a snapshot of an existing Harbor project for use in tests:
```bash
houba dev capture --project --repository \
--output tests/fixtures/captured/
```
See [docs/runbooks/capture-fixtures.md](docs/runbooks/capture-fixtures.md).
---
## Architecture
`houba` follows hexagonal architecture (ports & adapters):
```
houba/
├── domain/ pure business logic (semver, properties, tag filter, purge, plan, labels)
├── ports/ typing.Protocol interfaces (harbor, source_registry, image_builder,
│ git_repo, gitlab, notifier, clock)
├── adapters/ concrete implementations (httpx, subprocess)
├── use_cases/ orchestration (Phase C)
└── cli/ Typer entry points
```
**Golden rules**
- `domain/` never imports I/O (no `httpx`, no `requests`, no `subprocess`).
- `use_cases/` receive ports by constructor injection; they don't import adapters.
- `cli/` does parsing only; everything else is delegated.
- Environment variables are read only inside `houba/config.py`.
This makes the business logic 100% unit-testable with in-memory fakes (`tests/fakes/*`), and the adapters integration-testable in isolation with `respx` (HTTP) or fake-bin shell scripts (CLI tools).
---
## Development
```bash
uv sync # install deps
uv run pytest # full suite
uv run pytest tests/unit/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
```
Current test coverage: **92.5 % global**, **96 % on `domain/`**.
---
## License
Apache License 2.0 — see [LICENSE](LICENSE).
Copyright 2026 Tristan Rivoallan and contributors.