{"record":{"id":"1a0a531a4621021f","repo":"hashicorp/nomad","slug":"privatekey-is-required-for-private-key-keysource","errorCode":null,"errorMessage":"PrivateKey is required for `private_key` KeySource","messagePattern":"PrivateKey is required for `private_key` KeySource","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/acl.go","lineNumber":1778,"sourceCode":"\tc.PrivateKey.Canonicalize()\n}\n\nfunc (c *OIDCClientAssertion) IsSet() bool {\n\treturn c != nil && c.KeySource != \"\"\n}\n\nfunc (c *OIDCClientAssertion) Validate() error {\n\tif c == nil {\n\t\treturn nil\n\t}\n\tif len(c.Audience) == 0 || c.Audience[0] == \"\" {\n\t\treturn errors.New(\"missing Audience\")\n\t}\n\tswitch c.KeySource {\n\tcase OIDCKeySourceNomad:\n\tcase OIDCKeySourcePrivateKey:\n\t\tif c.PrivateKey == nil {\n\t\t\treturn errors.New(\"PrivateKey is required for `private_key` KeySource\")\n\t\t}\n\t\tif err := c.PrivateKey.Validate(); err != nil {\n\t\t\treturn fmt.Errorf(\"invalid PrivateKey: %w\", err)\n\t\t}\n\tcase OIDCKeySourceClientSecret:\n\t\tif c.ClientSecret == \"\" {\n\t\t\treturn errors.New(\"OIDCClientSecret is required for `client_secret` KeySource\")\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"invalid KeySource %q\", c.KeySource)\n\t}\n\treturn nil\n}\n\ntype OIDCClientAssertionKeyIDHeader string\n\nconst (\n\tOIDCClientAssertionHeaderKid     OIDCClientAssertionKeyIDHeader = \"kid\"","sourceCodeStart":1760,"sourceCodeEnd":1796,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/acl.go#L1760-L1796","documentation":"If the client assertion KeySource is `private_key`, the assertion must be signed with a locally provided key, so PrivateKey is mandatory. Validate returns this error when a private_key KeySource is selected without key material.","triggerScenarios":"Configuring OIDCClientAssertion with KeySource \"private_key\" but leaving PrivateKey nil.","commonSituations":"Choosing private_key signing for IdPs that don't support Nomad-managed keys but forgetting to supply the key config; configs migrated from KeySource \"nomad\" where the key field was unused.","solutions":["Set the PrivateKey field (PemKey or PemKeyFile, KeyID, etc.) alongside KeySource private_key","Or switch KeySource to \"nomad\" if the IdP can consume Nomad-generated keys, or \"client_secret\" for a plain secret"],"exampleFix":"// before\nassertion := &api.OIDCClientAssertion{KeySource: \"private_key\", Audience: aud}\n// after\nassertion := &api.OIDCClientAssertion{KeySource: \"private_key\", Audience: aud,\n  PrivateKey: &api.OIDCClientAssertionKey{PemKeyFile: \"/etc/nomad/assertion.key\", KeyID: \"key-1\", KeyIDHeader: \"kid\"}}","handlingStrategy":"validation","validationCode":"func privateKeyAssertionOK(c *structs.OIDCClientAssertion) bool {\n  return c == nil || c.KeySource != structs.OIDCKeySourcePrivateKey || c.PrivateKey != nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pair KeySource private_key with key material in the same config block","Validate keys load (parse PEM) before submission"],"tags":["nomad","oidc","jwt","validation"],"backgroundTag":"jwt-missing-signing-key","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"}