Gentoo Archives: gentoo-dev

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

Replies