Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH 2/2] webrsync: support sync-openpgp-key-path (bug 661838)
Date: Mon, 23 Jul 2018 05:40:45
Message-Id: 20180723053751.7900-3-zmedico@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH 0/2] webrsync: support sync-openpgp-key-path (bug 661838) by Zac Medico
1 Add repos.conf sync-webrsync-verify-signature = true|false setting that
2 enables sync-openpgp-key-path support like in the rsync and git sync
3 modules. This is disabled by default, in order to avoid interference
4 with legacy manual PORTAGE_GPG_DIR configuration.
5
6 When sync-webrsync-verify-signature = true is set in repos.conf,
7 if the PORTAGE_GPG_DIR has not been exported, emerge-webrsync will
8 assume that it has been called directly and it will output an error
9 message advising the user to instead call emerge --sync or emaint sync.
10
11 Bug: https://bugs.gentoo.org/661838
12 ---
13 bin/emerge-webrsync | 14 +++++-
14 lib/portage/sync/modules/webrsync/__init__.py | 4 +-
15 lib/portage/sync/modules/webrsync/webrsync.py | 69 +++++++++++++++++++++++----
16 man/portage.5 | 5 ++
17 4 files changed, 81 insertions(+), 11 deletions(-)
18
19 diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync
20 index b135567b7..a623f9b82 100755
21 --- a/bin/emerge-webrsync
22 +++ b/bin/emerge-webrsync
23 @@ -10,7 +10,13 @@
24 # - all output should prob be converted to e* funcs
25 # - add support for ROOT
26
27 +# repos.conf configuration for use with emerge --sync and emaint sync
28 +# using keyring from app-crypt/openpgp-keys-gentoo-release:
29 +# [gentoo]
30 +# sync-webrsync-verify-signature = true
31 +# sync-openpgp-key-path = /usr/share/openpgp-keys/gentoo-release.asc
32 #
33 +# Alternative (legacy) PORTAGE_GPG_DIR configuration:
34 # gpg key import
35 # KEY_ID=0x96D8BF6D
36 # gpg --homedir /etc/portage/gnupg --keyserver subkeys.pgp.net --recv-keys $KEY_ID
37 @@ -67,7 +73,13 @@ do_verbose=0
38 do_debug=0
39 keep=false
40
41 -if has webrsync-gpg ${FEATURES} ; then
42 +if has $(__repo_attr "${repo_name}" sync-webrsync-verify-signature) true yes; then
43 + if [[ ! -d ${PORTAGE_GPG_DIR} ]]; then
44 + eecho "Do not call ${argv0##*/} directly, instead call emerge --sync or emaint sync."
45 + exit 1
46 + fi
47 + WEBSYNC_VERIFY_SIGNATURE=1
48 +elif has webrsync-gpg ${FEATURES}; then
49 WEBSYNC_VERIFY_SIGNATURE=1
50 else
51 WEBSYNC_VERIFY_SIGNATURE=0
52 diff --git a/lib/portage/sync/modules/webrsync/__init__.py b/lib/portage/sync/modules/webrsync/__init__.py
53 index dc7def20c..1e09d1a47 100644
54 --- a/lib/portage/sync/modules/webrsync/__init__.py
55 +++ b/lib/portage/sync/modules/webrsync/__init__.py
56 @@ -45,7 +45,9 @@ module_spec = {
57 'exists and is a valid repository',
58 },
59 'validate_config': CheckSyncConfig,
60 - 'module_specific_options': (),
61 + 'module_specific_options': (
62 + 'sync-webrsync-verify-signature',
63 + ),
64 },
65 }
66 }
67 diff --git a/lib/portage/sync/modules/webrsync/webrsync.py b/lib/portage/sync/modules/webrsync/webrsync.py
68 index 3d79f4557..91780f7b2 100644
69 --- a/lib/portage/sync/modules/webrsync/webrsync.py
70 +++ b/lib/portage/sync/modules/webrsync/webrsync.py
71 @@ -1,17 +1,25 @@
72
73 '''WebRsync module for portage'''
74
75 +import io
76 import logging
77
78 import portage
79 from portage import os
80 from portage.util import writemsg_level
81 +from portage.util.futures import asyncio
82 from portage.output import create_color_func
83 good = create_color_func("GOOD")
84 bad = create_color_func("BAD")
85 warn = create_color_func("WARN")
86 from portage.sync.syncbase import SyncBase
87
88 +try:
89 + from gemato.exceptions import GematoException
90 + import gemato.openpgp
91 +except ImportError:
92 + gemato = None
93 +
94
95 class WebRsync(SyncBase):
96 '''WebRSync sync class'''
97 @@ -39,15 +47,58 @@ class WebRsync(SyncBase):
98 for var in ['uid', 'gid', 'groups']:
99 self.spawn_kwargs.pop(var, None)
100
101 - exitcode = portage.process.spawn_bash("%s" % \
102 - (self.bin_command),
103 - **self.spawn_kwargs)
104 - if exitcode != os.EX_OK:
105 - msg = "!!! emerge-webrsync error in %s" % self.repo.location
106 - self.logger(self.xterm_titles, msg)
107 - writemsg_level(msg + "\n", level=logging.ERROR, noiselevel=-1)
108 - return (exitcode, False)
109 - return (exitcode, True)
110 + verbose = '--verbose' in self.options['emerge_config'].opts
111 + quiet = '--quiet' in self.options['emerge_config'].opts
112 + openpgp_env = None
113 + try:
114 + if self.repo.module_specific_options.get(
115 + 'sync-webrsync-verify-signature', 'false') in ('true', 'yes'):
116 +
117 + if not self.repo.sync_openpgp_key_path:
118 + writemsg_level("!!! sync-openpgp-key-path is not set\n",
119 + level=logging.ERROR, noiselevel=-1)
120 + return (1, False)
121 +
122 + if not os.path.isfile(self.repo.sync_openpgp_key_path):
123 + writemsg_level("!!! sync-openpgp-key-path file not found: %s\n" %
124 + self.repo.sync_openpgp_key_path, level=logging.ERROR, noiselevel=-1)
125 + return (1, False)
126 +
127 + if gemato is None:
128 + writemsg_level("!!! Verifying against specified key requires gemato-11.0+ installed\n",
129 + level=logging.ERROR, noiselevel=-1)
130 + return (1, False)
131 +
132 + openpgp_env = gemato.openpgp.OpenPGPEnvironment()
133 +
134 + out = portage.output.EOutput(quiet=quiet)
135 + try:
136 + out.einfo('Using keys from %s' % (self.repo.sync_openpgp_key_path,))
137 + with io.open(self.repo.sync_openpgp_key_path, 'rb') as f:
138 + openpgp_env.import_key(f)
139 + self._refresh_keys(openpgp_env)
140 + self.spawn_kwargs["env"]["PORTAGE_GPG_DIR"] = openpgp_env.home
141 + except (GematoException, asyncio.TimeoutError) as e:
142 + writemsg_level("!!! Verification impossible due to keyring problem:\n%s\n"
143 + % (e,),
144 + level=logging.ERROR, noiselevel=-1)
145 + return (1, False)
146 +
147 + webrsync_cmd = [self.bin_command]
148 + if verbose:
149 + webrsync_cmd.append('--verbose')
150 + elif quiet:
151 + webrsync_cmd.append('--quiet')
152 + exitcode = portage.process.spawn(webrsync_cmd, **self.spawn_kwargs)
153 + if exitcode != os.EX_OK:
154 + msg = "!!! emerge-webrsync error in %s" % self.repo.location
155 + self.logger(self.xterm_titles, msg)
156 + writemsg_level(msg + "\n", level=logging.ERROR, noiselevel=-1)
157 + return (exitcode, False)
158 + return (exitcode, True)
159 + finally:
160 + if openpgp_env is not None:
161 + openpgp_env.close()
162
163
164 class PyWebRsync(SyncBase):
165 diff --git a/man/portage.5 b/man/portage.5
166 index a57531d44..8ebf980f5 100644
167 --- a/man/portage.5
168 +++ b/man/portage.5
169 @@ -1127,6 +1127,11 @@ when 0. Defaults to disabled.
170 .B sync\-rsync\-verify\-metamanifest = yes|no
171 Require the repository to contain a signed MetaManifest and verify
172 it using \fBapp\-portage/gemato\fR. Defaults to no.
173 +.TP
174 +.B sync\-webrsync\-verify\-signature = true|false
175 +Require the detached tarball signature to contain a good OpenPGP
176 +signature. This uses the OpenPGP key(ring) specified by the
177 +sync\-openpgp\-key\-path setting. Defaults to false.
178
179 .RE
180
181 --
182 2.13.6