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 ( ...@@ -5,7 +5,12 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/k3s-io/k3s/pkg/daemons/config" "github.com/k3s-io/k3s/pkg/daemons/config"
"github.com/k3s-io/k3s/pkg/generated/clientset/versioned/scheme"
"github.com/sirupsen/logrus" "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" "k8s.io/apiserver/pkg/endpoints/request"
) )
...@@ -24,23 +29,23 @@ func doAuth(roles []string, serverConfig *config.Control, next http.Handler, rw ...@@ -24,23 +29,23 @@ func doAuth(roles []string, serverConfig *config.Control, next http.Handler, rw
switch { switch {
case serverConfig == nil: case serverConfig == nil:
logrus.Errorf("Authenticate not initialized: serverConfig is nil") logrus.Errorf("Authenticate not initialized: serverConfig is nil")
rw.WriteHeader(http.StatusUnauthorized) unauthorized(rw, req)
return return
case serverConfig.Runtime.Authenticator == nil: case serverConfig.Runtime.Authenticator == nil:
logrus.Errorf("Authenticate not initialized: serverConfig.Runtime.Authenticator is nil") logrus.Errorf("Authenticate not initialized: serverConfig.Runtime.Authenticator is nil")
rw.WriteHeader(http.StatusUnauthorized) unauthorized(rw, req)
return return
} }
resp, ok, err := serverConfig.Runtime.Authenticator.AuthenticateRequest(req) resp, ok, err := serverConfig.Runtime.Authenticator.AuthenticateRequest(req)
if err != nil { if err != nil {
logrus.Errorf("Failed to authenticate request from %s: %v", req.RemoteAddr, err) logrus.Errorf("Failed to authenticate request from %s: %v", req.RemoteAddr, err)
rw.WriteHeader(http.StatusUnauthorized) unauthorized(rw, req)
return return
} }
if !ok || !hasRole(roles, resp.User.GetGroups()) { if !ok || !hasRole(roles, resp.User.GetGroups()) {
rw.WriteHeader(http.StatusForbidden) forbidden(rw, req)
return return
} }
...@@ -56,3 +61,27 @@ func authMiddleware(serverConfig *config.Control, roles ...string) mux.Middlewar ...@@ -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 ( ...@@ -19,6 +19,7 @@ import (
"github.com/k3s-io/k3s/pkg/bootstrap" "github.com/k3s-io/k3s/pkg/bootstrap"
"github.com/k3s-io/k3s/pkg/cli/cmds" "github.com/k3s-io/k3s/pkg/cli/cmds"
"github.com/k3s-io/k3s/pkg/daemons/config" "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/nodepassword"
"github.com/k3s-io/k3s/pkg/util" "github.com/k3s-io/k3s/pkg/util"
"github.com/k3s-io/k3s/pkg/version" "github.com/k3s-io/k3s/pkg/version"
...@@ -26,9 +27,12 @@ import ( ...@@ -26,9 +27,12 @@ import (
certutil "github.com/rancher/dynamiclistener/cert" certutil "github.com/rancher/dynamiclistener/cert"
coreclient "github.com/rancher/wrangler/pkg/generated/controllers/core/v1" coreclient "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/json"
"k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
) )
const ( const (
...@@ -86,22 +90,20 @@ func apiserver(runtime *config.ControlRuntime) http.Handler { ...@@ -86,22 +90,20 @@ func apiserver(runtime *config.ControlRuntime) http.Handler {
if runtime != nil && runtime.APIServer != nil { if runtime != nil && runtime.APIServer != nil {
runtime.APIServer.ServeHTTP(resp, req) runtime.APIServer.ServeHTTP(resp, req)
} else { } else {
data := []byte("apiserver not ready") responsewriters.ErrorNegotiated(
resp.WriteHeader(http.StatusInternalServerError) apierrors.NewServiceUnavailable("apiserver not ready"),
resp.Header().Set("Content-Type", "text/plain") scheme.Codecs.WithoutConversion(), schema.GroupVersion{}, resp, req,
resp.Header().Set("Content-length", strconv.Itoa(len(data))) )
resp.Write(data)
} }
}) })
} }
func apiserverDisabled() http.Handler { func apiserverDisabled() http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
data := []byte("apiserver disabled") responsewriters.ErrorNegotiated(
resp.WriteHeader(http.StatusServiceUnavailable) apierrors.NewServiceUnavailable("apiserver disabled"),
resp.Header().Set("Content-Type", "text/plain") scheme.Codecs.WithoutConversion(), schema.GroupVersion{}, resp, req,
resp.Header().Set("Content-length", strconv.Itoa(len(data))) )
resp.Write(data)
}) })
} }
...@@ -111,11 +113,10 @@ func bootstrapHandler(runtime *config.ControlRuntime) http.Handler { ...@@ -111,11 +113,10 @@ func bootstrapHandler(runtime *config.ControlRuntime) http.Handler {
} }
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 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) logrus.Warnf("Received HTTP bootstrap request from %s, but embedded etcd is not enabled.", req.RemoteAddr)
data := []byte("etcd disabled") responsewriters.ErrorNegotiated(
resp.WriteHeader(http.StatusBadRequest) apierrors.NewBadRequest("etcd disabled"),
resp.Header().Set("Content-Type", "text/plain") scheme.Codecs.WithoutConversion(), schema.GroupVersion{}, resp, req,
resp.Header().Set("Content-length", strconv.Itoa(len(data))) )
resp.Write(data)
}) })
} }
......
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