diff --git a/go.mod b/go.mod index 3168ba78..7976a92c 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( kmodules.xyz/offshoot-api v0.34.0 kmodules.xyz/prober v0.34.0 kubedb.dev/apimachinery v0.63.0 - kubestash.dev/apimachinery v0.27.0 + kubestash.dev/apimachinery v0.28.0-rc.0 sigs.k8s.io/controller-runtime v0.22.4 sigs.k8s.io/yaml v1.6.0 stash.appscode.dev/apimachinery v0.42.1 diff --git a/go.sum b/go.sum index 7e803d94..201a09a3 100644 --- a/go.sum +++ b/go.sum @@ -914,8 +914,8 @@ kubeops.dev/petset v0.0.15 h1:iwTRFAp0RNw0A87sw2c97UZ6WIA9H/nhJBpDhXLa7fk= kubeops.dev/petset v0.0.15/go.mod h1:sw96WiXfzhpmKpXj4a5AdmEHs0Bx4QMhf+iW15zY4Gg= kubeops.dev/sidekick v0.0.12 h1:pmUjQLZDKxgREiM6z0PogLR1aDbgvkE9jRjbxG6dEt0= kubeops.dev/sidekick v0.0.12/go.mod h1:RU7QH3E8DOLw15rBYlOOJSyczuwAnVVtYyZjJb00UB8= -kubestash.dev/apimachinery v0.27.0 h1:cBPAQRmXFlI/Z0A4IOCQ1r5fQcsV2/iLV8UrGTg7weQ= -kubestash.dev/apimachinery v0.27.0/go.mod h1:f3xtr2V2PWmpktitX4CQgE1g8Y49fyFbO8/FLpk/lJ4= +kubestash.dev/apimachinery v0.28.0-rc.0 h1:/8obzAxKhWzX4ar9Qyobqp7GFfVKKS1HnJD9q0orXZQ= +kubestash.dev/apimachinery v0.28.0-rc.0/go.mod h1:f3xtr2V2PWmpktitX4CQgE1g8Y49fyFbO8/FLpk/lJ4= open-cluster-management.io/api v1.2.0 h1:+yeQgJiErrur5S4s205UM37EcZ2XbC9pFSm0xgV5/hU= open-cluster-management.io/api v1.2.0/go.mod h1:YcmA6SpGEekIMxdoeVIIyOaBhMA6ImWRLXP4g8n8T+4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/vendor/kubestash.dev/apimachinery/apis/storage/v1alpha1/backupstorage_helpers.go b/vendor/kubestash.dev/apimachinery/apis/storage/v1alpha1/backupstorage_helpers.go index 31419582..5e28dbb1 100644 --- a/vendor/kubestash.dev/apimachinery/apis/storage/v1alpha1/backupstorage_helpers.go +++ b/vendor/kubestash.dev/apimachinery/apis/storage/v1alpha1/backupstorage_helpers.go @@ -97,8 +97,8 @@ func (b *BackupStorage) IsCredentialLessModeEnabled() bool { switch b.Spec.Storage.Provider { case ProviderS3: return b.Spec.Storage.S3.SecretName == "" - // case ProviderGCS: - // case ProviderAzure: + case ProviderAzure: + return b.Spec.Storage.Azure.SecretName == "" default: return false } diff --git a/vendor/kubestash.dev/apimachinery/pkg/cloud/annotations.go b/vendor/kubestash.dev/apimachinery/pkg/cloud/annotations.go index a4d85c26..8952196d 100644 --- a/vendor/kubestash.dev/apimachinery/pkg/cloud/annotations.go +++ b/vendor/kubestash.dev/apimachinery/pkg/cloud/annotations.go @@ -33,6 +33,7 @@ import ( kmapi "kmodules.xyz/client-go/api/v1" kmc "kmodules.xyz/client-go/client" "kmodules.xyz/client-go/meta" + sidekickapi "kubeops.dev/sidekick/apis/apps/v1alpha1" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -52,6 +53,9 @@ const ( AzureSubscriptionIDAnnotation = "klusters.dev/azure-subscription-id" AzureMIClientIDAnnotation = "azure.workload.identity/client-id" AzureMITenantIDAnnotation = "azure.workload.identity/tenant-id" + + AzureWorkloadIdentityUseLabel = "azure.workload.identity/use" + AzureWorkloadIdentityUseAnnotation = "azure.workload.identity/use-identity-binding" ) func GetCloudAnnotations(ctx context.Context, kc client.Client, storages ...storageapi.BackupStorage) (map[string]string, error) { @@ -139,12 +143,20 @@ func setBucketAnnotations(annotations map[string]string, storages ...storageapi. } func AddCloudAnnotationsToSAIfNeeded(ctx context.Context, kbClient client.Client, - bs *storageapi.BackupStorage, saRef *kmapi.ObjectReference, invTypRef *core.TypedObjectReference, + bs *storageapi.BackupStorage, sidekick *sidekickapi.Sidekick, invTypRef *core.TypedObjectReference, ) (bool, error) { - sa, err := getServiceAccount(ctx, kbClient, saRef) + sa, err := getServiceAccount(ctx, kbClient, &kmapi.ObjectReference{ + Name: sidekick.Spec.ServiceAccountName, + Namespace: sidekick.Namespace, + }) if err != nil { return true, fmt.Errorf("failed to get service account: %v", err) } + + if bs.IsCredentialLessModeEnabled() { + addSidekickAnnotationsIfNeeded(sidekick, bs) + } + if !isCloudAnnotationNeeded(bs, sa) { // Return if not needed return false, nil } @@ -168,11 +180,28 @@ func AddCloudAnnotationsToSAIfNeeded(ctx context.Context, kbClient client.Client return false, nil } +func addSidekickAnnotationsIfNeeded(sidekick *sidekickapi.Sidekick, bs *storageapi.BackupStorage) { + if bs.Spec.Storage.Provider == storageapi.ProviderAzure { + if sidekick.Labels == nil { + sidekick.Labels = make(map[string]string) + } + sidekick.Labels[AzureWorkloadIdentityUseLabel] = "true" + if sidekick.Annotations == nil { + sidekick.Annotations = make(map[string]string) + } + sidekick.Annotations[AzureWorkloadIdentityUseAnnotation] = "true" + } +} + func hasCredLessManagerProvidedAnnotation(bs *storageapi.BackupStorage, sa *core.ServiceAccount) bool { switch bs.Spec.Storage.Provider { case storageapi.ProviderS3: _, exists := sa.Annotations[AWSIRSARoleAnnotation] return exists + case storageapi.ProviderAzure: + _, hasClientId := sa.Annotations[AzureMIClientIDAnnotation] + _, hasTenantId := sa.Annotations[AzureMITenantIDAnnotation] + return hasClientId && hasTenantId default: return false } @@ -184,7 +213,10 @@ func isCloudAnnotationNeeded(bs *storageapi.BackupStorage, sa *core.ServiceAccou case storageapi.ProviderS3: _, ok := sa.Annotations[AWSSeedRoleAnnotationName] return !ok - // case storageapi.ProviderAzure: + case storageapi.ProviderAzure: + _, hasClientId := sa.Annotations[AzureMIClientIDAnnotation] + _, hasTenantId := sa.Annotations[AzureMITenantIDAnnotation] + return !hasTenantId || !hasClientId } } return false @@ -260,6 +292,10 @@ func hasRequiredCloudAnnotations(bs *storageapi.BackupStorage, sa *core.ServiceA if bs.Spec.Storage.Provider == storageapi.ProviderS3 { return sa.Annotations[AWSSeedRoleAnnotationName] != "" && sa.Annotations[BucketAnnotationKey] != "" } + if bs.Spec.Storage.Provider == storageapi.ProviderAzure { + return sa.Annotations[AzureSubscriptionIDAnnotation] != "" && sa.Annotations[AzureMINameAnnotation] != "" && + sa.Annotations[AzureResourceGroupAnnotation] != "" + } return false } @@ -431,12 +467,28 @@ func getAWSAnnotations(source map[string]string) (map[string]string, error) { return annotations, nil } +func getAzureAnnotations(source map[string]string) (map[string]string, error) { + required := map[string]string{ + AzureSubscriptionIDAnnotation: source[AzureSubscriptionIDAnnotation], + AzureMINameAnnotation: source[AzureMINameAnnotation], + AzureResourceGroupAnnotation: source[AzureResourceGroupAnnotation], + BucketAnnotationKey: source[BucketAnnotationKey], + } + annotations := make(map[string]string) + for key, val := range required { + annotations[key] = val + } + return annotations, nil +} + func getRequiredAnnotations(bs *storageapi.BackupStorage, annotations map[string]string) (map[string]string, error) { switch bs.Spec.Storage.Provider { case storageapi.ProviderS3: return getAWSAnnotations(annotations) // case storageapi.ProviderGCS: // return applyGCPAnnotations(sa, annotations) + case storageapi.ProviderAzure: + return getAzureAnnotations(annotations) default: return nil, fmt.Errorf("unsupported storage provider: %s", bs.Spec.Storage.Provider) diff --git a/vendor/modules.txt b/vendor/modules.txt index e0a54f77..1871f6a8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1883,7 +1883,7 @@ kubeops.dev/petset/crds kubeops.dev/sidekick/apis/apps kubeops.dev/sidekick/apis/apps/v1alpha1 kubeops.dev/sidekick/crds -# kubestash.dev/apimachinery v0.27.0 +# kubestash.dev/apimachinery v0.28.0-rc.0 ## explicit; go 1.25.0 kubestash.dev/apimachinery/apis kubestash.dev/apimachinery/apis/addons/v1alpha1