diff --git a/elbepack/commands/init.py b/elbepack/commands/init.py
index b7b6e092a..94aa4ab3b 100644
--- a/elbepack/commands/init.py
+++ b/elbepack/commands/init.py
@@ -211,8 +211,10 @@ def run_command(argv):
shutil.copyfile(args[0],
os.path.join(out_path, "source.xml"))
-
keys = []
+ if xml.has('initvm/mirror/primary_key'):
+ key = xml.node('initvm/mirror/primary_key')
+ keys.append(key.et.text)
for key in xml.all(".//initvm/mirror/url-list/url/raw-key"):
keys.append(key.et.text)
diff --git a/elbepack/debinstaller.py b/elbepack/debinstaller.py
index 1544bed9d..7ed5b6b75 100644
--- a/elbepack/debinstaller.py
+++ b/elbepack/debinstaller.py
@@ -6,6 +6,7 @@
import sys
import os
import re
+import tempfile
from shutil import copyfile
from urllib.request import urlopen
@@ -14,7 +15,7 @@
from gpg.constants import PROTOCOL_OpenPGP
from elbepack.filesystem import TmpdirFilesystem
-from elbepack.egpg import OverallStatus, check_signature
+from elbepack.egpg import OverallStatus, check_signature, unarmor_openpgp_keyring
from elbepack.shellhelper import CommandError, system
from elbepack.hashes import HashValidator, HashValidationFailed
@@ -74,7 +75,7 @@ def __init__(self, base_url, fname, fname_list):
m.group(1))
-def setup_apt_keyring(gpg_home, keyring_fname):
+def setup_apt_keyring(gpg_home, keyring_fname, primary_key):
ring_path = os.path.join(gpg_home, keyring_fname)
if not os.path.isdir("/etc/apt/trusted.gpg.d"):
print("/etc/apt/trusted.gpg.d doesn't exist")
@@ -100,6 +101,15 @@ def setup_apt_keyring(gpg_home, keyring_fname):
except CommandError:
print(f'adding keyring "{key}" to keyring "{ring_path}" failed')
+ if primary_key:
+ with tempfile.NamedTemporaryFile(buffering = 0) as fp:
+ print(f"Import primary key: ")
+ print(primary_key)
+ fp.write(unarmor_openpgp_keyring(primary_key))
+ try:
+ system(f'gpg {gpg_options} --import "{fp.name}"')
+ except:
+ print(f'adding primary key to keyring "{ring_path}" failed')
def download(url, local_fname):
try:
@@ -144,11 +154,11 @@ def verify_release(tmp, base_url):
sig.close()
-def download_kinitrd(tmp, suite, mirror, skip_signature=False):
+def download_kinitrd(tmp, suite, mirror, primary_key, skip_signature=False):
base_url = f"{mirror.replace('LOCALMACHINE', 'localhost')}/dists/{suite}/"
installer_path = "main/installer-amd64/current/images/"
- setup_apt_keyring(tmp.fname('/'), 'pubring.gpg')
+ setup_apt_keyring(tmp.fname('/'), 'pubring.gpg', primary_key)
# download release file
download(base_url + "Release", tmp.fname('Release'))
@@ -200,6 +210,16 @@ def get_primary_mirror(prj):
return mirror
+def get_primary_key(prj):
+ primary_key = ''
+
+ if prj.has("mirror/primary_key"):
+ m = prj.node("mirror")
+
+ key = m.text("primary_key")
+ primary_key = "\n".join(line.strip(" \t") for line in key.splitlines()[1:-1])
+
+ return primary_key
def copy_kinitrd(prj, target_dir):
@@ -217,7 +237,8 @@ def copy_kinitrd(prj, target_dir):
os.path.join(target_dir, "initrd.gz"))
else:
mirror = get_primary_mirror(prj)
- download_kinitrd(tmp, suite, mirror, prj.has("noauth"))
+ primary_key = get_primary_key(prj)
+ download_kinitrd(tmp, suite, mirror, primary_key, prj.has("noauth"))
copyfile(tmp.fname("initrd.gz"),
os.path.join(target_dir, "initrd.gz"))
diff --git a/elbepack/elbeproject.py b/elbepack/elbeproject.py
index e913b8e85..9aa23e87e 100644
--- a/elbepack/elbeproject.py
+++ b/elbepack/elbeproject.py
@@ -38,7 +38,8 @@
from elbepack.pbuilder import (pbuilder_write_config, pbuilder_write_repo_hook,
pbuilder_write_cross_config,
- pbuilder_write_apt_conf)
+ pbuilder_write_apt_conf,
+ pbuilder_get_debootstrap_key_path)
from elbepack.repomanager import ProjectRepo
from elbepack.config import cfg
@@ -865,19 +866,24 @@ def create_pbuilder(self, cross, noccache, ccachesize):
# Run pbuilder --create
no_check_gpg = ""
+ keyring = ""
+ debootstrap_key_path = pbuilder_get_debootstrap_key_path(self.chrootpath, self.xml)
if self.xml.prj.has('noauth'):
no_check_gpg = "--debootstrapopts --no-check-gpg"
+ elif debootstrap_key_path:
+ keyring = f'--debootstrapopts --keyring="{debootstrap_key_path}"'
+
if cross:
do('pbuilder --create '
f'--buildplace "{os.path.join(self.builddir, "pbuilder_cross")}" '
f'--configfile "{os.path.join(self.builddir, "cross_pbuilderrc")}" '
f'--aptconfdir "{os.path.join(self.builddir, "aptconfdir")}" '
- f'--debootstrapopts --include="git,gnupg" {no_check_gpg};')
+ f'--debootstrapopts --include="git,gnupg" {no_check_gpg} {keyring};')
else:
do('pbuilder --create '
f'--configfile "{os.path.join(self.builddir, "pbuilderrc")}" '
f'--aptconfdir "{os.path.join(self.builddir, "aptconfdir")}" '
- f'--debootstrapopts --include="git,gnupg" {no_check_gpg}')
+ f'--debootstrapopts --include="git,gnupg" {no_check_gpg} {keyring}')
def sync_xml_to_disk(self):
try:
diff --git a/elbepack/elbexml.py b/elbepack/elbexml.py
index bc86ff3ce..ffc009c1f 100644
--- a/elbepack/elbexml.py
+++ b/elbepack/elbexml.py
@@ -142,6 +142,21 @@ def get_primary_mirror(self, cdrompath, initvm=True, hostsysroot=False):
return replace_localmachine(mirror, initvm)
+ def get_primary_key(self, cdrompath, hostsysroot=False):
+ key = ''
+
+ if self.prj.has("mirror/cdrom") and cdrompath:
+ pass
+ elif self.prj.has("mirror/primary_host"):
+ m = self.prj.node("mirror")
+
+ if hostsysroot and self.prj.has("mirror/host") and self.prj.has("mirror/host_key"):
+ key = m.text("host_key")
+ elif self.prj.has("mirror/primary_key"):
+ key = m.text("primary_key")
+
+ return key
+
# XXX: maybe add cdrom path param ?
def create_apt_sources_list(self, build_sources=False, initvm=True, hostsysroot=False):
diff --git a/elbepack/pbuilder.py b/elbepack/pbuilder.py
index 51ba26b5b..c48e5a50d 100644
--- a/elbepack/pbuilder.py
+++ b/elbepack/pbuilder.py
@@ -151,6 +151,38 @@ def pbuilder_write_repo_hook(builddir, xml, cross):
f.write("apt-get update\n")
+def get_debootstrap_key(xml):
+ key = ''
+
+ if xml.prj.has("mirror/primary_host") and xml.prj.has("mirror/primary_key"):
+ m = xml.prj.node("mirror")
+
+ if m.has("options"):
+ options = "[%s]" % ' '.join([opt.et.text.strip(' \t\n')
+ for opt
+ in m.all("options/option")])
+ else:
+ options = ""
+
+ if not "trusted=yes" in options:
+ key = "\n".join(line.strip(" \t")
+ for line
+ in m.text('primary_key').splitlines()[1:-1])
+
+
+ return key
+
+def pbuilder_get_debootstrap_key_path(chrootpath, xml):
+ path = ''
+
+ # If we have a primary key for use with debootstrap, BuildEnv.debootstrap
+ # will have added the key. We use the same key for the pbuilder
+ # debootstrap options.
+ if get_debootstrap_key(xml):
+ path = os.path.join(chrootpath, 'etc', 'apt', 'trusted.gpg.d', 'elbe-xml-primary-key.gpg')
+
+ return path
+
def get_apt_keys(builddir, xml):
if xml.prj is None:
@@ -161,6 +193,10 @@ def get_apt_keys(builddir, xml):
keys = [Filesystem(builddir).read_file("repo/repo.pub")]
+ debootstrap_key = get_debootstrap_key(xml)
+ if debootstrap_key:
+ keys.append(debootstrap_key)
+
if xml.prj.has("mirror/primary_host") and xml.prj.has("mirror/url-list"):
for url in xml.prj.node("mirror/url-list"):
diff --git a/elbepack/rfs.py b/elbepack/rfs.py
index 1f5c8fb0a..544ebef06 100644
--- a/elbepack/rfs.py
+++ b/elbepack/rfs.py
@@ -144,6 +144,16 @@ def __exit__(self, typ, value, traceback):
do(f"rm {self.path}/etc/apt/sources.list.d/local.list")
do(f"rm {self.path}/etc/apt/trusted.gpg.d/elbe-localrepo.gpg")
+ def import_debootstrap_key(self, key):
+ path = ''
+
+ if key:
+ self.rfs.mkdir_p('etc/apt/trusted.gpg.d')
+ k = "\n".join(line.strip(" \t") for line in key.splitlines()[1:-1])
+ path = self.add_key(unarmor_openpgp_keyring(k), "elbe-xml-primary-key.gpg")
+
+ return path
+
def debootstrap(self, arch="default"):
# pylint: disable=too-many-statements
@@ -154,6 +164,10 @@ def debootstrap(self, arch="default"):
primary_mirror = self.xml.get_primary_mirror(
self.rfs.fname('/cdrom/targetrepo'), hostsysroot=self.hostsysroot)
+ primary_key = self.xml.get_primary_key(
+ self.rfs.fname('/cdrom/targetrepo'), hostsysroot=self.hostsysroot)
+
+ debootstrap_key_path = self.import_debootstrap_key(primary_key)
if self.xml.prj.has("mirror/primary_proxy"):
os.environ["no_proxy"] = "10.0.2.2,localhost,127.0.0.1"
@@ -202,13 +216,15 @@ def debootstrap(self, arch="default"):
else:
if self.xml.has("project/mirror/cdrom"):
keyring = f' --keyring="{self.rfs.fname("/elbe.keyring")}"'
+ elif debootstrap_key_path:
+ keyring = f' --keyring="{debootstrap_key_path}"'
cmd = (f'{strapcmd} --arch={arch} '
f'{keyring} "{suite}" "{self.rfs.path}" "{primary_mirror}"')
try:
self.cdrom_mount()
- if keyring:
+ if keyring and self.xml.has("project/mirror/cdrom"):
self.convert_asc_to_gpg("/cdrom/targetrepo/repo.pub", "/elbe.keyring")
do(cmd)
except CommandError:
@@ -227,13 +243,15 @@ def debootstrap(self, arch="default"):
else:
if self.xml.has("project/mirror/cdrom"):
keyring = f' --keyring="{self.rfs.fname("/elbe.keyring")}"'
+ elif debootstrap_key_path:
+ keyring = f' --keyring="{debootstrap_key_path}"'
cmd = (f'{strapcmd} --foreign --arch={arch} '
f'{keyring} "{suite}" "{self.rfs.path}" "{primary_mirror}"')
try:
self.cdrom_mount()
- if keyring:
+ if keyring and self.xml.has("project/mirror/cdrom"):
self.convert_asc_to_gpg("/cdrom/targetrepo/repo.pub", "/elbe.keyring")
do(cmd)
@@ -274,9 +292,12 @@ def add_key(self, key, keyname):
Adds the binary OpenPGP keyring 'key' as a trusted apt keyring
with file name 'keyname'.
"""
- with open(self.rfs.fname(f"/etc/apt/trusted.gpg.d/{keyname}"), "wb") as outfile:
+ keyfile = self.rfs.fname(f"/etc/apt/trusted.gpg.d/{keyname}")
+ with open(keyfile, "wb") as outfile:
outfile.write(key)
+ return keyfile
+
def import_keys(self):
if self.xml.has('project/mirror/url-list'):
# Should we use self.xml.prj.has("noauth")???
diff --git a/elbepack/virtapt.py b/elbepack/virtapt.py
index 970349318..3cf4b532a 100644
--- a/elbepack/virtapt.py
+++ b/elbepack/virtapt.py
@@ -150,6 +150,11 @@ def add_key(self, key, keyname):
outfile.write(key)
def import_keys(self):
+ if self.xml.has('project/mirror/primary_host') and self.xml.has('project/mirror/primary_key'):
+ m = self.xml.node('project/mirror')
+ key = "\n".join(line.strip(" \t") for line in m.text('primary_key').splitlines()[1:-1])
+ self.add_key(unarmor_openpgp_keyring(key), "elbe-virtapt-primary-key.gpg")
+
if self.xml.has('project/mirror/url-list'):
# Should we use self.xml.prj.has("noauth")???
#
diff --git a/schema/dbsfed.xsd b/schema/dbsfed.xsd
index 72bca5a3d..41ba3c523 100644
--- a/schema/dbsfed.xsd
+++ b/schema/dbsfed.xsd
@@ -283,6 +283,13 @@ SPDX-FileCopyrightText: Linutronix GmbH
+
+
+
+ Raw public key used to sign the primary mirror
+
+
+
@@ -305,6 +312,13 @@ SPDX-FileCopyrightText: Linutronix GmbH
+
+
+
+ Raw public key used to sign the host mirror
+
+
+