{"record":{"id":"025854ce90c02138","repo":"hashicorp/nomad","slug":"certificate-has-expired-or-is-not-yet-valid","errorCode":null,"errorMessage":"certificate has expired or is not yet valid","messagePattern":"certificate has expired or is not yet valid","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/auth/oidc/client_assertion.go","lineNumber":184,"sourceCode":"\tif k.PemCert != \"\" {\n\t\tsource = \"PemCert\"\n\t\tbts = []byte(k.PemCert)\n\t}\n\n\t// ensure newlines around pem header/footer\n\tbts = newlineHeaders(bts)\n\n\tblock, _ := pem.Decode(bts)\n\tif block == nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode %s PEM block\", source)\n\t}\n\tcert, err := x509.ParseCertificate(block.Bytes)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse %s bytes: %w\", source, err)\n\t}\n\tnow := time.Now()\n\tif now.Before(cert.NotBefore) || now.After(cert.NotAfter) {\n\t\treturn nil, errors.New(\"certificate has expired or is not yet valid\")\n\t}\n\treturn cert, nil\n}\n\n// hashKeyID derives a \"certificate thumbprint\" that the OIDC provider uses\n// to find the certificate to verify the private key JWT signature.\n// https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.7\nfunc hashKeyID(cert *x509.Certificate, header structs.OIDCClientAssertionKeyIDHeader) (string, error) {\n\tvar hasher hash.Hash\n\tswitch header {\n\tcase structs.OIDCClientAssertionHeaderX5t:\n\t\tif fips140.Enabled() {\n\t\t\treturn \"\", errors.New(\"x5t assertion headers use SHA-1, which is forbidden in FIPS-140 mode\")\n\t\t}\n\n\t\thasher = sha1.New()\n\tcase structs.OIDCClientAssertionHeaderX5tS256:\n\t\thasher = sha256.New()","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/lib/auth/oidc/client_assertion.go#L166-L202","documentation":"getCassCert parses a PEM-encoded X.509 certificate and verifies the wall-clock time falls within the certificate's validity window (NotBefore..NotAfter). It returns this error when time.Now() is outside that window, meaning the certificate cannot currently be trusted for signing the OIDC client-assertion private key JWT.","triggerScenarios":"BuildClientAssertionJWT calls getCassCert with the configured signing certificate PEM while (a) the certificate's NotAfter timestamp has passed, or (b) the certificate's NotBefore is in the future (e.g. clock skew or a not-yet-activated cert).","commonSituations":"Nomad ACL auth method configured with an OIDC client certificate that expired and nobody rotated it; server clock skew after NTP failure making a valid cert appear expired; a newly issued certificate deployed before its NotBefore date; long-lived certs issued years ago in test environments.","solutions":["Renew/reissue the OIDC client signing certificate and update the auth method config with the new PEM.","Check server clock sync (NTP) — a skewed clock makes valid certs appear expired or not-yet-valid.","If a new cert was just installed, confirm its NotBefore date has passed and redeploy after activation.","Use a longer-lived certificate or automate rotation before NotAfter to prevent recurrence."],"exampleFix":"// before (expired cert in config)\nkey_source = \"cert\" // cert PEM expired 2025-01-01\n// after\n# renew certificate, then update auth method:\nkey_source = \"cert\" # PEM with NotAfter in the future\n# or verify time:\n# openssl x509 -in cert.pem -noout -dates","handlingStrategy":"validation","validationCode":"pemBytes, _ := os.ReadFile(\"client-cert.pem\")\nblk, _ := pem.Decode(pemBytes)\ncert, err := x509.ParseCertificate(blk.Bytes)\nif err != nil { return err }\nnow := time.Now()\nif now.Before(cert.NotBefore) || now.After(cert.NotAfter) {\n    return fmt.Errorf(\"OIDC client cert not currently valid: notBefore=%s notAfter=%s\", cert.NotBefore, cert.NotAfter)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Monitor certificate NotAfter and alert well before expiry","Use NTP on servers to keep clocks accurate","Validate cert dates at startup of the auth method, not only at request time","Automate cert rotation before NotAfter"],"tags":["oidc","x509","certificate-expired","tls"],"backgroundTag":"certificate-expired","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"}