A GitHub composite action that validates multiple SSL/TLS certificates provided as a JSON array and produces a consolidated summary table in the job log and the GitHub Step Summary panel.
Certificates are grouped by subject, so an expired cert with a newer valid replacement for the same subject does not fail the check — only truly unrecoverable expirations cause a failure.
- Accepts any number of certificates as a JSON array of file paths
- Parses subject, issuer, and validity dates using
openssl - Works on Linux (GNU date) and macOS (BSD date) runners
- Groups certificates by subject — expired certs with a valid replacement are downgraded to informational
- Emits
::warningannotations in the Actions log for actionable issues - Writes a rich Markdown table to the GitHub Step Summary panel
- Exits 1 only when there is an unrecoverable failure (no valid replacement exists)
| Input | Required | Default | Description |
|---|---|---|---|
certificates |
✅ | — | JSON array of certificate file paths to validate |
warning_days |
❌ | 30 |
Days before expiry to emit a warning instead of passing |
- Per-certificate validation details printed to the job log
- A Markdown summary table written to the GitHub Step Summary panel
- Exits 1 if any certificate is expired, not yet valid, or cannot be parsed and has no valid replacement
- Exits 0 (with warnings) if all certs are valid but some are nearing expiry
| Icon | Meaning |
|---|---|
| ✅ | Valid — expiry is beyond warning_days |
Expiring Soon — expiry within warning_days |
|
| ⏳ | Expired (newer replacement exists) — does not fail the check |
| ❌ | Expired / Failed — no valid replacement found |
- name: Validate certificates
uses: AbsaOSS/validate-certificates@v1
with:
certificates: '["./certs/server.crt", "./certs/client.pem"]'
warning_days: '30'jobs:
find-certs:
name: Find Certificates
runs-on: ubuntu-latest
outputs:
certs: ${{ steps.set-certificates.outputs.certs }}
steps:
- uses: actions/checkout@v4
- name: Find all .crt and .pem files
id: set-certificates
run: |
certs=$(find ./deployment/certs \
-type f \( -name "*.crt" -o -name "*.pem" \) \
| jq -R -s -c 'split("\n")[:-1]')
echo "certs=$certs" >> $GITHUB_OUTPUT
validate-certificates:
name: Validate Certificates
needs: find-certs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate all deployment certificates
uses: AbsaOSS/validate-certificates@v1
with:
certificates: ${{ needs.find-certs.outputs.certs }}
warning_days: '60'on:
schedule:
- cron: '0 6 * * 1' # every Monday at 06:00 UTC
jobs:
cert-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate certificates
uses: AbsaOSS/validate-certificates@v1
with:
certificates: |
[
"./certs/api.example.com.crt",
"./certs/internal.example.com.pem",
"./certs/legacy.example.com.crt"
]
warning_days: '45'See the examples/ directory for ready-to-use workflow files.
- Runner must have
opensslandjqinstalled (both are available by default onubuntu-latestandmacos-latestGitHub-hosted runners)
Contributions are welcome! Please read CONTRIBUTING.md before opening a pull request.
Copyright 2026 ABSA Group Limited — licensed under the Apache License 2.0.