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:
@@ -31,7 +31,7 @@ import (
|
||||
"tailscale.com/ipn/ipnlocal/ipnlocaltest"
|
||||
"tailscale.com/ipn/store/mem"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/tempfork/acme"
|
||||
xacme "tailscale.com/tempfork/acme"
|
||||
"tailscale.com/tsconst"
|
||||
"tailscale.com/tstest"
|
||||
"tailscale.com/types/logger"
|
||||
@@ -263,7 +263,7 @@ func TestACMETLSALPNCertHook(t *testing.T) {
|
||||
|
||||
if got, ok := b.ForTest().GetACMETLSALPNCert(&tls.ClientHelloInfo{
|
||||
ServerName: "example.com",
|
||||
SupportedProtos: []string{acme.ALPNProto},
|
||||
SupportedProtos: []string{xacme.ALPNProto},
|
||||
}); !ok || got != cert {
|
||||
t.Fatalf("getACMETLSALPNCert = %v, %v; want stored cert, true", got, ok)
|
||||
}
|
||||
@@ -275,7 +275,7 @@ func TestACMETLSALPNCertHook(t *testing.T) {
|
||||
}
|
||||
if _, ok := b.ForTest().GetACMETLSALPNCert(&tls.ClientHelloInfo{
|
||||
ServerName: "other.example.com",
|
||||
SupportedProtos: []string{acme.ALPNProto},
|
||||
SupportedProtos: []string{xacme.ALPNProto},
|
||||
}); ok {
|
||||
t.Fatal("getACMETLSALPNCert for other name = ok, want false")
|
||||
}
|
||||
@@ -283,7 +283,7 @@ func TestACMETLSALPNCertHook(t *testing.T) {
|
||||
otherBackend := ipnlocaltest.NewBackend(t)
|
||||
if _, ok := otherBackend.ForTest().GetACMETLSALPNCert(&tls.ClientHelloInfo{
|
||||
ServerName: "example.com",
|
||||
SupportedProtos: []string{acme.ALPNProto},
|
||||
SupportedProtos: []string{xacme.ALPNProto},
|
||||
}); ok {
|
||||
t.Fatal("getACMETLSALPNCert on different LocalBackend = ok, want false")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user