Merge pull request #629 from padelsbach/cert-regen-2026
Update certs to fix failing nightlypull/631/head
commit
fff9e1eac8
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
Loading…
Reference in New Issue