This setting controls whether we'll fetch GPG keys remotely or not.
We disable it by default so that we only rely on locally available GPG
keys for checking package and repository metadata signatures.
This new setting only affects dnf/zypper based distributions as apt
and pacman do not support retrieving GPG keys remotely in the first
place.
zypper does not trust GPG keys listed in gpgkey= by default so we import
local GPG keys manually with rpm to work around that.
Fixes #757
QemuKvm=yes
EOF
+ # TODO: Drop once distribution-gpg-keys is in noble-backports.
+ if [[ "${{ matrix.tools }}" =~ opensuse|fedora|ubuntu ]]; then
+ tee --append mkosi.local.conf <<EOF
+ [Distribution]
+ RepositoryKeyFetch=yes
+ EOF
+ fi
+
# TODO: Remove once all distros have recent enough systemd that knows systemd.default_device_timeout_sec.
mkdir -p mkosi-initrd/mkosi.extra/usr/lib/systemd/system.conf.d
tee mkosi-initrd/mkosi.extra/usr/lib/systemd/system.conf.d/device-timeout.conf <<EOF
"--architecture", str(config.architecture),
*(["--mirror", config.mirror] if config.mirror else []),
"--repository-key-check", str(config.repository_key_check),
+ "--repository-key-fetch", str(config.repository_key_fetch),
"--repositories", ",".join(config.repositories),
"--package-manager-tree", ",".join(str(t) for t in config.package_manager_trees),
# Note that when compress_output == Compression.none == 0 we don't pass --compress-output which means the
"--repositories", ",".join(config.tools_tree_repositories),
"--package-manager-tree", ",".join(str(t) for t in config.tools_tree_package_manager_trees),
"--repository-key-check", str(config.repository_key_check),
+ "--repository-key-fetch", str(config.repository_key_fetch),
"--cache-only", str(config.cacheonly),
*(["--output-dir", str(config.output_dir)] if config.output_dir else []),
*(["--workspace-dir", str(config.workspace_dir)] if config.workspace_dir else []),
mirror: Optional[str]
local_mirror: Optional[str]
repository_key_check: bool
+ repository_key_fetch: bool
repositories: list[str]
cacheonly: Cacheonly
package_manager_trees: list[ConfigTree]
help="Controls signature and key checks on repositories",
universal=True,
),
+ ConfigSetting(
+ dest="repository_key_fetch",
+ metavar="BOOL",
+ nargs="?",
+ section="Distribution",
+ default=False,
+ parse=config_parse_boolean,
+ help="Controls whether distribution GPG keys can be fetched remotely",
+ universal=True,
+ ),
ConfigSetting(
dest="repositories",
metavar="REPOS",
Mirror: {none_to_default(config.mirror)}
Local Mirror (build): {none_to_none(config.local_mirror)}
Repo Signature/Key check: {yes_no(config.repository_key_check)}
+ Fetch Repository Keys: {yes_no(config.repository_key_fetch)}
Repositories: {line_join_list(config.repositories)}
Use Only Package Cache: {config.cacheonly}
Package Manager Trees: {line_join_list(config.package_manager_trees)}
find_rpm_gpgkey(
context,
f"RPM-GPG-KEY-AlmaLinux-{context.config.release}",
- ) or f"https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-{context.config.release}",
+ f"https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux-{context.config.release}",
+ ),
)
@classmethod
def gpgurls(context: Context) -> tuple[str, ...]:
rel = "RPM-GPG-KEY-CentOS-Official" if context.config.release == "9" else "RPM-GPG-KEY-CentOS-Official-SHA256"
return tuple(
- find_rpm_gpgkey(context, key) or f"https://www.centos.org/keys/{key}"
+ find_rpm_gpgkey(context, key, f"https://www.centos.org/keys/{key}")
for key in (rel, "RPM-GPG-KEY-CentOS-SIG-Extras")
)
find_rpm_gpgkey(
context,
f"RPM-GPG-KEY-EPEL-{context.config.release}",
- ) or f"https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-{context.config.release}",
+ f"https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-{context.config.release}",
+ ),
)
if context.config.local_mirror:
)
for sig, components, keys in sigs:
- gpgurls = tuple(find_rpm_gpgkey(context, key) or f"https://www.centos.org/keys/{key}" for key in keys)
+ gpgurls = tuple(find_rpm_gpgkey(context, key, f"https://www.centos.org/keys/{key}") for key in keys)
for c in components:
if mirror := context.config.mirror:
@tuplify
def find_fedora_rpm_gpgkeys(context: Context) -> Iterable[str]:
- key1 = find_rpm_gpgkey(context, key=f"RPM-GPG-KEY-fedora-{context.config.release}-primary")
- key2 = find_rpm_gpgkey(context, key=f"RPM-GPG-KEY-fedora-{context.config.release}-secondary")
+ key1 = find_rpm_gpgkey(context, key=f"RPM-GPG-KEY-fedora-{context.config.release}-primary", required=False)
+ key2 = find_rpm_gpgkey(context, key=f"RPM-GPG-KEY-fedora-{context.config.release}-secondary", required=False)
if key1:
# During branching, there is always a kerfuffle with the key transition.
yield key3
yield key1
+
if key2:
yield key2
+
if not key1 and not key2:
+ if not context.config.repository_key_fetch:
+ die("Fedora GPG keys not found in /usr/share/distribution-gpg-keys",
+ hint="Make sure the distribution-gpg-keys package is installed")
+
yield "https://fedoraproject.org/fedora.gpg"
find_rpm_gpgkey(
context,
"RPM-GPG-KEY-Mageia",
- ) or "https://mirrors.kernel.org/mageia/distrib/$releasever/$basearch/media/core/release/media_info/pubkey",
+ "https://mirrors.kernel.org/mageia/distrib/$releasever/$basearch/media/core/release/media_info/pubkey",
+ ),
)
if context.config.local_mirror:
find_rpm_gpgkey(
context,
"RPM-GPG-KEY-OpenMandriva",
- ) or "https://raw.githubusercontent.com/OpenMandrivaAssociation/openmandriva-repos/master/RPM-GPG-KEY-OpenMandriva",
+ "https://raw.githubusercontent.com/OpenMandrivaAssociation/openmandriva-repos/master/RPM-GPG-KEY-OpenMandriva",
+ ),
)
if context.config.local_mirror:
mirror = context.config.mirror or "https://download.opensuse.org"
if context.config.release == "tumbleweed" or context.config.release.isdigit():
- gpgkeys = (
- *([p] if (p := find_rpm_gpgkey(context, key="RPM-GPG-KEY-openSUSE-Tumbleweed")) else []),
- *([p] if (p := find_rpm_gpgkey(context, key="RPM-GPG-KEY-openSUSE")) else []),
+ gpgkeys = tuple(
+ p
+ for key in ("RPM-GPG-KEY-openSUSE-Tumbleweed", "RPM-GPG-KEY-openSUSE")
+ if (p := find_rpm_gpgkey(context, key, required=False))
)
+ if not gpgkeys and not context.config.repository_key_fetch:
+ die("OpenSUSE GPG keys not found in /usr/share/distribution-gpg-keys",
+ hint="Make sure the distribution-gpg-keys package is installed")
+
+ if zypper and gpgkeys:
+ run(
+ ["rpm", "--root=/buildroot", "--import", *(key.removeprefix("file://") for key in gpgkeys)],
+ sandbox=context.sandbox(
+ binary="rpm",
+ mounts=[
+ Mount(context.root, "/buildroot"),
+ *finalize_crypto_mounts(context.config)
+ ],
+ )
+ )
+
if context.config.release == "tumbleweed":
if context.config.architecture == Architecture.x86_64:
subdir = ""
find_rpm_gpgkey(
context,
f"RPM-GPG-KEY-redhat{major}-release",
- ) or "https://access.redhat.com/security/data/fd431d51.txt",
+ "https://access.redhat.com/security/data/fd431d51.txt",
+ ),
)
@staticmethod
find_rpm_gpgkey(
context,
f"RPM-GPG-KEY-redhat{major}-release",
- ) or "https://access.redhat.com/security/data/fd431d51.txt",
+ "https://access.redhat.com/security/data/fd431d51.txt",
+ ),
)
@classmethod
find_rpm_gpgkey(
context,
f"RPM-GPG-KEY-Rocky-{context.config.release}",
- ) or f"https://download.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-{context.config.release}",
+ f"https://download.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-{context.config.release}",
+ ),
)
@classmethod
import subprocess
import textwrap
from pathlib import Path
-from typing import Optional
+from typing import Literal, Optional, overload
from mkosi.context import Context
+from mkosi.log import die
from mkosi.run import run
from mkosi.types import PathString
priority: Optional[int] = None
-def find_rpm_gpgkey(context: Context, key: str) -> Optional[str]:
+@overload
+def find_rpm_gpgkey(
+ context: Context,
+ key: str,
+ fallback: Optional[str] = None,
+ *,
+ required: Literal[True] = True,
+) -> str: ...
+
+
+@overload
+def find_rpm_gpgkey(
+ context: Context,
+ key: str,
+ fallback: Optional[str] = None,
+ *,
+ required: Literal[False]
+) -> Optional[str]: ...
+
+
+def find_rpm_gpgkey(
+ context: Context,
+ key: str,
+ fallback: Optional[str] = None,
+ *,
+ required: bool = True
+) -> Optional[str]:
root = context.config.tools() if context.config.tools_tree_certificates else Path("/")
if gpgpath := next((root / "usr/share/distribution-gpg-keys").rglob(key), None):
if gpgpath := next(Path(context.pkgmngr / "etc/pki/rpm-gpg").rglob(key), None):
return (Path("/") / gpgpath.relative_to(context.pkgmngr)).as_uri()
+ if context.config.repository_key_fetch:
+ return fallback
+
+ if required:
+ die(f"{key} GPG key not found in /usr/share/distribution-gpg-keys",
+ hint="Make sure the distribution-gpg-keys package is installed")
+
return None
"zypper",
"--installroot=/buildroot",
"--cache-dir=/var/cache/zypp",
- "--gpg-auto-import-keys" if context.config.repository_key_check else "--no-gpg-checks",
"--non-interactive",
"--no-refresh",
+ *(["--gpg-auto-import-keys"] if context.config.repository_key_fetch else []),
+ *(["--no-gpg-checks"] if not context.config.repository_key_check else []),
*([f"--plus-content={repo}" for repo in context.config.repositories]),
]
Useful to disable checks when combined with `--local-mirror=` and using only
a repository from a local filesystem.
+`RepositoryKeyFetch=`, `--repository-key-fetch=`
+: Controls whether mkosi will fetch distribution GPG keys remotely. Disabled
+ by default. When disabled, the distribution GPG keys for the target distribution
+ have to be installed locally on the host system alongside the package manager for
+ that distribution.
+
+ This setting is only implemented for distributions using dnf or zypper as their
+ package manager. For other distributions the distribution GPG keys are always looked
+ up locally regardless of the value of this setting. To make the distribution GPG keys
+ for distributions available without enabling this setting, the corresponding package
+ has to be installed on the host. This is usually one of `archlinux-keyring`,
+ `debian-keyring`, `ubuntu-keyring` or `distribution-gpg-keys` (for rpm-based distributions).
+
`Repositories=`, `--repositories=`
: Enable package repositories that are disabled by default. This can be used to enable the EPEL repos for
CentOS or different components of the Debian/Ubuntu repositories.
"RepartOffline": true,
"Repositories": [],
"RepositoryKeyCheck": false,
+ "RepositoryKeyFetch": true,
"RootPassword": [
"test1234",
false
repart_offline=True,
repositories=[],
repository_key_check=False,
+ repository_key_fetch=True,
root_password=("test1234", False),
root_shell="/bin/tcsh",
runtime_build_sources=True,
options=[
"--directory", "",
"--incremental=no",
+ "--repository-key-fetch=yes",
"--base-tree", Path(image.output_dir) / "image",
"--overlay",
"--package=dnsmasq",