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

Replies