mirror of
https://github.com/xcat2/xcat-dep.git
synced 2026-09-12 12:36:23 +00:00
fix(build): repo gate signature must strictly match the CLI key; document gate in BUILD.md
Per review of the gate design: - Signature: fail (SIGKEY) if --gpg-key-name cannot be resolved to a fingerprint, so the gate always confirms the repo was signed by EXACTLY the CLI key -- never a soft pass. (EL already dies loudly on a duplicate rpm version via rpm_version; Ubuntu now matches.) - Document the gate + its intentional idiosyncrasies (what 'the repo' is, duplicate=hard error, signature identity) in BUILD.md. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
@@ -320,6 +320,35 @@ prove t/ # or: perl t/mockbuild-all.t
|
||||
The RPM-identity / `cross_copy_genesis` cases build tiny fixture rpms and are skipped
|
||||
automatically if `rpmbuild` is unavailable.
|
||||
|
||||
# Repository verification gate
|
||||
|
||||
After each per-target repo is built + signed, `mockbuild-all.pl` runs a **manifest-driven gate** that
|
||||
fails the build if the published repo is incomplete or mis-signed. It uses `packages-manifest.conf` as
|
||||
the single source of truth and is layered so the decision logic is pure and unit-tested
|
||||
(`MockBuildUtils::verify_repo_packages` / `verify_repo_signature`), separate from the disk/gpg I/O.
|
||||
|
||||
- **Runs automatically** at the end of `deploy_target` (per `rh<N>/<arch>` cell). Suppress with
|
||||
`--no-verify-repo`. Verify an already-built repo out of band with `--verify-repo=<repo>`
|
||||
(target derived from the `rh<N>/<arch>` path, or pass `--target`; manifest from `<repo-root>/
|
||||
packages-manifest.conf`; key/home from `--gpg-key-name`/`--gpg-home`).
|
||||
- **Completeness:** every package the target's manifest section requires (after `required_pkgs`
|
||||
skip-filtering) must be present with a version satisfying its pin.
|
||||
- **Signature:** the repo's `repodata/repomd.xml.asc` must be a *good* signature whose **primary-key
|
||||
fingerprint equals the fingerprint of `--gpg-key-name`** — i.e. the repo was signed by exactly the
|
||||
CLI key. Expired/revoked keys and expired signatures are rejected (not just `VALIDSIG`). If the CLI
|
||||
key cannot be resolved to a fingerprint (not in the keyring) the gate fails (`SIGKEY`), never passes.
|
||||
|
||||
**Semantic idiosyncrasies (intentional, and mirrored in the Ubuntu `sbuild-all.pl` gate):**
|
||||
|
||||
- **What "the repo" is:** the EL gate reads the **binary rpm files** in the per-target dir (via
|
||||
`rpm_version`); the Ubuntu gate reads the **published `binary-<arch>/Packages` index**. Both check
|
||||
the artifact that ships; they differ only in the RHEL-vs-Debian notion of "the repository".
|
||||
- **Duplicate = hard error:** if a required package appears with **two distinct versions** (a stale
|
||||
artifact not cleaned before the build), the gate **dies loudly** rather than silently picking one —
|
||||
identical on both EL (`rpm_version`) and Ubuntu (`parse_packages_index`).
|
||||
- **Version pins** are the manifest's *upstream* version; the Debian gate strips the epoch/revision
|
||||
(`deb_upstream_version`) before comparing, the EL gate compares `%{version}` directly.
|
||||
|
||||
# References
|
||||
|
||||
- [mock project repository](https://github.com/rpm-software-management/mock)
|
||||
|
||||
+12
-5
@@ -1168,11 +1168,18 @@ sub verify_target_repo {
|
||||
# Skipped with a printed note only when no gpg key/home is configured (nothing to check against).
|
||||
if ($gpg_sign || $gpg_home ne '') {
|
||||
require_command('gpg');
|
||||
my $repomd = "$dir/repodata/repomd.xml";
|
||||
my $asc = "$repomd.asc";
|
||||
my %exp_sig = ('repomd' => gpg_key_fingerprint($gpg_key_name, $gpg_home));
|
||||
my %obs_sig = ('repomd' => repomd_observed_signer($asc, $repomd, $gpg_home));
|
||||
push @problems, verify_repo_signature(\%exp_sig, \%obs_sig);
|
||||
my $repomd = "$dir/repodata/repomd.xml";
|
||||
my $asc = "$repomd.asc";
|
||||
my $exp_fpr = gpg_key_fingerprint($gpg_key_name, $gpg_home);
|
||||
# STRICT: the CLI key MUST resolve to a fingerprint so we can confirm it signed the repo. If it
|
||||
# does not (not in the keyring), we cannot verify -> hard fail, never a presence-only pass.
|
||||
if ($exp_fpr !~ /^[0-9A-Fa-f]{16,}$/) {
|
||||
push @problems, "SIGKEY: cannot resolve --gpg-key-name '$gpg_key_name' to a fingerprint (in the $gpg_home keyring?)";
|
||||
} else {
|
||||
my %exp_sig = ('repomd' => $exp_fpr);
|
||||
my %obs_sig = ('repomd' => repomd_observed_signer($asc, $repomd, $gpg_home));
|
||||
push @problems, verify_repo_signature(\%exp_sig, \%obs_sig);
|
||||
}
|
||||
} else {
|
||||
print "[verify-repo] $tgt: no gpg key/home configured -- skipping repomd signature check\n";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user