From e8eb98dad19a1a86637112da79b37af1a34646c8 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 3 Dec 2025 15:02:10 -0800 Subject: [PATCH] cmd/derper: add GCP cert support Fixes tailscale/corp#34881 Change-Id: I54159d3bccf87433c5f825cba6c78408085058e5 Signed-off-by: Brad Fitzpatrick --- cmd/derper/cert.go | 8 +++++++- cmd/derper/depaware.txt | 2 +- cmd/derper/derper.go | 6 +++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/cmd/derper/cert.go b/cmd/derper/cert.go index b95755c64..8d3525ff5 100644 --- a/cmd/derper/cert.go +++ b/cmd/derper/cert.go @@ -24,6 +24,7 @@ import ( "regexp" "time" + upstreamacme "golang.org/x/crypto/acme" "golang.org/x/crypto/acme/autocert" "tailscale.com/tailcfg" ) @@ -47,12 +48,17 @@ func certProviderByCertMode(mode, dir, hostname string) (certProvider, error) { return nil, errors.New("missing required --certdir flag") } switch mode { - case "letsencrypt": + case "letsencrypt", "gcp": certManager := &autocert.Manager{ Prompt: autocert.AcceptTOS, HostPolicy: autocert.HostWhitelist(hostname), Cache: autocert.DirCache(dir), } + if mode == "gcp" { + certManager.Client = &upstreamacme.Client{ + DirectoryURL: "https://dv.acme-v02.api.pki.goog/directory", + } + } if hostname == "derp.tailscale.com" { certManager.HostPolicy = prodAutocertHostPolicy certManager.Email = "security@tailscale.com" diff --git a/cmd/derper/depaware.txt b/cmd/derper/depaware.txt index 11a6318c3..b2465d28d 100644 --- a/cmd/derper/depaware.txt +++ b/cmd/derper/depaware.txt @@ -171,7 +171,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa tailscale.com/version from tailscale.com/cmd/derper+ tailscale.com/version/distro from tailscale.com/envknob+ tailscale.com/wgengine/filter/filtertype from tailscale.com/types/netmap - golang.org/x/crypto/acme from golang.org/x/crypto/acme/autocert + golang.org/x/crypto/acme from golang.org/x/crypto/acme/autocert+ golang.org/x/crypto/acme/autocert from tailscale.com/cmd/derper golang.org/x/crypto/argon2 from tailscale.com/tka golang.org/x/crypto/blake2b from golang.org/x/crypto/argon2+ diff --git a/cmd/derper/derper.go b/cmd/derper/derper.go index f177986a5..54b3b3e48 100644 --- a/cmd/derper/derper.go +++ b/cmd/derper/derper.go @@ -60,9 +60,9 @@ var ( httpPort = flag.Int("http-port", 80, "The port on which to serve HTTP. Set to -1 to disable. The listener is bound to the same IP (if any) as specified in the -a flag.") stunPort = flag.Int("stun-port", 3478, "The UDP port on which to serve STUN. The listener is bound to the same IP (if any) as specified in the -a flag.") configPath = flag.String("c", "", "config file path") - certMode = flag.String("certmode", "letsencrypt", "mode for getting a cert. possible options: manual, letsencrypt") - certDir = flag.String("certdir", tsweb.DefaultCertDir("derper-certs"), "directory to store LetsEncrypt certs, if addr's port is :443") - hostname = flag.String("hostname", "derp.tailscale.com", "LetsEncrypt host name, if addr's port is :443. When --certmode=manual, this can be an IP address to avoid SNI checks") + certMode = flag.String("certmode", "letsencrypt", "mode for getting a cert. possible options: manual, letsencrypt, gcp") + certDir = flag.String("certdir", tsweb.DefaultCertDir("derper-certs"), "directory to store ACME (e.g. LetsEncrypt) certs, if addr's port is :443") + hostname = flag.String("hostname", "derp.tailscale.com", "TLS host name for certs, if addr's port is :443. When --certmode=manual, this can be an IP address to avoid SNI checks") runSTUN = flag.Bool("stun", true, "whether to run a STUN server. It will bind to the same IP (if any) as the --addr flag value.") runDERP = flag.Bool("derp", true, "whether to run a DERP server. The only reason to set this false is if you're decommissioning a server but want to keep its bootstrap DNS functionality still running.") flagHome = flag.String("home", "", "what to serve at the root path. It may be left empty (the default, for a default homepage), \"blank\" for a blank page, or a URL to redirect to")