ipn/localapi,client/local: honour Retry-After on cert rate-limit (#20315)

* ipn/localapi,ipnlocal,feature/acme,client/local: honour Retry-After on cert rate-limit

serveCert now responds with 429 + Retry-After when the underlying ACME
error is a rate limit, instead of a generic 500. client/local surfaces
this as a typed RateLimitedError with the parsed hint so callers can
back off intelligently.

Updates tailscale/corp#42164

Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>

* tsweb,feature/acme,ipn/localapi,ipnlocal: generalise cert error → HTTP mapping via tsweb.HTTPStatuser

Introduces a tsweb.HTTPStatuser interface, any error can implement
to describe its intended HTTP response (code, message, headers).
Moves CertRateLimitedError from ipnlocal to feature/acme where it's
constructed, and it now uses HTTPStatuser to return 429 + Retry-After.

serveCert now checks for tsweb.HTTPStatuser rather than the specific
error type, so it no longer needs to know about the ACME rate-limit
type.

Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>

---------

Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
This commit is contained in:
Tom Meadows
2026-07-08 13:34:40 +01:00
committed by GitHub
parent 9106b237eb
commit 87b3d7b7e5
11 changed files with 163 additions and 36 deletions
+4 -4
View File
@@ -232,7 +232,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
tailscale.com/tstime from tailscale.com/control/controlclient+
tailscale.com/tstime/mono from tailscale.com/net/tstun+
tailscale.com/tstime/rate from tailscale.com/wgengine/filter
LDWI tailscale.com/tsweb from tailscale.com/util/eventbus+
tailscale.com/tsweb from tailscale.com/util/eventbus+
tailscale.com/tsweb/varz from tailscale.com/tsweb+
tailscale.com/types/appctype from tailscale.com/ipn/ipnlocal+
tailscale.com/types/bools from tailscale.com/tsnet+
@@ -500,7 +500,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
internal/nettrace from net+
internal/oserror from internal/syscall/windows+
internal/poll from net+
LDWI internal/profile from net/http/pprof
internal/profile from net/http/pprof
internal/profilerecord from runtime+
internal/race from internal/poll+
internal/reflectlite from context+
@@ -552,7 +552,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
net/http/internal from net/http+
net/http/internal/ascii from net/http+
net/http/internal/httpcommon from net/http
LDWI net/http/pprof from tailscale.com/ipn/localapi+
net/http/pprof from tailscale.com/ipn/localapi+
net/netip from crypto/x509+
net/textproto from github.com/coder/websocket+
net/url from crypto/x509+
@@ -567,7 +567,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
runtime from crypto/internal/fips140+
runtime/debug from github.com/klauspost/compress/zstd+
runtime/pprof from net/http/pprof+
LDWI runtime/trace from net/http/pprof
runtime/trace from net/http/pprof
slices from crypto/tls+
sort from compress/flate+
strconv from compress/flate+