Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support primary_key in mirror tag #367

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion elbepack/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
31 changes: 26 additions & 5 deletions elbepack/debinstaller.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import sys
import os
import re
import tempfile

from shutil import copyfile
from urllib.request import urlopen
Expand All @@ -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

Expand Down Expand Up @@ -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")
Expand All @@ -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:
Expand Down Expand Up @@ -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'))
Expand Down Expand Up @@ -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):

Expand All @@ -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"))
Expand Down
12 changes: 9 additions & 3 deletions elbepack/elbeproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
15 changes: 15 additions & 0 deletions elbepack/elbexml.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):

Expand Down
36 changes: 36 additions & 0 deletions elbepack/pbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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"):
Expand Down
27 changes: 24 additions & 3 deletions elbepack/rfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
Expand Down Expand Up @@ -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:
Expand All @@ -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)

Expand Down Expand Up @@ -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")???
Expand Down
5 changes: 5 additions & 0 deletions elbepack/virtapt.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")???
#
Expand Down
14 changes: 14 additions & 0 deletions schema/dbsfed.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,13 @@ SPDX-FileCopyrightText: Linutronix GmbH
</documentation>
</annotation>
</element>
<element name="primary_key" type="rfs:string" minOccurs="0" maxOccurs="1">
<annotation>
<documentation>
Raw public key used to sign the primary mirror
</documentation>
</annotation>
</element>
<element name="primary_proxy" type="rfs:string" minOccurs="0" maxOccurs="1">
<annotation>
<documentation>
Expand All @@ -305,6 +312,13 @@ SPDX-FileCopyrightText: Linutronix GmbH
</documentation>
</annotation>
</element>
<element name="host_key" type="rfs:string" minOccurs="0" maxOccurs="1">
<annotation>
<documentation>
Raw public key used to sign the host mirror
</documentation>
</annotation>
</element>
<element name="url-list" type="rfs:url-list" minOccurs="0">
<annotation>
<documentation>
Expand Down