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