Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check certificate expiry time #48120

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/check_certs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: certificates
on:
# Our certificates are good for ~1 year, but we regenerate them every
# month to be sure. Also support manually triggering the workflow.
schedule:
- cron: 0 0 * * 1
workflow_dispatch:
jobs:
update:
runs-on: ubuntu-20.04
steps:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Checkout
uses: actions/checkout@v4
- name: Check certificates
id: checkCerts
# Use a conditional step instead of a conditional job to work around #20700.
if: github.repository == 'web-platform-tests/wpt'
run: |
python wpt make-hosts-file | sudo tee -a /etc/hosts
python wpt check-certs --days=120
continue-on-error: true
- name: Create an issue
# Use a conditional step instead of a conditional job to work around #20700.
if: github.repository == 'web-platform-tests/wpt' && steps.checkCerts.outcome == 'failure'
uses: peter-evans/create-issue-from-file@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: WPT Certificates Must Be Updated
content-filepath: ./tools/ci/cert_update.md
labels: infra,priority:urgent
2 changes: 1 addition & 1 deletion .github/workflows/regen_certs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Commit and create pull request
# Use a conditional step instead of a conditional job to work around #20700.
if: github.repository == 'web-platform-tests/wpt'
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
author: wpt-pr-bot <wpt-pr-bot@users.noreply.github.com>
Expand Down
11 changes: 11 additions & 0 deletions tools/ci/cert_update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# WPT Certificates Update Required

@web-platform-tests/wpt-core-team

The wpt certificates are nearing their expiration date and must be regenerated.

There should be an open PR from github-actions with the title
[Regenerate WPT Certificates](https://github.com/web-platform-tests/wpt/pulls?q=is%3Apr+is%3Aopen+%22Regenerate+WPT+certificates%22+)
to be merged. Please ensure this is merged ASAP to avoid problems from certificates expiring.

If this PR is missing you can run `wpt regen-certs` locally to create new certificates.
4 changes: 2 additions & 2 deletions tools/ci/commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
},
"regen-certs": {
"path": "regen_certs.py",
"script": "run",
"parser": "get_parser",
"script": "run_regen",
"parser": "get_parser_regen",
"help": "Regenerate the WPT certificates",
"virtualenv": false
},
Expand Down
69 changes: 58 additions & 11 deletions tools/ci/regen_certs.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,6 @@
]
"""


def get_parser():
parser = argparse.ArgumentParser()
parser.add_argument("--checkend-seconds", type=int, default=5184000,
help="The number of seconds the certificates must be valid for")
parser.add_argument("--force", action="store_true",
help="Regenerate certificates even if not reaching expiry")
return parser


def check_cert(certificate, checkend_seconds):
"""Checks whether an x509 certificate will expire within a set period.

Expand Down Expand Up @@ -87,7 +77,16 @@ def calculate_spki(cert_path):
return base64.b64encode(dgst_output).decode('utf-8')


def run(**kwargs):
def get_parser_regen():
parser = argparse.ArgumentParser()
parser.add_argument("--checkend-seconds", type=int, default=5184000,
help="The number of seconds the certificates must be valid for")
parser.add_argument("--force", action="store_true",
help="Regenerate certificates even if not reaching expiry")
return parser


def run_regen(**kwargs):
logging.basicConfig()

if kwargs["force"]:
Expand All @@ -100,3 +99,51 @@ def run(**kwargs):
regen_chrome_spki()
else:
logger.info("Certificates are still valid for at least %s seconds, skipping regeneration" % checkend_seconds)


def get_parser_checkend():
parser = argparse.ArgumentParser()
parser.add_argument("--days", type=int, default=None,
help="The number of days the certificates must be valid for")
parser.add_argument("--hours", type=int, default=None,
help="The additional number of hours the certificates must be valid for")
parser.add_argument("--minutes", type=int, default=None,
help="The additional number of minutes the certificates must be valid for")
parser.add_argument("--seconds", type=int, default=None,
help="The additional number of seconds the certificates must be valid for")
return parser


def run_checkend(**kwargs):
logging.basicConfig()

time_delta_params = {key: value for key, value in kwargs.items()
if key in ["days", "hours", "minutes", "seconds"] and value is not None}
if time_delta_params:
allowed_delta = datetime.timedelta(**time_delta_params)
else:
allowed_delta = None

valid_expiry = True


for cert in ["tools/certs/cacert.pem",
"tools/certs/web-platform.test.pem"]:
expires_time = get_end_time(cert)
now = datetime.datetime.now(expires_time.tzinfo)
time_to_expiry: datetime.timedelta = expires_time - now

if time_to_expiry.total_seconds() > 0:
msg = (f"Certificate {cert} expires in {time_to_expiry.days} days, {time_to_expiry.seconds} seconds")
cert_valid_expiry = allowed_delta is None or time_to_expiry > allowed_delta
else:
msg = f"Certificate {cert} is expired"
cert_valid_expiry = False

if not cert_valid_expiry:
valid_expiry = False
logger.error(msg)
else:
logger.info(msg)

return 0 if valid_expiry else 1