mirror of https://github.com/kubernetes/kops.git
Block bootstrap when the node already exists
We now do this across all clouds, as it has been demonstrated on OpenStack.
This commit is contained in:
parent
2875f70cb5
commit
868823bbcf
|
|
@ -45,6 +45,7 @@ import (
|
|||
"k8s.io/kops/upup/pkg/fi/cloudup/hetzner"
|
||||
"k8s.io/kops/upup/pkg/fi/cloudup/openstack"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
"sigs.k8s.io/yaml"
|
||||
// +kubebuilder:scaffold:imports
|
||||
|
|
@ -138,7 +139,16 @@ func main() {
|
|||
klog.Fatalf("server cloud provider config not provided")
|
||||
}
|
||||
|
||||
srv, err := server.NewServer(&opt, verifier)
|
||||
uncachedClient, err := client.New(mgr.GetConfig(), client.Options{
|
||||
Scheme: mgr.GetScheme(),
|
||||
Mapper: mgr.GetRESTMapper(),
|
||||
})
|
||||
if err != nil {
|
||||
setupLog.Error(err, "error creating uncached client")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
srv, err := server.NewServer(&opt, verifier, uncachedClient)
|
||||
if err != nil {
|
||||
setupLog.Error(err, "unable to create server")
|
||||
os.Exit(1)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ import (
|
|||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
"k8s.io/kops/cmd/kops-controller/pkg/config"
|
||||
|
|
@ -40,6 +43,7 @@ import (
|
|||
"k8s.io/kops/upup/pkg/fi"
|
||||
"k8s.io/kops/upup/pkg/fi/secrets"
|
||||
"k8s.io/kops/util/pkg/vfs"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
)
|
||||
|
||||
|
|
@ -54,11 +58,14 @@ type Server struct {
|
|||
|
||||
// configBase is the base of the configuration storage.
|
||||
configBase vfs.Path
|
||||
|
||||
// uncachedClient is an uncached client for the kube apiserver
|
||||
uncachedClient client.Client
|
||||
}
|
||||
|
||||
var _ manager.LeaderElectionRunnable = &Server{}
|
||||
|
||||
func NewServer(opt *config.Options, verifier bootstrap.Verifier) (*Server, error) {
|
||||
func NewServer(opt *config.Options, verifier bootstrap.Verifier, uncachedClient client.Client) (*Server, error) {
|
||||
server := &http.Server{
|
||||
Addr: opt.Server.Listen,
|
||||
TLSConfig: &tls.Config{
|
||||
|
|
@ -68,10 +75,11 @@ func NewServer(opt *config.Options, verifier bootstrap.Verifier) (*Server, error
|
|||
}
|
||||
|
||||
s := &Server{
|
||||
opt: opt,
|
||||
certNames: sets.NewString(opt.Server.CertNames...),
|
||||
server: server,
|
||||
verifier: verifier,
|
||||
opt: opt,
|
||||
certNames: sets.NewString(opt.Server.CertNames...),
|
||||
server: server,
|
||||
verifier: verifier,
|
||||
uncachedClient: uncachedClient,
|
||||
}
|
||||
|
||||
configBase, err := vfs.Context.BuildVfsPath(opt.ConfigBase)
|
||||
|
|
@ -155,6 +163,26 @@ func (s *Server) bootstrap(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// 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")
|
||||
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.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)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
_, _ = w.Write([]byte("internal error"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
req := &nodeup.BootstrapRequest{}
|
||||
if err := json.Unmarshal(body, req); err != nil {
|
||||
klog.Infof("bootstrap %s decode err: %v", r.RemoteAddr, err)
|
||||
|
|
|
|||
Loading…
Reference in New Issue