Skip to content
Merged
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
9 changes: 7 additions & 2 deletions .github/workflows/sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,17 @@ jobs:
# Routes and guides are different, and get a pull request. A new endpoint
# usually needs a sentence of prose that a generator cannot write, and
# opening a pull request is what creates the moment to write it.
# Pinned the same way as the pages above, and for the same reason: only
# the repository that dispatched is pinned. These two read certpilot
# alone, and used to take the dispatched SHA whoever sent it, so an agent
# merge asked for certpilot's routes.json at an agent commit and got a
# 404 (run 36064618794).
- run: npm run sync
env:
CERTPILOT_REF: ${{ github.event.client_payload.sha }}
CERTPILOT_REF: ${{ github.event.client_payload.repo == 'certpilot-agent' && 'main' || github.event.client_payload.sha }}
- run: npm run sync:guides
env:
CERTPILOT_REF: ${{ github.event.client_payload.sha }}
CERTPILOT_REF: ${{ github.event.client_payload.repo == 'certpilot-agent' && 'main' || github.event.client_payload.sha }}

- uses: peter-evans/create-pull-request@v7
with:
Expand Down
9 changes: 8 additions & 1 deletion guides/agents.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Agents". Edit it there, not here. -->

Two APIs, kept completely apart.
Expand Down Expand Up @@ -300,6 +300,13 @@ grant's `renew_before_days`. A host that picked its own moment could decide to
renew hourly, and four hundred of them would be a denial of service against the
CA.

`renew_after` always falls inside the certificate's own lifetime, and never in
its first third. A lead time longer than two thirds of the lifetime is replaced
by renewing when a third remains, so a six-day certificate under the default 30
days renews at day four. Without that bound, a certificate shorter than its lead
time was handed a `renew_after` that had already passed, and the host renewed it
on every cycle ([#109](https://github.com/certpilot/certpilot/issues/109)).

## Installing, and reloading


Expand Down
2 changes: 1 addition & 1 deletion guides/ca-accounts-gateways.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "CA accounts and gateways". Edit it there, not here. -->

## Registering
Expand Down
2 changes: 1 addition & 1 deletion guides/certificate-transparency.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Certificate Transparency". Edit it there, not here. -->

This is the half of discovery a network scan cannot reach. A scan answers "what
Expand Down
11 changes: 10 additions & 1 deletion guides/certificates.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Certificates". Edit it there, not here. -->

`GET /certificates` filters on `status`, `environment`, `common_name`,
`ca_account_id`.

Despite its name, `common_name` matches **any** of a certificate's names, the
subject common name or any SAN, by substring and ignoring case. Conforming CAs
are dropping the common name (Pebble already issues without one), and a
certificate whose only name is in its SANs must still be findable by it. A
certificate matches once however many of its names do.

## Issuing

```http
Expand Down Expand Up @@ -48,6 +54,9 @@ a policy that finds something must say so even when it does not block.
`POST /certificates/:id/renew` runs the same path. The key is rotated and the
new one persisted; a renewal that produced a certificate without storing its
matching key would leave a record that looks healthy and cannot terminate TLS.
That is only possible for a key CertPilot already holds: a certificate whose
`key_custody` is `AGENT` or `EXTERNAL` is refused with `400`, and renewed by
whoever holds its key (see [Asking for one](/api/reference/renewal-queue#asking-for-one)).

On failure the record is marked `RENEWAL_FAILED` with `renewal_error` set, and
the previous certificate is left intact.
Expand Down
2 changes: 1 addition & 1 deletion guides/cloud-inventory.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Cloud inventory". Edit it there, not here. -->

The third place certificates hide. A scan finds what is **served**; Certificate
Expand Down
2 changes: 1 addition & 1 deletion guides/dashboard.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Dashboard". Edit it there, not here. -->

## Statistics
Expand Down
2 changes: 1 addition & 1 deletion guides/deployment.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Deployment", "Cryptographic posture". Edit it there, not here. -->

Everything above deployment in this document observes. This changes something
Expand Down
2 changes: 1 addition & 1 deletion guides/discovery.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Discovery". Edit it there, not here. -->

Scanning is operator-gated because it opens connections to third-party
Expand Down
2 changes: 1 addition & 1 deletion guides/display-tokens.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Display tokens". Edit it there, not here. -->

Create:
Expand Down
2 changes: 1 addition & 1 deletion guides/live-event-stream.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Live event stream". Edit it there, not here. -->

Opens with a `retry:` directive and a `snapshot` event carrying current
Expand Down
2 changes: 1 addition & 1 deletion guides/notification-channels.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Notification channels". Edit it there, not here. -->

Three channel types have a notifier: `slack`, `webhook`, `email`. Migration 001
Expand Down
2 changes: 1 addition & 1 deletion guides/pki-ca-management.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "PKI and CA authorities", "Ownership and acknowledgement". Edit it there, not here. -->

## Importing the CAs behind a CA account
Expand Down
2 changes: 1 addition & 1 deletion guides/policies.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Policies". Edit it there, not here. -->

Rule types, all of which are evaluated:
Expand Down
15 changes: 13 additions & 2 deletions guides/renewal-queue.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 9e9a56600009, last changed 2026-09-21T21:48:46Z.
<!-- Synced from docs/api-reference.md in certpilot/certpilot at 81031950a7b7, last changed 2026-09-26T11:56:08Z.
Source heading: "Renewal queue". Edit it there, not here. -->

Renewal is the only part of this system that changes the world. Everything else
Expand Down Expand Up @@ -34,6 +34,15 @@ weekly rate limit. A certificate with no CA account — anything discovered rath
than issued — is refused with **400** at this point rather than becoming a job
that fails forever.

So is a certificate whose private key CertPilot does not hold, again with
**400**. When `key_custody` is `AGENT`, the refusal names the agent and says how
to renew it on that host (`certpilot-agent request --name …`). When it is
`EXTERNAL`, it asks for a new signing request from whoever holds the key. A
renewal here always ends with the gateway generating a fresh keypair. For these
certificates, CertPilot would then hold a key it promised never to hold, and
the record would describe a certificate the key holder is not serving. A job
for one that was queued some other way is cancelled, not retried.

## Where a job stands

```json
Expand Down Expand Up @@ -137,7 +146,9 @@ true because the next call failed.

The advice overrides the configured lead time in both directions — it can bring
a renewal forward and hold one back — but **never past a seven-day safety
floor**. Inside that window a certificate renews regardless of what the CA
floor**, or past a third of the certificate's lifetime when that is shorter. A
six-day certificate is inside seven days from the moment it is issued, so an
unbounded floor would renew it on every sweep whatever the CA advised. Inside that window a certificate renews regardless of what the CA
suggested, so a bad window, or a stale one left by a poller that stopped
running, cannot defer something about to expire.

Expand Down
3 changes: 3 additions & 0 deletions scripts/sync-guides.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ const CODE_TREE = 'https://github.com/certpilot/certpilot/blob/main'
*/
const ANCHOR_TO_PAGE = {
'authenticating-an-unattended-screen': '/api/display-tokens',
// Certificates → renewing: a key CertPilot does not hold is refused, and
// the rule is written up where the renewal queue is (certpilot#114).
'asking-for-one': '/api/reference/renewal-queue#asking-for-one',
}

/**
Expand Down
Loading