From ffa90a3c74518199426be2401545c6315911ca8a Mon Sep 17 00:00:00 2001 From: Hans Hasselberg Date: Fri, 17 Jan 2020 23:06:01 +0100 Subject: [PATCH] setup grpc server with auto_encrypt certs --- agent/agent.go | 4 ++-- agent/xds/server.go | 12 +++++------- tlsutil/config.go | 26 ++++++++++++++++++++------ 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/agent/agent.go b/agent/agent.go index ca44d1c9fc68..de819e39a399 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -721,9 +721,9 @@ func (a *Agent) listenAndServeGRPC() error { if a.config.HTTPSPort > 0 { // gRPC uses the same TLS settings as the HTTPS API. If HTTPS is // enabled then gRPC will require HTTPS as well. - a.grpcServer, err = a.xdsServer.GRPCServer(a.config.CertFile, a.config.KeyFile) + a.grpcServer, err = a.xdsServer.GRPCServer(a.tlsConfigurator) } else { - a.grpcServer, err = a.xdsServer.GRPCServer("", "") + a.grpcServer, err = a.xdsServer.GRPCServer(nil) } if err != nil { return err diff --git a/agent/xds/server.go b/agent/xds/server.go index 7f11994ea067..2c0f1aa63490 100644 --- a/agent/xds/server.go +++ b/agent/xds/server.go @@ -10,7 +10,6 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" - "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" @@ -25,6 +24,7 @@ import ( "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/tlsutil" ) // ADSStream is a shorter way of referring to this thing... @@ -536,16 +536,14 @@ func (s *Server) Check(ctx context.Context, r *envoyauthz.CheckRequest) (*envoya // GRPCServer returns a server instance that can handle XDS and ext_authz // requests. -func (s *Server) GRPCServer(certFile, keyFile string) (*grpc.Server, error) { +func (s *Server) GRPCServer(tlsConfigurator *tlsutil.Configurator) (*grpc.Server, error) { opts := []grpc.ServerOption{ grpc.MaxConcurrentStreams(2048), } - if certFile != "" && keyFile != "" { - creds, err := credentials.NewServerTLSFromFile(certFile, keyFile) - if err != nil { - return nil, err + if tlsConfigurator != nil { + if cert := tlsConfigurator.Cert(); cert != nil { + opts = append(opts, grpc.Creds(*tlsConfigurator.TransportCredentials())) } - opts = append(opts, grpc.Creds(creds)) } srv := grpc.NewServer(opts...) envoydisco.RegisterAggregatedDiscoveryServiceServer(srv, s) diff --git a/tlsutil/config.go b/tlsutil/config.go index 58352af1b069..dd01416a2fc4 100644 --- a/tlsutil/config.go +++ b/tlsutil/config.go @@ -12,6 +12,8 @@ import ( "strings" "sync" "time" + + "google.golang.org/grpc/credentials" ) // DCWrapper is a function that is used to wrap a non-TLS connection @@ -441,12 +443,7 @@ func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config { // autoEncrypt cert too so that a client can encrypt incoming // connections without having a manual cert configured. tlsConfig.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { - cert := c.manual.cert - if cert == nil { - cert = c.autoEncrypt.cert - } - - return cert, nil + return c.Cert(), nil } // GetClientCertificate is used when acting as a client and responding @@ -477,6 +474,17 @@ func (c *Configurator) commonTLSConfig(verifyIncoming bool) *tls.Config { return tlsConfig } +// This function acquires a read lock because it reads from the config. +func (c *Configurator) Cert() *tls.Certificate { + c.RLock() + defer c.RUnlock() + cert := c.manual.cert + if cert == nil { + cert = c.autoEncrypt.cert + } + return cert +} + // This function acquires a read lock because it reads from the config. func (c *Configurator) VerifyIncomingRPC() bool { c.RLock() @@ -561,6 +569,12 @@ func (c *Configurator) VerifyServerHostname() bool { return c.base.VerifyServerHostname || c.autoEncrypt.verifyServerHostname } +// TransportCredentials returns credentials to be used with eg a grpc server. +func (c *Configurator) TransportCredentials() *credentials.TransportCredentials { + creds := credentials.NewTLS(&tls.Config{Certificates: []tls.Certificate{*c.Cert()}}) + return &creds +} + // IncomingRPCConfig generates a *tls.Config for incoming RPC connections. func (c *Configurator) IncomingRPCConfig() *tls.Config { c.log("IncomingRPCConfig")