Skip to content

Conversation

@vpnachev
Copy link
Member

@vpnachev vpnachev commented Aug 25, 2025

How to categorize this PR?
/area security ipcei documentation
/kind enhancement
/platform gcp

What this PR does / why we need it:
[GEP-26] Add support for Workload Identity credentials to etcd backups

Which issue(s) this PR fixes:
Part of gardener/gardener#9586

Special notes for your reviewer:
etcd-backup-restore will add support for WorkloadIdentity credentials with gardener/etcd-backup-restore#908


If anybody wants to try this change locally with gardener with extensions, the following patch to gardener is required

spoiler for patch:
diff --git a/pkg/apis/core/validation/backupbucket.go b/pkg/apis/core/validation/backupbucket.go
index 28d485980b..515bc47c5f 100644
--- a/pkg/apis/core/validation/backupbucket.go
+++ b/pkg/apis/core/validation/backupbucket.go
@@ -9,7 +9,6 @@ import (
 	"k8s.io/apimachinery/pkg/util/validation/field"
 
 	"github.com/gardener/gardener/pkg/apis/core"
-	securityv1alpha1 "github.com/gardener/gardener/pkg/apis/security/v1alpha1"
 )
 
 // ValidateBackupBucket validates a BackupBucket object.
@@ -61,11 +60,11 @@ func validateCredentials(spec *core.BackupBucketSpec, fldPath *field.Path) field
 	} else {
 		allErrs = append(allErrs, ValidateCredentialsRef(*spec.CredentialsRef, fldPath.Child("credentialsRef"))...)
 
-		// TODO(vpnachev): Allow WorkloadIdentities once the support in the controllers and components is fully implemented.
-		if spec.CredentialsRef.APIVersion == securityv1alpha1.SchemeGroupVersion.String() &&
-			spec.CredentialsRef.Kind == "WorkloadIdentity" {
-			allErrs = append(allErrs, field.Forbidden(fldPath.Child("credentialsRef"), "support for WorkloadIdentity as backup credentials is not yet fully implemented"))
-		}
+		// // TODO(vpnachev): Allow WorkloadIdentities once the support in the controllers and components is fully implemented.
+		// if spec.CredentialsRef.APIVersion == securityv1alpha1.SchemeGroupVersion.String() &&
+		// 	spec.CredentialsRef.Kind == "WorkloadIdentity" {
+		// 	allErrs = append(allErrs, field.Forbidden(fldPath.Child("credentialsRef"), "support for WorkloadIdentity as backup credentials is not yet fully implemented"))
+		// }
 	}
 
 	return allErrs
diff --git a/pkg/apis/core/validation/seed.go b/pkg/apis/core/validation/seed.go
index 746e96e4ac..4b8cae227a 100644
--- a/pkg/apis/core/validation/seed.go
+++ b/pkg/apis/core/validation/seed.go
@@ -17,7 +17,6 @@ import (
 	"github.com/gardener/gardener/pkg/apis/core"
 	"github.com/gardener/gardener/pkg/apis/core/helper"
 	v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
-	securityv1alpha1 "github.com/gardener/gardener/pkg/apis/security/v1alpha1"
 	"github.com/gardener/gardener/pkg/utils"
 	cidrvalidation "github.com/gardener/gardener/pkg/utils/validation/cidr"
 	featuresvalidation "github.com/gardener/gardener/pkg/utils/validation/features"
@@ -259,11 +258,11 @@ func validateSeedBackup(seedBackup *core.Backup, seedProviderType string, fldPat
 	} else {
 		allErrs = append(allErrs, ValidateCredentialsRef(*seedBackup.CredentialsRef, fldPath.Child("credentialsRef"))...)
 
-		// TODO(vpnachev): Allow WorkloadIdentities once the support in the controllers and components is fully implemented.
-		if seedBackup.CredentialsRef.APIVersion == securityv1alpha1.SchemeGroupVersion.String() &&
-			seedBackup.CredentialsRef.Kind == "WorkloadIdentity" {
-			allErrs = append(allErrs, field.Forbidden(fldPath.Child("credentialsRef"), "support for WorkloadIdentity as backup credentials is not yet fully implemented"))
-		}
+		// // TODO(vpnachev): Allow WorkloadIdentities once the support in the controllers and components is fully implemented.
+		// if seedBackup.CredentialsRef.APIVersion == securityv1alpha1.SchemeGroupVersion.String() &&
+		// 	seedBackup.CredentialsRef.Kind == "WorkloadIdentity" {
+		// 	allErrs = append(allErrs, field.Forbidden(fldPath.Child("credentialsRef"), "support for WorkloadIdentity as backup credentials is not yet fully implemented"))
+		// }
 	}
 
 	return allErrs
diff --git a/skaffold.yaml b/skaffold.yaml
index c8c90f1491..b5f9be37af 100644
--- a/skaffold.yaml
+++ b/skaffold.yaml
@@ -1608,6 +1608,14 @@ deploy:
             - name: gardener-node-agent
               repository: '{{.IMAGE_REPO_local_skaffold_gardener_node_agent}}'
               tag: '{{.IMAGE_TAG_local_skaffold_gardener_node_agent}}@{{.IMAGE_DIGEST_local_skaffold_gardener_node_agent}}'
+          componentImageVectorOverwrites: |
+            components:
+            - name: etcd-druid
+              imageVectorOverwrite: |
+                images:
+                - name: etcd-backup-restore
+                  tag: v0.38.0-gcs-v4
+                  repository: ghcr.io/vpnachev/etcdbrctl
         createNamespace: true
         wait: true
     hooks:

cc @dimityrmirchev

Release note:

This extension now supports `WorkloadIdentity`s as credentials for etcd backup.

@vpnachev vpnachev requested a review from a team as a code owner August 25, 2025 16:30
@gardener-robot gardener-robot added area/documentation Documentation related area/ipcei IPCEI (Important Project of Common European Interest) area/security Security related kind/enhancement Enhancement, improvement, extension platform/gcp Google cloud platform/infrastructure needs/review Needs review size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. needs/second-opinion Needs second review by someone else labels Aug 25, 2025
@gardener-robot-ci-3 gardener-robot-ci-3 added the reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) label Aug 25, 2025
Copy link
Member

@dimityrmirchev dimityrmirchev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!


if !slices.Contains(allowedTokenURLs, rawTokenURL) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("credentialsConfig").Child(keyTokenURL), cfg[keyTokenURL], "should be one of the allowed URLs: "+strings.Join(allowedTokenURLs, ", ")))
allErrs = append(allErrs, field.NotSupported(fldPath.Child("credentialsConfig").Child(keyTokenURL), cfg[keyTokenURL], allowedTokenURLs))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Forbidden should be the proper word to describe a value that can be allowed otherwise. This is also what the documentation suggests.

Suggested change
allErrs = append(allErrs, field.NotSupported(fldPath.Child("credentialsConfig").Child(keyTokenURL), cfg[keyTokenURL], allowedTokenURLs))
allErrs = append(allErrs, field.Forbidden(fldPath.Child("credentialsConfig").Child(keyTokenURL), cfg[keyTokenURL], allowedTokenURLs))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think so, looking the docs for https://pkg.go.dev/k8s.io/[email protected]/pkg/util/validation/field#Forbidden and https://pkg.go.dev/k8s.io/[email protected]/pkg/util/validation/field#NotSupported NotSupported is the correct one as we have list of supported values, forbidden means that in certain conditions the value is acceptable, but in the particular case it is not allowed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forbidden means that in certain conditions the value is acceptable

Exactly, if the admission is configured to allow the value then this value will be accepted. In the documentation it even mentions as an example a security policy, which is exactly the case here. We allow only known token URLs.

Not supported as mentioned in the documentation "This is used to report unknown values for enumerated fields (e.g. a list of valid values)" would be used to indicate a value is not supported, e.g. you input a "mode" and the modes can be any of ["low", "medium", "high"] but not "ultra" as per the application and not configuration.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done with ea48800

@gardener-robot gardener-robot added the needs/changes Needs (more) changes label Aug 27, 2025
vpnachev and others added 2 commits August 27, 2025 23:05
Co-authored-by: Dimitar Mirchev <[email protected]>
W.r.t. what kind of error to be token_url validation
Copy link
Member

@dimityrmirchev dimityrmirchev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for addressing my comments!

/lgtm

@gardener-robot gardener-robot added reviewed/lgtm Has approval for merging and removed needs/changes Needs (more) changes needs/review Needs review needs/second-opinion Needs second review by someone else labels Aug 29, 2025
Copy link
Contributor

@kon-angelo kon-angelo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@kon-angelo kon-angelo merged commit f152674 into gardener:master Sep 17, 2025
25 checks passed
@gardener-robot gardener-robot added the status/closed Issue is closed (either delivered or triaged) label Sep 17, 2025
@vpnachev vpnachev deleted the gep26/support-workload-identity-for-backups branch September 19, 2025 05:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/documentation Documentation related area/ipcei IPCEI (Important Project of Common European Interest) area/security Security related kind/enhancement Enhancement, improvement, extension platform/gcp Google cloud platform/infrastructure reviewed/lgtm Has approval for merging reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. status/closed Issue is closed (either delivered or triaged)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants