From 7b545dde4b9cbd469099ef9763185d36cf887f50 Mon Sep 17 00:00:00 2001 From: Ciprian Hacman Date: Sat, 27 May 2023 09:47:40 +0300 Subject: [PATCH 1/2] kops-controller: Return `http.StatusConflict` when node already exists --- cmd/kops-controller/pkg/server/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/kops-controller/pkg/server/server.go b/cmd/kops-controller/pkg/server/server.go index 58ae01e323..43f1c67ab5 100644 --- a/cmd/kops-controller/pkg/server/server.go +++ b/cmd/kops-controller/pkg/server/server.go @@ -181,7 +181,7 @@ func (s *Server) bootstrap(w http.ResponseWriter, r *http.Request) { err := s.uncachedClient.Get(ctx, types.NamespacedName{Name: id.NodeName}, node) if err == nil { klog.Infof("bootstrap %s node %q already exists; denying to avoid node-impersonation attacks", r.RemoteAddr, id.NodeName) - w.WriteHeader(http.StatusForbidden) + w.WriteHeader(http.StatusConflict) _, _ = w.Write([]byte("node already registered")) return } From 505c0c87de0d6470f255a1876e0a7365215a8449 Mon Sep 17 00:00:00 2001 From: Ciprian Hacman Date: Sat, 27 May 2023 12:58:50 +0300 Subject: [PATCH 2/2] kops-controller: Return `http.StatusConflict` only when node is ready --- cmd/kops-controller/pkg/server/server.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/cmd/kops-controller/pkg/server/server.go b/cmd/kops-controller/pkg/server/server.go index 43f1c67ab5..985e2888e5 100644 --- a/cmd/kops-controller/pkg/server/server.go +++ b/cmd/kops-controller/pkg/server/server.go @@ -30,8 +30,8 @@ import ( "runtime/debug" "time" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/klog/v2" @@ -175,15 +175,17 @@ func (s *Server) bootstrap(w http.ResponseWriter, r *http.Request) { // Once the node is registered, we don't allow further registrations, this protects against a pod or escaped workload attempting to impersonate the node. { - node := &unstructured.Unstructured{} - node.SetAPIVersion("v1") - node.SetKind("node") + node := &corev1.Node{} err := s.uncachedClient.Get(ctx, types.NamespacedName{Name: id.NodeName}, node) if err == nil { - klog.Infof("bootstrap %s node %q already exists; denying to avoid node-impersonation attacks", r.RemoteAddr, id.NodeName) - w.WriteHeader(http.StatusConflict) - _, _ = w.Write([]byte("node already registered")) - return + for _, condition := range node.Status.Conditions { + if condition.Type == corev1.NodeReady && condition.Status == corev1.ConditionTrue { + klog.Infof("bootstrap %s node %q already exists; denying to avoid node-impersonation attacks", r.RemoteAddr, id.NodeName) + w.WriteHeader(http.StatusConflict) + _, _ = w.Write([]byte("node already registered")) + return + } + } } if err != nil && !errors.IsNotFound(err) { klog.Infof("bootstrap %s error querying for node %q: %v", r.RemoteAddr, id.NodeName, err)