github.com/go-graphite/carbonapi@v0.17.0/pkg/tlsconfig/parse.go (about)

     1  package tlsconfig
     2  
     3  import (
     4  	"crypto/tls"
     5  	"crypto/x509"
     6  	"os"
     7  
     8  	merry2 "github.com/ansel1/merry/v2"
     9  )
    10  
    11  // ParseServerTLSConfig parses server and client TLSConfig struct and returns &tls.Config, list of warnings or error if
    12  // parsing has failed.
    13  // At this moment warnings are only about insecure ciphers
    14  func ParseServerTLSConfig(serverTLSConfig, clientTLSConfig *TLSConfig) (*tls.Config, []string, error) {
    15  	caCertPool := x509.NewCertPool()
    16  
    17  	for _, caCert := range serverTLSConfig.CACertFiles {
    18  		cert, err := os.ReadFile(caCert)
    19  		if err != nil {
    20  			return nil, nil, err
    21  		}
    22  		caCertPool.AppendCertsFromPEM(cert)
    23  	}
    24  
    25  	if len(serverTLSConfig.CertificatePairs) == 0 {
    26  		return nil, nil, merry2.Errorf("no server certificate pairs provided")
    27  	}
    28  
    29  	certificates := make([]tls.Certificate, 0, len(serverTLSConfig.CertificatePairs))
    30  
    31  	for _, certPair := range serverTLSConfig.CertificatePairs {
    32  		certificate, err := tls.LoadX509KeyPair(certPair.CertFile, certPair.PrivateKeyFile)
    33  		if err != nil {
    34  			return nil, nil, err
    35  		}
    36  		certificates = append(certificates, certificate)
    37  	}
    38  
    39  	minTLSVersion, err := ParseTLSVersion(serverTLSConfig.MinTLSVersion)
    40  	if err != nil {
    41  		return nil, nil, err
    42  	}
    43  	maxTLSVersion, err := ParseTLSVersion(serverTLSConfig.MaxTLSVersion)
    44  	if err != nil {
    45  		return nil, nil, err
    46  	}
    47  
    48  	curves, err := ParseCurves(serverTLSConfig.Curves)
    49  	if err != nil {
    50  		return nil, nil, err
    51  	}
    52  
    53  	ciphers, warns, err := CipherSuitesToUint16(serverTLSConfig.CipherSuites)
    54  	if err != nil {
    55  		return nil, nil, err
    56  	}
    57  
    58  	clientAuth, err := ParseClientAuthType(serverTLSConfig.ClientAuth)
    59  	if err != nil {
    60  		return nil, nil, err
    61  	}
    62  
    63  	if serverTLSConfig.InsecureSkipVerify {
    64  		warns = append(warns, "InsecureSkipVerify is set to true, it's not recommended to use that in production")
    65  	}
    66  
    67  	tlsConfig := &tls.Config{
    68  		RootCAs:            caCertPool,
    69  		Certificates:       certificates,
    70  		MinVersion:         minTLSVersion,
    71  		MaxVersion:         maxTLSVersion,
    72  		ServerName:         serverTLSConfig.ServerName,
    73  		InsecureSkipVerify: serverTLSConfig.InsecureSkipVerify,
    74  		CurvePreferences:   curves,
    75  		CipherSuites:       ciphers,
    76  		ClientAuth:         clientAuth,
    77  	}
    78  
    79  	if clientAuth == tls.NoClientCert && len(clientTLSConfig.CACertFiles) > 0 {
    80  		warns = append(warns, "NoClientCert checking specified, but client CAs provided")
    81  	}
    82  
    83  	if clientAuth != tls.NoClientCert {
    84  		if len(clientTLSConfig.CACertFiles) == 0 {
    85  			return nil, nil, merry2.Errorf("clientAuth set to '%v', but no client CAs provided", serverTLSConfig.ClientAuth)
    86  		}
    87  		clientCACertPool := x509.NewCertPool()
    88  
    89  		for _, caCert := range clientTLSConfig.CACertFiles {
    90  			cert, err := os.ReadFile(caCert)
    91  			if err != nil {
    92  				return nil, nil, err
    93  			}
    94  			clientCACertPool.AppendCertsFromPEM(cert)
    95  		}
    96  		tlsConfig.ClientCAs = clientCACertPool
    97  	}
    98  
    99  	return tlsConfig, warns, nil
   100  }
   101  
   102  // ParseClientTLSConfig parses TLSConfig as it should be used for HTTPS client mTLS and returns &tls.Config, list of
   103  // warnings or error if parsing has failed.
   104  // At this moment warnings are only about insecure ciphers
   105  func ParseClientTLSConfig(serverTLSConfig *TLSConfig) (*tls.Config, []string, error) {
   106  	caCertPool := x509.NewCertPool()
   107  
   108  	for _, caCert := range serverTLSConfig.CACertFiles {
   109  		cert, err := os.ReadFile(caCert)
   110  		if err != nil {
   111  			return nil, nil, err
   112  		}
   113  		caCertPool.AppendCertsFromPEM(cert)
   114  	}
   115  
   116  	if len(serverTLSConfig.CertificatePairs) == 0 {
   117  		return nil, nil, merry2.Errorf("no server certificate pairs provided")
   118  	}
   119  
   120  	certificates := make([]tls.Certificate, 0, len(serverTLSConfig.CertificatePairs))
   121  
   122  	for _, certPair := range serverTLSConfig.CertificatePairs {
   123  		certificate, err := tls.LoadX509KeyPair(certPair.CertFile, certPair.PrivateKeyFile)
   124  		if err != nil {
   125  			return nil, nil, err
   126  		}
   127  		certificates = append(certificates, certificate)
   128  	}
   129  
   130  	minTLSVersion, err := ParseTLSVersion(serverTLSConfig.MinTLSVersion)
   131  	if err != nil {
   132  		return nil, nil, err
   133  	}
   134  	maxTLSVersion, err := ParseTLSVersion(serverTLSConfig.MaxTLSVersion)
   135  	if err != nil {
   136  		return nil, nil, err
   137  	}
   138  
   139  	curves, err := ParseCurves(serverTLSConfig.Curves)
   140  	if err != nil {
   141  		return nil, nil, err
   142  	}
   143  
   144  	ciphers, warns, err := CipherSuitesToUint16(serverTLSConfig.CipherSuites)
   145  	if err != nil {
   146  		return nil, nil, err
   147  	}
   148  
   149  	if serverTLSConfig.InsecureSkipVerify {
   150  		warns = append(warns, "InsecureSkipVerify is set to true, it's not recommended to use that in production")
   151  	}
   152  
   153  	tlsConfig := &tls.Config{
   154  		RootCAs:            caCertPool,
   155  		Certificates:       certificates,
   156  		MinVersion:         minTLSVersion,
   157  		MaxVersion:         maxTLSVersion,
   158  		ServerName:         serverTLSConfig.ServerName,
   159  		InsecureSkipVerify: serverTLSConfig.InsecureSkipVerify,
   160  		CurvePreferences:   curves,
   161  		CipherSuites:       ciphers,
   162  	}
   163  
   164  	return tlsConfig, warns, nil
   165  }