v2.45.0 (webhook deploy targets, tags and notes on certificates, and an Infisical backend that runs)
A new deploy target can hand a renewed certificate to an HTTPS endpoint you name, and the private key too only if you ask for it in so many words. Certificates get tags and a free-text note. The Infisical storage backend, which could not run in any earlier release, now does. The API contract moves from 2.32 to 2.34.
Thanks to @jensaops for asking for tags and notes (#1043), and to @tuxpowered for the request that became the webhook target (#218).
Read this before upgrading
The Kubernetes Secret target no longer follows redirects
A 3xx from the API server is now a failure that says so, without quoting the address it named. If your API server address redirects, point the target at the final address.
Vault: a redirect to another host is refused
A redirect within the configured address (a path or trailing-slash redirect) is followed as before. A redirect to another host, to another port, or from https to http is refused before anything is sent there; the error names the host and says what to do. If your Vault runs without request forwarding and a standby answers with a redirect to the active node, set vault_url to the active node or to a load balancer.
The Infisical backend works for the first time, and site_url must be https
With the SDK version the project pins, the backend could not import its SDK in any earlier release (it imported a module name the package does not have, called methods the client does not have, and read a result field that is named differently). If you had it configured, every operation failed. It now runs, and there is nothing to migrate. It needs the infisical-python package (requirements-infisical-storage.txt), which the published Docker image does not contain (it carries boto3 and none of the Vault, Azure Key Vault or Infisical SDKs), so use an extended image: --build-arg EXTRA_REQUIREMENTS=requirements-infisical-storage.txt.
site_url must be https://; http:// is accepted only for a loopback address (localhost, 127.0.0.1, ::1). The SDK's HTTP client follows redirects and cannot be configured from CertMate, so the one thing CertMate can refuse is plain HTTP, where anyone on the path could answer with a redirect.
New
- Webhook deploy target. After a certificate is issued or renewed, CertMate can send it to an HTTPS endpoint with a JSON payload you write. Settings → Deploy → Deploy Targets lists every target and edits the webhook ones; the API takes the same objects in
deploy_hooks.targets. What it holds to:- The key is a decision about a destination. The private key is read only if the payload names
{{privkey_pkcs8}}or{{privkey_traditional}}(there is no bareprivkey), and saving such a target requires the destination host to be typed. CertMate records who confirmed it and when, per host: change the host and it asks again. The audit log marks every delivery that carried a key (where it went, for which domain, the certificate's fingerprint, never the key). - Domains are required. A target that sends certificate material is never applied to "all domains" by default.
- The server is always verified.
httpsonly, against the system store, against a CA you supply, or against the pinned SHA-256 fingerprint of an appliance's own certificate. There is no setting that turns verification off. - Where it may send. The host is resolved once, every address is checked and the connection goes to the one that was checked. Loopback, link-local and cloud-metadata addresses are never a destination; a private network needs
allow_internalon that target. A redirect is a failure, not a hop. - Retries. Network errors and the statuses
408,425,429,500,502,503and504are retried with backoff (3 attempts by default, at most 5); any other4xxis not; every delivery carries anIdempotency-Key, and asigning_secretsigns the body. - There is no "send a test". A test that delivered a key to an appliance with an upload API would install it in place of the real one. Preview what would be sent (
POST /api/deploy/targets/preview) renders the request against an example certificate and key, reads no file and sends nothing. - The notification webhooks are unchanged: they still never carry the private key.
- The key is a decision about a destination. The private key is read only if the payload names
- Tags and notes on server certificates (#1043).
PATCH /api/certificates/<domain>acceptsnotes(up to 2000 characters) andtags(up to 20; letters, digits and. _ - : /, stored lower case);GETreturns both. They survive renewal, Edit & Reissue and a backup restore. The dashboard shows tags on each row, filters by them (the bar stays hidden until something is tagged), has an Edit section in the detail panel, and the ⌘K palette searches tags and notes. Deploy hooks getCERTMATE_TAGS, always set. - Deploy Targets in the UI also lists the Kubernetes Secret targets, which until now could only be seen through the API. They are listed and left alone: edit them through the API.
Fixed
- Editing a probe removed its host.
GET /api/certificatesdid not returndeployment_host, so Settings → Probe opened with an empty host and saving it sentnull, which the server reads as "delete it". Changing only the port silently removed the host that makes a wildcard verifiable. The field is now returned. - A note, tag or probe edit no longer rewrites
settings.json. It did, for every edit, and every settings save takes a backup, so tagging many certificates left one backup each, named for a change that never happened. - What a deploy target reports is stripped of the bearer token and of the key it just sent (as PEM, JSON-escaped, base64, URL-encoded or a single line of it) before the answer is shortened, not after: cutting first left whatever fragment of the key fell inside the cut. The shared sanitiser also redacts a PEM block that was base64-encoded.
- A key press inside a table row now belongs to the control that has focus (a tag chip, an action button) and no longer also opens the row.
- Infisical: the three mismatches above.
Known limits
- The webhook target's own credentials (
auth_token,auth_password,signing_secret) are kept insettings.json(mode0600) and returned to an administrator byGET /api/deploy/config, as a Kubernetes target's token already is. Give the receiver a token that can do this one thing. - The webhook target is https-only: a receiver that listens on plain HTTP by default (n8n does) needs TLS enabled on it or in front of it.
- The webhook target sends JSON. A bundle as a file upload or PKCS#12, and request headers other than the authentication one, are not in this release; say what a receiver needs.
- The Infisical backend was checked against the real SDK and a local stand-in server that speaks what the SDK sends, not against Infisical Cloud.
How it was checked
- A real certificate. A certificate renewed from Let's Encrypt staging was delivered by the webhook target over real TLS to a local receiver pinned by its fingerprint, and the key that arrived, in both PKCS#8 and the traditional form, is the key of the certificate that arrived.
- Against n8n. The target delivered to a real n8n 2.41.4 Webhook node over TLS, an RSA and an EC certificate in the payload proposed in #218: every certificate and both key forms arrived identical to what was sent. It also showed that n8n keeps the request body, key included, in its own database by default; Receiving it in n8n in deploy-hooks.md says so, and how to give n8n TLS.
- In a browser. The Deploy Targets screen was driven in Chrome: typing the wrong host or a prefix of it leaves Save target disabled, a confirmed target is not asked again on a rename, a different host asks again, a target name containing markup stays text, and a save keeps a target an API client added in the meantime and every target of another type. 25 browser tests cover this. 15 deliberate breakages of the screen and its guards are each caught by the test meant to catch them (one was not at first, the page posting back a consent it had loaded, and was fixed); a 16th, which only makes the tests wait for the page to be idle, is masked by the guards in the component and is not caught on its own.
- The Infisical backend against its real SDK. 12 tests run it end to end through the installed package, in the job that installs it, and 9 deliberate breakages are caught. The two that reproduce the original defect (the wrong module name and the wrong method names) pass every test that does not use the real SDK, which is why the backend ran in no release.