k3s-io/k3s · warning
method not allowed
Error message
method not allowed
What it means
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.
Source
Thrown at pkg/server/handlers/cert.go:34
"strconv"
"strings"
"github.com/k3s-io/k3s/pkg/bootstrap"
"github.com/k3s-io/k3s/pkg/cluster"
"github.com/k3s-io/k3s/pkg/daemons/config"
"github.com/k3s-io/k3s/pkg/daemons/control/deps"
"github.com/k3s-io/k3s/pkg/util"
"github.com/k3s-io/k3s/pkg/util/errors"
"github.com/k3s-io/k3s/pkg/version"
certutil "github.com/rancher/dynamiclistener/cert"
"github.com/sirupsen/logrus"
"k8s.io/client-go/util/keyutil"
)
func CACertReplace(control *config.Control) http.HandlerFunc {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodPut {
util.SendError(errors.New("method not allowed"), resp, req, http.StatusMethodNotAllowed)
return
}
force, _ := strconv.ParseBool(req.FormValue("force"))
if err := caCertReplace(control, req.Body, force); err != nil {
util.SendErrorWithID(err, "certificate", resp, req, http.StatusInternalServerError)
return
}
logrus.Infof("certificate: Cluster Certificate Authority data has been updated, %s must be restarted.", version.Program)
resp.WriteHeader(http.StatusNoContent)
})
}
// caCertReplace stores new CA Certificate data from the client. The data is temporarily written out to disk,
// validated to confirm that the new certs share a common root with the existing certs, and if so are saved to
// the datastore. If the functions succeeds, servers should be restarted immediately to load the new certs
// from the bootstrap data.
func caCertReplace(control *config.Control, buf io.ReadCloser, force bool) error {
tmpdir, err := os.MkdirTemp(control.DataDir, ".rotate-ca-tmp-")View on GitHub (pinned to 6ba341e396)
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.
Example fix
# before: 405 curl -sk https://127.0.0.1:6443/v1-k3s/cacert --data-binary @newca.crt # after: 200/204 curl -sk -X PUT https://127.0.0.1:6443/v1-k3s/cacert --data-binary @newca.crt
Defensive patterns
Strategy: validation
Validate before calling
// Client-side guard: only PUT is accepted by CACertReplace
if method != http.MethodPut {
return fmt.Errorf("cacert endpoint requires PUT, got %s", method)
} Try / catch
if resp.StatusCode == http.StatusMethodNotAllowed {
// re-issue as PUT via k3s certificate rotate-ca or curl -X PUT
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Hand-crafted curl calls to the CA rotation endpoint; monitoring that GETs every discovered route; custom automation using the wrong verb.
Related errors
- new CA bundle contains only a single certificate but should
- method not allowed
- method not allowed
- etcd datastore disabled
- hijacking not supported
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/4b56beca5b5d1fa7.
Report an issue: GitHub.