CRL Monitor
Go to file
dependabot[bot] a9ef40ef40
Bump golangci/golangci-lint-action from 6 to 8 (#107)
Bumps
[golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action)
from 6 to 8.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/golangci/golangci-lint-action/releases">golangci/golangci-lint-action's
releases</a>.</em></p>
<blockquote>
<h2>v8.0.0</h2>
<p><strong>Requires <code>golangci-lint</code> version &gt;=
<code>v2.1.0</code></strong></p>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Changes</h3>
<ul>
<li>feat: use absolute paths by default when using working-directory
option by <a href="https://github.com/ldez"><code>@​ldez</code></a> in
<a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1231">golangci/golangci-lint-action#1231</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/golangci/golangci-lint-action/compare/v7...v8.0.0">https://github.com/golangci/golangci-lint-action/compare/v7...v8.0.0</a></p>
<h2>v7.0.1</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Documentation</h3>
<ul>
<li>docs: add note about github.workspace by <a
href="https://github.com/mattjohnsonpint"><code>@​mattjohnsonpint</code></a>
in <a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1218">golangci/golangci-lint-action#1218</a></li>
<li>docs: clarify that ’args: --path-mode=abs’ is needed for
working-directory by <a
href="https://github.com/HaraldNordgren"><code>@​HaraldNordgren</code></a>
in <a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1230">golangci/golangci-lint-action#1230</a></li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>build(deps): bump the dependencies group across 1 directory with 3
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1213">golangci/golangci-lint-action#1213</a></li>
<li>build(deps-dev): bump the dev-dependencies group with 3 updates by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1215">golangci/golangci-lint-action#1215</a></li>
<li>build(deps-dev): bump the dev-dependencies group with 4 updates by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1220">golangci/golangci-lint-action#1220</a></li>
<li>build(deps): bump <code>@​types/node</code> from 22.13.14 to 22.14.0
in the dependencies group by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1221">golangci/golangci-lint-action#1221</a></li>
<li>build(deps-dev): bump the dev-dependencies group with 3 updates by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1224">golangci/golangci-lint-action#1224</a></li>
<li>build(deps): bump <code>@​types/node</code> from 22.14.0 to 22.14.1
in the dependencies group by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1225">golangci/golangci-lint-action#1225</a></li>
<li>build(deps-dev): bump the dev-dependencies group with 2 updates by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1227">golangci/golangci-lint-action#1227</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/mattjohnsonpint"><code>@​mattjohnsonpint</code></a>
made their first contribution in <a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1218">golangci/golangci-lint-action#1218</a></li>
<li><a
href="https://github.com/HaraldNordgren"><code>@​HaraldNordgren</code></a>
made their first contribution in <a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1230">golangci/golangci-lint-action#1230</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/golangci/golangci-lint-action/compare/v7.0.0...v7.0.1">https://github.com/golangci/golangci-lint-action/compare/v7.0.0...v7.0.1</a></p>
<h2>v7.0.0</h2>
<!-- raw HTML omitted -->
<p>⚠️ <strong>The GitHub Action v7 supports golangci-lint v2
only.</strong> ⚠️</p>
<h2>What's Changed</h2>
<h3>Changes</h3>
<ul>
<li>feat: golangci-lint v2 support by <a
href="https://github.com/ldez"><code>@​ldez</code></a> in <a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1198">golangci/golangci-lint-action#1198</a></li>
</ul>
<h3>Documentation</h3>
<ul>
<li>docs: update annotation permissions by <a
href="https://github.com/ldez"><code>@​ldez</code></a> in <a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1203">golangci/golangci-lint-action#1203</a></li>
<li>docs: fix checks permissions for annotations by <a
href="https://github.com/kema-dev"><code>@​kema-dev</code></a> in <a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1204">golangci/golangci-lint-action#1204</a></li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>build(deps-dev): bump the dev-dependencies group with 3 updates by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/golangci/golangci-lint-action/pull/1207">golangci/golangci-lint-action#1207</a></li>
</ul>
<h2>New Contributors</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="4afd733a84"><code>4afd733</code></a>
8.0.0</li>
<li><a
href="7774f98a88"><code>7774f98</code></a>
feat: use absolute paths by default when using working-directory option
(<a
href="https://redirect.github.com/golangci/golangci-lint-action/issues/1231">#1231</a>)</li>
<li><a
href="9fae48acfc"><code>9fae48a</code></a>
7.0.1</li>
<li><a
href="16ece5e01d"><code>16ece5e</code></a>
docs: clarify that ’args: --path-mode=abs’ is needed for
working-directory (...</li>
<li><a
href="a3942e2497"><code>a3942e2</code></a>
build(deps-dev): bump the dev-dependencies group with 2 updates (<a
href="https://redirect.github.com/golangci/golangci-lint-action/issues/1227">#1227</a>)</li>
<li><a
href="7ecb048b56"><code>7ecb048</code></a>
build(deps): bump <code>@​types/node</code> from 22.14.0 to 22.14.1 in
the dependencies gro...</li>
<li><a
href="63a0d0e695"><code>63a0d0e</code></a>
build(deps-dev): bump the dev-dependencies group with 3 updates (<a
href="https://redirect.github.com/golangci/golangci-lint-action/issues/1224">#1224</a>)</li>
<li><a
href="c2427fec79"><code>c2427fe</code></a>
docs: update problem matchers section</li>
<li><a
href="642f8ee631"><code>642f8ee</code></a>
build(deps): bump <code>@​types/node</code> from 22.13.14 to 22.14.0 in
the dependencies gr...</li>
<li><a
href="d84be9250b"><code>d84be92</code></a>
build(deps-dev): bump the dev-dependencies group with 4 updates (<a
href="https://redirect.github.com/golangci/golangci-lint-action/issues/1220">#1220</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/golangci/golangci-lint-action/compare/v6...v8">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golangci/golangci-lint-action&package-manager=github_actions&previous-version=6&new-version=8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ameer Ghani <inahga@letsencrypt.org>
Co-authored-by: Ameer Ghani <inahga@gmail.com>
2025-06-26 18:33:30 +00:00
.github Bump golangci/golangci-lint-action from 6 to 8 (#107) 2025-06-26 18:33:30 +00:00
checker Add more context to error logs (#86) 2025-06-26 17:34:25 +00:00
churner churner: fetch and lint CRL at issuance time (#89) 2025-03-10 10:00:17 -07:00
cmd Set up lambdas (#14) 2022-12-02 17:47:19 -05:00
db Bump golangci/golangci-lint-action from 6 to 8 (#107) 2025-06-26 18:33:30 +00:00
lambda Use errors.Join instead of multierr (#31) 2024-01-11 15:47:39 -05:00
retryhttp retries: use longer exponential backoff (#113) 2025-06-26 17:18:06 +00:00
storage Add more context to error logs (#86) 2025-06-26 17:34:25 +00:00
.gitignore Add a script and GH action to produce builds (#24) 2023-12-20 18:03:34 -05:00
.golangci.yaml Bump golangci/golangci-lint-action from 6 to 8 (#107) 2025-06-26 18:33:30 +00:00
CODE_OF_CONDUCT.md CRL-monitor 2022-10-12 13:51:43 -04:00
LICENSE CRL-monitor 2022-10-12 13:51:43 -04:00
README.md Update README (#93) 2025-03-12 22:08:51 -04:00
build-release.sh Add a script and GH action to produce builds (#24) 2023-12-20 18:03:34 -05:00
go.mod Bump github.com/aws/aws-lambda-go from 1.48.0 to 1.49.0 (#110) 2025-06-26 17:42:41 +00:00
go.sum Bump github.com/aws/aws-lambda-go from 1.48.0 to 1.49.0 (#110) 2025-06-26 17:42:41 +00:00

README.md

crl-monitor

Build Status

CRL-Monitor monitors CRLs.

It issues certificates, revokes them, and then looks for them to appear in CRLs. Each component runs as an AWS Lambda.

The churner runs periodically. On each run it issues a certificate, fetches and lints the certificate's CRL URL, revokes the certificate, and stores its serial number and metadata for the checker to later verify that it shows up as revoked. It also checks previously seen serials. If they haven't shown up in a CRL after a reasonable amount of time, checker produces an error.

The checker runs in response to the upload of each new CRL shard in S3. It diffs the newly uploaded CRL shard against its previous version and verifies:

  • New CRL has a later date and higher CRL number than the previous version.
  • New CRL passes lints.
  • For any serials removed between the old shard and the new one:
    • The certificate is expired (based on fetching it by serial from Let's Encrypt).
  • For any serials added (if the certificate was issued by the churner):
    • The certificate's CRLDistributionPoint matches the CRL shard's IssuingDistributionPoint.

The checker also removes from database any certificates it sees, to indicate that their revocation has been published, so the churner won't alert about them It then marks as completed (deletes) any churner-issued certificates that show up on the new CRL.

Build and Deployment

This repository has two binaries named checker and two binaries named churner. The binaries under cmd are for local use and testing. The binaries under lambda are for deployment to AWS Lambda. The key difference is that the lambda/ binaries register a lambda handler (lambda.StartWithOptions()), which AWS then calls. That handler can return errors, and we have separate Cloudwatch monitoring that alerts when any errors are detected.

The lambda binaries are built by a release workflow on GitHub Actions triggered by uploading a release tag (starting with v). Those binaries are uploaded to S3 under a versioned path. They are then deployed to Lambda using Terraform (in another repository).

Testing

Most of the tests are unittests and can be run with:

go test ./...

There is also an integration test for DynamoDB code. To run this, install Java and run:

./db/run_integration_test.sh

Architecture Diagram

sequenceDiagram
  participant churn as Certificate Churner<br />Lambda
  participant ca as Let's Encrypt<br />Certification Authority
  participant ddb as Pending Certificates<br />DynamoDB
  participant s3 as CRL Storage<br />S3 Bucket
  participant checker as CRL Checker<br />Lambda

  loop timer
    activate churn
    churn->>ca: Issue certificate
    churn->>ca: Fetch CRL
    churn->>ca: Revoke certificate
    churn->>ddb: Store certificate metadata
    ddb->>churn: Get previous revoked serials
    Note over churn: Alert if any<br />expected serials missed<br />inclusion deadline
    deactivate churn
  end

  loop New CRL
    ca->>s3: Publish CRL Shard
    activate checker
    s3->>checker: S3 Event
    checker->>s3: Read current CRL
    checker->>s3: Read previous CRL
    Note over checker: Alert if CRL<br />fails linting
    loop random selection of serials
      checker->>ca: Get Certificate
    end
    Note over checker: Alert if CRL had<br />serials leave early
    checker->>ddb: Get revoked serials
    checker->>ddb: Delete seen serials
    deactivate checker
  end