diff options
| author | Michael Vogt <michael.vogt@ubuntu.com> | 2012-06-12 10:59:03 +0200 |
|---|---|---|
| committer | Michael Vogt <michael.vogt@ubuntu.com> | 2012-06-12 10:59:03 +0200 |
| commit | bcef41df6bdefdd95e0b7cab0428b4655accf9fa (patch) | |
| tree | c0ace88aa730e62982f7563e9fcec5397cca4cc8 | |
| parent | 2d2ba80ac8aafbfc4f5a2a2ae6490ad994d57d9d (diff) | |
| parent | 43aee9eda68e374067d6d6a9c4dd3c3e9b986041 (diff) | |
| download | python-apt-bcef41df6bdefdd95e0b7cab0428b4655accf9fa.tar.gz | |
merged from the mvo branch
| -rw-r--r-- | apt/auth.py | 176 | ||||
| -rw-r--r-- | debian/changelog | 5 | ||||
| -rw-r--r-- | po/python-apt.pot | 134 | ||||
| -rwxr-xr-x | tests/fakeroot-apt-key | 2 | ||||
| -rw-r--r-- | tests/test_auth.py | 223 |
5 files changed, 473 insertions, 67 deletions
diff --git a/apt/auth.py b/apt/auth.py new file mode 100644 index 00000000..38c4bdc6 --- /dev/null +++ b/apt/auth.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# auth - authentication key management +# +# Copyright (c) 2004 Canonical +# Copyright (c) 2012 Sebastian Heinlein +# +# Author: Michael Vogt <mvo@debian.org> +# Sebastian Heinlein <devel@glatzor.de> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +"""Handle GnuPG keys used to trust signed repositories.""" + +import atexit +import os +import os.path +import subprocess +import tempfile + +import apt_pkg +from apt_pkg import gettext as _ + + +class TrustedKey(object): + + """Represents a trusted key.""" + + def __init__(self, name, keyid, date): + self.raw_name = name + # Allow to translated some known keys + self.name = _(name) + self.keyid = keyid + self.date = date + + def __str__(self): + return "%s\n%s %s" % (self.name, self.keyid, self.date) + + +def _call_apt_key_script(*args, **kwargs): + """Run the apt-key script with the given arguments.""" + cmd = [apt_pkg.config.find_file("Dir::Bin::Apt-Key", "/usr/bin/apt-key")] + cmd.extend(args) + env = os.environ.copy() + env["LANG"] = "C" + if apt_pkg.config.find_dir("Dir") != "/": + # If the key is to be installed into a chroot we have to export the + # configuration from the chroot to the apt-key script by using + # a temporary APT_CONFIG file. The apt-key script uses apt-config shell + # internally + conf_fd, conf_name = tempfile.mkstemp(prefix="apt-key", suffix="conf") + atexit.register(os.remove, conf_name) + try: + os.write(conf_fd, apt_pkg.config.dump().encode("UTF-8")) + finally: + os.close(conf_fd) + env["APT_CONFIG"] = conf_name + proc = subprocess.Popen(cmd, env=env, universal_newlines=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + try: + proc.stdin.write(kwargs["stdin"]) + except KeyError: + pass + finally: + proc.stdin.close() + return_code = proc.wait() + output = proc.stdout.read() + if return_code: + raise SystemError("The apt-key script failed with return code %s:\n" + "%s\n%s" % (return_code, " ".join(cmd), output)) + return output.strip() + +def add_key_from_file(filename): + """Import a GnuPG key file to trust repositores signed by it. + + Keyword arguments: + filename -- the absolute path to the public GnuPG key file + """ + if not os.path.abspath(filename): + raise SystemError("An absolute path is required: %s" % filename) + if not os.access(filename, os.R_OK): + raise SystemError("Key file cannot be accessed: %s" % filename) + _call_apt_key_script("add", filename) + +def add_key_from_keyserver(keyid, keyserver): + """Import a GnuPG key file to trust repositores signed by it. + + Keyword arguments: + keyid -- the identifier of the key, e.g. 0x0EB12DSA + keyserver -- the URL or hostname of the key server + """ + _call_apt_key_script("adv", "--quiet", "--keyserver", keyserver, + "--recv", keyid) + +def add_key(content): + """Import a GnuPG key to trust repositores signed by it. + + Keyword arguments: + content -- the content of the GnuPG public key + """ + _call_apt_key_script("adv", "--quiet", "--batch", + "--import", "-", stdin=content) + +def remove_key(fingerprint): + """Remove a GnuPG key to no longer trust repositores signed by it. + + Keyword arguments: + fingerprint -- the fingerprint identifying the key + """ + _call_apt_key_script("rm", fingerprint) + +def export_key(fingerprint): + """Return the GnuPG key in text format. + + Keyword arguments: + fingerprint -- the fingerprint identifying the key + """ + return _call_apt_key_script("export", fingerprint) + +def update(): + """Update the local keyring with the archive keyring and remove from + the local keyring the archive keys which are no longer valid. The + archive keyring is shipped in the archive-keyring package of your + distribution, e.g. the debian-archive-keyring package in Debian. + """ + return _call_apt_key_script("update") + +def net_update(): + """Work similar to the update command above, but get the archive + keyring from an URI instead and validate it against a master key. + This requires an installed wget(1) and an APT build configured to + have a server to fetch from and a master keyring to validate. APT + in Debian does not support this command and relies on update + instead, but Ubuntu's APT does. + """ + return _call_apt_key_script("net-update") + +def list_keys(): + """Returns a list of TrustedKey instances for each key which is + used to trust repositories. + """ + # The output of `apt-key list` is difficult to parse since the + # --with-colons parameter isn't user + output = _call_apt_key_script("adv", "--with-colons", "--batch", + "--list-keys") + res = [] + for line in output.split("\n"): + fields = line.split(":") + if fields[0] == "pub": + key = TrustedKey(fields[9], fields[4][-8:], fields[5]) + res.append(key) + return res + +if __name__ == "__main__": + # Add some known keys we would like to see translated so that they get + # picked up by gettext + lambda: _("Ubuntu Archive Automatic Signing Key <ftpmaster@ubuntu.com>") + lambda: _("Ubuntu CD Image Automatic Signing Key <cdimage@ubuntu.com>") + + apt_pkg.init() + for trusted_key in list_keys(): + print(trusted_key) diff --git a/debian/changelog b/debian/changelog index 41683a27..73cc14a3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,6 +17,11 @@ python-apt (0.8.5) UNRELEASED; urgency=low * pre-build.sh: call dpkg-checkbuilddeps with the list of our source-build-dependencies; this may save someone else an hour down the line scratching their head over gratuitous test-suite failures... + + [ Sebastian Heinlein ] + * lp:~glatzor/python-apt/auth: + - this is a port of the software-properties AptAuth module to python-apt + with some cleanups. It provides a wrapper API for the apt-key command -- Michael Vogt <mvo@debian.org> Tue, 17 Apr 2012 14:09:24 +0200 diff --git a/po/python-apt.pot b/po/python-apt.pot index 00637f52..d6ac301e 100644 --- a/po/python-apt.pot +++ b/po/python-apt.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-04-17 21:15+0200\n" +"POT-Creation-Date: 2012-06-12 10:44+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -24,327 +24,327 @@ msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:33 +#: ../data/templates/Ubuntu.info.in:151 msgid "Ubuntu 12.04 'Precise Pangolin'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:40 +#: ../data/templates/Ubuntu.info.in:158 msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:151 +#: ../data/templates/Ubuntu.info.in:269 msgid "Ubuntu 11.10 'Oneiric Ocelot'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:158 +#: ../data/templates/Ubuntu.info.in:276 msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:270 +#: ../data/templates/Ubuntu.info.in:388 msgid "Ubuntu 11.04 'Natty Narwhal'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:277 +#: ../data/templates/Ubuntu.info.in:395 msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:368 +#: ../data/templates/Ubuntu.info.in:486 msgid "Ubuntu 10.10 'Maverick Meerkat'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:388 +#: ../data/templates/Ubuntu.info.in:506 msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:400 +#: ../data/templates/Ubuntu.info.in:518 msgid "Canonical Partners" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:402 +#: ../data/templates/Ubuntu.info.in:520 msgid "Software packaged by Canonical for their partners" msgstr "" #. CompDescriptionLong -#: ../data/templates/Ubuntu.info.in:403 +#: ../data/templates/Ubuntu.info.in:521 msgid "This software is not part of Ubuntu." msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:410 +#: ../data/templates/Ubuntu.info.in:528 msgid "Independent" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:412 +#: ../data/templates/Ubuntu.info.in:530 msgid "Provided by third-party software developers" msgstr "" #. CompDescriptionLong -#: ../data/templates/Ubuntu.info.in:413 +#: ../data/templates/Ubuntu.info.in:531 msgid "Software offered by third party developers." msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:451 +#: ../data/templates/Ubuntu.info.in:569 msgid "Ubuntu 10.04 'Lucid Lynx'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:471 +#: ../data/templates/Ubuntu.info.in:589 msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:514 +#: ../data/templates/Ubuntu.info.in:632 msgid "Ubuntu 9.10 'Karmic Koala'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:534 +#: ../data/templates/Ubuntu.info.in:652 msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:577 +#: ../data/templates/Ubuntu.info.in:695 msgid "Ubuntu 9.04 'Jaunty Jackalope'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:596 +#: ../data/templates/Ubuntu.info.in:714 msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:639 +#: ../data/templates/Ubuntu.info.in:757 msgid "Ubuntu 8.10 'Intrepid Ibex'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:659 +#: ../data/templates/Ubuntu.info.in:777 msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:703 +#: ../data/templates/Ubuntu.info.in:821 msgid "Ubuntu 8.04 'Hardy Heron'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:723 +#: ../data/templates/Ubuntu.info.in:841 msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:768 +#: ../data/templates/Ubuntu.info.in:886 msgid "Ubuntu 7.10 'Gutsy Gibbon'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:787 +#: ../data/templates/Ubuntu.info.in:905 msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:832 +#: ../data/templates/Ubuntu.info.in:950 msgid "Ubuntu 7.04 'Feisty Fawn'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:851 +#: ../data/templates/Ubuntu.info.in:969 msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:893 +#: ../data/templates/Ubuntu.info.in:1011 msgid "Ubuntu 6.10 'Edgy Eft'" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:898 +#: ../data/templates/Ubuntu.info.in:1016 msgid "Community-maintained" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:904 +#: ../data/templates/Ubuntu.info.in:1022 msgid "Restricted software" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:912 +#: ../data/templates/Ubuntu.info.in:1030 msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:954 +#: ../data/templates/Ubuntu.info.in:1072 msgid "Ubuntu 6.06 LTS 'Dapper Drake'" msgstr "" #. CompDescriptionLong -#: ../data/templates/Ubuntu.info.in:957 +#: ../data/templates/Ubuntu.info.in:1075 msgid "Canonical-supported free and open-source software" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:959 +#: ../data/templates/Ubuntu.info.in:1077 msgid "Community-maintained (universe)" msgstr "" #. CompDescriptionLong -#: ../data/templates/Ubuntu.info.in:960 +#: ../data/templates/Ubuntu.info.in:1078 msgid "Community-maintained free and open-source software" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:962 +#: ../data/templates/Ubuntu.info.in:1080 msgid "Non-free drivers" msgstr "" #. CompDescriptionLong -#: ../data/templates/Ubuntu.info.in:963 +#: ../data/templates/Ubuntu.info.in:1081 msgid "Proprietary drivers for devices" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:965 +#: ../data/templates/Ubuntu.info.in:1083 msgid "Restricted software (Multiverse)" msgstr "" #. CompDescriptionLong -#: ../data/templates/Ubuntu.info.in:966 +#: ../data/templates/Ubuntu.info.in:1084 msgid "Software restricted by copyright or legal issues" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:973 +#: ../data/templates/Ubuntu.info.in:1091 msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:989 +#: ../data/templates/Ubuntu.info.in:1107 msgid "Important security updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:994 +#: ../data/templates/Ubuntu.info.in:1112 msgid "Recommended updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:999 +#: ../data/templates/Ubuntu.info.in:1117 msgid "Pre-released updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1004 +#: ../data/templates/Ubuntu.info.in:1122 msgid "Unsupported updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1015 +#: ../data/templates/Ubuntu.info.in:1133 msgid "Ubuntu 5.10 'Breezy Badger'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1030 +#: ../data/templates/Ubuntu.info.in:1148 msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1046 +#: ../data/templates/Ubuntu.info.in:1164 msgid "Ubuntu 5.10 Security Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1051 +#: ../data/templates/Ubuntu.info.in:1169 msgid "Ubuntu 5.10 Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1056 +#: ../data/templates/Ubuntu.info.in:1174 msgid "Ubuntu 5.10 Backports" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1067 +#: ../data/templates/Ubuntu.info.in:1185 msgid "Ubuntu 5.04 'Hoary Hedgehog'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1082 +#: ../data/templates/Ubuntu.info.in:1200 msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:1085 ../data/templates/Debian.info.in:149 +#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:149 msgid "Officially supported" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1098 +#: ../data/templates/Ubuntu.info.in:1216 msgid "Ubuntu 5.04 Security Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1103 +#: ../data/templates/Ubuntu.info.in:1221 msgid "Ubuntu 5.04 Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1108 +#: ../data/templates/Ubuntu.info.in:1226 msgid "Ubuntu 5.04 Backports" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1114 +#: ../data/templates/Ubuntu.info.in:1232 msgid "Ubuntu 4.10 'Warty Warthog'" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:1120 +#: ../data/templates/Ubuntu.info.in:1238 msgid "Community-maintained (Universe)" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:1122 +#: ../data/templates/Ubuntu.info.in:1240 msgid "Non-free (Multiverse)" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1129 +#: ../data/templates/Ubuntu.info.in:1247 msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:1132 +#: ../data/templates/Ubuntu.info.in:1250 msgid "No longer officially supported" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:1134 +#: ../data/templates/Ubuntu.info.in:1252 msgid "Restricted copyright" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1141 +#: ../data/templates/Ubuntu.info.in:1259 msgid "Ubuntu 4.10 Security Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1146 +#: ../data/templates/Ubuntu.info.in:1264 msgid "Ubuntu 4.10 Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:1151 +#: ../data/templates/Ubuntu.info.in:1269 msgid "Ubuntu 4.10 Backports" msgstr "" @@ -410,7 +410,7 @@ msgid "Non-DFSG-compatible Software" msgstr "" #. TRANSLATORS: %s is a country -#: ../aptsources/distro.py:206 ../aptsources/distro.py:434 +#: ../aptsources/distro.py:206 ../aptsources/distro.py:436 #, python-format msgid "Server for %s" msgstr "" diff --git a/tests/fakeroot-apt-key b/tests/fakeroot-apt-key new file mode 100755 index 00000000..7be99711 --- /dev/null +++ b/tests/fakeroot-apt-key @@ -0,0 +1,2 @@ +#!/bin/sh +fakeroot /usr/bin/apt-key $* diff --git a/tests/test_auth.py b/tests/test_auth.py new file mode 100644 index 00000000..f975c670 --- /dev/null +++ b/tests/test_auth.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python + +import os +import shutil +import sys +import tempfile +import time +import unittest + +if sys.version_info.major > 2: + from http.server import HTTPServer + from http.server import SimpleHTTPRequestHandler as HTTPRequestHandler +else: + from BaseHTTPServer import HTTPServer + from SimpleHTTPServer import SimpleHTTPRequestHandler as HTTPRequestHandler + +import apt_pkg +import apt.auth + +WHEEZY_KEY = """-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.12 (GNU/Linux) + +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 +DHcut3Yey8o= +=id4q +-----END PGP PUBLIC KEY BLOCK-----""" + + +class TestAuthKeys(unittest.TestCase): + + """Test handling of keys for signed repositories.""" + + def setUp(self): + # reset any config manipulations done in the individual tests + apt_pkg.init_config() + # save the apt config to restore later + cnf = {} + for item in apt_pkg.config.keys(): + cnf[item] = apt_pkg.config.find(item) + self.addCleanup(self._restore_apt_config, cnf) + + self.tmpdir = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, self.tmpdir) + apt_pkg.config.set("Dir", self.tmpdir) + apt_pkg.config.set("Dir::Bin::Apt-key", "fakeroot-apt-key") + apt_pkg.config.set("Dir::Etc", "etc/apt/") + trustedparts_dir = apt_pkg.config.find_dir("Dir::Etc::Trustedparts") + confparts_dir = apt_pkg.config.find_dir("Dir::Etc::parts") + self.assertTrue(trustedparts_dir.startswith(self.tmpdir)) + os.makedirs(trustedparts_dir) + os.makedirs(confparts_dir) + shutil.copy("fakeroot-apt-key", self.tmpdir) + + def _restore_apt_config(self, cnf): + """Restore previous apt configuration.""" + for item in cnf: + apt_pkg.config.set(item, cnf[item]) + + def testAddAndExportKey(self): + """Add an example key.""" + apt.auth.add_key(WHEEZY_KEY) + # Strip the headers from the keys to avoid test errors because + # the exported key used a differenct GnuPG version than the + # original example key + self.assertEqual(apt.auth.export_key("46925553").split("\n")[2:], + WHEEZY_KEY.split("\n")[2:]) + + def testAddAndListKey(self): + """Add an example key and test if it is correctly returned by + list_keys() + """ + apt.auth.add_key(WHEEZY_KEY) + ret = apt.auth.list_keys() + self.assertEqual(len(ret), 1) + key = ret[0] + self.assertEqual(key.name, + "Debian Archive Automatic Signing Key (7.0/wheezy) " + "<ftpmaster@debian.org>") + self.assertEqual(key.keyid, "46925553") + self.assertEqual(key.date, "2012-04-27") + + def testAddKeyFromFile(self): + """Test adding a key from file.""" + keyfd, keyname = tempfile.mkstemp() + self.addCleanup(os.close, keyfd) + os.write(keyfd, WHEEZY_KEY.encode("UTF-8")) + + apt.auth.add_key_from_file(keyname) + + ret = apt.auth.list_keys() + self.assertEqual(len(ret), 1) + key = ret[0] + self.assertEqual(key.name, + "Debian Archive Automatic Signing Key (7.0/wheezy) " + "<ftpmaster@debian.org>") + self.assertEqual(key.keyid, "46925553") + self.assertEqual(key.date, "2012-04-27") + + def testAddKeyFromServer(self): + """Install a GnuPG key from a remote server.""" + self._start_keyserver() + self.addCleanup(self._stop_keyserver) + + apt.auth.add_key_from_keyserver("46925553", "hkp://localhost:19191") + + ret = apt.auth.list_keys() + self.assertEqual(len(ret), 1) + key = ret[0] + self.assertEqual(key.name, + "Debian Archive Automatic Signing Key (7.0/wheezy) " + "<ftpmaster@debian.org>") + self.assertEqual(key.keyid, "46925553") + self.assertEqual(key.date, "2012-04-27") + + def _start_keyserver(self): + """Start a fake keyserver on http://localhost:19191 + Thanks pitti. + """ + dir = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, dir) + os.mkdir(os.path.join(dir, "pks")) + with open(os.path.join(dir, "pks", "lookup"), "w") as key_file: + key_file.write(WHEEZY_KEY) + + self.keyserver_pid = os.fork() + if self.keyserver_pid == 0: + # quiesce server log + os.dup2(os.open('/dev/null', os.O_WRONLY), sys.stderr.fileno()) + os.chdir(dir) + httpd = HTTPServer(('localhost', 19191), HTTPRequestHandler) + httpd.serve_forever() + os._exit(0) + + # wait a bit until server is ready + time.sleep(0.5) + + def _stop_keyserver(self): + '''Stop fake keyserver''' + assert self.keyserver_pid + + os.kill(self.keyserver_pid, 15) + os.wait() + + +if __name__ == "__main__": + unittest.main() |
