Merge lp:~cjwatson/launchpad/bionic-gpg into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 18914
Proposed branch: lp:~cjwatson/launchpad/bionic-gpg
Merge into: lp:launchpad
Diff against target: 256 lines (+49/-36)
5 files modified
lib/lp/services/gpg/handler.py (+14/-28)
lib/lp/services/gpg/interfaces.py (+25/-0)
lib/lp/services/gpg/tests/test_gpghandler.py (+3/-1)
lib/lp/testing/gpgkeys/__init__.py (+5/-6)
utilities/make-lp-user (+2/-1)
To merge this branch: bzr merge lp:~cjwatson/launchpad/bionic-gpg
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+364986@code.launchpad.net

Commit message

Use gpg1 rather than gpg if it exists.

Description of the change

On bionic, gpg is gpg2, which we don't support yet.

In the process, I refactored various scattered places where gpg was hardcoded into a single get_gpg_path function, and similarly refactored three places that configured a GPGME context into a single get_gpgme_context function.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/services/gpg/handler.py'
2--- lib/lp/services/gpg/handler.py 2019-03-18 10:12:37 +0000
3+++ lib/lp/services/gpg/handler.py 2019-03-22 19:58:42 +0000
4@@ -31,6 +31,8 @@
5 from lp.app.validators.email import valid_email
6 from lp.services.config import config
7 from lp.services.gpg.interfaces import (
8+ get_gpg_path,
9+ get_gpgme_context,
10 GPGKeyAlgorithm,
11 GPGKeyDoesNotExistOnServer,
12 GPGKeyExpired,
13@@ -116,14 +118,6 @@
14
15 atexit.register(removeHome, self.home)
16
17- def _getContext(self):
18- """Return a new appropriately-configured GPGME context."""
19- context = gpgme.Context()
20- # Stick to GnuPG 1.
21- context.set_engine_info(gpgme.PROTOCOL_OpenPGP, "/usr/bin/gpg", None)
22- context.armor = True
23- return context
24-
25 def sanitizeFingerprint(self, fingerprint):
26 """See IGPGHandler."""
27 return sanitize_fingerprint(fingerprint)
28@@ -230,7 +224,7 @@
29 assert not isinstance(content, unicode)
30 assert not isinstance(signature, unicode)
31
32- ctx = self._getContext()
33+ ctx = get_gpgme_context()
34
35 # We may not yet have the public key, so find out the fingerprint we
36 # need to fetch.
37@@ -273,7 +267,7 @@
38 def importPublicKey(self, content):
39 """See IGPGHandler."""
40 assert isinstance(content, str)
41- context = self._getContext()
42+ context = get_gpgme_context()
43
44 newkey = StringIO(content)
45 with gpgme_timeline("import", "new public key"):
46@@ -308,7 +302,7 @@
47 if 'GPG_AGENT_INFO' in os.environ:
48 del os.environ['GPG_AGENT_INFO']
49
50- context = self._getContext()
51+ context = get_gpgme_context()
52 newkey = StringIO(content)
53 with gpgme_timeline("import", "new secret key"):
54 import_result = context.import_(newkey)
55@@ -334,7 +328,7 @@
56
57 def generateKey(self, name):
58 """See `IGPGHandler`."""
59- context = self._getContext()
60+ context = get_gpgme_context()
61
62 # Make sure that gpg-agent doesn't interfere.
63 if 'GPG_AGENT_INFO' in os.environ:
64@@ -372,8 +366,7 @@
65 if isinstance(content, unicode):
66 raise TypeError('Content cannot be Unicode.')
67
68- # setup context
69- ctx = self._getContext()
70+ ctx = get_gpgme_context()
71
72 # setup containers
73 plain = StringIO(content)
74@@ -404,7 +397,7 @@
75
76 # Find the key and make it the only one allowed to sign content
77 # during this session.
78- context = self._getContext()
79+ context = get_gpgme_context()
80 context.signers = [removeSecurityProxy(key.key)]
81
82 # Set up containers.
83@@ -432,7 +425,7 @@
84 """Get an iterator of the keys this gpg handler
85 already knows about.
86 """
87- ctx = self._getContext()
88+ ctx = get_gpgme_context()
89
90 # XXX michaeln 2010-05-07 bug=576405
91 # Currently gpgme.Context().keylist fails if passed a unicode
92@@ -458,7 +451,7 @@
93 pubkey = self._getPubKey(fingerprint)
94 key = self.importPublicKey(pubkey)
95 if not key.matches(fingerprint):
96- ctx = self._getContext()
97+ ctx = get_gpgme_context()
98 with gpgme_timeline("delete", key.fingerprint):
99 ctx.delete(key.key)
100 raise GPGKeyMismatchOnServer(fingerprint, key.fingerprint)
101@@ -602,17 +595,9 @@
102 self._buildFromGpgmeKey(key)
103 return self
104
105- def _getContext(self):
106- """Return a new appropriately-configured GPGME context."""
107- context = gpgme.Context()
108- # Stick to GnuPG 1.
109- context.set_engine_info(gpgme.PROTOCOL_OpenPGP, "/usr/bin/gpg", None)
110- context.armor = True
111- return context
112-
113 def _buildFromFingerprint(self, fingerprint):
114 """Build key information from a fingerprint."""
115- context = self._getContext()
116+ context = get_gpgme_context()
117 # retrive additional key information
118 try:
119 with gpgme_timeline("get-key", fingerprint):
120@@ -658,11 +643,12 @@
121 # XXX cprov 20081014: gpgme_op_export() only supports public keys.
122 # See http://www.fifi.org/cgi-bin/info2www?(gpgme)Exporting+Keys
123 p = subprocess.Popen(
124- ['gpg', '--export-secret-keys', '-a', self.fingerprint],
125+ [get_gpg_path(), '--export-secret-keys', '-a',
126+ self.fingerprint],
127 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
128 return p.stdout.read()
129
130- context = self._getContext()
131+ context = get_gpgme_context()
132 keydata = StringIO()
133 with gpgme_timeline("export", self.fingerprint):
134 context.export(self.fingerprint.encode('ascii'), keydata)
135
136=== modified file 'lib/lp/services/gpg/interfaces.py'
137--- lib/lp/services/gpg/interfaces.py 2019-03-18 10:12:37 +0000
138+++ lib/lp/services/gpg/interfaces.py 2019-03-22 19:58:42 +0000
139@@ -2,6 +2,8 @@
140 # GNU Affero General Public License version 3 (see the file LICENSE).
141
142 __all__ = [
143+ 'get_gpg_path',
144+ 'get_gpgme_context',
145 'GPGKeyAlgorithm',
146 'GPGKeyDoesNotExistOnServer',
147 'GPGKeyExpired',
148@@ -22,6 +24,7 @@
149 ]
150
151 import httplib
152+import os.path
153 import re
154
155 from lazr.enum import (
156@@ -56,6 +59,28 @@
157 return False
158
159
160+def get_gpg_path():
161+ """Return the path to the GPG executable we prefer.
162+
163+ We stick to GnuPG 1 until we've worked out how to get things working
164+ with GnuPG 2.
165+ """
166+ if os.path.exists("/usr/bin/gpg1"):
167+ return "/usr/bin/gpg1"
168+ else:
169+ return "/usr/bin/gpg"
170+
171+
172+def get_gpgme_context():
173+ """Return a new appropriately-configured GPGME context."""
174+ import gpgme
175+
176+ context = gpgme.Context()
177+ context.set_engine_info(gpgme.PROTOCOL_OpenPGP, get_gpg_path(), None)
178+ context.armor = True
179+ return context
180+
181+
182 # XXX: cprov 2004-10-04:
183 # (gpg+dbschema) the data structure should be rearranged to support 4 field
184 # needed: keynumber(1,16,17,20), keyalias(R,g,D,G), title and description
185
186=== modified file 'lib/lp/services/gpg/tests/test_gpghandler.py'
187--- lib/lp/services/gpg/tests/test_gpghandler.py 2019-03-18 10:12:37 +0000
188+++ lib/lp/services/gpg/tests/test_gpghandler.py 2019-03-22 19:58:42 +0000
189@@ -12,6 +12,7 @@
190 from zope.security.proxy import removeSecurityProxy
191
192 from lp.services.gpg.interfaces import (
193+ get_gpg_path,
194 GPGKeyDoesNotExistOnServer,
195 GPGKeyMismatchOnServer,
196 GPGKeyTemporarilyNotFoundError,
197@@ -327,7 +328,8 @@
198 # plumbing.
199 with open(os.devnull, "w") as devnull:
200 gpg_proc = subprocess.Popen(
201- ["gpg", "--quiet", "--status-fd", "1", "--verify"],
202+ [get_gpg_path(), "--quiet", "--status-fd", "1",
203+ "--verify"],
204 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
205 stderr=devnull, universal_newlines=True)
206 status = gpg_proc.communicate(signed_content)[0].splitlines()
207
208=== modified file 'lib/lp/testing/gpgkeys/__init__.py'
209--- lib/lp/testing/gpgkeys/__init__.py 2018-05-06 08:52:34 +0000
210+++ lib/lp/testing/gpgkeys/__init__.py 2019-03-22 19:58:42 +0000
211@@ -28,7 +28,10 @@
212
213 from lp.registry.interfaces.gpg import IGPGKeySet
214 from lp.registry.interfaces.person import IPersonSet
215-from lp.services.gpg.interfaces import IGPGHandler
216+from lp.services.gpg.interfaces import (
217+ get_gpgme_context,
218+ IGPGHandler,
219+ )
220
221
222 gpgkeysdir = os.path.join(os.path.dirname(__file__), 'data')
223@@ -127,11 +130,7 @@
224 if isinstance(content, unicode):
225 raise TypeError('Content cannot be Unicode.')
226
227- # setup context
228- ctx = gpgme.Context()
229- # Stick to GnuPG 1.
230- ctx.set_engine_info(gpgme.PROTOCOL_OpenPGP, "/usr/bin/gpg", None)
231- ctx.armor = True
232+ ctx = get_gpgme_context()
233
234 # setup containers
235 cipher = StringIO(content)
236
237=== modified file 'utilities/make-lp-user'
238--- utilities/make-lp-user 2019-02-23 07:41:11 +0000
239+++ utilities/make-lp-user 2019-03-22 19:58:42 +0000
240@@ -46,6 +46,7 @@
241 from lp.registry.interfaces.ssh import ISSHKeySet
242 from lp.registry.interfaces.teammembership import TeamMembershipStatus
243 from lp.services.gpg.interfaces import (
244+ get_gpg_path,
245 GPGKeyAlgorithm,
246 IGPGHandler,
247 )
248@@ -138,7 +139,7 @@
249 # Prevent translated gpg output from messing up our parsing.
250 env['LC_ALL'] = 'C'
251
252- command_line = ['gpg'] + arguments
253+ command_line = [get_gpg_path()] + arguments
254 pipe = subprocess.Popen(
255 command_line, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
256 stdout, stderr = pipe.communicate()