Gentoo Archives: gentoo-commits

From: "Michał Górny" <mgorny@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: man/, pym/portage/sync/modules/git/
Date: Mon, 05 Feb 2018 18:44:53
Message-Id: 1517856204.7a507942b669b6a157612e8f7ce3fe362c39b38f.mgorny@gentoo
1 commit: 7a507942b669b6a157612e8f7ce3fe362c39b38f
2 Author: Michał Górny <mgorny <AT> gentoo <DOT> org>
3 AuthorDate: Thu Feb 1 13:18:28 2018 +0000
4 Commit: Michał Górny <mgorny <AT> gentoo <DOT> org>
5 CommitDate: Mon Feb 5 18:43:24 2018 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=7a507942
7
8 git: Support verifying commit signature post-sync
9
10 Add a new sync-git-verify-commit-signature option (defaulting to false)
11 that verifies the top commit signature after syncing. The verification
12 is currently done using built-in git routines.
13
14 The verification passes if the signature is good or untrusted.
15 In the latter case, a warning is printed. In any other case,
16 the verification causes sync to fail and an appropriate error is output.
17
18 Reviewed-by: Zac Medico <zmedico <AT> gentoo.org>
19
20 man/portage.5 | 4 +++
21 pym/portage/sync/modules/git/__init__.py | 3 +-
22 pym/portage/sync/modules/git/git.py | 48 ++++++++++++++++++++++++++++++--
23 3 files changed, 52 insertions(+), 3 deletions(-)
24
25 diff --git a/man/portage.5 b/man/portage.5
26 index 54ce7eec9..549c51c73 100644
27 --- a/man/portage.5
28 +++ b/man/portage.5
29 @@ -1007,6 +1007,10 @@ See also example for sync-git-clone-env.
30 .B sync\-git\-pull\-extra\-opts
31 Extra options to give to git when updating repository (git pull).
32 .TP
33 +.B sync\-git\-verify\-commit\-signature = true|false
34 +Require the top commit in the repository to contain a good OpenPGP
35 +signature. Defaults to false.
36 +.TP
37 .B sync\-hooks\-only\-on\-change
38 If set to true, then sync of a given repository will not trigger postsync
39 hooks unless hooks would have executed for a master repository or the
40
41 diff --git a/pym/portage/sync/modules/git/__init__.py b/pym/portage/sync/modules/git/__init__.py
42 index 2f1d35226..270d97186 100644
43 --- a/pym/portage/sync/modules/git/__init__.py
44 +++ b/pym/portage/sync/modules/git/__init__.py
45 @@ -1,4 +1,4 @@
46 -# Copyright 2014-2017 Gentoo Foundation
47 +# Copyright 2014-2018 Gentoo Foundation
48 # Distributed under the terms of the GNU General Public License v2
49
50 doc = """Git plug-in module for portage.
51 @@ -58,6 +58,7 @@ module_spec = {
52 'sync-git-env',
53 'sync-git-pull-env',
54 'sync-git-pull-extra-opts',
55 + 'sync-git-verify-commit-signature',
56 ),
57 }
58 }
59
60 diff --git a/pym/portage/sync/modules/git/git.py b/pym/portage/sync/modules/git/git.py
61 index 8b4cab273..7e5ddf3b5 100644
62 --- a/pym/portage/sync/modules/git/git.py
63 +++ b/pym/portage/sync/modules/git/git.py
64 @@ -1,4 +1,4 @@
65 -# Copyright 2005-2017 Gentoo Foundation
66 +# Copyright 2005-2018 Gentoo Foundation
67 # Distributed under the terms of the GNU General Public License v2
68
69 import logging
70 @@ -7,7 +7,7 @@ import subprocess
71 import portage
72 from portage import os
73 from portage.util import writemsg_level, shlex_split
74 -from portage.output import create_color_func
75 +from portage.output import create_color_func, EOutput
76 good = create_color_func("GOOD")
77 bad = create_color_func("BAD")
78 warn = create_color_func("WARN")
79 @@ -71,6 +71,7 @@ class GitSync(NewBase):
80 else:
81 # default
82 git_cmd_opts += " --depth 1"
83 +
84 if self.repo.module_specific_options.get('sync-git-clone-extra-opts'):
85 git_cmd_opts += " %s" % self.repo.module_specific_options['sync-git-clone-extra-opts']
86 git_cmd = "%s clone%s %s ." % (self.bin_command, git_cmd_opts,
87 @@ -85,6 +86,8 @@ class GitSync(NewBase):
88 self.logger(self.xterm_titles, msg)
89 writemsg_level(msg + "\n", level=logging.ERROR, noiselevel=-1)
90 return (exitcode, False)
91 + if not self.verify_head():
92 + return (1, False)
93 return (os.EX_OK, True)
94
95
96 @@ -125,12 +128,53 @@ class GitSync(NewBase):
97 self.logger(self.xterm_titles, msg)
98 writemsg_level(msg + "\n", level=logging.ERROR, noiselevel=-1)
99 return (exitcode, False)
100 + if not self.verify_head():
101 + return (1, False)
102
103 current_rev = subprocess.check_output(rev_cmd,
104 cwd=portage._unicode_encode(self.repo.location))
105
106 return (os.EX_OK, current_rev != previous_rev)
107
108 + def verify_head(self):
109 + if (self.repo.module_specific_options.get(
110 + 'sync-git-verify-commit-signature', 'false') != 'true'):
111 + return True
112 +
113 + rev_cmd = [self.bin_command, "log", "--pretty=format:%G?", "-1"]
114 + try:
115 + status = (portage._unicode_decode(
116 + subprocess.check_output(rev_cmd,
117 + cwd=portage._unicode_encode(self.repo.location)))
118 + .strip())
119 + except subprocess.CalledProcessError:
120 + return False
121 +
122 + out = EOutput()
123 + if status == 'G': # good signature is good
124 + out.einfo('Trusted signature found on top commit')
125 + return True
126 + elif status == 'U': # untrusted
127 + out.ewarn('Top commit signature is valid but not trusted')
128 + return True
129 + else:
130 + if status == 'B':
131 + expl = 'bad signature'
132 + elif status == 'X':
133 + expl = 'expired signature'
134 + elif status == 'Y':
135 + expl = 'expired key'
136 + elif status == 'R':
137 + expl = 'revoked key'
138 + elif status == 'E':
139 + expl = 'unable to verify signature (missing key?)'
140 + elif status == 'N':
141 + expl = 'no signature'
142 + else:
143 + expl = 'unknown issue'
144 + out.eerror('No valid signature found: %s' % (expl,))
145 + return False
146 +
147 def retrieve_head(self, **kwargs):
148 '''Get information about the head commit'''
149 if kwargs: