github.com/netdata/go.d.plugin@v0.58.1/pkg/tlscfg/config.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package tlscfg
     4  
     5  import (
     6  	"crypto/tls"
     7  	"crypto/x509"
     8  	"fmt"
     9  	"os"
    10  )
    11  
    12  // TLSConfig represents the standard client TLS configuration.
    13  type TLSConfig struct {
    14  	// TLSCA specifies the certificate authority to use when verifying server certificates.
    15  	TLSCA string `yaml:"tls_ca"`
    16  
    17  	// TLSCert specifies tls certificate file.
    18  	TLSCert string `yaml:"tls_cert"`
    19  
    20  	// TLSKey specifies tls key file.
    21  	TLSKey string `yaml:"tls_key"`
    22  
    23  	// InsecureSkipVerify controls whether a client verifies the server's certificate chain and host name.
    24  	InsecureSkipVerify bool `yaml:"tls_skip_verify"`
    25  }
    26  
    27  // NewTLSConfig creates a tls.Config, may be nil without an error if TLS is not configured.
    28  func NewTLSConfig(cfg TLSConfig) (*tls.Config, error) {
    29  	if cfg.TLSCA == "" && cfg.TLSKey == "" && cfg.TLSCert == "" && !cfg.InsecureSkipVerify {
    30  		return nil, nil
    31  	}
    32  
    33  	tlsConfig := &tls.Config{
    34  		InsecureSkipVerify: cfg.InsecureSkipVerify,
    35  		Renegotiation:      tls.RenegotiateNever,
    36  	}
    37  
    38  	if cfg.TLSCA != "" {
    39  		pool, err := loadCertPool([]string{cfg.TLSCA})
    40  		if err != nil {
    41  			return nil, err
    42  		}
    43  		tlsConfig.RootCAs = pool
    44  	}
    45  
    46  	if cfg.TLSCert != "" && cfg.TLSKey != "" {
    47  		cert, err := loadCertificate(cfg.TLSCert, cfg.TLSKey)
    48  		if err != nil {
    49  			return nil, err
    50  		}
    51  		tlsConfig.Certificates = []tls.Certificate{cert}
    52  	}
    53  
    54  	return tlsConfig, nil
    55  }
    56  
    57  func loadCertPool(certFiles []string) (*x509.CertPool, error) {
    58  	pool := x509.NewCertPool()
    59  	for _, certFile := range certFiles {
    60  		pem, err := os.ReadFile(certFile)
    61  		if err != nil {
    62  			return nil, fmt.Errorf("could not read certificate %q: %v", certFile, err)
    63  		}
    64  		if !pool.AppendCertsFromPEM(pem) {
    65  			return nil, fmt.Errorf("could not parse any PEM certificates %q: %v", certFile, err)
    66  		}
    67  	}
    68  	return pool, nil
    69  }
    70  
    71  func loadCertificate(certFile, keyFile string) (tls.Certificate, error) {
    72  	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
    73  	if err != nil {
    74  		return tls.Certificate{}, fmt.Errorf("could not load keypair %s:%s: %v", certFile, keyFile, err)
    75  	}
    76  	return cert, nil
    77  }