github.com/crowdsecurity/crowdsec@v1.6.1/pkg/csconfig/tls.go (about)

     1  package csconfig
     2  
     3  import (
     4  	"crypto/tls"
     5  	"crypto/x509"
     6  	"fmt"
     7  	"os"
     8  	"time"
     9  
    10  	log "github.com/sirupsen/logrus"
    11  )
    12  
    13  type TLSCfg struct {
    14  	CertFilePath       string         `yaml:"cert_file"`
    15  	KeyFilePath        string         `yaml:"key_file"`
    16  	ClientVerification string         `yaml:"client_verification,omitempty"`
    17  	ServerName         string         `yaml:"server_name"`
    18  	CACertPath         string         `yaml:"ca_cert_path"`
    19  	AllowedAgentsOU    []string       `yaml:"agents_allowed_ou"`
    20  	AllowedBouncersOU  []string       `yaml:"bouncers_allowed_ou"`
    21  	CRLPath            string         `yaml:"crl_path"`
    22  	CacheExpiration    *time.Duration `yaml:"cache_expiration,omitempty"`
    23  }
    24  
    25  func (t *TLSCfg) GetAuthType() (tls.ClientAuthType, error) {
    26  	if t.ClientVerification == "" {
    27  		// sounds like a sane default: verify client cert if given, but don't make it mandatory
    28  		return tls.VerifyClientCertIfGiven, nil
    29  	}
    30  
    31  	switch t.ClientVerification {
    32  	case "NoClientCert":
    33  		return tls.NoClientCert, nil
    34  	case "RequestClientCert":
    35  		log.Warn("RequestClientCert is insecure, please use VerifyClientCertIfGiven or RequireAndVerifyClientCert instead")
    36  		return tls.RequestClientCert, nil
    37  	case "RequireAnyClientCert":
    38  		log.Warn("RequireAnyClientCert is insecure, please use VerifyClientCertIfGiven or RequireAndVerifyClientCert instead")
    39  		return tls.RequireAnyClientCert, nil
    40  	case "VerifyClientCertIfGiven":
    41  		return tls.VerifyClientCertIfGiven, nil
    42  	case "RequireAndVerifyClientCert":
    43  		return tls.RequireAndVerifyClientCert, nil
    44  	default:
    45  		return 0, fmt.Errorf("unknown TLS client_verification value: %s", t.ClientVerification)
    46  	}
    47  }
    48  
    49  func (t *TLSCfg) GetTLSConfig() (*tls.Config, error) {
    50  	if t == nil {
    51  		return &tls.Config{}, nil
    52  	}
    53  
    54  	clientAuthType, err := t.GetAuthType()
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	caCertPool, err := x509.SystemCertPool()
    60  	if err != nil {
    61  		log.Warnf("Error loading system CA certificates: %s", err)
    62  	}
    63  
    64  	if caCertPool == nil {
    65  		caCertPool = x509.NewCertPool()
    66  	}
    67  
    68  	// the > condition below is a weird way to say "if a client certificate is required"
    69  	// see https://pkg.go.dev/crypto/tls#ClientAuthType
    70  	if clientAuthType > tls.RequestClientCert && t.CACertPath != "" {
    71  		log.Infof("(tls) Client Auth Type set to %s", clientAuthType.String())
    72  
    73  		caCert, err := os.ReadFile(t.CACertPath)
    74  		if err != nil {
    75  			return nil, fmt.Errorf("while opening cert file: %w", err)
    76  		}
    77  
    78  		caCertPool.AppendCertsFromPEM(caCert)
    79  	}
    80  
    81  	return &tls.Config{
    82  		ServerName: t.ServerName, //should it be removed ?
    83  		ClientAuth: clientAuthType,
    84  		ClientCAs:  caCertPool,
    85  		MinVersion: tls.VersionTLS12, // TLS versions below 1.2 are considered insecure - see https://www.rfc-editor.org/rfc/rfc7525.txt for details
    86  	}, nil
    87  }