Merge pull request #629 from padelsbach/cert-regen-2026

Update certs to fix failing nightly
pull/631/head
Aidan Garske 2026-09-16 09:42:05 -07:00 committed by GitHub
commit fff9e1eac8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 145 additions and 7 deletions

View File

@ -3,7 +3,9 @@
# expire, so a cert dying becomes a scheduled regeneration instead of a red
# morning. Already expired ones are reported but not failed: several are legacy
# or deliberately stale fixtures (ntru-cert.pem, expired-* used for negative
# tests). Covers PEM and DER X.509 certs, and PEM/DER CRLs (nextUpdate).
# tests). Covers PEM and DER X.509 certs, PEM/DER CRLs (nextUpdate), and the
# certs inside PKCS#12 bundles (*.p12, opened with the examples' password).
# A bundle is never a fixture, so an expired one fails outright.
set -eu
DIR="${1:-certs}"
@ -54,10 +56,45 @@ check_crl() {
fi
}
P12_PASS="${P12_PASS:-wolfSSL test}"
# True if the PEM cert in $cert is still valid $1 seconds from now.
cert_ok() {
printf '%s\n' "$cert" | openssl x509 -checkend "$1" -noout >/dev/null 2>&1
}
check_p12() {
f="$1"
certs=$(openssl pkcs12 -in "$f" -nokeys -passin "pass:${P12_PASS}" \
2>/dev/null) \
|| { echo "::notice::$f does not open with P12_PASS, skipped"; return 0; }
n=$(printf '%s\n' "$certs" | grep -c -- '-----BEGIN CERTIFICATE-----')
i=0
while [ "$i" -lt "$n" ]; do
i=$((i + 1))
checked=$((checked + 1))
cert=$(printf '%s\n' "$certs" | awk -v want="$i" \
'/-----BEGIN CERTIFICATE-----/{c++} c==want')
end=$(printf '%s\n' "$cert" | openssl x509 -enddate -noout | cut -d= -f2)
if ! cert_ok 0; then
echo "::error::$f cert $i expired ($end) -- run certs/generate-client-bundle.sh"
rc=1
elif ! cert_ok "$fail_secs"; then
echo "::error::$f cert $i expires within $FAIL_DAYS days ($end)" \
"-- regenerate now"
rc=1
elif ! cert_ok "$warn_secs"; then
echo "::warning::$f cert $i expires within $WARN_DAYS days ($end)" \
"-- schedule regeneration"
fi
done
}
for f in $(find "$DIR" -name '*.pem' | sort); do check_cert "$f" PEM; done
for f in $(find "$DIR" -name '*.der' | sort); do check_cert "$f" DER; done
for f in $(find "$DIR" \( -name '*crl*.pem' -o -name '*.crl' \) | sort); do check_crl "$f" PEM; done
for f in $(find "$DIR" -name '*crl*.der' | sort); do check_crl "$f" DER; done
for f in $(find "$DIR" -name '*.p12' | sort); do check_p12 "$f"; done
echo "checked $checked cert/CRL file(s); fail threshold ${FAIL_DAYS}d, warn ${WARN_DAYS}d"
exit $rc

View File

@ -1,10 +1,111 @@
#!/bin/sh
# Rebuild test-clientbundle.p12, the PKCS#12 bundle tls/client-tls-pkcs12.c
# loads (client cert, client key and the CA that signed the server cert).
#
# By default the bundle is built from the PEMs already in this directory,
# so it stays in step with the server-cert.pem the server examples use.
# Set WOLFSSL_ROOT_DIR to a wolfSSL checkout to refresh those PEMs from it
# first. The password is the one the example uses.
#
# Rerun this whenever the PEMs are regenerated: the bundle carries its own
# copies of the certs and expires with them (certs/check-expiry.sh flags
# it 30 days ahead).
set -eu
# set this to point to the wolfSSL root directory for updating certs
WOLFSSL_ROOT_DIR=${WOLFSSL_ROOT_DIR:-"~/clean-wolfssl"}
cd "$(dirname "$0")"
pass="wolfSSL test"
out="test-clientbundle.p12"
now=$(date +%s)
cp ${WOLFSSL_ROOT_DIR}/certs/client-cert.pem ./
cp ${WOLFSSL_ROOT_DIR}/certs/client-key.pem ./
cp ${WOLFSSL_ROOT_DIR}/certs/ca-cert.pem ./
fail() {
echo "FAIL: $*" >&2
exit 1
}
echo "wolfSSL test" | openssl pkcs12 -des3 -descert -export -in client-cert.pem -inkey client-key.pem -certfile ca-cert.pem -out test-clientbundle.p12 -password stdin
# "Sep 14 21:25:29 2027 GMT" -> epoch seconds; GNU date, then BSD date.
to_epoch() {
date -d "$1" +%s 2>/dev/null \
|| date -jf "%b %e %T %Y %Z" "$1" +%s 2>/dev/null \
|| echo 0
}
# Print one line per cert in a bundle and set end_text/end_secs to the
# earliest notAfter. Fails if the bundle does not open with the password.
describe() {
certs=$(openssl pkcs12 -in "$1" -nokeys -passin "pass:${pass}" \
2>/dev/null) || return 1
n=$(printf '%s\n' "$certs" | grep -c -- '-----BEGIN CERTIFICATE-----')
end_secs=0
end_text=""
i=0
while [ "$i" -lt "$n" ]; do
i=$((i + 1))
cert=$(printf '%s\n' "$certs" | awk -v want="$i" \
'/-----BEGIN CERTIFICATE-----/{c++} c==want')
subj=$(printf '%s\n' "$cert" | openssl x509 -noout -subject \
| sed 's/^subject=//')
end=$(printf '%s\n' "$cert" | openssl x509 -noout -enddate \
| sed 's/^notAfter=//')
secs=$(to_epoch "$end")
if [ "$end_secs" -eq 0 ] || [ "$secs" -lt "$end_secs" ]; then
end_secs=$secs
end_text=$end
fi
echo " cert ${i}: notAfter ${end} (${subj})"
done
}
# Says "valid until <date> (N days left)" or "expired <date> (N days ago)".
lifetime() {
if [ "$end_secs" -gt "$now" ]; then
days=$(( (end_secs - now) / 86400 ))
echo "valid until ${end_text} (${days} days left)"
else
days=$(( (now - end_secs) / 86400 ))
echo "expired ${end_text} (${days} days ago)"
fi
}
if [ -f "$out" ]; then
if describe "$out" >/dev/null; then
echo "previous ${out}: $(lifetime)"
else
echo "previous ${out}: does not open with the example's password"
fi
else
echo "no previous ${out}"
fi
if [ -n "${WOLFSSL_ROOT_DIR:-}" ]; then
for f in client-cert.pem client-key.pem ca-cert.pem; do
src="${WOLFSSL_ROOT_DIR}/certs/${f}"
[ -r "$src" ] || fail "cannot read ${src}"
cp "$src" ./
echo "copied ${f} from ${WOLFSSL_ROOT_DIR}"
done
fi
for f in client-cert.pem client-key.pem ca-cert.pem; do
[ -r "$f" ] || fail "missing ${f} in $(pwd)"
done
# Explicit algorithms so the output does not drift with the OpenSSL
# version: 3DES for the certs and AES-256 (PBES2) for the key, SHA-256 MAC,
# which is what the committed bundle has always used and wolfSSL parses.
echo "$pass" | openssl pkcs12 -export -in client-cert.pem \
-inkey client-key.pem -certfile ca-cert.pem \
-certpbe PBE-SHA1-3DES -keypbe AES-256-CBC -macalg sha256 \
-out "$out" -password stdin || fail "openssl pkcs12 -export failed"
# Read it back the way the example will, and report what is inside.
describe "$out" \
|| fail "${out} was written but does not open with the example's password"
[ "$n" -eq 2 ] || fail "${out} holds ${n} certificate(s), expected client + CA"
if ! openssl pkcs12 -in "$out" -nocerts -nodes -passin "pass:${pass}" \
2>/dev/null | openssl pkey -noout 2>/dev/null; then
fail "${out} holds no readable private key"
fi
[ "$end_secs" -gt "$now" ] \
|| fail "new ${out} is already expired ($(lifetime)); refresh the PEMs"
echo "OK: wrote $(pwd)/${out} ($(wc -c < "$out") bytes, ${n} certs, key)"
echo "new ${out}: $(lifetime)"

Binary file not shown.