mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-02-14 10:00:11 +00:00
Some checks failed
Post / images (amd64, placement) (push) Failing after 50s
Post / images (amd64, registration) (push) Failing after 41s
Post / images (amd64, registration-operator) (push) Failing after 40s
Post / images (amd64, work) (push) Failing after 44s
Post / images (arm64, addon-manager) (push) Failing after 41s
Post / images (arm64, placement) (push) Failing after 42s
Post / images (arm64, registration) (push) Failing after 41s
Post / images (amd64, addon-manager) (push) Failing after 5m29s
Post / images (arm64, registration-operator) (push) Failing after 43s
Post / images (arm64, work) (push) Failing after 5m35s
Post / image manifest (addon-manager) (push) Has been skipped
Post / image manifest (placement) (push) Has been skipped
Post / image manifest (registration) (push) Has been skipped
Post / image manifest (registration-operator) (push) Has been skipped
Post / image manifest (work) (push) Has been skipped
Post / trigger clusteradm e2e (push) Has been skipped
Post / coverage (push) Failing after 40m4s
Scorecard supply-chain security / Scorecard analysis (push) Failing after 4m1s
Signed-off-by: Yang Le <yangle@redhat.com>
198 lines
6.7 KiB
Go
198 lines
6.7 KiB
Go
package aws_irsa
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/informers"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/tools/cache"
|
|
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
|
"k8s.io/klog/v2"
|
|
|
|
clusterv1 "open-cluster-management.io/api/cluster/v1"
|
|
operatorv1 "open-cluster-management.io/api/operator/v1"
|
|
"open-cluster-management.io/sdk-go/pkg/basecontroller/events"
|
|
"open-cluster-management.io/sdk-go/pkg/basecontroller/factory"
|
|
|
|
"open-cluster-management.io/ocm/pkg/common/helpers"
|
|
"open-cluster-management.io/ocm/pkg/registration/register"
|
|
"open-cluster-management.io/ocm/pkg/registration/register/csr"
|
|
"open-cluster-management.io/ocm/pkg/registration/register/token"
|
|
)
|
|
|
|
//TODO: Remove these constants in once we have the function fully implemented for the AWSIRSADriver
|
|
|
|
const (
|
|
// TLSKeyFile is the name of tls key file in kubeconfigSecret
|
|
TLSKeyFile = "tls.key"
|
|
// TLSCertFile is the name of the tls cert file in kubeconfigSecret
|
|
TLSCertFile = "tls.crt"
|
|
ManagedClusterArn = "managed-cluster-arn"
|
|
ManagedClusterIAMRoleSuffix = "managed-cluster-iam-role-suffix"
|
|
)
|
|
|
|
type AWSIRSADriver struct {
|
|
name string
|
|
managedClusterArn string
|
|
hubClusterArn string
|
|
managedClusterRoleSuffix string
|
|
|
|
awsIRSAControl AWSIRSAControl
|
|
|
|
// addonClients holds the addon clients and informers
|
|
addonClients *register.AddOnClients
|
|
|
|
// tokenControl is used for token-based addon authentication
|
|
tokenControl token.TokenControl
|
|
|
|
// csrControl is used for CSR-based addon authentication
|
|
csrControl csr.CSRControl
|
|
}
|
|
|
|
func (c *AWSIRSADriver) Process(
|
|
ctx context.Context, controllerName string, secret *corev1.Secret, additionalSecretData map[string][]byte,
|
|
recorder events.Recorder) (*corev1.Secret, *metav1.Condition, error) {
|
|
|
|
isApproved, err := c.awsIRSAControl.isApproved(c.name)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if !isApproved {
|
|
return nil, nil, nil
|
|
}
|
|
|
|
recorder.Eventf(ctx, "EKSRegistrationRequestApproved", "An EKS registration request is approved for %s", controllerName)
|
|
return secret, nil, nil
|
|
}
|
|
|
|
func (c *AWSIRSADriver) BuildKubeConfigFromTemplate(kubeConfig *clientcmdapi.Config) *clientcmdapi.Config {
|
|
hubClusterAccountId, hubClusterName := helpers.GetAwsAccountIdAndClusterName(c.hubClusterArn)
|
|
awsRegion := helpers.GetAwsRegion(c.hubClusterArn)
|
|
kubeConfig.AuthInfos = map[string]*clientcmdapi.AuthInfo{register.DefaultKubeConfigAuth: {
|
|
Exec: &clientcmdapi.ExecConfig{
|
|
APIVersion: "client.authentication.k8s.io/v1beta1",
|
|
Command: "/awscli/dist/aws",
|
|
Args: []string{
|
|
"--region",
|
|
awsRegion,
|
|
"eks",
|
|
"get-token",
|
|
"--cluster-name",
|
|
hubClusterName,
|
|
"--output",
|
|
"json",
|
|
"--role",
|
|
fmt.Sprintf("arn:aws:iam::%s:role/ocm-hub-%s", hubClusterAccountId, c.managedClusterRoleSuffix),
|
|
},
|
|
},
|
|
}}
|
|
return kubeConfig
|
|
}
|
|
|
|
func (c *AWSIRSADriver) InformerHandler() (cache.SharedIndexInformer, factory.EventFilterFunc) {
|
|
return c.awsIRSAControl.Informer(), nil
|
|
}
|
|
|
|
func (c *AWSIRSADriver) IsHubKubeConfigValid(ctx context.Context, secretOption register.SecretOption) (bool, error) {
|
|
if secretOption.BootStrapKubeConfigFile == "" {
|
|
return false, nil
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func (c *AWSIRSADriver) ManagedClusterDecorator(cluster *clusterv1.ManagedCluster) *clusterv1.ManagedCluster {
|
|
if cluster.Annotations == nil {
|
|
cluster.Annotations = make(map[string]string)
|
|
}
|
|
cluster.Annotations[operatorv1.ClusterAnnotationsKeyPrefix+"/"+ManagedClusterArn] = c.managedClusterArn
|
|
cluster.Annotations[operatorv1.ClusterAnnotationsKeyPrefix+"/"+ManagedClusterIAMRoleSuffix] = c.managedClusterRoleSuffix
|
|
return cluster
|
|
}
|
|
|
|
func (c *AWSIRSADriver) BuildClients(ctx context.Context, secretOption register.SecretOption, bootstrap bool) (*register.Clients, error) {
|
|
clients, err := register.BuildClientsFromSecretOption(secretOption, bootstrap)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
c.awsIRSAControl, err = NewAWSIRSAControl(clients.ClusterInformer, clients.ClusterClient)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create AWS IRSA control: %w", err)
|
|
}
|
|
|
|
// Store addon clients and initialize controls for addon authentication after bootstrap
|
|
if !bootstrap {
|
|
c.addonClients = ®ister.AddOnClients{
|
|
AddonClient: clients.AddonClient,
|
|
AddonInformer: clients.AddonInformer,
|
|
}
|
|
|
|
kubeConfig, err := register.KubeConfigFromSecretOption(secretOption, bootstrap)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
kubeClient, err := kubernetes.NewForConfig(kubeConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
c.tokenControl = token.NewTokenControl(kubeClient.CoreV1())
|
|
|
|
// Initialize CSR control for CSR-based addon authentication
|
|
logger := klog.FromContext(ctx)
|
|
kubeInformerFactory := informers.NewSharedInformerFactoryWithOptions(
|
|
kubeClient,
|
|
10*time.Minute,
|
|
informers.WithTweakListOptions(func(listOptions *metav1.ListOptions) {
|
|
listOptions.LabelSelector = fmt.Sprintf("%s=%s", clusterv1.ClusterNameLabelKey, secretOption.ClusterName)
|
|
}),
|
|
)
|
|
csrControl, err := csr.NewCSRControl(logger, kubeInformerFactory.Certificates(), kubeClient)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create CSR control: %w", err)
|
|
}
|
|
c.csrControl = csrControl
|
|
}
|
|
|
|
return clients, nil
|
|
}
|
|
|
|
func (c *AWSIRSADriver) Fork(addonName string, authConfig register.AddonAuthConfig, secretOption register.SecretOption) (register.RegisterDriver, error) {
|
|
// Check if token-based authentication should be used (shared helper)
|
|
tokenDriver, err := token.TryForkTokenDriver(addonName, authConfig, secretOption, c.tokenControl, c.addonClients)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if tokenDriver != nil {
|
|
return tokenDriver, nil
|
|
}
|
|
|
|
// For CSR driver, create a CSR-based driver for addon authentication
|
|
// This handles:
|
|
// - CustomSigner type (secretOption.Signer != KubeAPIServerClientSignerName)
|
|
// - KubeClient type with CSR authentication
|
|
|
|
// Get CSR configuration from AddonAuthConfig (type-safe interface)
|
|
csrConfig := authConfig.GetCSRConfiguration()
|
|
if csrConfig == nil {
|
|
return nil, fmt.Errorf("CSR configuration is nil for addon %s", addonName)
|
|
}
|
|
|
|
// Note: tokenControl is not set for addon CSR drivers since they use CSR-based auth
|
|
return csr.NewCSRDriverForAddOn(addonName, csrConfig, secretOption, c.csrControl), nil
|
|
}
|
|
|
|
func NewAWSIRSADriver(opt *AWSOption, secretOption register.SecretOption) register.RegisterDriver {
|
|
return &AWSIRSADriver{
|
|
managedClusterArn: opt.ManagedClusterArn,
|
|
managedClusterRoleSuffix: opt.ManagedClusterRoleSuffix,
|
|
hubClusterArn: opt.HubClusterArn,
|
|
name: secretOption.ClusterName,
|
|
}
|
|
}
|
|
|
|
var _ register.RegisterDriver = &AWSIRSADriver{}
|
|
var _ register.AddonDriverFactory = &AWSIRSADriver{}
|