Discussion:
[gentoo-portage-dev] [PATCH 0/2] webrsync: support sync-openpgp-key-path (bug 661838)
Zac Medico
2018-07-23 05:37:49 UTC
Permalink
Add repos.conf sync-webrsync-verify-signature = true|false setting that
enables sync-openpgp-key-path support like in the rsync and git sync
modules. This is disabled by default, in order to avoid interference
with legacy manual PORTAGE_GPG_DIR configuration.

When sync-webrsync-verify-signature = true is set in repos.conf,
if the PORTAGE_GPG_DIR has not been exported, emerge-webrsync will
assume that it has been called directly and it will output an error
message advising the user to instead call emerge --sync or emaint sync.

Bug: https://bugs.gentoo.org/661838

Zac Medico (2):
emerge-webrsync: exit early for signature problem (bug 661838)
webrsync: support sync-openpgp-key-path (bug 661838)

bin/emerge-webrsync | 21 +++++++-
lib/portage/sync/modules/webrsync/__init__.py | 4 +-
lib/portage/sync/modules/webrsync/webrsync.py | 69 +++++++++++++++++++++++----
man/portage.5 | 5 ++
4 files changed, 88 insertions(+), 11 deletions(-)
--
2.13.6
Zac Medico
2018-07-23 05:37:50 UTC
Permalink
Exit early after signature verification failure, since it's
typically inappropriate to try other mirrors in this case
(it may indicate a keyring problem).

Bug: https://bugs.gentoo.org/661838
---
bin/emerge-webrsync | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync
index 560dd0236..b135567b7 100755
--- a/bin/emerge-webrsync
+++ b/bin/emerge-webrsync
@@ -191,6 +191,13 @@ check_file_signature() {
fi
done <<< "${gnupg_status}"
fi
+ if [[ ${r} -ne 0 ]]; then
+ # Exit early since it's typically inappropriate to
+ # try other mirrors in this case (it may indicate
+ # a keyring problem).
+ eecho "signature verification failed"
+ exit 1
+ fi
else
eecho "cannot check signature: gpg binary not found"
exit 1
--
2.13.6
Zac Medico
2018-07-23 05:37:51 UTC
Permalink
Add repos.conf sync-webrsync-verify-signature = true|false setting that
enables sync-openpgp-key-path support like in the rsync and git sync
modules. This is disabled by default, in order to avoid interference
with legacy manual PORTAGE_GPG_DIR configuration.

When sync-webrsync-verify-signature = true is set in repos.conf,
if the PORTAGE_GPG_DIR has not been exported, emerge-webrsync will
assume that it has been called directly and it will output an error
message advising the user to instead call emerge --sync or emaint sync.

Bug: https://bugs.gentoo.org/661838
---
bin/emerge-webrsync | 14 +++++-
lib/portage/sync/modules/webrsync/__init__.py | 4 +-
lib/portage/sync/modules/webrsync/webrsync.py | 69 +++++++++++++++++++++++----
man/portage.5 | 5 ++
4 files changed, 81 insertions(+), 11 deletions(-)

diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync
index b135567b7..a623f9b82 100755
--- a/bin/emerge-webrsync
+++ b/bin/emerge-webrsync
@@ -10,7 +10,13 @@
# - all output should prob be converted to e* funcs
# - add support for ROOT

+# repos.conf configuration for use with emerge --sync and emaint sync
+# using keyring from app-crypt/openpgp-keys-gentoo-release:
+# [gentoo]
+# sync-webrsync-verify-signature = true
+# sync-openpgp-key-path = /usr/share/openpgp-keys/gentoo-release.asc
#
+# Alternative (legacy) PORTAGE_GPG_DIR configuration:
# gpg key import
# KEY_ID=0x96D8BF6D
# gpg --homedir /etc/portage/gnupg --keyserver subkeys.pgp.net --recv-keys $KEY_ID
@@ -67,7 +73,13 @@ do_verbose=0
do_debug=0
keep=false

-if has webrsync-gpg ${FEATURES} ; then
+if has $(__repo_attr "${repo_name}" sync-webrsync-verify-signature) true yes; then
+ if [[ ! -d ${PORTAGE_GPG_DIR} ]]; then
+ eecho "Do not call ${argv0##*/} directly, instead call emerge --sync or emaint sync."
+ exit 1
+ fi
+ WEBSYNC_VERIFY_SIGNATURE=1
+elif has webrsync-gpg ${FEATURES}; then
WEBSYNC_VERIFY_SIGNATURE=1
else
WEBSYNC_VERIFY_SIGNATURE=0
diff --git a/lib/portage/sync/modules/webrsync/__init__.py b/lib/portage/sync/modules/webrsync/__init__.py
index dc7def20c..1e09d1a47 100644
--- a/lib/portage/sync/modules/webrsync/__init__.py
+++ b/lib/portage/sync/modules/webrsync/__init__.py
@@ -45,7 +45,9 @@ module_spec = {
'exists and is a valid repository',
},
'validate_config': CheckSyncConfig,
- 'module_specific_options': (),
+ 'module_specific_options': (
+ 'sync-webrsync-verify-signature',
+ ),
},
}
}
diff --git a/lib/portage/sync/modules/webrsync/webrsync.py b/lib/portage/sync/modules/webrsync/webrsync.py
index 3d79f4557..91780f7b2 100644
--- a/lib/portage/sync/modules/webrsync/webrsync.py
+++ b/lib/portage/sync/modules/webrsync/webrsync.py
@@ -1,17 +1,25 @@

'''WebRsync module for portage'''

+import io
import logging

import portage
from portage import os
from portage.util import writemsg_level
+from portage.util.futures import asyncio
from portage.output import create_color_func
good = create_color_func("GOOD")
bad = create_color_func("BAD")
warn = create_color_func("WARN")
from portage.sync.syncbase import SyncBase

+try:
+ from gemato.exceptions import GematoException
+ import gemato.openpgp
+except ImportError:
+ gemato = None
+

class WebRsync(SyncBase):
'''WebRSync sync class'''
@@ -39,15 +47,58 @@ class WebRsync(SyncBase):
for var in ['uid', 'gid', 'groups']:
self.spawn_kwargs.pop(var, None)

- exitcode = portage.process.spawn_bash("%s" % \
- (self.bin_command),
- **self.spawn_kwargs)
- if exitcode != os.EX_OK:
- msg = "!!! emerge-webrsync error in %s" % self.repo.location
- self.logger(self.xterm_titles, msg)
- writemsg_level(msg + "\n", level=logging.ERROR, noiselevel=-1)
- return (exitcode, False)
- return (exitcode, True)
+ verbose = '--verbose' in self.options['emerge_config'].opts
+ quiet = '--quiet' in self.options['emerge_config'].opts
+ openpgp_env = None
+ try:
+ if self.repo.module_specific_options.get(
+ 'sync-webrsync-verify-signature', 'false') in ('true', 'yes'):
+
+ if not self.repo.sync_openpgp_key_path:
+ writemsg_level("!!! sync-openpgp-key-path is not set\n",
+ level=logging.ERROR, noiselevel=-1)
+ return (1, False)
+
+ if not os.path.isfile(self.repo.sync_openpgp_key_path):
+ writemsg_level("!!! sync-openpgp-key-path file not found: %s\n" %
+ self.repo.sync_openpgp_key_path, level=logging.ERROR, noiselevel=-1)
+ return (1, False)
+
+ if gemato is None:
+ writemsg_level("!!! Verifying against specified key requires gemato-11.0+ installed\n",
+ level=logging.ERROR, noiselevel=-1)
+ return (1, False)
+
+ openpgp_env = gemato.openpgp.OpenPGPEnvironment()
+
+ out = portage.output.EOutput(quiet=quiet)
+ try:
+ out.einfo('Using keys from %s' % (self.repo.sync_openpgp_key_path,))
+ with io.open(self.repo.sync_openpgp_key_path, 'rb') as f:
+ openpgp_env.import_key(f)
+ self._refresh_keys(openpgp_env)
+ self.spawn_kwargs["env"]["PORTAGE_GPG_DIR"] = openpgp_env.home
+ except (GematoException, asyncio.TimeoutError) as e:
+ writemsg_level("!!! Verification impossible due to keyring problem:\n%s\n"
+ % (e,),
+ level=logging.ERROR, noiselevel=-1)
+ return (1, False)
+
+ webrsync_cmd = [self.bin_command]
+ if verbose:
+ webrsync_cmd.append('--verbose')
+ elif quiet:
+ webrsync_cmd.append('--quiet')
+ exitcode = portage.process.spawn(webrsync_cmd, **self.spawn_kwargs)
+ if exitcode != os.EX_OK:
+ msg = "!!! emerge-webrsync error in %s" % self.repo.location
+ self.logger(self.xterm_titles, msg)
+ writemsg_level(msg + "\n", level=logging.ERROR, noiselevel=-1)
+ return (exitcode, False)
+ return (exitcode, True)
+ finally:
+ if openpgp_env is not None:
+ openpgp_env.close()


class PyWebRsync(SyncBase):
diff --git a/man/portage.5 b/man/portage.5
index a57531d44..8ebf980f5 100644
--- a/man/portage.5
+++ b/man/portage.5
@@ -1127,6 +1127,11 @@ when 0. Defaults to disabled.
.B sync\-rsync\-verify\-metamanifest = yes|no
Require the repository to contain a signed MetaManifest and verify
it using \fBapp\-portage/gemato\fR. Defaults to no.
+.TP
+.B sync\-webrsync\-verify\-signature = true|false
+Require the detached tarball signature to contain a good OpenPGP
+signature. This uses the OpenPGP key(ring) specified by the
+sync\-openpgp\-key\-path setting. Defaults to false.

.RE
--
2.13.6
Loading...