Commit 3d01ca13 authored by Brad Davidson's avatar Brad Davidson Committed by Brad Davidson

Make supervisor errors parsable by Kubernetes client libs

This gives nicer errors from Kubernetes components during startup, and reduces LOC a bit by using the upstream responsewriters module instead of writing the headers and body by hand. Signed-off-by: 's avatarBrad Davidson <brad.davidson@rancher.com>
parent a69d635c
......@@ -5,7 +5,12 @@ import (
"github.com/gorilla/mux"
"github.com/k3s-io/k3s/pkg/daemons/config"
"github.com/k3s-io/k3s/pkg/generated/clientset/versioned/scheme"
"github.com/sirupsen/logrus"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
"k8s.io/apiserver/pkg/endpoints/request"
)
......@@ -24,23 +29,23 @@ func doAuth(roles []string, serverConfig *config.Control, next http.Handler, rw
switch {
case serverConfig == nil:
logrus.Errorf("Authenticate not initialized: serverConfig is nil")
rw.WriteHeader(http.StatusUnauthorized)
unauthorized(rw, req)
return
case serverConfig.Runtime.Authenticator == nil:
logrus.Errorf("Authenticate not initialized: serverConfig.Runtime.Authenticator is nil")
rw.WriteHeader(http.StatusUnauthorized)
unauthorized(rw, req)
return
}
resp, ok, err := serverConfig.Runtime.Authenticator.AuthenticateRequest(req)
if err != nil {
logrus.Errorf("Failed to authenticate request from %s: %v", req.RemoteAddr, err)
rw.WriteHeader(http.StatusUnauthorized)
unauthorized(rw, req)
return
}
if !ok || !hasRole(roles, resp.User.GetGroups()) {
rw.WriteHeader(http.StatusForbidden)
forbidden(rw, req)
return
}
......@@ -56,3 +61,27 @@ func authMiddleware(serverConfig *config.Control, roles ...string) mux.Middlewar
})
}
}
func unauthorized(resp http.ResponseWriter, req *http.Request) {
responsewriters.ErrorNegotiated(
&apierrors.StatusError{ErrStatus: metav1.Status{
Status: metav1.StatusFailure,
Code: http.StatusUnauthorized,
Reason: metav1.StatusReasonUnauthorized,
Message: "not authorized",
}},
scheme.Codecs.WithoutConversion(), schema.GroupVersion{}, resp, req,
)
}
func forbidden(resp http.ResponseWriter, req *http.Request) {
responsewriters.ErrorNegotiated(
&apierrors.StatusError{ErrStatus: metav1.Status{
Status: metav1.StatusFailure,
Code: http.StatusForbidden,
Reason: metav1.StatusReasonForbidden,
Message: "forbidden",
}},
scheme.Codecs.WithoutConversion(), schema.GroupVersion{}, resp, req,
)
}
......@@ -19,6 +19,7 @@ import (
"github.com/k3s-io/k3s/pkg/bootstrap"
"github.com/k3s-io/k3s/pkg/cli/cmds"
"github.com/k3s-io/k3s/pkg/daemons/config"
"github.com/k3s-io/k3s/pkg/generated/clientset/versioned/scheme"
"github.com/k3s-io/k3s/pkg/nodepassword"
"github.com/k3s-io/k3s/pkg/util"
"github.com/k3s-io/k3s/pkg/version"
......@@ -26,9 +27,12 @@ import (
certutil "github.com/rancher/dynamiclistener/cert"
coreclient "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
"github.com/sirupsen/logrus"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/json"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
)
const (
......@@ -86,22 +90,20 @@ func apiserver(runtime *config.ControlRuntime) http.Handler {
if runtime != nil && runtime.APIServer != nil {
runtime.APIServer.ServeHTTP(resp, req)
} else {
data := []byte("apiserver not ready")
resp.WriteHeader(http.StatusInternalServerError)
resp.Header().Set("Content-Type", "text/plain")
resp.Header().Set("Content-length", strconv.Itoa(len(data)))
resp.Write(data)
responsewriters.ErrorNegotiated(
apierrors.NewServiceUnavailable("apiserver not ready"),
scheme.Codecs.WithoutConversion(), schema.GroupVersion{}, resp, req,
)
}
})
}
func apiserverDisabled() http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
data := []byte("apiserver disabled")
resp.WriteHeader(http.StatusServiceUnavailable)
resp.Header().Set("Content-Type", "text/plain")
resp.Header().Set("Content-length", strconv.Itoa(len(data)))
resp.Write(data)
responsewriters.ErrorNegotiated(
apierrors.NewServiceUnavailable("apiserver disabled"),
scheme.Codecs.WithoutConversion(), schema.GroupVersion{}, resp, req,
)
})
}
......@@ -111,11 +113,10 @@ func bootstrapHandler(runtime *config.ControlRuntime) http.Handler {
}
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
logrus.Warnf("Received HTTP bootstrap request from %s, but embedded etcd is not enabled.", req.RemoteAddr)
data := []byte("etcd disabled")
resp.WriteHeader(http.StatusBadRequest)
resp.Header().Set("Content-Type", "text/plain")
resp.Header().Set("Content-length", strconv.Itoa(len(data)))
resp.Write(data)
responsewriters.ErrorNegotiated(
apierrors.NewBadRequest("etcd disabled"),
scheme.Codecs.WithoutConversion(), schema.GroupVersion{}, resp, req,
)
})
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment