crowdsecurity/crowdsec · error
failed to load client cert/key pair: %w
Error message
failed to load client cert/key pair: %w
What it means
When both ssl_client_cert and ssl_client_key are configured for MySQL, ConnectionString loads them with tls.LoadX509KeyPair. Any failure (unreadable files, mismatched pair, bad PEM) is wrapped as 'failed to load client cert/key pair: %w'.
Source
Thrown at pkg/csconfig/database.go:184
if d.SSLCACert != "" {
caCert, err := os.ReadFile(d.SSLCACert)
if err != nil {
return "", fmt.Errorf("failed to read CA cert file %s: %w", d.SSLCACert, err)
}
if tlsConfig.RootCAs == nil {
tlsConfig.RootCAs = x509.NewCertPool()
}
if !tlsConfig.RootCAs.AppendCertsFromPEM(caCert) {
return "", fmt.Errorf("failed to append CA cert file %s: %w", d.SSLCACert, err)
}
params.Set("tls", "custom")
}
if d.SSLClientCert != "" && d.SSLClientKey != "" {
cert, err := tls.LoadX509KeyPair(d.SSLClientCert, d.SSLClientKey)
if err != nil {
return "", fmt.Errorf("failed to load client cert/key pair: %w", err)
}
tlsConfig.Certificates = []tls.Certificate{cert}
params.Set("tls", "custom")
}
if params.Get("tls") == "custom" {
// Register the custom TLS config
err := mysql.RegisterTLSConfig("custom", tlsConfig)
if err != nil {
return "", fmt.Errorf("failed to register custom TLS config: %w", err)
}
}
connString = fmt.Sprintf("%s?%s", connString, params.Encode())
case "postgres", "postgresql", "pgx":
if d.isSocketConfig() {
connString = fmt.Sprintf("host=%s user=%s dbname=%s password=%s", d.DbPath, d.User, d.DbName, d.Password)
} else {
connString = fmt.Sprintf("host=%s port=%d user=%s dbname=%s password=%s", d.Host, d.Port, d.User, d.DbName, d.Password)View on GitHub (pinned to 909b515798)
Solutions
- Verify both files are readable and PEM-encoded (`openssl x509 -in cert.pem -noout`, `openssl rsa -in key.pem -check`)
- Confirm cert and key match: compare `openssl x509 -noout -modulus` and `openssl rsa -noout -modulus` hashes
- Decrypt the key if needed (`openssl rsa -in key.pem -out key-nocrypt.pem`) or fix the pair files
Example fix
// before ssl_client_cert: /etc/crowdsec/db/client-new.pem ssl_client_key: /etc/crowdsec/db/client-old.key # mismatched // after ssl_client_cert: /etc/crowdsec/db/client.pem ssl_client_key: /etc/crowdsec/db/client.key # matching pair, chmod 600 owned by crowdsec
Defensive patterns
Strategy: validation
Validate before calling
if _, err := tls.LoadX509KeyPair(certPath, keyPath); err != nil { return fmt.Errorf("client tls pair invalid: %w", err) } Try / catch
if _, err := dbCfg.ConnectionString(); err != nil { if strings.Contains(err.Error(), "client cert/key pair") { log.Fatalf("TLS client pair invalid: %v", err) } } Prevention
- Keep cert and key files as an exact matching pair; rotate them together
- Ensure key files are unencrypted PEM and readable by the service user
- Verify pair match via modulus comparison before deployment
When it happens
Trigger: Client cert or key path wrong/unreadable; cert and key belong to different pairs; key encrypted or in unsupported format; invalid PEM content.
Common situations: Rotating client certs and mismatching cert with an old key; missing intermediate cert in chain file; key file with restrictive permissions (0600 root) while crowdsec runs as another user.
Related errors
- failed to append CA cert file %s: %w
- failed to read CA cert file %s: %w
- failed to register custom TLS config: %w
- certificate revoked by OCSP
- certificate revoked by CRL
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/6d77b1443698bc81.
Report an issue: GitHub.