aboutsummaryrefslogtreecommitdiff
blob: 8977d88ee66e2d06e73ad378929d86dc6eb9e47f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#!/bin/bash
# Copyright 2010-2015 Gentoo Authors; Distributed under the GPL v2
# might be earlier copyright, no history available

# Keep this variable in sync in both sign-autobuilds.sh & sync-autobuilds.sh
_ARCHES="alpha amd64 arm64 arm hppa ia64 loong m68k mips ppc riscv s390 sh sparc x86"
        #alpha amd64 arm64 arm hppa ia64 loong m68k mips ppc riscv s390 sh sparc x86
ARCHES=${ARCHES:-${_ARCHES}}

RELEASES=/var/tmp/gmirror-releases/releases/
[[ $HOSTNAME == TODO ]] && RELEASES=/var/tmp/gmirror/releases/

: "${DEBUG:=}"
: "${VERBOSE=}"
GPG=(gpg --homedir /home/gmirror/.gnupg-releng/ --batch --no-tty)

# Do not change
DEBUGP=
VERBOSEP=false
[ -n "$DEBUG" ] && DEBUGP='echo'
[ -n "$VERBOSE" ] && VERBOSEP=''
[ -n "$DEBUG" ] && RSYNC_OPTS="${RSYNC_OPTS} -n"
[ -n "$VERBOSE" ] && RSYNC_OPTS="${RSYNC_OPTS} -v"

# needs more debugging
# set -e

warn() {
	echo "WARN: $*" 1>&2
}

signone() {
	f="$1"
	$DEBUGP "${GPG[@]}" --armor --detach-sign "${f}"
}

signone_clearsign() {
	# only for text files!
	f="${1}"
	d="$(dirname "${f}")/.$(basename "${f}").asc.tmp"
	rm -f "${d}"
	# Clearsign aborts if the destfile exists
	$DEBUGP "${GPG[@]}" --armor --clearsign --output "$d" "${f}"
	$DEBUGP mv "${d}" "${f}"
}

cleanup() {
	# A sync mismatch means these seem like bad signatures due to different CDN
	# cache times.
	# [TXT]	latest-install-alpha-minimal.txt	2023-10-09 03:00	116
    # [TXT]	latest-install-alpha-minimal.txt.asc	2023-10-09 00:21	488
	#
	# Using a clearsign in a seperate file doesn't help here either, because it
	# can still be out of date compared to the underlying file.
	# It must be exactly 1 file, clearsigned.
	find autobuilds \
		-type f \
		-name 'latest*txt.asc' \
		-exec grep -L -e '^-----BEGIN PGP SIGNED MESSAGE-----$' \{\} \+ \
	| tr '\n' '\0' \
	| xargs -0 --no-run-if-empty rm -f

}

gpgconf --kill all

for a in $ARCHES ; do
cd "$RELEASES/$a" >/dev/null || continue

[[ -d autobuilds ]] || continue

#echo "Release files:"

# 2023/10/08: Unknown if the latest files are consumed by any machine-readable
# process that would break if the changed into being clearsigned, so use a
# detached signature for now.
find_src_names=(
	'('
		-false
		-or -name '*.tar.xz'
		-or -name '*.tar.zst'  # future builds?
		-or -name '*.tar.zstd' # future builds?
		-or -name '*.iso'      # iso images
		-or -name '*.qcow2'    # disk images
		# hppa netboot
		-or -name '*.lif'
		# s390 netboot
		-or -name 'netboot*T[0-9][0-9][0-9][0-9][0-9][0-9]Z'
	')'
)

find_src_files_cmd=(
	find autobuilds
	-type f
	"${find_src_names[@]}"
)

find_src_links_cmd=(
	find autobuilds
	-type l
	"${find_src_names[@]}"
)

find_sig_names=(
	'('
		-false
		-or -name '*.asc'
	')'
)
find_sig_files_cmd=(
	find autobuilds
	-type f
	"${find_sig_names[@]}"
)
find_sig_links_cmd=(
	find autobuilds
	-type l
	"${find_sig_names[@]}"
)

find_unsigned_helper_cmd=(
	find autobuilds
	-type f
	\(
		-false
		# Gentoo format digest files.
		-or -name '*.DIGESTS'
		# .sha256 files exist to support the OpenStack builder process
		-or -name '*.sha256'
		# marker files to declare latest builds.
		-or -name 'latest*txt'
	\)
	-exec grep -L -e '^-----BEGIN PGP SIGNED MESSAGE-----$' \{\} \+
)

src_files="$( "${find_src_files_cmd[@]}" )"
src_links="$( "${find_src_links_cmd[@]}" )"
sig_files="$( "${find_sig_files_cmd[@]}" )"
sig_links="$( "${find_sig_links_cmd[@]}" )"

unsigned_files="$(comm -23 <(echo "$src_files" |sort) <(echo "$sig_files" | sed -e 's,.asc$,,g' |sort))"
unsigned_links="$(comm -23 <(echo "$src_links" |sort) <(echo "$sig_links" | sed -e 's,.asc$,,g' |sort))"

#$VERBOSEP echo "=== ARCH: $a"

for src in ${unsigned_files} ; do
	dgst=${src}.asc
	if [[ -f "${src}" ]]; then
		if [[ ! -e "${dgst}" ]]; then
			$VERBOSEP echo "Signing $src"
			signone "$src"
		fi
		# what if it existed but was NOT a file, this is an error
		if [[ -e "${dgst}" ]] && [[ ! -f "${dgst}" ]]; then
			warn "Unexpected link: $dgst"
		fi
	fi
done

for src in ${unsigned_links}; do
	dgst=${src}.asc
	if [[ -L "${src}" ]] && [[ ! -e "${dgst}" ]]; then
		link_rel=$(readlink "${src}")
		link_rel_sig=${link_rel}.asc
		link_abs=$(readlink -f "${src}")
		link_abs_sig=${link_abs}.asc
		if [[ -e "${link_rel_sig}" ]] || [[ -e "${link_abs_sig}" ]]; then
			ln -sf "${link_rel_sig}" "${dgst}"
		else
			warn "Link with no obvious signature: ${src} ; checked $link_rel_sig and $link_abs_sig"
		fi
	fi
done

for dgst in ${sig_files}; do
	src=${dgst%.asc}
	# If both the source & signature are files, not symlinks, and the source is
	# newer, then resign. Need to check both for being files, in case we are in
	# a symlink location.
	if [[ -f "${src}" ]] && [[ -f "${dgst}" ]] && [[ "${src}" -nt "${dgst}" ]]; then
		$VERBOSEP echo "Resigning $dgst"
		rm -f "${dgst}"
		signone "$src"
	fi
done

#echo "Text helper files:"

unsigned="$( "${find_unsigned_helper_cmd[@]}" )"
for src in $unsigned ; do
	$VERBOSEP echo "Signing (inline/cleartext) $src"
	signone_clearsign "$src"
done

cleanup

done