diff --git a/controlplane/kubeadm/internal/controllers/fakes_test.go b/controlplane/kubeadm/internal/controllers/fakes_test.go index ebc04e404246..dd8a9f65e95b 100644 --- a/controlplane/kubeadm/internal/controllers/fakes_test.go +++ b/controlplane/kubeadm/internal/controllers/fakes_test.go @@ -96,6 +96,10 @@ func (f fakeWorkloadCluster) AllowBootstrapTokensToGetNodes(_ context.Context) e return nil } +func (f fakeWorkloadCluster) AddClusterAdminRoleBinding(_ context.Context) error { + return nil +} + func (f fakeWorkloadCluster) ReconcileKubeletRBACRole(_ context.Context, _ semver.Version) error { return nil } diff --git a/controlplane/kubeadm/internal/controllers/upgrade.go b/controlplane/kubeadm/internal/controllers/upgrade.go index f51bce9d84b7..be7e28b3b8ff 100644 --- a/controlplane/kubeadm/internal/controllers/upgrade.go +++ b/controlplane/kubeadm/internal/controllers/upgrade.go @@ -68,6 +68,12 @@ func (r *KubeadmControlPlaneReconciler) upgradeControlPlane( return ctrl.Result{}, errors.Wrap(err, "failed to set role and role binding for kubeadm") } + // Ensure kubeadm cluster role & bindings for v1.29+ + // as per https://github.com/kubernetes/kubernetes/pull/121305 + if err := workloadCluster.AddClusterAdminRoleBinding(ctx); err != nil { + return ctrl.Result{}, errors.Wrap(err, "failed to set role and role binding for kubeadm") + } + if err := workloadCluster.UpdateKubernetesVersionInKubeadmConfigMap(ctx, parsedVersion); err != nil { return ctrl.Result{}, errors.Wrap(err, "failed to update the kubernetes version in the kubeadm config map") } diff --git a/controlplane/kubeadm/internal/workload_cluster.go b/controlplane/kubeadm/internal/workload_cluster.go index 9d7de352b817..af669d23d7e0 100644 --- a/controlplane/kubeadm/internal/workload_cluster.go +++ b/controlplane/kubeadm/internal/workload_cluster.go @@ -120,6 +120,7 @@ type WorkloadCluster interface { RemoveNodeFromKubeadmConfigMap(ctx context.Context, nodeName string, version semver.Version) error ForwardEtcdLeadership(ctx context.Context, machine *clusterv1.Machine, leaderCandidate *clusterv1.Machine) error AllowBootstrapTokensToGetNodes(ctx context.Context) error + AddClusterAdminRoleBinding(ctx context.Context) error // State recovery tasks. ReconcileEtcdMembers(ctx context.Context, nodeNames []string, version semver.Version) ([]string, error) diff --git a/controlplane/kubeadm/internal/workload_cluster_rbac.go b/controlplane/kubeadm/internal/workload_cluster_rbac.go index eb22e348051b..f3e7a0445d69 100644 --- a/controlplane/kubeadm/internal/workload_cluster_rbac.go +++ b/controlplane/kubeadm/internal/workload_cluster_rbac.go @@ -35,6 +35,14 @@ const ( // GetNodesClusterRoleName defines the name of the ClusterRole and ClusterRoleBinding to get nodes. GetNodesClusterRoleName = "kubeadm:get-nodes" + // SuperAdminKubeConfigFileName defines name for the kubeconfig aimed to be used by the super-admin of the cluster. + SuperAdminKubeConfigFileName = "super-admin.conf" + + // ClusterAdminsGroupAndClusterRoleBinding is the name of the Group used for kubeadm generated cluster + // admin credentials and the name of the ClusterRoleBinding that binds the same Group to the "cluster-admin" + // built-in ClusterRole. + ClusterAdminsGroupAndClusterRoleBinding = "kubeadm:cluster-admins" + // NodesGroup defines the well-known group for all nodes. NodesGroup = "system:nodes" @@ -66,6 +74,27 @@ func (w *Workload) EnsureResource(ctx context.Context, obj client.Object) error return nil } +// AddClusterAdminRoleBinding creates ClusterRoleBinding rules to use the Super Admin kubeconfig created in Kubeadm v1.29. +func (w *Workload) AddClusterAdminRoleBinding(ctx context.Context) error { + return w.EnsureResource(ctx, &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: ClusterAdminsGroupAndClusterRoleBinding, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, + Kind: "ClusterRole", + Name: "cluster-admin", + }, + Subjects: []rbacv1.Subject{ + { + Kind: rbacv1.GroupKind, + Name: ClusterAdminsGroupAndClusterRoleBinding, + }, + }, + }, + ) +} + // AllowBootstrapTokensToGetNodes creates RBAC rules to allow Node Bootstrap Tokens to list nodes. func (w *Workload) AllowBootstrapTokensToGetNodes(ctx context.Context) error { if err := w.EnsureResource(ctx, &rbacv1.ClusterRole{