{"record":{"id":"4b56beca5b5d1fa7","repo":"k3s-io/k3s","slug":"method-not-allowed-4b56be","errorCode":null,"errorMessage":"method not allowed","messagePattern":"method not allowed","errorType":"http","errorClass":null,"httpStatus":405,"severity":"warning","filePath":"pkg/server/handlers/cert.go","lineNumber":34,"sourceCode":"\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/k3s-io/k3s/pkg/bootstrap\"\n\t\"github.com/k3s-io/k3s/pkg/cluster\"\n\t\"github.com/k3s-io/k3s/pkg/daemons/config\"\n\t\"github.com/k3s-io/k3s/pkg/daemons/control/deps\"\n\t\"github.com/k3s-io/k3s/pkg/util\"\n\t\"github.com/k3s-io/k3s/pkg/util/errors\"\n\t\"github.com/k3s-io/k3s/pkg/version\"\n\tcertutil \"github.com/rancher/dynamiclistener/cert\"\n\t\"github.com/sirupsen/logrus\"\n\t\"k8s.io/client-go/util/keyutil\"\n)\n\nfunc CACertReplace(control *config.Control) http.HandlerFunc {\n\treturn http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {\n\t\tif req.Method != http.MethodPut {\n\t\t\tutil.SendError(errors.New(\"method not allowed\"), resp, req, http.StatusMethodNotAllowed)\n\t\t\treturn\n\t\t}\n\t\tforce, _ := strconv.ParseBool(req.FormValue(\"force\"))\n\t\tif err := caCertReplace(control, req.Body, force); err != nil {\n\t\t\tutil.SendErrorWithID(err, \"certificate\", resp, req, http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tlogrus.Infof(\"certificate: Cluster Certificate Authority data has been updated, %s must be restarted.\", version.Program)\n\t\tresp.WriteHeader(http.StatusNoContent)\n\t})\n}\n\n// caCertReplace stores new CA Certificate data from the client.  The data is temporarily written out to disk,\n// validated to confirm that the new certs share a common root with the existing certs, and if so are saved to\n// the datastore.  If the functions succeeds, servers should be restarted immediately to load the new certs\n// from the bootstrap data.\nfunc caCertReplace(control *config.Control, buf io.ReadCloser, force bool) error {\n\ttmpdir, err := os.MkdirTemp(control.DataDir, \".rotate-ca-tmp-\")","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/k3s-io/k3s/blob/6ba341e396edc16b8dcae978a7c5e3ac7ee5606e/pkg/server/handlers/cert.go#L16-L52","documentation":"CACertReplace in pkg/server/handlers/cert.go serves the /v1-k3s/cacert endpoint used by 'k3s certificate rotate-ca'. It only accepts HTTP PUT; any other method (GET, POST, HEAD via curl defaults) is rejected with HTTP 405 'method not allowed' before any body is read.","triggerScenarios":"Issuing anything but PUT to /v1-k3s/cacert - e.g. curl without -X PUT, a health probe, or a browser preflight/GET on the endpoint.","commonSituations":"Hand-crafted curl calls to the CA rotation endpoint; monitoring that GETs every discovered route; custom automation using the wrong verb.","solutions":["Use PUT: curl -fL -X PUT --data-binary @newca.pem https://server:6443/v1-k3s/cacert.","Prefer the supported CLI: 'k3s certificate rotate-ca --cacert=/path/newca.crt --cakey=/path/newca.key' which issues the correct request.","Remove the endpoint from GET-based liveness/probing config."],"exampleFix":"# before: 405\ncurl -sk https://127.0.0.1:6443/v1-k3s/cacert --data-binary @newca.crt\n\n# after: 200/204\ncurl -sk -X PUT https://127.0.0.1:6443/v1-k3s/cacert --data-binary @newca.crt","handlingStrategy":"validation","validationCode":"// Client-side guard: only PUT is accepted by CACertReplace\nif method != http.MethodPut {\n    return fmt.Errorf(\"cacert endpoint requires PUT, got %s\", method)\n}","typeGuard":null,"tryCatchPattern":"if resp.StatusCode == http.StatusMethodNotAllowed {\n    // re-issue as PUT via k3s certificate rotate-ca or curl -X PUT\n}","preventionTips":["Drive CA rotation through 'k3s certificate rotate-ca' instead of raw HTTP.","Always set -X PUT explicitly in curl; never rely on defaults for mutation endpoints.","Keep GET-based probes away from mutation endpoints like /v1-k3s/cacert."],"tags":["http","k3s","method-not-allowed","certificates","ca-rotation"],"backgroundTag":null,"analyzedSha":"6ba341e396edc16b8dcae978a7c5e3ac7ee5606e","analyzedAt":"2026-08-15T16:27:54.286Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}