master
go 77 lines 2.12 KB
Raw
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,omitempty" json:"tls_ca"`
16
17 // TLSCert specifies tls certificate file.
18 TLSCert string `yaml:"tls_cert,omitempty" json:"tls_cert"`
19
20 // TLSKey specifies tls key file.
21 TLSKey string `yaml:"tls_key,omitempty" json:"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,omitempty" json:"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 }