diff options
| author | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-02-09 03:19:29 +0000 |
|---|---|---|
| committer | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-02-09 03:34:12 +0000 |
| commit | ff406688aef6eb0e89cfcb6698734a7e9e1e001c (patch) | |
| tree | 116acc2dd06fd116d4d6f13ee91bcf81a8013bca /recipes-containers | |
| parent | d04103169c462913a68e7346e4f78682b74d93f0 (diff) | |
| download | meta-virtualization-ff406688aef6eb0e89cfcb6698734a7e9e1e001c.tar.gz | |
container-registry: add tests and documentation for secure registry
Add comprehensive test coverage and documentation for the secure
registry infrastructure.
Tests added:
TestRegistryAuthentication - auth modes (none, home, authfile,
credsfile, env, creds, token) for push and import
TestSecureRegistryTLSOnly - TLS-only mode using running registry
TestSecureRegistryWithAuth - isolated TLS+auth instance on port 5001
TestDockerRegistryConfig - static analysis of bbclass/recipe logic
TestContainerCrossInstallSecure - auto IMAGE_INSTALL verification
TestVcontainerSecureRegistry - script pattern verification for
virtio-9p CA transport, daemon _9p=1, shared folder reads
README.md: Document authentication modes (none, home, authfile,
credsfile, env), secure registry setup, PKI generation, target
integration, and CI/CD examples.
conftest.py: Add --secure-registry pytest option and skip_secure
fixture for tests requiring openssl/htpasswd.
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'recipes-containers')
| -rw-r--r-- | recipes-containers/container-registry/README.md | 245 |
1 files changed, 244 insertions, 1 deletions
diff --git a/recipes-containers/container-registry/README.md b/recipes-containers/container-registry/README.md index 1a0f74eb..470442b9 100644 --- a/recipes-containers/container-registry/README.md +++ b/recipes-containers/container-registry/README.md | |||
| @@ -171,6 +171,247 @@ DOCKER_REGISTRY_INSECURE = "localhost:5000" | |||
| 171 | CONTAINER_REGISTRY_STORAGE = "/data/container-registry" | 171 | CONTAINER_REGISTRY_STORAGE = "/data/container-registry" |
| 172 | ``` | 172 | ``` |
| 173 | 173 | ||
| 174 | ## Authentication | ||
| 175 | |||
| 176 | Support for pushing to authenticated registries (Docker Hub, GitHub Container Registry, private registries). | ||
| 177 | |||
| 178 | ### Authentication Modes | ||
| 179 | |||
| 180 | | Mode | BitBake | Script | Description | | ||
| 181 | |------|---------|--------|-------------| | ||
| 182 | | `none` | Yes | Yes | No authentication (default, local registries) | | ||
| 183 | | `home` | Yes | Yes | Use `~/.docker/config.json` (opt-in) | | ||
| 184 | | `authfile` | Yes | Yes | Explicit Docker-style config.json path | | ||
| 185 | | `credsfile` | Yes | Yes | Simple key=value credentials file | | ||
| 186 | | `env` | No | Yes | Environment variables (script only) | | ||
| 187 | |||
| 188 | ### BitBake Configuration | ||
| 189 | |||
| 190 | ```bitbake | ||
| 191 | # Authentication mode | ||
| 192 | CONTAINER_REGISTRY_AUTH_MODE = "none" # Default, no auth | ||
| 193 | CONTAINER_REGISTRY_AUTH_MODE = "home" # Use ~/.docker/config.json | ||
| 194 | CONTAINER_REGISTRY_AUTH_MODE = "authfile" # Explicit auth file | ||
| 195 | CONTAINER_REGISTRY_AUTH_MODE = "credsfile" # Simple credentials file | ||
| 196 | |||
| 197 | # For authfile mode | ||
| 198 | CONTAINER_REGISTRY_AUTHFILE = "/path/to/docker-config.json" | ||
| 199 | |||
| 200 | # For credsfile mode | ||
| 201 | CONTAINER_REGISTRY_CREDSFILE = "${HOME}/.config/container-registry/credentials" | ||
| 202 | ``` | ||
| 203 | |||
| 204 | ### Script Options | ||
| 205 | |||
| 206 | ```bash | ||
| 207 | # Use existing Docker login (~/.docker/config.json) | ||
| 208 | container-registry.sh push --use-home-auth | ||
| 209 | |||
| 210 | # Explicit auth file | ||
| 211 | container-registry.sh push --authfile /path/to/docker-config.json | ||
| 212 | |||
| 213 | # Simple credentials file | ||
| 214 | container-registry.sh push --credsfile ~/.config/container-registry/credentials | ||
| 215 | |||
| 216 | # Environment variables | ||
| 217 | export CONTAINER_REGISTRY_AUTH_MODE=env | ||
| 218 | export CONTAINER_REGISTRY_TOKEN=ghp_xxxxx | ||
| 219 | container-registry.sh push | ||
| 220 | |||
| 221 | # Direct credentials (less secure - in shell history) | ||
| 222 | container-registry.sh push --creds user:password | ||
| 223 | container-registry.sh push --token ghp_xxxxx | ||
| 224 | |||
| 225 | # Import from authenticated source registry | ||
| 226 | container-registry.sh import ghcr.io/org/private:v1 --src-authfile ~/.docker/config.json | ||
| 227 | container-registry.sh import ghcr.io/org/private:v1 --src-credsfile ~/.config/ghcr-creds | ||
| 228 | ``` | ||
| 229 | |||
| 230 | ### Credentials File Format | ||
| 231 | |||
| 232 | Simple key=value format (not checked into source control): | ||
| 233 | |||
| 234 | ```bash | ||
| 235 | # ~/.config/container-registry/credentials | ||
| 236 | # Username/password OR token (token takes precedence) | ||
| 237 | CONTAINER_REGISTRY_USER=myuser | ||
| 238 | CONTAINER_REGISTRY_PASSWORD=mypassword | ||
| 239 | |||
| 240 | # Or for token-based auth (GitHub, GitLab, etc.): | ||
| 241 | CONTAINER_REGISTRY_TOKEN=ghp_xxxxxxxxxxxx | ||
| 242 | ``` | ||
| 243 | |||
| 244 | Create with proper permissions: | ||
| 245 | ```bash | ||
| 246 | mkdir -p ~/.config/container-registry | ||
| 247 | cat > ~/.config/container-registry/credentials << 'EOF' | ||
| 248 | CONTAINER_REGISTRY_TOKEN=ghp_xxxxxxxxxxxx | ||
| 249 | EOF | ||
| 250 | chmod 600 ~/.config/container-registry/credentials | ||
| 251 | ``` | ||
| 252 | |||
| 253 | ### CI/CD Integration | ||
| 254 | |||
| 255 | For CI/CD with BitBake, use `credsfile` mode and have CI write the credentials file: | ||
| 256 | |||
| 257 | ```yaml | ||
| 258 | # Example GitHub Actions | ||
| 259 | - name: Setup registry credentials | ||
| 260 | run: | | ||
| 261 | mkdir -p ~/.config/container-registry | ||
| 262 | echo "CONTAINER_REGISTRY_TOKEN=${{ secrets.GHCR_TOKEN }}" > ~/.config/container-registry/credentials | ||
| 263 | chmod 600 ~/.config/container-registry/credentials | ||
| 264 | |||
| 265 | - name: Build and push | ||
| 266 | run: | | ||
| 267 | bitbake container-base | ||
| 268 | ./container-registry/container-registry.sh push --credsfile ~/.config/container-registry/credentials | ||
| 269 | ``` | ||
| 270 | |||
| 271 | For script-only usage, environment variables are simpler: | ||
| 272 | |||
| 273 | ```yaml | ||
| 274 | - name: Push to registry | ||
| 275 | env: | ||
| 276 | CONTAINER_REGISTRY_AUTH_MODE: env | ||
| 277 | CONTAINER_REGISTRY_TOKEN: ${{ secrets.GHCR_TOKEN }} | ||
| 278 | run: ./container-registry/container-registry.sh push | ||
| 279 | ``` | ||
| 280 | |||
| 281 | ### Security Notes | ||
| 282 | |||
| 283 | - **No credentials in BitBake variables**: Like git fetcher, avoid passwords in metadata that gets logged/shared | ||
| 284 | - **Use file-based auth**: Credentials files can be excluded from version control and have proper permissions | ||
| 285 | - **Opt-in for home directory**: `home` mode requires explicit opt-in (like `BB_USE_HOME_NPMRC`) | ||
| 286 | - **Prefer tokens over passwords**: Tokens can be scoped and revoked | ||
| 287 | |||
| 288 | ## Secure Registry Mode | ||
| 289 | |||
| 290 | Enable TLS and authentication for the local registry (opt-in). | ||
| 291 | |||
| 292 | ### Configuration | ||
| 293 | |||
| 294 | ```bitbake | ||
| 295 | # Enable secure mode | ||
| 296 | CONTAINER_REGISTRY_SECURE = "1" | ||
| 297 | |||
| 298 | # Optional: custom username (default: yocto) | ||
| 299 | CONTAINER_REGISTRY_USERNAME = "myuser" | ||
| 300 | |||
| 301 | # Optional: explicit password (default: auto-generate) | ||
| 302 | CONTAINER_REGISTRY_PASSWORD = "mypassword" | ||
| 303 | |||
| 304 | # Optional: certificate validity (days) | ||
| 305 | CONTAINER_REGISTRY_CERT_DAYS = "365" # Server cert | ||
| 306 | CONTAINER_REGISTRY_CA_DAYS = "3650" # CA cert (10 years) | ||
| 307 | |||
| 308 | # Optional: additional SAN entries for server cert | ||
| 309 | CONTAINER_REGISTRY_CERT_SAN = "DNS:myhost.local,IP:192.168.1.100" | ||
| 310 | ``` | ||
| 311 | |||
| 312 | ### Setup | ||
| 313 | |||
| 314 | PKI (CA and server certificates) is auto-generated during the bitbake build: | ||
| 315 | |||
| 316 | ```bash | ||
| 317 | # Generate script AND PKI infrastructure | ||
| 318 | bitbake container-registry-index -c generate_registry_script | ||
| 319 | |||
| 320 | # Build target image (CA cert is automatically baked in) | ||
| 321 | bitbake container-image-host | ||
| 322 | ``` | ||
| 323 | |||
| 324 | The `generate_registry_script` task automatically generates the PKI if it doesn't exist. No manual steps required. | ||
| 325 | |||
| 326 | ### Starting the Registry | ||
| 327 | |||
| 328 | To actually run the registry (for pushing/pulling images): | ||
| 329 | |||
| 330 | ```bash | ||
| 331 | # Start registry (generates htpasswd auth on first run) | ||
| 332 | ./container-registry/container-registry.sh start | ||
| 333 | ``` | ||
| 334 | |||
| 335 | Output: | ||
| 336 | ``` | ||
| 337 | Setting up authentication... | ||
| 338 | Password saved to: .../auth/password | ||
| 339 | Starting SECURE container registry... | ||
| 340 | URL: https://localhost:5000 | ||
| 341 | ``` | ||
| 342 | |||
| 343 | ### Generated Files | ||
| 344 | |||
| 345 | ``` | ||
| 346 | ${CONTAINER_REGISTRY_STORAGE}/ | ||
| 347 | ├── pki/ # Generated by: bitbake ... -c generate_registry_script | ||
| 348 | │ ├── ca.key # CA private key (600) | ||
| 349 | │ ├── ca.crt # CA certificate - baked into target images | ||
| 350 | │ ├── server.key # Server private key (600) | ||
| 351 | │ └── server.crt # Server certificate with SAN | ||
| 352 | ├── auth/ # Generated by: container-registry.sh start | ||
| 353 | │ ├── htpasswd # Bcrypt credentials for registry | ||
| 354 | │ └── password # Plaintext password for reference (600) | ||
| 355 | └── ... | ||
| 356 | ``` | ||
| 357 | |||
| 358 | ### Push (auto-uses credentials) | ||
| 359 | |||
| 360 | ```bash | ||
| 361 | ./container-registry/container-registry.sh push | ||
| 362 | # Automatically uses: | ||
| 363 | # --dest-cert-dir=.../pki | ||
| 364 | # --dest-creds=yocto:<auto-password> | ||
| 365 | ``` | ||
| 366 | |||
| 367 | ### Target Integration | ||
| 368 | |||
| 369 | Install CA certificate on target images: | ||
| 370 | |||
| 371 | ```bitbake | ||
| 372 | # Automatically included when CONTAINER_REGISTRY_SECURE = "1" | ||
| 373 | # and IMAGE_FEATURES:append = " container-registry" | ||
| 374 | IMAGE_INSTALL:append = " container-registry-ca" | ||
| 375 | ``` | ||
| 376 | |||
| 377 | This installs CA cert to: | ||
| 378 | - `/etc/docker/certs.d/{registry}/ca.crt` (Docker) | ||
| 379 | - `/etc/containers/certs.d/{registry}/ca.crt` (Podman/CRI-O) | ||
| 380 | - `/usr/local/share/ca-certificates/container-registry-ca.crt` (system) | ||
| 381 | |||
| 382 | ### vdkr with Secure Registry | ||
| 383 | |||
| 384 | ```bash | ||
| 385 | # Pass secure mode and CA cert to VM | ||
| 386 | vdkr --secure-registry --ca-cert $STORAGE/pki/ca.crt pull myimage | ||
| 387 | |||
| 388 | # Or with credentials | ||
| 389 | vdkr --secure-registry --ca-cert $STORAGE/pki/ca.crt \ | ||
| 390 | --registry-user yocto --registry-password mypass pull myimage | ||
| 391 | ``` | ||
| 392 | |||
| 393 | ### Verification | ||
| 394 | |||
| 395 | ```bash | ||
| 396 | # Verify TLS with curl | ||
| 397 | curl --cacert $STORAGE/pki/ca.crt \ | ||
| 398 | -u yocto:$(cat $STORAGE/auth/password) \ | ||
| 399 | https://localhost:5000/v2/_catalog | ||
| 400 | |||
| 401 | # Check server certificate SAN | ||
| 402 | openssl x509 -in $STORAGE/pki/server.crt -noout -text | grep -A1 "Subject Alternative Name" | ||
| 403 | ``` | ||
| 404 | |||
| 405 | ### Secure Mode vs Insecure Mode | ||
| 406 | |||
| 407 | | Feature | Insecure (`SECURE=0`) | Secure (`SECURE=1`) | | ||
| 408 | |---------|----------------------|---------------------| | ||
| 409 | | Protocol | HTTP | HTTPS | | ||
| 410 | | TLS | None | Self-signed CA + server cert | | ||
| 411 | | Auth | Optional | Required (htpasswd) | | ||
| 412 | | Target config | `insecure-registries` | CA cert distribution | | ||
| 413 | | Skopeo args | `--dest-tls-verify=false` | `--dest-cert-dir` | | ||
| 414 | |||
| 174 | ## vdkr Registry Usage | 415 | ## vdkr Registry Usage |
| 175 | 416 | ||
| 176 | ### Pull Behavior with Registry Fallback | 417 | ### Pull Behavior with Registry Fallback |
| @@ -233,9 +474,11 @@ This installs: | |||
| 233 | |------|-------------| | 474 | |------|-------------| |
| 234 | | `container-registry-index.bb` | Generates helper script with baked-in paths | | 475 | | `container-registry-index.bb` | Generates helper script with baked-in paths | |
| 235 | | `container-registry-populate.bb` | Alternative bitbake-driven push | | 476 | | `container-registry-populate.bb` | Alternative bitbake-driven push | |
| 477 | | `container-registry-ca.bb` | Target package for CA certificate (secure mode) | | ||
| 236 | | `container-oci-registry-config.bb` | OCI tools config (Podman/Skopeo/Buildah/CRI-O) | | 478 | | `container-oci-registry-config.bb` | OCI tools config (Podman/Skopeo/Buildah/CRI-O) | |
| 237 | | `docker-registry-config.bb` | Docker daemon config | | 479 | | `docker-registry-config.bb` | Docker daemon config | |
| 238 | | `files/container-registry-dev.yml` | Development registry config | | 480 | | `files/container-registry-dev.yml` | Development registry config (HTTP) | |
| 481 | | `files/container-registry-secure.yml` | Secure registry config template (HTTPS+auth) | | ||
| 239 | 482 | ||
| 240 | ## Storage | 483 | ## Storage |
| 241 | 484 | ||
