Commit Graph

55 Commits

Author SHA1 Message Date
Ludovic Vielle
cbd0387490 Expose ACME cooldown end time and error details
Operators could see that a rate-limit cooldown was active, but not
when it ends, and failure logs omitted most of the CA problem
document. Add a until-timestamp gauge and log the full acme.Error
surface so cooldowns and ACME responses are diagnosable.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-22 16:38:11 +02:00
Bryan Frimin
9f6a0c1d40 Fixes cubic review
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-22 13:57:56 +02:00
Bryan Frimin
3f202002d9 Fix parsing int error
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-22 13:20:53 +02:00
Bryan Frimin
81b7ee5fad Close cert provisioning correctness gaps
Several race and validity gaps could leave certificate provisioning
stuck, unusable, or noisy:

- Accept the HTTP-01 challenge only after the key authorization is
  committed, so the CA cannot hit the token before this instance can
  serve it and invalidate the order.
- Persist challenge metadata under a blocking write-back lock; a row
  merely locked by a competing transaction no longer silently drops the
  accepted order.
- Abandon a recovered VALID order and restart instead of issuing it
  with a freshly generated key that cannot match the existing cert.
- Exclude rate-limited rows from the ten-minute stale reset so the
  resumable order survives the ACME cooldown.
- Size the provisioning poll lease to exceed the max processing window
  so a released claim lock cannot let another worker process the same
  row concurrently.
- Parse Retry-After as unsigned seconds and clamp overflow so malformed
  values fall back to the default cooldown instead of disabling it.
- Normalize the acme_errors problem_type label to the RFC 8555 set to
  bound Prometheus cardinality.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-22 13:20:53 +02:00
Bryan Frimin
45c45ac5a0 Style
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-22 13:20:52 +02:00
Bryan Frimin
121d4dcf93 Fix certmanager provisioning retry and metrics
Address several provisioning defects that either stalled the retry
budget or crashed the process:

- Classify CAA resolver/transport failures apart from a real CAA policy
  denial. Both shared the "caa records" wording, so a transient resolver
  error was persisted as customer misconfiguration and retried forever
  without consuming the retry budget. A new ErrCAANotPermitted sentinel
  now marks the genuine misconfiguration; other CAA errors are treated
  as ordinary transient failures.

- Honor an explicit Retry-After: 0 (or a past date) as permission for an
  immediate retry instead of promoting it to the one-hour default
  cooldown. acme.RateLimit collapses zero, invalid, and absent headers
  to a zero duration, so the header is now parsed directly to tell an
  explicit zero apart from a missing one.

- Reuse already-registered Prometheus collectors when a second
  ACMEService shares a registerer. The fixed-name collectors were
  MustRegistered, so a duplicate registration panicked the process.

- Persist provisioning failures on a context detached from the process
  tick deadline. A timed-out attempt reached persistFailure with an
  expired context, so the write-back failed and the retry budget never
  advanced, leaving the certificate indefinitely retriable.

- Use pgx.StrictNamedArgs in the certificate FOR UPDATE loaders to match
  the coredata SQL contract.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-22 13:20:52 +02:00
Bryan Frimin
9724a2ce50 Harden cert provisioning failure and write-back
Rate limits no longer inflate ssl_retry_count into an instant FAILED
path. Centralize outcomes in decideProvisioningOutcome, keep ACME
order state on transient and rate-limit errors, bound each Process
tick with a timeout, and block on FOR UPDATE when persisting a
freshly issued certificate.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-22 13:20:52 +02:00
Bryan Frimin
4b4e7ea1f8 Fix OAuth code exchange and go lint
Authorization-code exchange used ExternalClientID, which
is empty for registered clients and broke e2e token
grants. Pass the authenticated client's GID instead.

Also satisfy wsl_v5 blank-line rules, wire the delete
reference dialog through its mutation hook, and name the
filemanager logger.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-21 15:44:23 +02:00
Bryan Frimin
43ce3a7c53 Harden compliance portal auth and TLS
Align console references and OAuth branding with the
compliance-page model, and fix certificate cache eviction,
portal OAuth handlers, and magic-link edge cases left after
the trust-center rename.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-21 15:44:22 +02:00
Bryan Frimin
b03acbd029 Fix step-ca root CA access on Linux CI
Host chmod cannot open 0700 dirs owned by UID 1000, so
`-f` never sees root_ca.crt. Chmod from inside the
container as root while waiting for the cert.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-21 15:44:22 +02:00
Bryan Frimin
4cec74c1a1 Limit TLS cache warming to live domains
After the certificates split, WarmCache loaded every ACTIVE
certificate. Org deletes cascade-remove custom_domains but leave
certificates behind, so orphans could regain a usable SNI cache
entry on rebuild. Warm and serve only certs still referenced by a
domain, and purge unreferenced cache rows.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-21 15:44:20 +02:00
Bryan Frimin
6da00604ed Address remaining compliance portal review nits
Fill in certificate renewal processing, preserve OAuth and JWKS
edge cases, embed the compliance-portal app in production builds,
and close the smaller portal routing and n8n update gaps.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-21 15:44:19 +02:00
Bryan Frimin
14604a3176 Replace Pebble with step-ca for local ACME
Pebble skipped real HTTP-01 validation, which hid integration gaps
for compliance-page custom domains. step-ca with a Caddy port-80
proxy exercises the same path production uses while keeping issued
certs persistent across compose restarts.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-21 15:44:15 +02:00
Bryan Frimin
b524e9b497 Refactor certmanager to worker service
Replace the Provisioner and Renewer with poll-based provision and renew
workers orchestrated by a certmanager Service. Certificate operations are
now hostname-centric and driven by the certificates table, decoupled from
custom-domain business logic.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-21 15:43:07 +02:00
Sacha Al Himdani
4c57d201a4 Make license declarations consistently MIT
The source headers, LICENSE files, and license metadata had drifted
apart. Align the entire project to MIT:

- Convert every source-file header to the MIT text across all comment
  styles (Go, TS, TSX, JS, MJS, SQL, CSS, GraphQL, shell), including
  SPDX-License-Identifier tags
- Set the root and cookie-banner LICENSE files to the MIT text with a
  "MIT License" title line
- Switch the package.json license fields, Docker image label, and
  cookie-banner README to MIT
- Update docs and the genmodels header generator accordingly
- Normalize copyright lines to a single format
  (Copyright (c) <year(s)> Probo Inc <hello@probo.com>.): unify the
  hello@getprobo.com and hello@probo.inc emails to hello@probo.com and
  the comma-separated years to a hyphenated range

Genuine third-party references are intentionally left untouched: the
Lucide icon attributions (Lucide is ISC) and the trivy dependency
license allowlist.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-13 16:21:14 +02:00
Sacha Al Himdani
9ac71f948f Update contact email to hello@probo.com
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-09 16:45:23 +02:00
Émile Ré
f5703d390b Enforce Go style rules across codebase
Apply five style rules: convert iota string enums to typed
string constants, replace errors.As with errors.AsType,
merge three-group imports into two groups, fix multiline
parameter/argument formatting, and replace fmt.Sprintf URL
construction with net/url.

Signed-off-by: Émile Ré <emile@probo.com>
2026-05-20 11:46:39 +04:00
Émile Ré
9156d6a16a Add wsl linter and fix
Signed-off-by: Émile Ré <emile@probo.com>
2026-05-20 09:27:28 +04:00
Bryan Frimin
da9ba64b07 Persist cleared provisioning error before HTTP challenge
When DNS and CAA checks pass, ProvisioningError is set to nil but
was only persisted later alongside the challenge data. If
GetHTTPChallenge then failed, the update was never reached,
leaving stale DNS/CAA error messages visible to the user.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-04-24 16:05:11 +02:00
Bryan Frimin
976acbd114 Surface domain provisioning errors to users
When DNS verification, CAA checks, or HTTP challenge completion
fail during certificate provisioning, the error is now stored on
the custom domain record and exposed via GraphQL. The console
displays it in both the domain card and domain detail dialog so
users can diagnose configuration issues without checking logs.

Previously these failures returned an error that was only logged
server-side, leaving users with no visibility into why their
domain was stuck in a pending state.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-04-24 16:05:11 +02:00
Bryan Frimin
f17fb7bf49 Upgrade to kit v0.3.0
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-04-03 11:56:06 +02:00
Sacha Al Himdani
8c02c53315 Update copyright headers across all Go files
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-25 17:38:32 +01:00
Bryan Frimin
2004bf6050 Fix CAA issuer matching to handle parameters
CAA issue records may contain parameters after a semicolon per
RFC 8659 (e.g. "letsencrypt.org; accounturi=..."). Split on ";"
and compare only the issuer domain so these records are accepted.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-25 12:23:32 +01:00
Bryan Frimin
9b66d05c3c Check CAA records before ACME certificate issuance
Before requesting a certificate from the ACME provider, verify
that CAA DNS records for the domain permit issuance by the
configured CA. This avoids wasting ACME attempts on domains
whose CAA policy would reject the request.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-25 12:23:30 +01:00
Bryan Frimin
f0d43fd8e5 Fix ACME challenge retry to create fresh orders
When CompleteHTTPChallenge fails, the challenge is already marked
invalid by Let's Encrypt. Retrying Accept on the same challenge
always fails with "authorization must be pending". Reset the
domain to pending with cleared challenge data so each retry
creates a new ACME order.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-25 09:30:40 +01:00
Bryan Frimin
6a77d42dd6 Style
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-16 00:28:47 +01:00
Bryan Frimin
ef76a8d2e1 Remove deadcode
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-13 17:18:02 +01:00
Émile Ré
87415c0324 Remove useless encryption key injections
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-03-11 14:42:37 +04:00
Bryan Frimin
d4b3025463 Use go 1.26 syntax
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-06 15:00:42 +01:00
Bryan Frimin
a9a2e75c59 Fix wrong error type
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-06 09:36:07 +01:00
Bryan Frimin
ece54f1616 Fix golint errors
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-02 18:42:50 +01:00
Émile Ré
20582a831c Uncomment cert provisioner dns config check
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-01-17 12:35:46 -08:00
Émile Ré
8b3bda56e6 Add magic link login for trust center
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-01-17 12:34:24 -08:00
Bryan Frimin
3eeafb21bd Fix ACME queue bloqued in case of error
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-12-15 19:10:16 +01:00
Bryan Frimin
ca23e945b3 Fix go/cgo dns resolver behaviour
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-12-15 18:34:32 +01:00
Bryan Frimin
32e7936737 Fix ACME renew infinit loop
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-12-15 17:19:28 +01:00
Bryan Frimin
653ac5addb Fix error message
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-11-13 21:22:27 +01:00
Bryan Frimin
24abdb9d14 Fix import and error management
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-11-13 20:55:43 +01:00
MustafaAamir
60a3402b24 fix(certmanager#514): check DNS configuration before starting ACME
Signed-off-by: MustafaAamir <mustafa.290101@gmail.com>
2025-11-13 20:55:43 +01:00
Bryan Frimin
59aa332ab5 Move to vanity import url
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-31 17:01:52 +01:00
Bryan Frimin
6f2bd9c92f Fix failed to to cannot
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-30 16:38:08 +01:00
Bryan Frimin
84a80b9469 Fix cert provisioner clearing valid challenges on transient errors
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-14 15:47:55 +02:00
Bryan Frimin
6631e0fa99 Fix failed ACME block the queue
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-14 15:47:53 +02:00
Bryan Frimin
1b01659fbc Fix noisy SSL error
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-14 14:20:58 +02:00
Bryan Frimin
916485e119 Fix retry on error
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-11 10:59:15 +02:00
Bryan Frimin
26c7364e27 Remove insecure acme option
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-09 15:04:56 +02:00
Bryan Frimin
2f505497c1 Fix error not wrapped
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-09 15:04:55 +02:00
Bryan Frimin
a2485ec6fa Remove decrypt key by default
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-09 15:04:55 +02:00
Bryan Frimin
7a4046ad65 Adapt to new sql model
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-09 15:04:54 +02:00
Bryan Frimin
cf186a4120 Add support for persistent ACME account keys
Allow ACME account keys to be configured via config file to maintain
the same Let's Encrypt account across deployments. Add DecodePrivateKey
function with PEM block type constants to support EC, RSA, and PKCS8
key formats. When no account key is provided, fall back to generating
a new one with a warning.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-09 15:04:53 +02:00