Gentoo Archives: gentoo-commits

From: "Michał Górny" <mgorny@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: eclass/
Date: Sat, 10 Oct 2020 18:21:38
Message-Id: 1602354086.f302f3b08b352dc4ac1c89dec343cd89093a04d6.mgorny@gentoo
1 commit: f302f3b08b352dc4ac1c89dec343cd89093a04d6
2 Author: Michał Górny <mgorny <AT> gentoo <DOT> org>
3 AuthorDate: Sun Sep 6 16:00:51 2020 +0000
4 Commit: Michał Górny <mgorny <AT> gentoo <DOT> org>
5 CommitDate: Sat Oct 10 18:21:26 2020 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=f302f3b0
7
8 verify-sig.eclass: New eclass to verify OpenPGP sigs
9
10 verify-sig eclass provides a streamlined approach to verifying upstream
11 signatures on distfiles. Its primary purpose is to permit developers
12 to easily verify signatures while bumping packages. The eclass removes
13 the risk of developer forgetting to perform the verification,
14 or performing it incorrectly, e.g. due to additional keys in the local
15 keyring. It also permits users to verify the developer's work.
16
17 Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>
18
19 eclass/verify-sig.eclass | 177 +++++++++++++++++++++++++++++++++++++++++++++++
20 1 file changed, 177 insertions(+)
21
22 diff --git a/eclass/verify-sig.eclass b/eclass/verify-sig.eclass
23 new file mode 100644
24 index 00000000000..c075ff66217
25 --- /dev/null
26 +++ b/eclass/verify-sig.eclass
27 @@ -0,0 +1,177 @@
28 +# Copyright 2020 Gentoo Authors
29 +# Distributed under the terms of the GNU General Public License v2
30 +
31 +# @ECLASS: verify-sig.eclass
32 +# @MAINTAINER:
33 +# Michał Górny <mgorny@g.o>
34 +# @SUPPORTED_EAPIS: 7
35 +# @AUTHOR:
36 +# Michał Górny <mgorny@g.o>
37 +# @BLURB: Eclass to verify upstream signatures on distfiles
38 +# @DESCRIPTION:
39 +# verify-sig eclass provides a streamlined approach to verifying
40 +# upstream signatures on distfiles. Its primary purpose is to permit
41 +# developers to easily verify signatures while bumping packages.
42 +# The eclass removes the risk of developer forgetting to perform
43 +# the verification, or performing it incorrectly, e.g. due to additional
44 +# keys in the local keyring. It also permits users to verify
45 +# the developer's work.
46 +#
47 +# To use the eclass, start by packaging the upstream's key
48 +# as app-crypt/openpgp-keys-*. Then inherit the eclass, add detached
49 +# signatures to SRC_URI and set VERIFY_SIG_OPENPGP_KEY_PATH. The eclass
50 +# provides verify-sig USE flag to toggle the verification.
51 +#
52 +# Example use:
53 +# @CODE
54 +# inherit verify-sig
55 +#
56 +# SRC_URI="https://example.org/${P}.tar.gz
57 +# verify-sig? ( https://example.org/${P}.tar.gz.sig )"
58 +# BDEPEND="
59 +# verify-sig? ( app-crypt/openpgp-keys-example )"
60 +#
61 +# VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/openpgp-keys/example.asc
62 +# @CODE
63 +
64 +case "${EAPI:-0}" in
65 + 0|1|2|3|4|5|6)
66 + die "Unsupported EAPI=${EAPI} (obsolete) for ${ECLASS}"
67 + ;;
68 + 7)
69 + ;;
70 + *)
71 + die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
72 + ;;
73 +esac
74 +
75 +EXPORT_FUNCTIONS src_unpack
76 +
77 +if [[ ! ${_VERIFY_SIG_ECLASS} ]]; then
78 +
79 +IUSE="verify-sig"
80 +
81 +BDEPEND="
82 + verify-sig? (
83 + app-crypt/gnupg
84 + >=app-portage/gemato-16
85 + )"
86 +
87 +# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEY_PATH
88 +# @DEFAULT_UNSET
89 +# @DESCRIPTION:
90 +# Path to key bundle used to perform the verification. This is required
91 +# when using default src_unpack. Alternatively, the key path can be
92 +# passed directly to the verification functions.
93 +
94 +# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEYSERVER
95 +# @DEFAULT_UNSET
96 +# @DESCRIPTION:
97 +# Keyserver used to refresh keys. If not specified, the keyserver
98 +# preference from the key will be respected. If no preference
99 +# is specified by the key, the GnuPG default will be used.
100 +
101 +# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEY_REFRESH
102 +# @USER_VARIABLE
103 +# @DESCRIPTION:
104 +# Attempt to refresh keys via WKD/keyserver. Set it to "yes"
105 +# in make.conf to enable. Note that this requires working Internet
106 +# connection.
107 +: ${VERIFY_SIG_OPENPGP_KEY_REFRESH:=no}
108 +
109 +# @FUNCTION: verify-sig_verify_detached
110 +# @USAGE: <file> <sig-file> [<key-file>]
111 +# @DESCRIPTION:
112 +# Read the detached signature from <sig-file> and verify <file> against
113 +# it. <key-file> can either be passed directly, or it defaults
114 +# to VERIFY_SIG_OPENPGP_KEY_PATH. The function dies if verification
115 +# fails.
116 +verify-sig_verify_detached() {
117 + local file=${1}
118 + local sig=${2}
119 + local key=${3:-${VERIFY_SIG_OPENPGP_KEY_PATH}}
120 +
121 + [[ -n ${key} ]] ||
122 + die "${FUNCNAME}: no key passed and VERIFY_SIG_OPENPGP_KEY_PATH unset"
123 +
124 + local extra_args=()
125 + [[ ${VERIFY_SIG_OPENPGP_KEY_REFRESH} == yes ]] || extra_args+=( -R )
126 + [[ -n ${VERIFY_SIG_OPENPGP_KEYSERVER+1} ]] && extra_args+=(
127 + --keyserver "${VERIFY_SIG_OPENPGP_KEYSERVER}"
128 + )
129 +
130 + einfo "Verifying ${file##*/} ..."
131 + gemato gpg-wrap -K "${key}" "${extra_args[@]}" -- \
132 + gpg --verify "${sig}" "${file}" ||
133 + die "PGP signature verification failed"
134 +}
135 +
136 +# @FUNCTION: verify-sig_src_unpack
137 +# @DESCRIPTION:
138 +# Default src_unpack override that verifies signatures for all
139 +# distfiles if 'verify-sig' flag is enabled. The function dies if any
140 +# of the signatures fails to verify or if any distfiles are not signed.
141 +# Please write src_unpack() yourself if you need to perform partial
142 +# verification.
143 +verify-sig_src_unpack() {
144 + if use verify-sig; then
145 + local f suffix found
146 + local distfiles=() signatures=() nosigfound=() straysigs=()
147 +
148 + # find all distfiles and signatures, and combine them
149 + for f in ${A}; do
150 + found=
151 + for suffix in .sig; do
152 + if [[ ${f} == *${suffix} ]]; then
153 + signatures+=( "${f}" )
154 + found=sig
155 + break
156 + else
157 + if has "${f}${suffix}" ${A}; then
158 + distfiles+=( "${f}" )
159 + found=dist+sig
160 + break
161 + fi
162 + fi
163 + done
164 + if [[ ! ${found} ]]; then
165 + nosigfound+=( "${f}" )
166 + fi
167 + done
168 +
169 + # check if all distfiles are signed
170 + if [[ ${#nosigfound[@]} -gt 0 ]]; then
171 + eerror "The following distfiles lack detached signatures:"
172 + for f in "${nosigfound[@]}"; do
173 + eerror " ${f}"
174 + done
175 + die "Unsigned distfiles found"
176 + fi
177 +
178 + # check if there are no stray signatures
179 + for f in "${signatures[@]}"; do
180 + if ! has "${f%.*}" "${distfiles[@]}"; then
181 + straysigs+=( "${f}" )
182 + fi
183 + done
184 + if [[ ${#straysigs[@]} -gt 0 ]]; then
185 + eerror "The following signatures do not match any distfiles:"
186 + for f in "${straysigs[@]}"; do
187 + eerror " ${f}"
188 + done
189 + die "Unused signatures found"
190 + fi
191 +
192 + # now perform the verification
193 + for f in "${signatures[@]}"; do
194 + verify-sig_verify_detached \
195 + "${DISTDIR}/${f%.*}" "${DISTDIR}/${f}"
196 + done
197 + fi
198 +
199 + # finally, unpack the distfiles
200 + default_src_unpack
201 +}
202 +
203 +_VERIFY_SIG_ECLASS=1
204 +fi