...
1#!/bin/bash
2# Copyright (C) 2023 SUSE LLC.
3# Copyright (C) 2023 Open Containers Authors
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17set -Eeuo pipefail
18
19project="runc"
20root="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/..")"
21
22function log() {
23 echo "[*]" "$@" >&2
24}
25
26function bail() {
27 log "$@"
28 exit 1
29}
30
31# Temporary GPG keyring for messing around with.
32tmp_gpgdir="$(mktemp -d --tmpdir "$project-validate-tmpkeyring.XXXXXX")"
33trap 'rm -r "$tmp_gpgdir"' EXIT
34
35# Get the set of MAINTAINERS.
36readarray -t maintainers < <(sed -E 's|.* <.*> \(@?(.*)\)$|\1|' <"$root/MAINTAINERS")
37echo "------------------------------------------------------------"
38echo "$project maintainers:"
39printf " * %s\n" "${maintainers[@]}"
40echo "------------------------------------------------------------"
41
42# Create a dummy gpg keyring from the set of MAINTAINERS.
43while IFS="" read -r username || [ -n "$username" ]; do
44 curl -sSL "https://github.com/$username.gpg" |
45 gpg --no-default-keyring --keyring="$tmp_gpgdir/$username.keyring" --import
46done < <(printf '%s\n' "${maintainers[@]}")
47
48# Make sure all of the keys in the keyring have a github=... comment.
49awk <"$root/$project.keyring" '
50 /^-----BEGIN PGP PUBLIC KEY BLOCK-----$/ { key_idx++; in_pgp=1; has_comment=0; }
51
52 # PGP comments are never broken up over several lines, and we only have one
53 # comment entry in our keyring file anyway.
54 in_pgp && /^Comment:.* github=\w+.*/ { has_comment=1 }
55
56 /^-----END PGP PUBLIC KEY BLOCK-----$/ {
57 if (!has_comment) {
58 print "[!] Key", key_idx, "in '$project'.keyring is missing a github= comment."
59 exit 1
60 }
61 }
62'
63
64echo "------------------------------------------------------------"
65echo "$project release managers:"
66sed -En "s|^Comment:.* github=(\w+).*| * \1|p" <"$root/$project.keyring" | sort -u
67echo "------------------------------------------------------------"
68gpg --no-default-keyring --keyring="$tmp_gpgdir/keyring" \
69 --import --import-options=show-only <"$root/$project.keyring"
70echo "------------------------------------------------------------"
71
72# Check that each entry in the kering is actually a maintainer's key.
73while IFS="" read -d $'\0' -r block || [ -n "$block" ]; do
74 username="$(sed -En "s|^Comment:.* github=(\w+).*|\1|p" <<<"$block")"
75
76 # FIXME: This is to work around codespell thinking that f-p-r is a
77 # misspelling of some other word, and the lack of support for inline
78 # ignores in codespell.
79 fprfield="f""p""r"
80
81 # Check the username is actually a maintainer. This is just a sanity check,
82 # since you can put whatever you like in the Comment field.
83 [ -f "$tmp_gpgdir/$username.keyring" ] || bail "User $username in runc.keyring is not a maintainer!"
84 grep "(@$username)$" "$root/MAINTAINERS" >/dev/null || bail "User $username in runc.keyring is not a maintainer!"
85
86 # Check that the key in the block actually matches a known key for that
87 # maintainer. Note that a block can contain multiple keys, so we need to
88 # check all of them. Since we have to handle multiple keys anyway, we'll
89 # also verify all of the subkeys (this is simpler to implement anyway since
90 # the --with-colons format outputs fingerprints for both primary and
91 # subkeys in the same way).
92 #
93 # Fingerprints have a field 1 of $fprfield and field 10 containing the
94 # fingerprint. See <https://github.com/gpg/gnupg/blob/master/doc/DETAILS>
95 # for more details.
96 while IFS="" read -r key || [ -n "$key" ]; do
97 gpg --no-default-keyring --keyring="$tmp_gpgdir/$username.keyring" \
98 --list-keys --with-colons | grep "$fprfield:::::::::$key:" >/dev/null ||
99 bail "(Sub?)Key $key in $project.keyring is NOT actually one of $username's keys!"
100 log "Successfully verified $username's (sub?)key $key is legitimate."
101 done < <(gpg --no-default-keyring \
102 --import --import-options=show-only --with-colons <<<"$block" |
103 grep "^$fprfield:" | cut -d: -f10)
104done < <(awk <"$root/$project.keyring" '
105 /^-----BEGIN PGP PUBLIC KEY BLOCK-----$/ { in_block=1 }
106 in_block { print }
107 /^-----END PGP PUBLIC KEY BLOCK-----$/ { in_block=0; printf("\0"); }
108')
View as plain text