{"record":{"id":"914b465b2b87e3f9","repo":"kubernetes/kops","slug":"challenge-ca-not-set","errorCode":null,"errorMessage":"challenge.ca not set","messagePattern":"challenge\\.ca not set","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/bootstrap/challenge_client.go","lineNumber":83,"sourceCode":"}\n\nfunc (c *ChallengeClient) DoCallbackChallenge(ctx context.Context, clusterName string, targetEndpoint string, bootstrapRequest *nodeup.BootstrapRequest) error {\n\tchallenge := bootstrapRequest.Challenge\n\n\tif challenge == nil {\n\t\treturn fmt.Errorf(\"challenge not set\")\n\t}\n\tif challenge.ChallengeID == \"\" {\n\t\treturn fmt.Errorf(\"challenge.id not set\")\n\t}\n\tif len(challenge.ChallengeSecret) == 0 {\n\t\treturn fmt.Errorf(\"challenge.secret not set\")\n\t}\n\tif challenge.Endpoint == \"\" {\n\t\treturn fmt.Errorf(\"challenge.endpoint not set\")\n\t}\n\tif len(challenge.ServerCA) == 0 {\n\t\treturn fmt.Errorf(\"challenge.ca not set\")\n\t}\n\n\tclientCertificate, err := c.getClientCertificate(ctx, clusterName)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tserverCAs := x509.NewCertPool()\n\tif !serverCAs.AppendCertsFromPEM(challenge.ServerCA) {\n\t\treturn fmt.Errorf(\"error loading certificate pool\")\n\t}\n\n\tserverName := challengeServerHostName(clusterName)\n\ttlsConfig := &tls.Config{\n\t\tRootCAs:      serverCAs,\n\t\tCertificates: []tls.Certificate{*clientCertificate},\n\t\tServerName:   serverName,\n\t}","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/bootstrap/challenge_client.go#L65-L101","documentation":"DoCallbackChallenge requires ServerCA to contain the PEM-encoded CA bundle used to authenticate the kops-controller's TLS certificate. An empty ServerCA means the client cannot build the RootCAs pool, so TLS verification of the callback server would be impossible; validation rejects it upfront.","triggerScenarios":"Calling DoCallbackChallenge with a Challenge whose ServerCA slice is empty — the cluster CA PEM data was never attached to the challenge configuration.","commonSituations":"Node bootstrap config missing the cluster CA bundle; a stripped-down or hand-crafted Challenge struct; reading challenge data from a store that dropped the CA bytes.","solutions":["Populate Challenge.ServerCA with the cluster CA certificate PEM bytes before calling","Re-generate the bootstrap configuration so it embeds the cluster CA","Check where the challenge is persisted/loaded and ensure the CA field is serialized"],"exampleFix":"// before\nch := &bootstrap.Challenge{ChallengeID: id, ChallengeSecret: secret, Endpoint: ep}\n// after\nch := &bootstrap.Challenge{ChallengeID: id, ChallengeSecret: secret, Endpoint: ep, ServerCA: caBundlePEM}","handlingStrategy":"validation","validationCode":"if ch == nil || len(ch.ServerCA) == 0 {\n\treturn fmt.Errorf(\"challenge ServerCA missing before DoCallbackChallenge\")\n}\nif !bytes.Contains(ch.ServerCA, []byte(\"-----BEGIN CERTIFICATE-----\")) {\n\treturn fmt.Errorf(\"ServerCA is not PEM\")\n}","typeGuard":null,"tryCatchPattern":"if err := client.DoCallbackChallenge(ctx, clusterName, ch); err != nil {\n\tif strings.Contains(err.Error(), \"challenge.ca not set\") {\n\t\t// reload CA bundle from cluster pki and retry\n\t}\n\treturn err\n}","preventionTips":["Embed the cluster CA bundle in bootstrap config generation","Validate PEM markers on config load"],"tags":["bootstrap","validation","tls","missing-config"],"backgroundTag":"missing-required-argument","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}