Skip to content

Commit 68e1e7a

Browse files
committed
try to automate this process
1 parent e464f85 commit 68e1e7a

2 files changed

Lines changed: 139 additions & 1 deletion

File tree

.github/workflows/cert-renewal.yml

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
name: Certificate Renewal
2+
3+
on:
4+
schedule:
5+
# Run on the 1st of every month at 00:00 UTC
6+
# GitHub Actions doesn't support "every 800 days" directly,
7+
# so we check monthly if renewal is needed
8+
- cron: '0 0 1 * *'
9+
workflow_dispatch: # Allow manual triggering
10+
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
15+
jobs:
16+
check-and-renew-certificates:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Checkout repository
20+
uses: actions/checkout@v4
21+
22+
- name: Check certificate expiration
23+
id: check-cert
24+
run: |
25+
# Get the expiration date of the current certificate
26+
CERT_FILE="tests/resources/unittests.crt"
27+
28+
if [ ! -f "$CERT_FILE" ]; then
29+
echo "Certificate file not found!"
30+
echo "needs_renewal=true" >> $GITHUB_OUTPUT
31+
exit 0
32+
fi
33+
34+
# Get certificate expiration date in seconds since epoch
35+
EXPIRY_DATE=$(openssl x509 -enddate -noout -in "$CERT_FILE" | cut -d= -f2)
36+
EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s 2>/dev/null || date -j -f "%b %d %H:%M:%S %Y %Z" "$EXPIRY_DATE" +%s)
37+
38+
# Get current date in seconds since epoch
39+
CURRENT_EPOCH=$(date +%s)
40+
41+
# Calculate days until expiration
42+
DAYS_UNTIL_EXPIRY=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 ))
43+
44+
echo "Certificate expires in $DAYS_UNTIL_EXPIRY days"
45+
46+
# Renew if less than 30 days until expiration
47+
# This gives us buffer time before the 825-day Apple limit
48+
if [ $DAYS_UNTIL_EXPIRY -lt 30 ]; then
49+
echo "Certificate needs renewal (less than 30 days until expiration)"
50+
echo "needs_renewal=true" >> $GITHUB_OUTPUT
51+
else
52+
echo "Certificate is still valid"
53+
echo "needs_renewal=false" >> $GITHUB_OUTPUT
54+
fi
55+
56+
- name: Install OpenSSL
57+
if: steps.check-cert.outputs.needs_renewal == 'true'
58+
run: |
59+
sudo apt-get update
60+
sudo apt-get install -y openssl
61+
62+
- name: Regenerate certificates
63+
if: steps.check-cert.outputs.needs_renewal == 'true'
64+
working-directory: tests/resources
65+
run: |
66+
# Regenerate the certificate (824 days to stay under Apple's 825-day limit)
67+
openssl req -x509 -new -key unittests.key -config unittests.conf -out unittests.crt -days 824
68+
69+
# Regenerate the PKCS#12 bundle with macOS-compatible encryption
70+
# Using SHA1 and 3DES instead of modern algorithms that macOS Security Framework doesn't support
71+
openssl pkcs12 -export -out unittests.p12 -inkey unittests.key -in unittests.crt -password pass:1234 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1
72+
73+
# Verify the new certificate
74+
echo "New certificate details:"
75+
openssl x509 -in unittests.crt -noout -dates -subject
76+
77+
- name: Check for changes
78+
if: steps.check-cert.outputs.needs_renewal == 'true'
79+
id: check-changes
80+
run: |
81+
if git diff --quiet tests/resources/unittests.crt tests/resources/unittests.p12; then
82+
echo "No changes detected"
83+
echo "has_changes=false" >> $GITHUB_OUTPUT
84+
else
85+
echo "Changes detected"
86+
echo "has_changes=true" >> $GITHUB_OUTPUT
87+
fi
88+
89+
- name: Create Pull Request
90+
if: steps.check-cert.outputs.needs_renewal == 'true' && steps.check-changes.outputs.has_changes == 'true'
91+
uses: peter-evans/create-pull-request@v6
92+
with:
93+
token: ${{ secrets.GITHUB_TOKEN }}
94+
commit-message: |
95+
chore: renew test certificates for 824 days
96+
97+
Automatically regenerated test certificates to comply with Apple's
98+
825-day certificate lifetime requirement.
99+
100+
Generated using:
101+
- openssl req -x509 -new -key unittests.key -config unittests.conf -out unittests.crt -days 824
102+
- openssl pkcs12 -export -out unittests.p12 -inkey unittests.key -in unittests.crt -password pass:1234 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1
103+
104+
🤖 Assisted by GenAI
105+
branch: cert-renewal-${{ github.run_number }}
106+
delete-branch: true
107+
title: 'chore: renew test certificates'
108+
body: |
109+
## Certificate Renewal
110+
111+
This PR automatically renews the test certificates in `tests/resources/`.
112+
113+
### Changes
114+
- Updated `tests/resources/unittests.crt` (renewed for 824 days)
115+
- Updated `tests/resources/unittests.p12` (PKCS#12 bundle)
116+
117+
### Background
118+
Apple requires that certificate lifetimes be 825 days or less. These certificates are used in unit tests that create TLS connections between localhost server and client.
119+
120+
### Verification
121+
The certificates were regenerated using the commands documented in `tests/resources/unittests.readme`:
122+
```bash
123+
openssl req -x509 -new -key unittests.key -config unittests.conf -out unittests.crt -days 824
124+
openssl pkcs12 -export -out unittests.p12 -inkey unittests.key -in unittests.crt -password pass:1234 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1
125+
```
126+
127+
### Testing
128+
Please verify that the unit tests pass with the new certificates before merging.
129+
130+
---
131+
🤖 This PR was automatically generated by the certificate renewal workflow.
132+
labels: |
133+
automated
134+
maintenance
135+
certificates

tests/resources/unittests.readme

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,7 @@ Apple won't trust any certificate whose lifetime is over 825 days.
1313
Once it expires unit tests will start failing and it will need to be updated like so:
1414

1515
$ openssl req -x509 -new -key unittests.key -config unittests.conf -out unittests.crt -days 824
16-
$ openssl pkcs12 -export -out unittests.p12 -inkey unittests.key -in unittests.crt -password pass:1234
16+
$ openssl pkcs12 -export -out unittests.p12 -inkey unittests.key -in unittests.crt -password pass:1234 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1
17+
18+
Note: The PKCS#12 command uses SHA1 and 3DES encryption for macOS compatibility.
19+
Modern OpenSSL 3.x defaults to algorithms that macOS Security Framework cannot import.

0 commit comments

Comments
 (0)