{"record":{"id":"3d5a98b9de2e43cb","repo":"hashicorp/nomad","slug":"missing-certificate-information","errorCode":null,"errorMessage":"missing certificate information","messagePattern":"missing certificate information","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/auth/auth.go","lineNumber":410,"sourceCode":"\t\tidentity.ClientID = claims.NodeIdentityClaims.NodeID\n\t\tidentity.Claims = claims\n\t}\n\n\treturn s.ResolveClientIdentityACL(identity)\n}\n\n// verifyTLS is a helper function that performs TLS verification, if required,\n// given the passed RPCContext and valid names.\n//\n// It will always set the TLSName on the identity if we are performing\n// verification, so callers don't have to worry about setting it themselves.\nfunc verifyTLS(verify bool, ctx RPCContext, validNames []string, identity *structs.AuthenticatedIdentity) error {\n\n\tif verify && !ctx.IsStatic() {\n\n\t\ttlsCert := ctx.Certificate()\n\t\tif tlsCert == nil {\n\t\t\treturn errors.New(\"missing certificate information\")\n\t\t}\n\n\t\t// Always set on the identity, even before validating the name, so we\n\t\t// can capture it for metrics.\n\t\tidentity.TLSName = tlsCert.Subject.CommonName\n\n\t\t// Perform the certificate validation, using the passed valid names.\n\t\t_, err := validateCertificateForNames(tlsCert, validNames)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// validateCertificateForNames returns true if the certificate is valid for any\n// of the given domain names.","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/auth/auth.go#L392-L428","documentation":"verifyTLS enforces mutual TLS on RPC connections: when verification is required and the connection is not static, ctx.Certificate() must return the peer's TLS certificate. If it is nil, the connection somehow arrived without a client certificate, so authentication cannot proceed and this error is thrown.","triggerScenarios":"Calling AuthenticateServerOnly, AuthenticateNodeIdentityGenerator, or AuthenticateClientOnly with verify=true against an RPCContext whose TLS handshake did not yield a client certificate — e.g. a plaintext connection routed into a TLS-verified path, or a client connecting without presenting a cert.","commonSituations":"Client configured with TLS but no cert/key (verify_incoming setups missing client certs); proxy/load balancer terminating TLS so Nomad never sees the peer cert; mixed TLS/plaintext RPC ports misconfigured; static/loopback connections bypassing the check while real agent connections lack certs.","solutions":["Configure the connecting agent/client with both ca_file, cert_file, and key_file so it presents a client certificate during the TLS handshake.","Verify verify_incoming/verify_outgoing TLS settings in server and client configs are consistent (both sides expecting mTLS).","If TLS is terminated at a proxy, use the proxy's client-cert passthrough or forward the identity in a way Nomad's RPC surface accepts.","Confirm the connection is actually using TLS (check rpc port config and tls setting) rather than plaintext hitting a verified path."],"exampleFix":"// before: client HCL with no client cert\ntls { http = true, rpc = true, ca_file = \"ca.pem\" }\n// after: present a client certificate\ntls { http = true, rpc = true, ca_file = \"ca.pem\", cert_file = \"client.pem\", key_file = \"client-key.pem\" }","handlingStrategy":"validation","validationCode":"// confirm the client is configured for mTLS before dialing\nif tlsConfig.Certificates == nil || len(tlsConfig.Certificates) == 0 {\n    return errors.New(\"client TLS config must include cert_file/key_file for mTLS\")\n}","typeGuard":"func hasClientCert(conn *tls.Conn) bool {\n    state := conn.ConnectionState()\n    return len(state.PeerCertificates) > 0\n}","tryCatchPattern":null,"preventionTips":["Always set cert_file and key_file on clients in mTLS-enabled clusters.","Never terminate TLS at a proxy without cert passthrough when verify_incoming is on.","Test with `openssl s_client -cert ...` that the client cert is presented and accepted."],"tags":["tls","mtls","authentication","rpc"],"backgroundTag":"missing-client-certificate","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}