From 59f8b02d473782f56a62005ef30e58851116ce8e Mon Sep 17 00:00:00 2001
From: Steven Danna <steve@chef.io>
Date: Sat, 26 Jan 2019 17:17:50 +0000
Subject: [PATCH] Set minimum TLS protocol version to TLSv1.2, set
 PreferServerCipherSuites

Some environments are subject to strict rules about the permitted TLS
protocol verion and available ciphers. Setting TLSv1.2 as the minimum
version ensures we do not use weaker protocols. We've opted against
making this configurable given the age of TLSv1.2 and the increasing
push to deprecate TLSv1.1 and older.

The PreferServerCipherSuites setting is also commonly flagged by SSL
quality scanning tools. Since Go provides a relatively modern set of
default ciphers by default, defaulting this to true is unlikely to
make much practical difference.

Signed-off-by: Steven Danna <steve@chef.io>
---
 cmd/dex/serve.go | 47 ++++++++++++++++++++++++++++-------------------
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/cmd/dex/serve.go b/cmd/dex/serve.go
index 10200a30..b9f940cc 100644
--- a/cmd/dex/serve.go
+++ b/cmd/dex/serve.go
@@ -116,13 +116,19 @@ func serve(cmd *cobra.Command, args []string) error {
 	var grpcOptions []grpc.ServerOption
 
 	if c.GRPC.TLSCert != "" {
-		if c.GRPC.TLSClientCA != "" {
-			// Parse certificates from certificate file and key file for server.
-			cert, err := tls.LoadX509KeyPair(c.GRPC.TLSCert, c.GRPC.TLSKey)
-			if err != nil {
-				return fmt.Errorf("invalid config: error parsing gRPC certificate file: %v", err)
-			}
+		// Parse certificates from certificate file and key file for server.
+		cert, err := tls.LoadX509KeyPair(c.GRPC.TLSCert, c.GRPC.TLSKey)
+		if err != nil {
+			return fmt.Errorf("invalid config: error parsing gRPC certificate file: %v", err)
+		}
+
+		tlsConfig := tls.Config{
+			Certificates:             []tls.Certificate{cert},
+			MinVersion:               tls.VersionTLS12,
+			PreferServerCipherSuites: true,
+		}
 
+		if c.GRPC.TLSClientCA != "" {
 			// Parse certificates from client CA file to a new CertPool.
 			cPool := x509.NewCertPool()
 			clientCert, err := ioutil.ReadFile(c.GRPC.TLSClientCA)
@@ -133,23 +139,17 @@ func serve(cmd *cobra.Command, args []string) error {
 				return errors.New("invalid config: failed to parse client CA")
 			}
 
-			tlsConfig := tls.Config{
-				Certificates: []tls.Certificate{cert},
-				ClientAuth:   tls.RequireAndVerifyClientCert,
-				ClientCAs:    cPool,
-			}
+			tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
+			tlsConfig.ClientCAs = cPool
+
+			// Only add metrics if client auth is enabled
 			grpcOptions = append(grpcOptions,
-				grpc.Creds(credentials.NewTLS(&tlsConfig)),
 				grpc.StreamInterceptor(grpcMetrics.StreamServerInterceptor()),
 				grpc.UnaryInterceptor(grpcMetrics.UnaryServerInterceptor()),
 			)
-		} else {
-			opt, err := credentials.NewServerTLSFromFile(c.GRPC.TLSCert, c.GRPC.TLSKey)
-			if err != nil {
-				return fmt.Errorf("invalid config: load grpc certs: %v", err)
-			}
-			grpcOptions = append(grpcOptions, grpc.Creds(opt))
 		}
+
+		grpcOptions = append(grpcOptions, grpc.Creds(credentials.NewTLS(&tlsConfig)))
 	}
 
 	s, err := c.Storage.Config.Open(logger)
@@ -275,9 +275,18 @@ func serve(cmd *cobra.Command, args []string) error {
 		}()
 	}
 	if c.Web.HTTPS != "" {
+		httpsSrv := &http.Server{
+			Addr:    c.Web.HTTPS,
+			Handler: serv,
+			TLSConfig: &tls.Config{
+				PreferServerCipherSuites: true,
+				MinVersion:               tls.VersionTLS12,
+			},
+		}
+
 		logger.Infof("listening (https) on %s", c.Web.HTTPS)
 		go func() {
-			err := http.ListenAndServeTLS(c.Web.HTTPS, c.Web.TLSCert, c.Web.TLSKey, serv)
+			err = httpsSrv.ListenAndServeTLS(c.Web.TLSCert, c.Web.TLSKey)
 			errc <- fmt.Errorf("listening on %s failed: %v", c.Web.HTTPS, err)
 		}()
 	}
-- 
GitLab