Merge ~simpoir/ubuntu/+source/landscape-client:hirsute-upgrade-tool-gpg into ubuntu/+source/landscape-client:ubuntu/hirsute-devel

Proposed by Simon Poirier
Status: Work in progress
Proposed branch: ~simpoir/ubuntu/+source/landscape-client:hirsute-upgrade-tool-gpg
Merge into: ubuntu/+source/landscape-client:ubuntu/hirsute-devel
Diff against target: 170 lines (+149/-0)
3 files modified
debian/changelog (+7/-0)
debian/patches/0003-lp1903776-release-upgrade.patch (+141/-0)
debian/patches/series (+1/-0)
Reviewer Review Type Date Requested Status
Canonical Server Team Pending
Ubuntu Server Dev import team Pending
Review via email: mp+394185@code.launchpad.net
To post a comment you must log in.

Unmerged commits

31d0ff6... by Simon Poirier

Import d/p/0003-lp1903776-release-upgrade.patch (LP: #1903776) │

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index 7cd0974..7780849 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,10 @@
6+landscape-client (19.12-0ubuntu6) hirsute; urgency=medium
7+
8+ * d/p/0003-lp1903776-release-upgrade.patch (LP: #1903776)
9+ - Use /etc/apt/trusted.gpg.d for validating upgrade-tool signature.
10+
11+ -- Simon Poirier <simon.poirier@canonical.com> Mon, 16 Nov 2020 16:58:12 -0500
12+
13 landscape-client (19.12-0ubuntu5) groovy; urgency=medium
14
15 * d/landscape-client.service (LP: #1870087)
16diff --git a/debian/patches/0003-lp1903776-release-upgrade.patch b/debian/patches/0003-lp1903776-release-upgrade.patch
17new file mode 100644
18index 0000000..bd3a154
19--- /dev/null
20+++ b/debian/patches/0003-lp1903776-release-upgrade.patch
21@@ -0,0 +1,141 @@
22+Description: Use /etc/apt/trusted.gpg.d for validating upgrade-tool signature.
23+Author: Simon Poirier <simon.poirier@canonical.com>
24+Origin: upstream, https://github.com/CanonicalLtd/landscape-client/commit/bcbe04db6ca45c7a0afac171e85a9c88c19253ae
25+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1903776
26+
27+diff --git a/landscape/lib/gpg.py b/landscape/lib/gpg.py
28+index 66400d18..58218c54 100644
29+--- a/landscape/lib/gpg.py
30++++ b/landscape/lib/gpg.py
31+@@ -1,6 +1,9 @@
32++import itertools
33+ import shutil
34+ import tempfile
35+
36++from glob import glob
37++
38+ from twisted.internet.utils import getProcessOutputAndValue
39+
40+
41+@@ -8,14 +11,15 @@ class InvalidGPGSignature(Exception):
42+ """Raised when the gpg signature for a given file is invalid."""
43+
44+
45+-def gpg_verify(filename, signature, gpg="/usr/bin/gpg"):
46++def gpg_verify(filename, signature, gpg="/usr/bin/gpg", apt_dir="/etc/apt"):
47+ """Verify the GPG signature of a file.
48+
49+ @param filename: Path to the file to verify the signature against.
50+ @param signature: Path to signature to use.
51+ @param gpg: Optionally, path to the GPG binary to use.
52++ @param apt_dir: Optionally, path to apt trusted keyring.
53+ @return: a C{Deferred} resulting in C{True} if the signature is
54+- valid, C{False} otherwise.
55++ valid, C{False} otherwise.
56+ """
57+
58+ def remove_gpg_home(ignored):
59+@@ -32,9 +36,17 @@ def check_gpg_exit_code(args):
60+ "code='%d')" % (gpg, out, err, code))
61+
62+ gpg_home = tempfile.mkdtemp()
63+- args = ("--no-options", "--homedir", gpg_home, "--no-default-keyring",
64+- "--ignore-time-conflict", "--keyring", "/etc/apt/trusted.gpg",
65+- "--verify", signature, filename)
66++ keyrings = tuple(itertools.chain(*[
67++ ("--keyring", keyring)
68++ for keyring in sorted(
69++ glob("{}/trusted.gpg".format(apt_dir)) +
70++ glob("{}/trusted.gpg.d/*.gpg".format(apt_dir))
71++ )
72++ ]))
73++ args = (
74++ "--no-options", "--homedir", gpg_home, "--no-default-keyring",
75++ "--ignore-time-conflict"
76++ ) + keyrings + ("--verify", signature, filename)
77+
78+ result = getProcessOutputAndValue(gpg, args=args)
79+ result.addBoth(remove_gpg_home)
80+diff --git a/landscape/lib/tests/test_gpg.py b/landscape/lib/tests/test_gpg.py
81+index e6165a26..4c84e008 100644
82+--- a/landscape/lib/tests/test_gpg.py
83++++ b/landscape/lib/tests/test_gpg.py
84+@@ -1,9 +1,10 @@
85+ import mock
86+ import os
87++import textwrap
88+ import unittest
89+
90+ from twisted.internet import reactor
91+-from twisted.internet.defer import Deferred
92++from twisted.internet.defer import Deferred, inlineCallbacks
93+
94+ from landscape.lib import testing
95+ from landscape.lib.gpg import gpg_verify
96+@@ -16,6 +17,8 @@ def test_gpg_verify(self):
97+ L{gpg_verify} runs the given gpg binary and returns C{True} if the
98+ provided signature is valid.
99+ """
100++ aptdir = self.makeDir()
101++ os.mknod("{}/trusted.gpg".format(aptdir))
102+ gpg_options = self.makeFile()
103+ gpg = self.makeFile("#!/bin/sh\n"
104+ "touch $3/trustdb.gpg\n"
105+@@ -27,14 +30,15 @@ def test_gpg_verify(self):
106+ @mock.patch("tempfile.mkdtemp")
107+ def do_test(mkdtemp_mock):
108+ mkdtemp_mock.return_value = gpg_home
109+- result = gpg_verify("/some/file", "/some/signature", gpg=gpg)
110++ result = gpg_verify(
111++ "/some/file", "/some/signature", gpg=gpg, apt_dir=aptdir)
112+
113+ def check_result(ignored):
114+ self.assertEqual(
115+ open(gpg_options).read(),
116+ "--no-options --homedir %s --no-default-keyring "
117+- "--ignore-time-conflict --keyring /etc/apt/trusted.gpg "
118+- "--verify /some/signature /some/file" % gpg_home)
119++ "--ignore-time-conflict --keyring %s/trusted.gpg "
120++ "--verify /some/signature /some/file" % (gpg_home, aptdir))
121+ self.assertFalse(os.path.exists(gpg_home))
122+
123+ result.addCallback(check_result)
124+@@ -70,3 +74,38 @@ def check_failure(failure):
125+
126+ reactor.callWhenRunning(do_test)
127+ return deferred
128++
129++ @inlineCallbacks
130++ def test_gpg_verify_trusted_dir(self):
131++ """
132++ gpg_verify uses keys from the trusted.gpg.d if such a folder exists.
133++ """
134++ apt_dir = self.makeDir()
135++ os.mkdir("{}/trusted.gpg.d".format(apt_dir))
136++ os.mknod("{}/trusted.gpg.d/foo.gpg".format(apt_dir))
137++ os.mknod("{}/trusted.gpg.d/baz.gpg".format(apt_dir))
138++ os.mknod("{}/trusted.gpg.d/bad.gpg~".format(apt_dir))
139++
140++ gpg_call = self.makeFile()
141++ fake_gpg = self.makeFile(textwrap.dedent("""\
142++ #!/bin/sh
143++ touch $3/trustdb.gpg
144++ echo -n $@ > {}
145++ """).format(gpg_call))
146++ os.chmod(fake_gpg, 0o755)
147++ gpg_home = self.makeDir()
148++
149++ with mock.patch("tempfile.mkdtemp", return_value=gpg_home):
150++ yield gpg_verify(
151++ "/some/file", "/some/signature", gpg=fake_gpg, apt_dir=apt_dir)
152++
153++ expected = (
154++ "--no-options --homedir {gpg_home} --no-default-keyring "
155++ "--ignore-time-conflict "
156++ "--keyring {apt_dir}/trusted.gpg.d/baz.gpg "
157++ "--keyring {apt_dir}/trusted.gpg.d/foo.gpg "
158++ "--verify /some/signature /some/file"
159++ ).format(gpg_home=gpg_home, apt_dir=apt_dir)
160++ with open(gpg_call) as call:
161++ self.assertEqual(expected, call.read())
162++ self.assertFalse(os.path.exists(gpg_home))
163diff --git a/debian/patches/series b/debian/patches/series
164index 6b9a76f..fc5d6e4 100644
165--- a/debian/patches/series
166+++ b/debian/patches/series
167@@ -1,2 +1,3 @@
168 0001-Handle-EINVAL-error-of-SIOCETHTOOL-ioctl.patch
169 0002-lp1870087-stale-locks.patch
170+0003-lp1903776-release-upgrade.patch

Subscribers

People subscribed via source and target branches