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

  1. Use PUT: curl -fL -X PUT --data-binary @newca.pem https://server:6443/v1-k3s/cacert.
  2. Prefer the supported CLI: 'k3s certificate rotate-ca --cacert=/path/newca.crt --cakey=/path/newca.key' which issues the correct request.
  3. 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

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


AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15). Data as JSON: /api/errors/4b56beca5b5d1fa7. Report an issue: GitHub.