91 lines
5.6 KiB
Markdown
91 lines
5.6 KiB
Markdown
# Staged Docker repository authentication
|
|
|
|
`deployctl verify-repository` accepts strict JSON with `directory` (absolute trusted
|
|
staging directory), `suite`, `architecture`, and `versions` (exact version strings
|
|
for docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin and
|
|
docker-compose-plugin). It does not select a latest version or resolve dependencies.
|
|
|
|
The directory must contain `docker.asc`, `Release`, `Release.gpg` and uncompressed
|
|
`Packages`. The caller obtains these from the Docker Ubuntu repository. No runtime
|
|
network request is performed by this command. Limits are 1 MiB, 1 MiB, 64 KiB and
|
|
16 MiB respectively. Files must be nonempty regular files; symlinks are rejected.
|
|
Trusted ancestors and absence of concurrent writers are required. This is not an
|
|
atomic filesystem snapshot against hostile writers. Additional staging files are
|
|
ignored, never executed.
|
|
|
|
## Trust and verification
|
|
|
|
1. Exact armored key SHA-256 is pinned in source. Initial trust was bootstrapped
|
|
from `https://download.docker.com/linux/ubuntu/gpg`, not supplied by the request.
|
|
Primary fingerprint: `9DC858229FC7DD38854AE2D88D81803C0EBFCD88`.
|
|
Rotation or formatting changes require a reviewed source update; fail closed.
|
|
2. Linux `/usr/bin/gpg` dearmors into a new private temporary directory; `/usr/bin/gpgv`
|
|
verifies the detached signature against the copied Release bytes, with that
|
|
keyring and isolated homedir. No shell, ambient GnuPG config or personal keyring.
|
|
Each child has a 15-second timeout and bounded output. Errors do not expose raw
|
|
GnuPG diagnostics or metadata. Non-Linux or missing tools fail closed.
|
|
3. Successful process exit and a single accepted primary-fingerprint signature
|
|
are required; weak digests, expired/revoked/bad signatures and unknown status
|
|
types fail closed. SHA-256/384/512 are accepted.
|
|
4. Authenticated Release must describe Docker CE and the requested supported Ubuntu
|
|
suite, architecture and stable component. Date must be within 30 days and no
|
|
more than 10 minutes in the future; Valid-Until is enforced when present.
|
|
5. The exact uncompressed stable Packages entry's SHA-256 and byte size must match.
|
|
Five explicitly requested versions are resolved to authenticated index records;
|
|
the derived lock is checked by installplan's source/path/version constraints.
|
|
|
|
The machine clock, OS and installed GnuPG are trusted. This is not a persistent
|
|
anti-rollback ledger: an older authentic Release inside the freshness window can
|
|
pass, and a missing Valid-Until is governed by the local 30-day policy. No online
|
|
key revocation lookup is performed. Key pin maintenance is an operator responsibility.
|
|
|
|
## Result boundaries
|
|
|
|
`repositoryAuthenticated: true` attests to these metadata bytes at `verifiedAt`.
|
|
For `verify-repository`, `packageBytesVerified: false` and `executable: false` remain explicit: no deb bytes,
|
|
Ubuntu dependency repository, dependency closure, installation scripts, system
|
|
compatibility or service behavior have been verified. The result is not a signed
|
|
capability. `plan-environment` still treats a supplied lock as untrusted and does
|
|
not accept a caller's authentication claim to clear its trust blockers.
|
|
|
|
Signature scratch data is removed on normal return; a killed process can leave its own
|
|
private temporary directory. Deployment writes remain disabled. `writesEnabled`
|
|
in `version` refers to deployment writes, not verification scratch files.
|
|
|
|
`scripts/probe-docker-repository.sh /absolute/path/to/deployctl` is an optional
|
|
local online integration check. It downloads public metadata over HTTPS into a
|
|
new temporary directory, tests real authentication and rejects tampering. Versions
|
|
selected by this test are fixtures, not recommended installation versions. It
|
|
does not install packages, alter APT, use SSH or touch application data.
|
|
|
|
## Verify actual deb bytes
|
|
|
|
`verify-artifacts` requires the same request fields as `verify-repository`, plus
|
|
`artifactDirectory`: an absolute trusted directory containing exactly the five deb
|
|
files named by the basename of each authenticated `Filename`. No other entries,
|
|
subdirectories, symlinks or special files are accepted. The two directories must
|
|
not be concurrently modified. Repository signatures and metadata are verified
|
|
anew in the same call; the command accepts neither a supplied lock nor trust flags.
|
|
|
|
Each file is streamed through SHA-256 with a 64 KiB copy buffer and its signed
|
|
index size as the read bound (plus one overflow-detection byte). The existing
|
|
lock policy caps each file at 512 MiB and requires exactly five files. A last-file
|
|
failure rejects the entire result. No partial successful report is emitted.
|
|
The verifier never unpacks a deb or executes its contents. It does not change
|
|
the staged files. Metadata identity checks supplement, not replace, the trusted
|
|
directory/no concurrent writer requirement.
|
|
|
|
Only `verify-artifacts` may set `packageBytesVerified: true`; `executable` stays
|
|
false. This verifies the selected five Docker package bytes, not the complete
|
|
Ubuntu dependency closure, package-internal safety or installation compatibility.
|
|
It is a point-in-time observation: do not reuse this JSON to authorize later
|
|
execution of paths that may have changed. A future installer must recheck or
|
|
own immutable verified snapshots under its operation lock.
|
|
|
|
Set `DEPLOYCTL_ONLINE_ARTIFACT_PROBE=1` along with
|
|
`DEPLOYCTL_ONLINE_REPOSITORY_PROBE=1` when running `scripts/verify-linux.sh` to
|
|
also download the five real public deb fixtures into a new local temporary
|
|
directory. The optional probe verifies all files, then changes one byte without
|
|
changing length and asserts rejection. It retains test files for inspection;
|
|
they are not installed and one is intentionally damaged by the negative test.
|