blob: 2cfb2d78b679b76bed1cc2a2088c6028750e40ba [file] [view] [edit]
# LibJWT CI base image
`ghcr.io/benmcollins/libjwt/gnutls-leancrypto-mbedtls`
A `debian:forky` image with every LibJWT crypto/JSON backend usable in one
place, built so the **GnuTLS ML-DSA success path actually works** and the
**latest MbedTLS 3.6.x LTS** is present - neither of which forky's stock apt
packages provide.
| Component | Source | Notes |
|-----------|--------|-------|
| OpenSSL | forky apt (`libssl-dev`) | 3.6.x >= 3.5, so the OpenSSL ML-DSA path works |
| GnuTLS | **from source** `--with-leancrypto` | ML-DSA (FIPS 204 / RFC 9964, `kty="AKP"`) success path; stock GnuTLS returns `-106` |
| leancrypto | **from source** | the PQC provider GnuTLS statically links against |
| MbedTLS | **from source**, 3.6.x LTS | the tested baseline; the PSA-based backend also builds against MbedTLS 4.x |
| jansson + json-c | forky apt | both JSON backends installed, either selectable |
| libcurl, check, bats, jq, lcov, valgrind | forky apt | build + test + coverage + memcheck tooling |
Only the three components that genuinely need a custom/newer build are compiled
from source (into `/usr/local`); every build-dependency comes from native
Debian apt. `libgnutls28-dev` / `libmbedtls-dev` are deliberately **not**
installed so their apt `.pc` files cannot shadow the from-source ones.
## Pinned versions
Set via `ARG` in the [`Dockerfile`](./Dockerfile) - bump these for a respin:
```dockerfile
ARG LEANCRYPTO_VERSION=v1.7.2
ARG GNUTLS_VERSION=3.8.13 # >= 3.8.10 enables ML-DSA
ARG GNUTLS_SERIES=v3.8 # keep in sync with GNUTLS_VERSION's major.minor
ARG MBEDTLS_VERSION=3.6.6 # 3.6.x LTS baseline (4.x also builds)
```
The final layer of the Dockerfile asserts these guarantees (pkg-config floors,
`/usr/local` precedence, and a live `certtool` ML-DSA key-gen proving the
leancrypto provider is wired in), so a bad respin fails the build instead of
publishing a silently broken image.
## Respinning the image
Automatically, via the [`ci-image.yml`](../workflows/ci-image.yml) workflow:
- It runs on **`workflow_dispatch`** (Actions -> *Build CI Base Image* -> *Run
workflow*) and on pushes to `master` that touch the `Dockerfile` or that
workflow.
- It pushes `:latest`, `:forky`, and `:<sha>` tags to GHCR using the built-in
`GITHUB_TOKEN` (no secrets to manage).
Locally:
```bash
docker build -f .github/docker/Dockerfile \
-t ghcr.io/benmcollins/libjwt/gnutls-leancrypto-mbedtls:latest .
```
## Using it
The image bakes in the full toolchain, so a consuming CI job just builds:
```bash
cmake -B build -DWITH_OPENSSL=ON -DWITH_GNUTLS=ON -DWITH_MBEDTLS=ON \
-DWITH_ML_DSA=ON -DWITH_LIBCURL=YES
cmake --build build -- all
ctest --test-dir build --output-on-failure
```
> The package must be **public** (Packages -> settings -> *Change visibility*)
> for `container:` jobs to pull it without a `credentials:` block.