Merge lp:~cjwatson/launchpad/snap-tools-fingerprint into lp:launchpad
- snap-tools-fingerprint
- Merge into devel
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 18408 |
Proposed branch: | lp:~cjwatson/launchpad/snap-tools-fingerprint |
Merge into: | lp:launchpad |
Diff against target: |
207 lines (+59/-25) 5 files modified
lib/lp/services/config/schema-lazr.conf (+5/-0) lib/lp/snappy/tests/test_snapbuildbehaviour.py (+1/-1) lib/lp/soyuz/adapters/archivedependencies.py (+32/-22) lib/lp/soyuz/adapters/tests/test_archivedependencies.py (+18/-2) lib/lp/soyuz/tests/soyuz.py (+3/-0) |
To merge this branch: | bzr merge lp:~cjwatson/launchpad/snap-tools-fingerprint |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+325620@code.launchpad.net |
Commit message
Allow configuring a fingerprint for the archive given in snappy.
Description of the change
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/config/schema-lazr.conf' | |||
2 | --- lib/lp/services/config/schema-lazr.conf 2017-06-01 12:05:30 +0000 | |||
3 | +++ lib/lp/services/config/schema-lazr.conf 2017-06-14 08:12:16 +0000 | |||
4 | @@ -1804,6 +1804,11 @@ | |||
5 | 1804 | # datatype: string | 1804 | # datatype: string |
6 | 1805 | tools_source: none | 1805 | tools_source: none |
7 | 1806 | 1806 | ||
8 | 1807 | # Optional OpenPGP signing key fingerprint for the archive given in | ||
9 | 1808 | # tools_source. | ||
10 | 1809 | # datatype: string | ||
11 | 1810 | tools_fingerprint: none | ||
12 | 1811 | |||
13 | 1807 | # The store's primary URL endpoint. | 1812 | # The store's primary URL endpoint. |
14 | 1808 | store_url: none | 1813 | store_url: none |
15 | 1809 | 1814 | ||
16 | 1810 | 1815 | ||
17 | === modified file 'lib/lp/snappy/tests/test_snapbuildbehaviour.py' | |||
18 | --- lib/lp/snappy/tests/test_snapbuildbehaviour.py 2017-06-13 17:08:16 +0000 | |||
19 | +++ lib/lp/snappy/tests/test_snapbuildbehaviour.py 2017-06-14 08:12:16 +0000 | |||
20 | @@ -69,7 +69,7 @@ | |||
21 | 69 | 69 | ||
22 | 70 | def setUp(self): | 70 | def setUp(self): |
23 | 71 | super(TestSnapBuildBehaviourBase, self).setUp() | 71 | super(TestSnapBuildBehaviourBase, self).setUp() |
25 | 72 | self.pushConfig("snappy", tools_source=None) | 72 | self.pushConfig("snappy", tools_source=None, tools_fingerprint=None) |
26 | 73 | 73 | ||
27 | 74 | def makeJob(self, archive=None, pocket=PackagePublishingPocket.UPDATES, | 74 | def makeJob(self, archive=None, pocket=PackagePublishingPocket.UPDATES, |
28 | 75 | **kwargs): | 75 | **kwargs): |
29 | 76 | 76 | ||
30 | === modified file 'lib/lp/soyuz/adapters/archivedependencies.py' | |||
31 | --- lib/lp/soyuz/adapters/archivedependencies.py 2017-04-29 23:51:28 +0000 | |||
32 | +++ lib/lp/soyuz/adapters/archivedependencies.py 2017-06-14 08:12:16 +0000 | |||
33 | @@ -153,7 +153,8 @@ | |||
34 | 153 | 153 | ||
35 | 154 | 154 | ||
36 | 155 | def expand_dependencies(archive, distro_arch_series, pocket, component, | 155 | def expand_dependencies(archive, distro_arch_series, pocket, component, |
38 | 156 | source_package_name, tools_source=None, logger=None): | 156 | source_package_name, tools_source=None, |
39 | 157 | tools_fingerprint=None, logger=None): | ||
40 | 157 | """Return the set of dependency archives, pockets and components. | 158 | """Return the set of dependency archives, pockets and components. |
41 | 158 | 159 | ||
42 | 159 | :param archive: the context `IArchive`. | 160 | :param archive: the context `IArchive`. |
43 | @@ -164,6 +165,8 @@ | |||
44 | 164 | :param tools_source: if not None, a sources.list entry to use as an | 165 | :param tools_source: if not None, a sources.list entry to use as an |
45 | 165 | additional dependency for build tools, just before the default | 166 | additional dependency for build tools, just before the default |
46 | 166 | primary archive. | 167 | primary archive. |
47 | 168 | :param tools_fingerprint: if not None, the OpenPGP signing key | ||
48 | 169 | fingerprint for the archive given in `tools_source`. | ||
49 | 167 | :param logger: an optional logger. | 170 | :param logger: an optional logger. |
50 | 168 | :return: a list of (archive, distro_arch_series, pocket, [component]), | 171 | :return: a list of (archive, distro_arch_series, pocket, [component]), |
51 | 169 | representing the dependencies defined by the given build context. | 172 | representing the dependencies defined by the given build context. |
52 | @@ -201,7 +204,9 @@ | |||
53 | 201 | # Consider build tools archive dependencies. | 204 | # Consider build tools archive dependencies. |
54 | 202 | if tools_source is not None: | 205 | if tools_source is not None: |
55 | 203 | try: | 206 | try: |
57 | 204 | deps.append(tools_source % {'series': distro_series.name}) | 207 | deps.append( |
58 | 208 | (tools_source % {'series': distro_series.name}, | ||
59 | 209 | tools_fingerprint)) | ||
60 | 205 | except Exception: | 210 | except Exception: |
61 | 206 | # Someone messed up the configuration; don't add it. | 211 | # Someone messed up the configuration; don't add it. |
62 | 207 | if logger is not None: | 212 | if logger is not None: |
63 | @@ -240,7 +245,8 @@ | |||
64 | 240 | 245 | ||
65 | 241 | @defer.inlineCallbacks | 246 | @defer.inlineCallbacks |
66 | 242 | def get_sources_list_for_building(build, distroarchseries, sourcepackagename, | 247 | def get_sources_list_for_building(build, distroarchseries, sourcepackagename, |
68 | 243 | tools_source=None, logger=None): | 248 | tools_source=None, tools_fingerprint=None, |
69 | 249 | logger=None): | ||
70 | 244 | """Return sources.list entries and keys required to build the given item. | 250 | """Return sources.list entries and keys required to build the given item. |
71 | 245 | 251 | ||
72 | 246 | The sources.list entries are returned in the order that is most useful: | 252 | The sources.list entries are returned in the order that is most useful: |
73 | @@ -257,6 +263,8 @@ | |||
74 | 257 | :param tools_source: if not None, a sources.list entry to use as an | 263 | :param tools_source: if not None, a sources.list entry to use as an |
75 | 258 | additional dependency for build tools, just before the default | 264 | additional dependency for build tools, just before the default |
76 | 259 | primary archive. | 265 | primary archive. |
77 | 266 | :param tools_fingerprint: if not None, the OpenPGP signing key | ||
78 | 267 | fingerprint for the archive given in `tools_source`. | ||
79 | 260 | :param logger: an optional logger. | 268 | :param logger: an optional logger. |
80 | 261 | :return: a Deferred resolving to a tuple containing a list of deb | 269 | :return: a Deferred resolving to a tuple containing a list of deb |
81 | 262 | sources.list entries (lines) and a list of base64-encoded public | 270 | sources.list entries (lines) and a list of base64-encoded public |
82 | @@ -265,7 +273,8 @@ | |||
83 | 265 | deps = expand_dependencies( | 273 | deps = expand_dependencies( |
84 | 266 | build.archive, distroarchseries, build.pocket, | 274 | build.archive, distroarchseries, build.pocket, |
85 | 267 | build.current_component, sourcepackagename, | 275 | build.current_component, sourcepackagename, |
87 | 268 | tools_source=tools_source, logger=logger) | 276 | tools_source=tools_source, tools_fingerprint=tools_fingerprint, |
88 | 277 | logger=logger) | ||
89 | 269 | sources_list_lines, trusted_keys = ( | 278 | sources_list_lines, trusted_keys = ( |
90 | 270 | yield _get_sources_list_for_dependencies(deps, logger=logger)) | 279 | yield _get_sources_list_for_dependencies(deps, logger=logger)) |
91 | 271 | 280 | ||
92 | @@ -360,8 +369,9 @@ | |||
93 | 360 | # interaction. | 369 | # interaction. |
94 | 361 | gpghandler = removeSecurityProxy(getUtility(IGPGHandler)) | 370 | gpghandler = removeSecurityProxy(getUtility(IGPGHandler)) |
95 | 362 | for dep in dependencies: | 371 | for dep in dependencies: |
98 | 363 | if isinstance(dep, basestring): | 372 | if len(dep) == 2: |
99 | 364 | sources_list_lines.append(dep) | 373 | sources_list_line, fingerprint = dep |
100 | 374 | sources_list_lines.append(sources_list_line) | ||
101 | 365 | else: | 375 | else: |
102 | 366 | archive, distro_arch_series, pocket, components = dep | 376 | archive, distro_arch_series, pocket, components = dep |
103 | 367 | has_published_binaries = _has_published_binaries( | 377 | has_published_binaries = _has_published_binaries( |
104 | @@ -379,23 +389,23 @@ | |||
105 | 379 | archive, distro_arch_series, pocket, components) | 389 | archive, distro_arch_series, pocket, components) |
106 | 380 | sources_list_lines.append(sources_list_line) | 390 | sources_list_lines.append(sources_list_line) |
107 | 381 | fingerprint = archive.signing_key_fingerprint | 391 | fingerprint = archive.signing_key_fingerprint |
121 | 382 | if fingerprint is not None and fingerprint not in trusted_keys: | 392 | if fingerprint is not None and fingerprint not in trusted_keys: |
122 | 383 | def get_key(): | 393 | def get_key(): |
123 | 384 | with default_timeout(15.0): | 394 | with default_timeout(15.0): |
124 | 385 | try: | 395 | try: |
125 | 386 | return gpghandler.retrieveKey(fingerprint) | 396 | return gpghandler.retrieveKey(fingerprint) |
126 | 387 | except GPGKeyNotFoundError as e: | 397 | except GPGKeyNotFoundError as e: |
127 | 388 | # For now, just log this and proceed without the | 398 | # For now, just log this and proceed without the |
128 | 389 | # key. We'll have to fix any outstanding cases | 399 | # key. We'll have to fix any outstanding cases of |
129 | 390 | # of this before we can switch to requiring | 400 | # this before we can switch to requiring |
130 | 391 | # authentication across the board. | 401 | # authentication across the board. |
131 | 392 | if logger is not None: | 402 | if logger is not None: |
132 | 393 | logger.warning(str(e)) | 403 | logger.warning(str(e)) |
133 | 394 | return None | 404 | return None |
134 | 395 | 405 | ||
138 | 396 | key = yield deferToThread(get_key) | 406 | key = yield deferToThread(get_key) |
139 | 397 | if key is not None: | 407 | if key is not None: |
140 | 398 | trusted_keys[fingerprint] = base64.b64encode(key.export()) | 408 | trusted_keys[fingerprint] = base64.b64encode(key.export()) |
141 | 399 | 409 | ||
142 | 400 | defer.returnValue( | 410 | defer.returnValue( |
143 | 401 | (sources_list_lines, [v for k, v in sorted(trusted_keys.items())])) | 411 | (sources_list_lines, [v for k, v in sorted(trusted_keys.items())])) |
144 | 402 | 412 | ||
145 | === modified file 'lib/lp/soyuz/adapters/tests/test_archivedependencies.py' | |||
146 | --- lib/lp/soyuz/adapters/tests/test_archivedependencies.py 2017-06-13 17:22:44 +0000 | |||
147 | +++ lib/lp/soyuz/adapters/tests/test_archivedependencies.py 2017-06-14 08:12:16 +0000 | |||
148 | @@ -16,7 +16,9 @@ | |||
149 | 16 | ) | 16 | ) |
150 | 17 | import transaction | 17 | import transaction |
151 | 18 | from twisted.internet import defer | 18 | from twisted.internet import defer |
152 | 19 | from twisted.internet.threads import deferToThread | ||
153 | 19 | from zope.component import getUtility | 20 | from zope.component import getUtility |
154 | 21 | from zope.security.proxy import removeSecurityProxy | ||
155 | 20 | 22 | ||
156 | 21 | from lp.archivepublisher.interfaces.archivesigningkey import ( | 23 | from lp.archivepublisher.interfaces.archivesigningkey import ( |
157 | 22 | IArchiveSigningKey, | 24 | IArchiveSigningKey, |
158 | @@ -24,6 +26,7 @@ | |||
159 | 24 | from lp.registry.interfaces.distribution import IDistributionSet | 26 | from lp.registry.interfaces.distribution import IDistributionSet |
160 | 25 | from lp.registry.interfaces.pocket import PackagePublishingPocket | 27 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
161 | 26 | from lp.services.config import config | 28 | from lp.services.config import config |
162 | 29 | from lp.services.gpg.interfaces import IGPGHandler | ||
163 | 27 | from lp.services.log.logger import BufferLogger | 30 | from lp.services.log.logger import BufferLogger |
164 | 28 | from lp.soyuz.adapters.archivedependencies import ( | 31 | from lp.soyuz.adapters.archivedependencies import ( |
165 | 29 | default_component_dependency_name, | 32 | default_component_dependency_name, |
166 | @@ -522,6 +525,18 @@ | |||
167 | 522 | # sources.list, which is useful for specialised build types. | 525 | # sources.list, which is useful for specialised build types. |
168 | 523 | ppa = yield self.makeArchive(publish_binary=True) | 526 | ppa = yield self.makeArchive(publish_binary=True) |
169 | 524 | build = self.makeBuild(archive=ppa) | 527 | build = self.makeBuild(archive=ppa) |
170 | 528 | |||
171 | 529 | # Upload the tools archive key to the keyserver. | ||
172 | 530 | tools_key_name = "ppa-sample-4096@canonical.com" | ||
173 | 531 | tools_key_path = os.path.join(gpgkeysdir, "%s.sec" % tools_key_name) | ||
174 | 532 | with open(tools_key_path) as tools_key_file: | ||
175 | 533 | secret_key_export = tools_key_file.read() | ||
176 | 534 | # Remove security proxy to avoid problems with running in a thread. | ||
177 | 535 | gpghandler = removeSecurityProxy(getUtility(IGPGHandler)) | ||
178 | 536 | gpghandler.importSecretKey(secret_key_export) | ||
179 | 537 | yield deferToThread( | ||
180 | 538 | gpghandler.uploadPublicKey, self.fingerprints[tools_key_name]) | ||
181 | 539 | |||
182 | 525 | yield self.assertSourcesListAndKeys( | 540 | yield self.assertSourcesListAndKeys( |
183 | 526 | [(ppa, ["hoary main"]), | 541 | [(ppa, ["hoary main"]), |
184 | 527 | ("deb http://example.org", ["hoary main"]), | 542 | ("deb http://example.org", ["hoary main"]), |
185 | @@ -531,8 +546,9 @@ | |||
186 | 531 | "hoary-updates main restricted universe multiverse", | 546 | "hoary-updates main restricted universe multiverse", |
187 | 532 | ]), | 547 | ]), |
188 | 533 | ], | 548 | ], |
191 | 534 | ["ppa-sample@canonical.com"], build, | 549 | ["ppa-sample@canonical.com", tools_key_name], build, |
192 | 535 | tools_source="deb http://example.org %(series)s main") | 550 | tools_source="deb http://example.org %(series)s main", |
193 | 551 | tools_fingerprint=self.fingerprints[tools_key_name]) | ||
194 | 536 | 552 | ||
195 | 537 | @defer.inlineCallbacks | 553 | @defer.inlineCallbacks |
196 | 538 | def test_build_tools_bad_formatting(self): | 554 | def test_build_tools_bad_formatting(self): |
197 | 539 | 555 | ||
198 | === modified file 'lib/lp/soyuz/tests/soyuz.py' | |||
199 | --- lib/lp/soyuz/tests/soyuz.py 2017-04-29 23:51:28 +0000 | |||
200 | +++ lib/lp/soyuz/tests/soyuz.py 2017-06-14 08:12:16 +0000 | |||
201 | @@ -114,3 +114,6 @@ | |||
202 | 114 | key = base64.b64decode(encoded_key) | 114 | key = base64.b64decode(encoded_key) |
203 | 115 | return Equals(self.fingerprint).match( | 115 | return Equals(self.fingerprint).match( |
204 | 116 | getUtility(IGPGHandler).importPublicKey(key).fingerprint) | 116 | getUtility(IGPGHandler).importPublicKey(key).fingerprint) |
205 | 117 | |||
206 | 118 | def __str__(self): | ||
207 | 119 | return "Base64KeyMatches(%s)" % self.fingerprint |