crowdsecurity/crowdsec · error
while opening cert file: %w
Error message
while opening cert file: %w
What it means
GetTLSConfig, when a client-auth mode stricter than RequestClientCert is set and CACertPath is non-empty, reads the CA certificate bundle with os.ReadFile to build the trust pool. Any read failure (missing file, permission denied, is-a-directory) is wrapped as 'while opening cert file'. Without the CA the server cannot verify client certificates, so startup fails fast.
Source
Thrown at pkg/csconfig/tls.go:75
}
caCertPool, err := x509.SystemCertPool()
if err != nil {
log.Warnf("Error loading system CA certificates: %s", err)
}
if caCertPool == nil {
caCertPool = x509.NewCertPool()
}
// the > condition below is a weird way to say "if a client certificate is required"
// see https://pkg.go.dev/crypto/tls#ClientAuthType
if clientAuthType > tls.RequestClientCert && t.CACertPath != "" {
log.Infof("(tls) Client Auth Type set to %s", clientAuthType.String())
caCert, err := os.ReadFile(t.CACertPath)
if err != nil {
return nil, fmt.Errorf("while opening cert file: %w", err)
}
caCertPool.AppendCertsFromPEM(caCert)
}
return &tls.Config{
ServerName: t.ServerName, //should it be removed ?
ClientAuth: clientAuthType,
ClientCAs: caCertPool,
MinVersion: tls.VersionTLS12, // TLS versions below 1.2 are considered insecure - see https://www.rfc-editor.org/rfc/rfc7525.txt for details
}, nil
}
View on GitHub (pinned to 909b515798)
Solutions
- Verify the file exists at the configured path: `ls -l <ca_cert_path>` and fix the path in the tls config if it doesn't.
- Fix permissions/ownership so the crowdsec process user can read it: `chown crowdsec:crowdsec ca.pem && chmod 644 ca.pem`.
- Ensure the path points to a PEM CA bundle (not a directory, not the private key): check `head -1` shows '-----BEGIN CERTIFICATE-----'.
- In containers, confirm the CA file is mounted into the container at the exact configured path.
- If client cert verification is not intended, set client_verification: NoClientCert and remove ca_cert_path.
Example fix
// before (config.yaml) tls: ca_cert_path: /etc/crowdsec/ssl/ca.crt # file does not exist // after tls: ca_cert_path: /etc/crowdsec/ssl/ca.pem # existing PEM bundle # or: $ sudo chown crowdsec:crowdsec /etc/crowdsec/ssl/ca.pem && sudo chmod 644 /etc/crowdsec/ssl/ca.pem
Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(tlsCfg.CACertPath)
if err != nil {
return fmt.Errorf("ca_cert_path %q: %w", tlsCfg.CACertPath, err)
}
if info.IsDir() {
return fmt.Errorf("ca_cert_path %q is a directory", tlsCfg.CACertPath)
}
if f, err := os.Open(tlsCfg.CACertPath); err == nil {
defer f.Close() // readable by current user
} Try / catch
if _, err := tlsCfg.GetTLSConfig(); err != nil {
var perr *fs.PathError
if errors.As(err, &perr) {
log.Fatalf("CA cert unreadable: %s -> %v", perr.Path, perr.Err)
}
return err
} Prevention
- Pre-provision CA files and verify with `openssl x509 -in ca.pem -noout` before config rollout.
- Set stable ownership (crowdsec user) and mode 644 on cert files.
- In containers, mount CA bundles read-only at the exact configured path.
When it happens
Trigger: client_verification is set to RequireAndVerifyClientCert / VerifyClientCertIfGiven (anything > RequestClientCert) and tls.ca_cert_path points to a nonexistent, unreadable, or wrong file.
Common situations: CA path typo in config.yaml, CA file not mounted/copied into a container, wrong ownership so the crowdsec user cannot read it, or pointing at a directory or key file instead of the CA PEM bundle.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- client certificate OU %v doesn't match expected OU %v
- failed to load cacert: %w
- allowed_ou configuration contains invalid empty string
- cannot use TLS with a unix socket
- user/password authentication and TLS authentication are mutu
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/681d1654bdb2b2d2.
Report an issue: GitHub.