1package exporter 2 3import ( 4 "crypto/tls" 5 "crypto/x509" 6 "io/ioutil" 7 8 log "github.com/sirupsen/logrus" 9) 10 11// CreateClientTLSConfig verifies configured files and return a prepared tls.Config 12func (e *Exporter) CreateClientTLSConfig() (*tls.Config, error) { 13 tlsConfig := tls.Config{ 14 InsecureSkipVerify: e.options.SkipTLSVerification, 15 } 16 17 if e.options.ClientCertFile != "" && e.options.ClientKeyFile != "" { 18 cert, err := LoadKeyPair(e.options.ClientCertFile, e.options.ClientKeyFile) 19 if err != nil { 20 return nil, err 21 } 22 tlsConfig.Certificates = []tls.Certificate{*cert} 23 } 24 25 if e.options.CaCertFile != "" { 26 certificates, err := LoadCAFile(e.options.CaCertFile) 27 if err != nil { 28 return nil, err 29 } 30 tlsConfig.RootCAs = certificates 31 } 32 33 return &tlsConfig, nil 34} 35 36// CreateServerTLSConfig verifies configured files and return a prepared tls.Config 37func (e *Exporter) CreateServerTLSConfig(certFile, keyFile, caCertFile string) (*tls.Config, error) { 38 // Verify that the initial key pair is accepted 39 _, err := LoadKeyPair(certFile, keyFile) 40 if err != nil { 41 return nil, err 42 } 43 44 tlsConfig := tls.Config{ 45 GetCertificate: GetServerCertificateFunc(certFile, keyFile), 46 } 47 48 if caCertFile != "" { 49 // Verify that the initial CA file is accepted when configured 50 _, err := LoadCAFile(caCertFile) 51 if err != nil { 52 return nil, err 53 } 54 tlsConfig.GetConfigForClient = GetConfigForClientFunc(certFile, keyFile, caCertFile) 55 } 56 57 return &tlsConfig, nil 58} 59 60// GetServerCertificateFunc returns a function for tls.Config.GetCertificate 61func GetServerCertificateFunc(certFile, keyFile string) func(*tls.ClientHelloInfo) (*tls.Certificate, error) { 62 return func(*tls.ClientHelloInfo) (*tls.Certificate, error) { 63 return LoadKeyPair(certFile, keyFile) 64 } 65} 66 67// GetConfigForClientFunc returns a function for tls.Config.GetConfigForClient 68func GetConfigForClientFunc(certFile, keyFile, caCertFile string) func(*tls.ClientHelloInfo) (*tls.Config, error) { 69 return func(*tls.ClientHelloInfo) (*tls.Config, error) { 70 certificates, err := LoadCAFile(caCertFile) 71 if err != nil { 72 return nil, err 73 } 74 75 tlsConfig := tls.Config{ 76 ClientAuth: tls.RequireAndVerifyClientCert, 77 ClientCAs: certificates, 78 GetCertificate: GetServerCertificateFunc(certFile, keyFile), 79 } 80 return &tlsConfig, nil 81 } 82} 83 84// LoadKeyPair reads and parses a public/private key pair from a pair of files. 85// The files must contain PEM encoded data. 86func LoadKeyPair(certFile, keyFile string) (*tls.Certificate, error) { 87 log.Debugf("Load key pair: %s %s", certFile, keyFile) 88 cert, err := tls.LoadX509KeyPair(certFile, keyFile) 89 if err != nil { 90 return nil, err 91 } 92 return &cert, nil 93} 94 95// LoadCAFile reads and parses CA certificates from a file into a pool. 96// The file must contain PEM encoded data. 97func LoadCAFile(caFile string) (*x509.CertPool, error) { 98 log.Debugf("Load CA cert file: %s", caFile) 99 pemCerts, err := ioutil.ReadFile(caFile) 100 if err != nil { 101 return nil, err 102 } 103 pool := x509.NewCertPool() 104 pool.AppendCertsFromPEM(pemCerts) 105 return pool, nil 106} 107