package clusterinfo import ( "fmt" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" bootstrapapi "k8s.io/cluster-bootstrap/token/api" "k8s.io/klog/v2" cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util" ) const ( // BootstrapSignerClusterRoleName sets the name for the ClusterRole that allows access to ConfigMaps in the kube-public ns BootstrapSignerClusterRoleName = "karmada:bootstrap-signer-clusterinfo" ) // CreateBootstrapConfigMapIfNotExists creates the kube-public ConfigMap if it doesn't exist already func CreateBootstrapConfigMapIfNotExists(clientSet *kubernetes.Clientset, file string) error { klog.V(1).Infoln("[bootstrap-token] loading karmada admin kubeconfig") adminConfig, err := clientcmd.LoadFromFile(file) if err != nil { return fmt.Errorf("failed to load admin kubeconfig, %w", err) } if err = clientcmdapi.FlattenConfig(adminConfig); err != nil { return err } adminCluster := adminConfig.Contexts[adminConfig.CurrentContext].Cluster // Copy the cluster from admin.conf to the bootstrap kubeconfig, contains the CA cert and the server URL klog.V(1).Infoln("[bootstrap-token] copying the cluster from admin.conf to the bootstrap kubeconfig") bootstrapConfig := &clientcmdapi.Config{ Clusters: map[string]*clientcmdapi.Cluster{ "": adminConfig.Clusters[adminCluster], }, } bootstrapBytes, err := clientcmd.Write(*bootstrapConfig) if err != nil { return err } // Create or update the ConfigMap in the kube-public namespace klog.V(1).Infoln("[bootstrap-token] creating/updating ConfigMap in kube-public namespace") return cmdutil.CreateOrUpdateConfigMap(clientSet, &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: bootstrapapi.ConfigMapClusterInfo, Namespace: metav1.NamespacePublic, }, Data: map[string]string{ bootstrapapi.KubeConfigKey: string(bootstrapBytes), }, }) } // CreateClusterInfoRBACRules creates the RBAC rules for exposing the cluster-info ConfigMap in the kube-public namespace to unauthenticated users func CreateClusterInfoRBACRules(clientSet *kubernetes.Clientset) error { klog.V(1).Info("Creating the RBAC rules for exposing the cluster-info ConfigMap in the kube-public namespace") err := cmdutil.CreateOrUpdateRole(clientSet, &rbacv1.Role{ ObjectMeta: metav1.ObjectMeta{ Name: BootstrapSignerClusterRoleName, Namespace: metav1.NamespacePublic, }, Rules: []rbacv1.PolicyRule{ { Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"configmaps"}, ResourceNames: []string{bootstrapapi.ConfigMapClusterInfo}, }, }, }) if err != nil { return err } return cmdutil.CreateOrUpdateRoleBinding(clientSet, &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: BootstrapSignerClusterRoleName, Namespace: metav1.NamespacePublic, }, RoleRef: rbacv1.RoleRef{ APIGroup: rbacv1.GroupName, Kind: "Role", Name: BootstrapSignerClusterRoleName, }, Subjects: []rbacv1.Subject{ { Kind: rbacv1.UserKind, Name: user.Anonymous, }, }, }) }