package unifiedauth import ( "context" "fmt" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeclient "k8s.io/client-go/kubernetes" "k8s.io/klog/v2" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" "github.com/karmada-io/karmada/pkg/util" "github.com/karmada-io/karmada/pkg/util/names" ) // ensureImpersonationSecret make sure create impersonation secret for all Cluster. // This logic is used only in the upgrade scenario of the current version // and can be deleted in the next version. func (c *Controller) ensureImpersonationSecret() { controlPlaneKubeClient := kubeclient.NewForConfigOrDie(c.ControllerPlaneConfig) clusterList := &clusterv1alpha1.ClusterList{} if err := c.Client.List(context.TODO(), clusterList); err != nil { klog.Errorf("Failed to list clusterList, error: %v", err) return } for index, cluster := range clusterList.Items { err := c.ensureImpersonationSecretForCluster(controlPlaneKubeClient, &clusterList.Items[index]) if err != nil { klog.Errorf("Failed to ensure impersonation secret exist for cluster %s", cluster.Name) return } } } func (c *Controller) ensureImpersonationSecretForCluster(karmadaKubeClient kubeclient.Interface, cluster *clusterv1alpha1.Cluster) error { klog.V(4).Infof("Create impersonation secret for cluster %s", cluster.Name) // create a ClusterClient for the given member cluster clusterClient, err := c.ClusterClientSetFunc(cluster.Name, c.Client, nil) if err != nil { klog.Errorf("Failed to create a ClusterClient for the given member cluster: %v, err is : %v", cluster.Name, err) return err } // clusterNamespace store namespace where serviceaccount and secret exist. clusterNamespace := cluster.Spec.SecretRef.Namespace // create a ServiceAccount for impersonation in cluster. impersonationSA := &corev1.ServiceAccount{} impersonationSA.Namespace = clusterNamespace impersonationSA.Name = names.GenerateServiceAccountName("impersonator") if impersonationSA, err = c.ensureServiceAccountExist(clusterClient.KubeClient, impersonationSA); err != nil { return err } clusterImpersonatorSecret, err := util.WaitForServiceAccountSecretCreation(clusterClient.KubeClient, impersonationSA) if err != nil { return fmt.Errorf("failed to get serviceAccount secret for impersonation from cluster(%s), error: %v", cluster.Name, err) } // create secret to store impersonation info in control plane impersonationSecret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Namespace: clusterNamespace, Name: names.GenerateImpersonationSecretName(cluster.Name), OwnerReferences: []metav1.OwnerReference{ *metav1.NewControllerRef(cluster, clusterv1alpha1.SchemeGroupVersion.WithKind("Cluster")), }, }, Data: map[string][]byte{ clusterv1alpha1.SecretCADataKey: clusterImpersonatorSecret.Data["ca.crt"], clusterv1alpha1.SecretTokenKey: clusterImpersonatorSecret.Data[clusterv1alpha1.SecretTokenKey], }, } _, err = util.CreateSecret(karmadaKubeClient, impersonationSecret) if err != nil { return fmt.Errorf("failed to create impersonator secret in control plane. error: %v", err) } return nil } // ensureServiceAccountExist makes sure that the specific service account exist in cluster. // If service account not exit, just create it. func (c *Controller) ensureServiceAccountExist(client kubeclient.Interface, saObj *corev1.ServiceAccount) (*corev1.ServiceAccount, error) { exist, err := util.IsServiceAccountExist(client, saObj.Namespace, saObj.Name) if err != nil { return nil, fmt.Errorf("failed to check if impersonation service account exist. error: %v", err) } if exist { return saObj, nil } createdObj, err := util.CreateServiceAccount(client, saObj) if err != nil { return nil, fmt.Errorf("ensure impersonation service account failed due to create failed, error: %v", err) } return createdObj, nil }