1// Copyright (c) The Thanos Authors. 2// Licensed under the Apache License 2.0. 3 4package tls 5 6import ( 7 "crypto/tls" 8 "crypto/x509" 9 "io/ioutil" 10 11 "github.com/go-kit/kit/log" 12 "github.com/go-kit/kit/log/level" 13 "github.com/pkg/errors" 14) 15 16// NewServerConfig provides new server TLS configuration. 17func NewServerConfig(logger log.Logger, cert, key, clientCA string) (*tls.Config, error) { 18 if key == "" && cert == "" { 19 if clientCA != "" { 20 return nil, errors.New("when a client CA is used a server key and certificate must also be provided") 21 } 22 23 level.Info(logger).Log("msg", "disabled TLS, key and cert must be set to enable") 24 return nil, nil 25 } 26 27 level.Info(logger).Log("msg", "enabling server side TLS") 28 29 if key == "" || cert == "" { 30 return nil, errors.New("both server key and certificate must be provided") 31 } 32 33 tlsCfg := &tls.Config{ 34 MinVersion: tls.VersionTLS12, 35 } 36 37 tlsCert, err := tls.LoadX509KeyPair(cert, key) 38 if err != nil { 39 return nil, errors.Wrap(err, "server credentials") 40 } 41 42 tlsCfg.Certificates = []tls.Certificate{tlsCert} 43 44 if clientCA != "" { 45 caPEM, err := ioutil.ReadFile(clientCA) 46 if err != nil { 47 return nil, errors.Wrap(err, "reading client CA") 48 } 49 50 certPool := x509.NewCertPool() 51 if !certPool.AppendCertsFromPEM(caPEM) { 52 return nil, errors.Wrap(err, "building client CA") 53 } 54 tlsCfg.ClientCAs = certPool 55 tlsCfg.ClientAuth = tls.RequireAndVerifyClientCert 56 57 level.Info(logger).Log("msg", "server TLS client verification enabled") 58 } 59 60 return tlsCfg, nil 61} 62 63// NewClientConfig provides new client TLS configuration. 64func NewClientConfig(logger log.Logger, cert, key, caCert, serverName string) (*tls.Config, error) { 65 var certPool *x509.CertPool 66 if caCert != "" { 67 caPEM, err := ioutil.ReadFile(caCert) 68 if err != nil { 69 return nil, errors.Wrap(err, "reading client CA") 70 } 71 72 certPool = x509.NewCertPool() 73 if !certPool.AppendCertsFromPEM(caPEM) { 74 return nil, errors.Wrap(err, "building client CA") 75 } 76 level.Info(logger).Log("msg", "TLS client using provided certificate pool") 77 } else { 78 var err error 79 certPool, err = x509.SystemCertPool() 80 if err != nil { 81 return nil, errors.Wrap(err, "reading system certificate pool") 82 } 83 level.Info(logger).Log("msg", "TLS client using system certificate pool") 84 } 85 86 tlsCfg := &tls.Config{ 87 RootCAs: certPool, 88 } 89 90 if serverName != "" { 91 tlsCfg.ServerName = serverName 92 } 93 94 if (key != "") != (cert != "") { 95 return nil, errors.New("both client key and certificate must be provided") 96 } 97 98 if cert != "" { 99 cert, err := tls.LoadX509KeyPair(cert, key) 100 if err != nil { 101 return nil, errors.Wrap(err, "client credentials") 102 } 103 tlsCfg.Certificates = []tls.Certificate{cert} 104 level.Info(logger).Log("msg", "TLS client authentication enabled") 105 } 106 return tlsCfg, nil 107} 108