cmd/derper: add --acme-email flag for GCP cert mode (#18278)
GCP Certificate Manager requires an email contact on ACME accounts. Add --acme-email flag that is required for --certmode=gcp and optional for --certmode=letsencrypt. Fixes #18277 Signed-off-by: Raj Singh <raj@tailscale.com>
This commit is contained in:
+8
-1
@@ -44,7 +44,7 @@ type certProvider interface {
|
||||
HTTPHandler(fallback http.Handler) http.Handler
|
||||
}
|
||||
|
||||
func certProviderByCertMode(mode, dir, hostname, eabKID, eabKey string) (certProvider, error) {
|
||||
func certProviderByCertMode(mode, dir, hostname, eabKID, eabKey, email string) (certProvider, error) {
|
||||
if dir == "" {
|
||||
return nil, errors.New("missing required --certdir flag")
|
||||
}
|
||||
@@ -59,6 +59,9 @@ func certProviderByCertMode(mode, dir, hostname, eabKID, eabKey string) (certPro
|
||||
if eabKID == "" || eabKey == "" {
|
||||
return nil, errors.New("--certmode=gcp requires --acme-eab-kid and --acme-eab-key flags")
|
||||
}
|
||||
if email == "" {
|
||||
return nil, errors.New("--certmode=gcp requires --acme-email flag")
|
||||
}
|
||||
keyBytes, err := decodeEABKey(eabKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -73,6 +76,10 @@ func certProviderByCertMode(mode, dir, hostname, eabKID, eabKey string) (certPro
|
||||
}
|
||||
if hostname == "derp.tailscale.com" {
|
||||
certManager.HostPolicy = prodAutocertHostPolicy
|
||||
}
|
||||
if email != "" {
|
||||
certManager.Email = email
|
||||
} else if hostname == "derp.tailscale.com" {
|
||||
certManager.Email = "security@tailscale.com"
|
||||
}
|
||||
return certManager, nil
|
||||
|
||||
+11
-5
@@ -91,7 +91,7 @@ func TestCertIP(t *testing.T) {
|
||||
t.Fatalf("Error closing key.pem: %v", err)
|
||||
}
|
||||
|
||||
cp, err := certProviderByCertMode("manual", dir, hostname, "", "")
|
||||
cp, err := certProviderByCertMode("manual", dir, hostname, "", "", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -174,19 +174,25 @@ func TestGCPCertMode(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
|
||||
// Missing EAB credentials
|
||||
_, err := certProviderByCertMode("gcp", dir, "test.example.com", "", "")
|
||||
_, err := certProviderByCertMode("gcp", dir, "test.example.com", "", "", "test@example.com")
|
||||
if err == nil {
|
||||
t.Fatal("expected error when EAB credentials are missing")
|
||||
}
|
||||
|
||||
// Missing email
|
||||
_, err = certProviderByCertMode("gcp", dir, "test.example.com", "kid", "dGVzdC1rZXk", "")
|
||||
if err == nil {
|
||||
t.Fatal("expected error when email is missing")
|
||||
}
|
||||
|
||||
// Invalid base64
|
||||
_, err = certProviderByCertMode("gcp", dir, "test.example.com", "kid", "not-valid!")
|
||||
_, err = certProviderByCertMode("gcp", dir, "test.example.com", "kid", "not-valid!", "test@example.com")
|
||||
if err == nil {
|
||||
t.Fatal("expected error for invalid base64")
|
||||
}
|
||||
|
||||
// Valid base64url (no padding)
|
||||
cp, err := certProviderByCertMode("gcp", dir, "test.example.com", "kid", "dGVzdC1rZXk")
|
||||
cp, err := certProviderByCertMode("gcp", dir, "test.example.com", "kid", "dGVzdC1rZXk", "test@example.com")
|
||||
if err != nil {
|
||||
t.Fatalf("base64url: %v", err)
|
||||
}
|
||||
@@ -195,7 +201,7 @@ func TestGCPCertMode(t *testing.T) {
|
||||
}
|
||||
|
||||
// Valid standard base64 (with padding, gcloud format)
|
||||
cp, err = certProviderByCertMode("gcp", dir, "test.example.com", "kid", "dGVzdC1rZXk=")
|
||||
cp, err = certProviderByCertMode("gcp", dir, "test.example.com", "kid", "dGVzdC1rZXk=", "test@example.com")
|
||||
if err != nil {
|
||||
t.Fatalf("base64: %v", err)
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ var (
|
||||
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")
|
||||
acmeEABKid = flag.String("acme-eab-kid", "", "ACME External Account Binding (EAB) Key ID (required for --certmode=gcp)")
|
||||
acmeEABKey = flag.String("acme-eab-key", "", "ACME External Account Binding (EAB) HMAC key, base64-encoded (required for --certmode=gcp)")
|
||||
acmeEmail = flag.String("acme-email", "", "ACME account contact email address (required for --certmode=gcp, optional for letsencrypt)")
|
||||
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")
|
||||
@@ -345,7 +346,7 @@ func main() {
|
||||
if serveTLS {
|
||||
log.Printf("derper: serving on %s with TLS", *addr)
|
||||
var certManager certProvider
|
||||
certManager, err = certProviderByCertMode(*certMode, *certDir, *hostname, *acmeEABKid, *acmeEABKey)
|
||||
certManager, err = certProviderByCertMode(*certMode, *certDir, *hostname, *acmeEABKid, *acmeEABKey, *acmeEmail)
|
||||
if err != nil {
|
||||
log.Fatalf("derper: can not start cert provider: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user