{"record":{"id":"ab0328c8a0e19964","repo":"crowdsecurity/crowdsec","slug":"user-password-authentication-and-tls-authenticatio","errorCode":null,"errorMessage":"user/password authentication and TLS authentication are mutually exclusive","messagePattern":"user/password authentication and TLS authentication are mutually exclusive","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/csconfig/api.go","lineNumber":187,"sourceCode":"\t\tif strings.HasPrefix(l.Credentials.URL, \"http\") && !strings.HasSuffix(l.Credentials.URL, \"/\") {\n\t\t\tl.Credentials.URL += \"/\"\n\t\t}\n\t}\n\n\t// is the configuration asking for client authentication via TLS?\n\tcredTLSClientAuth := l.Credentials.CertPath != \"\" || l.Credentials.KeyPath != \"\"\n\n\t// is the configuration asking for TLS encryption and server authentication?\n\tcredTLS := credTLSClientAuth || l.Credentials.CACertPath != \"\"\n\n\tcredSocket := strings.HasPrefix(l.Credentials.URL, \"/\")\n\n\tif credTLS && credSocket {\n\t\treturn errors.New(\"cannot use TLS with a unix socket\")\n\t}\n\n\tif credTLSClientAuth && l.Credentials.Login != \"\" {\n\t\treturn errors.New(\"user/password authentication and TLS authentication are mutually exclusive\")\n\t}\n\n\tif l.InsecureSkipVerify == nil {\n\t\tapiclient.InsecureSkipVerify = false\n\t} else {\n\t\tapiclient.InsecureSkipVerify = *l.InsecureSkipVerify\n\t}\n\n\tif l.Credentials.CACertPath != \"\" {\n\t\tcaCert, err := os.ReadFile(l.Credentials.CACertPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to load cacert: %w\", err)\n\t\t}\n\n\t\tcaCertPool, err := x509.SystemCertPool()\n\t\tif err != nil {\n\t\t\tlog.Warningf(\"Error loading system CA certificates: %s\", err)\n\t\t}","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/csconfig/api.go#L169-L205","documentation":"The LAPI client supports either username/password authentication or TLS mutual (certificate) authentication, not both. Load() rejects a configuration that sets client TLS cert/key auth while a login is present, because the two credential mechanisms are mutually exclusive by design.","triggerScenarios":"api.client.credentials contains login (non-empty) together with client cert/key paths that enable credTLSClientAuth; LocalApiClientCfg.Load() raises the error during config load.","commonSituations":"Merging a bouncer-style cert config with an agent-style login/password config; leftovers from a previous auth scheme after migrating from TLS certs to password auth; copy-pasted credentials blocks from two different hosts.","solutions":["Remove the login (and password) entries when authenticating with a client certificate","Or remove the client cert/key and ca_cert_path entries and keep login/password","Restart crowdsec after cleaning the credentials block"],"exampleFix":"// before\napi:\n  client:\n    credentials:\n      login: myuser\n      cert_path: /etc/crowdsec/ssl/client.crt\n      key_path: /etc/crowdsec/ssl/client.key\n// after\napi:\n  client:\n    credentials:\n      login: myuser\n      password: mypassword\n      url: https://lapi.example.com:8080","handlingStrategy":"validation","validationCode":"if l.Credentials.Login != \"\" && (l.Credentials.CertPath != \"\" || l.Credentials.KeyPath != \"\") {\n    return errors.New(\"choose either login/password or TLS client cert auth\")\n}\nif err := l.Load(); err != nil { ... }","typeGuard":"func usesTLSClientAuth(cred Credentials) bool { return cred.CertPath != \"\" && cred.KeyPath != \"\" }","tryCatchPattern":"if err := clientCfg.Load(); err != nil {\n    return fmt.Errorf(\"lapi client config: %w\", err)\n}","preventionTips":["Pick one auth scheme per host and remove the other entries entirely","After migrating auth schemes, verify no stale cert/key or login fields remain","Test agent startup in CI with the shipped default config"],"tags":["go","config","tls","authentication"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}