From b4e483d38bdb1f0ac5656bd834cb25073bd3ab87 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Mon, 1 Mar 2021 18:37:47 -0800 Subject: [PATCH] Add gRPC MaxConnectionAge config. (#5311) This allows servers to tell clients to go away after some period of time, which triggers the clients to re-resolve DNS. Per grpc/grpc#12295, this is the preferred way to do this. Related: #5307. --- cmd/config.go | 6 ++++++ grpc/server.go | 14 +++++++++++--- test/config-next/akamai-purger.json | 1 + test/config-next/ca-a.json | 2 ++ test/config-next/ca-b.json | 2 ++ test/config-next/nonce.json | 1 + test/config-next/publisher.json | 1 + test/config-next/ra.json | 1 + test/config-next/sa.json | 1 + test/config-next/va-remote-a.json | 1 + test/config-next/va-remote-b.json | 1 + test/config-next/va.json | 1 + 12 files changed, 29 insertions(+), 3 deletions(-) diff --git a/cmd/config.go b/cmd/config.go index 0199fe5dd..92e85c6d2 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -269,6 +269,12 @@ type GRPCServerConfig struct { // (SANs). The server will reject clients that do not present a certificate // with a SAN present on the `ClientNames` list. ClientNames []string `json:"clientNames"` + // MaxConnectionAge specifies how long a connection may live before the server sends a GoAway to the + // client. Because gRPC connections re-resolve DNS after a connection close, + // this controls how long it takes before a client learns about changes to its + // backends. + // https://pkg.go.dev/google.golang.org/grpc/keepalive#ServerParameters + MaxConnectionAge ConfigDuration } // PortConfig specifies what ports the VA should call to on the remote diff --git a/grpc/server.go b/grpc/server.go index 8b6e5c418..d91f10f9f 100644 --- a/grpc/server.go +++ b/grpc/server.go @@ -5,12 +5,13 @@ import ( "errors" "net" - "github.com/grpc-ecosystem/go-grpc-prometheus" + grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/jmhodges/clock" "github.com/letsencrypt/boulder/cmd" bcreds "github.com/letsencrypt/boulder/grpc/creds" "github.com/prometheus/client_golang/prometheus" "google.golang.org/grpc" + "google.golang.org/grpc/keepalive" ) // CodedError is a alias required to appease go vet @@ -42,10 +43,17 @@ func NewServer(c *cmd.GRPCServerConfig, tlsConfig *tls.Config, metrics serverMet } si := newServerInterceptor(metrics, clk) - return grpc.NewServer( + options := []grpc.ServerOption{ grpc.Creds(creds), grpc.UnaryInterceptor(si.intercept), - ), l, nil + } + if c.MaxConnectionAge.Duration > 0 { + options = append(options, + grpc.KeepaliveParams(keepalive.ServerParameters{ + MaxConnectionAge: c.MaxConnectionAge.Duration, + })) + } + return grpc.NewServer(options...), l, nil } // serverMetrics is a struct type used to return a few registered metrics from diff --git a/test/config-next/akamai-purger.json b/test/config-next/akamai-purger.json index f28b0ff72..8b8b16a1b 100644 --- a/test/config-next/akamai-purger.json +++ b/test/config-next/akamai-purger.json @@ -14,6 +14,7 @@ }, "grpc": { "address": ":9099", + "maxConnectionAge": "30s", "clientNames": [ "health-checker.boulder", "ra.boulder" diff --git a/test/config-next/ca-a.json b/test/config-next/ca-a.json index 93ace68a4..6c21affb9 100644 --- a/test/config-next/ca-a.json +++ b/test/config-next/ca-a.json @@ -8,6 +8,7 @@ }, "hostnamePolicyFile": "test/hostname-policy.yaml", "grpcCA": { + "maxConnectionAge": "30s", "address": ":9093", "clientNames": [ "health-checker.boulder", @@ -15,6 +16,7 @@ ] }, "grpcOCSPGenerator": { + "maxConnectionAge": "30s", "address": ":9096", "clientNames": [ "health-checker.boulder", diff --git a/test/config-next/ca-b.json b/test/config-next/ca-b.json index a54db39e9..2f2e900a9 100644 --- a/test/config-next/ca-b.json +++ b/test/config-next/ca-b.json @@ -8,6 +8,7 @@ }, "hostnamePolicyFile": "test/hostname-policy.yaml", "grpcCA": { + "maxConnectionAge": "30s", "address": ":9093", "clientNames": [ "health-checker.boulder", @@ -15,6 +16,7 @@ ] }, "grpcOCSPGenerator": { + "maxConnectionAge": "30s", "address": ":9096", "clientNames": [ "health-checker.boulder", diff --git a/test/config-next/nonce.json b/test/config-next/nonce.json index 231b95e3b..ce4dfa64c 100644 --- a/test/config-next/nonce.json +++ b/test/config-next/nonce.json @@ -8,6 +8,7 @@ }, "debugAddr": ":8111", "grpc": { + "maxConnectionAge": "30s", "address": ":9101", "clientNames": [ "health-checker.boulder", diff --git a/test/config-next/publisher.json b/test/config-next/publisher.json index 93ab9c8c5..2844240e2 100644 --- a/test/config-next/publisher.json +++ b/test/config-next/publisher.json @@ -4,6 +4,7 @@ "blockProfileRate": 1000000000, "debugAddr": ":8009", "grpc": { + "maxConnectionAge": "30s", "address": ":9091", "clientNames": [ "health-checker.boulder", diff --git a/test/config-next/ra.json b/test/config-next/ra.json index c44ab32a1..351d297e3 100644 --- a/test/config-next/ra.json +++ b/test/config-next/ra.json @@ -42,6 +42,7 @@ "timeout": "15s" }, "grpc": { + "maxConnectionAge": "30s", "address": ":9094", "clientNames": [ "admin-revoker.boulder", diff --git a/test/config-next/sa.json b/test/config-next/sa.json index fe6fcf504..a50f03d0e 100644 --- a/test/config-next/sa.json +++ b/test/config-next/sa.json @@ -12,6 +12,7 @@ "keyFile": "test/grpc-creds/sa.boulder/key.pem" }, "grpc": { + "maxConnectionAge": "30s", "address": ":9095", "clientNames": [ "admin-revoker.boulder", diff --git a/test/config-next/va-remote-a.json b/test/config-next/va-remote-a.json index 0cbeac4be..b260c6e7c 100644 --- a/test/config-next/va-remote-a.json +++ b/test/config-next/va-remote-a.json @@ -19,6 +19,7 @@ "keyFile": "test/grpc-creds/va.boulder/key.pem" }, "grpc": { + "maxConnectionAge": "30s", "address": ":9097", "clientNames": [ "health-checker.boulder", diff --git a/test/config-next/va-remote-b.json b/test/config-next/va-remote-b.json index ca2812af9..f911c63cd 100644 --- a/test/config-next/va-remote-b.json +++ b/test/config-next/va-remote-b.json @@ -19,6 +19,7 @@ "keyFile": "test/grpc-creds/va.boulder/key.pem" }, "grpc": { + "maxConnectionAge": "30s", "address": ":9098", "clientNames": [ "health-checker.boulder", diff --git a/test/config-next/va.json b/test/config-next/va.json index 6742fc2b8..a3d702635 100644 --- a/test/config-next/va.json +++ b/test/config-next/va.json @@ -19,6 +19,7 @@ "keyFile": "test/grpc-creds/va.boulder/key.pem" }, "grpc": { + "maxConnectionAge": "30s", "address": ":9092", "clientNames": [ "health-checker.boulder",