karmada/pkg/karmadactl/cmdinit/bootstraptoken/clusterinfo/clusterinfo.go

100 lines
3.2 KiB
Go

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,
},
},
})
}