feat(dashboard): choose a certificate's expiry at issue time, up to a configured maximum #18
Labels
No labels
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
status/deferred
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/purser#18
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Today the lifetime is a single deployment-wide value (
PURSER_CERT_LIFETIME, read once from the environment). Every certificate this instance issues gets the same one.Operator direction, 2026-08-05:
🔑 A safe default with a deliberate exception, rather than one compromise value that is wrong for both cases. ✅ The immediate driver: certificates for family devices that should last a specific trip, without making every routine certificate long-lived.
Why this is a separate tracker from
purser#4⛔
#4is a VALUE decision — pick a number, record the reasoning. It closes when the value is chosen and documented.✅ This is a FEATURE — per-request lifetime plumbing plus a UI control. It closes on working code.
📌 Filing them together would mean one tracker that cannot close until both are done, and
#4's half is what unblocks the operator's trip.Scope
Service.Issuetakes a lifetime per request rather than readingCfg.CertLifetimePURSER_CERT_LIFETIMEand requires no interaction#4measured, and it hands back a certificate that is not the one requested while reporting successnot_afteris read back from the SIGNED CERTIFICATE, not from what was requested — the store must record what the CA actually granteddocs/operations.mdconfiguration table updated⚠️ Depends on
A long lifetime is only safe once revocation works — see the CRL tracker in
alcatraz-infra. TodayNotAfteris the only enforcement, so a 365-day certificate cannot be withdrawn.Anchor
Operator direction 2026-08-05, after establishing that unattended renewal is not available: Cisco Secure Client keeps its own certificate store (not the system Keychain) and is provisioned unattended only by EMM/MDM, which is disproportionate here. The lifetime is the only lever, so it should be a good one. Filed by @bosun.
Six ACs ticked — each re-derived from
mainat9f991484Closed on #49's merge with all six unticked. Same close-without-pre-tick gap that hit #29 an hour ago; caught immediately this time rather than by the operator.
These are state-asserting ACs, so the tick is a claim about how the world is. Verified against the merged code, not inferred from the merge:
mainService.Issuetakes a lifetime per requestservice.go:82—Issue(ctx, cn, issuedBy string, lifetime time.Duration)PURSER_CERT_LIFETIME, no interaction neededserver.go:174,192—d.CertLifetime = s.Cfg.CertLifetime,lifetime := s.Cfg.CertLifetime;LifetimeIsFixedat:176;TestDashboard_ExpiryControlIsHiddenWhenThereIsNoChoiceservice.go:261—"purser: refusing a certificate lifetime of %s — the maximum this …"TestIssue_LifetimeAboveTheMaximumIsRefusedNotClamped+TestIssue_LifetimeBelowTheMaximumIsHonoured, plus boundary arms at exactly the maximum and exactly the download windownot_afterread back from the SIGNED certificateservice.go:164—NotAfter: res.Leaf.NotAfter, off the signed leaf rather than the requestdocs/operations.mdconfiguration table updated:83table row, plus the opt-in explanation at:190–194and the why not checked against the provisioner note at:214Two worth naming beyond the tick.
The refusal names the limit, and the boundary arms are at the exact edge — at-maximum accepted, at-download-window refused. That is the dimension rather than a point either side of it, which is what AC4 was asking for.
NotAftercomes offres.Leaf. The store records what the CA actually granted, not what was asked for — which is the whole point, since a silent clamp is what #4 measured and it returns success while handing back a different certificate.Deployment status, stated because merged is not deployed
PURSER_MAX_CERT_LIFETIMEnow has a supplier (alcatraz-infra#470, merged) and a reader (this PR, merged). It is not yet effective on the host: the operator has not set it in.env, and the container has not been recreated. Unset, it equals the default and the expiry control stays hidden — so this feature grants nothing until it is deliberately turned on, which is what the docs say it does.