@@ -22,6 +22,7 @@ package operator
2222import (
2323 "encoding/json"
2424
25+ barmanapi "github.com/cloudnative-pg/barman-cloud/pkg/api"
2526 cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
2627 "github.com/cloudnative-pg/cloudnative-pg/pkg/utils"
2728 "github.com/cloudnative-pg/cnpg-i/pkg/lifecycle"
@@ -387,6 +388,134 @@ var _ = Describe("LifecycleImplementation", func() {
387388 Expect (args ).To (Equal ([]string {"--log-level=info" }))
388389 })
389390 })
391+
392+ Describe ("collectAzureWorkloadIdentityUsage" , func () {
393+ It ("returns true when any referred object store uses default Azure credentials" , func (ctx SpecContext ) {
394+ ns := "test-ns"
395+ cluster := & cnpgv1.Cluster {ObjectMeta : metav1.ObjectMeta {Name : "c" , Namespace : ns }}
396+ pc := & config.PluginConfiguration {
397+ Cluster : cluster ,
398+ BarmanObjectName : "primary-store" ,
399+ RecoveryBarmanObjectName : "recovery-store" ,
400+ }
401+ primaryStore := & barmancloudv1.ObjectStore {
402+ ObjectMeta : metav1.ObjectMeta {Name : pc .BarmanObjectName , Namespace : ns },
403+ Spec : barmancloudv1.ObjectStoreSpec {
404+ Configuration : barmanapi.BarmanObjectStoreConfiguration {
405+ BarmanCredentials : barmanapi.BarmanCredentials {
406+ Azure : & barmanapi.AzureCredentials {UseDefaultAzureCredentials : true },
407+ },
408+ },
409+ },
410+ }
411+ recoveryStore := & barmancloudv1.ObjectStore {
412+ ObjectMeta : metav1.ObjectMeta {Name : pc .RecoveryBarmanObjectName , Namespace : ns },
413+ }
414+ cli := buildClientFunc (primaryStore , recoveryStore ).Build ()
415+
416+ impl := LifecycleImplementation {Client : cli }
417+ useWorkloadIdentity , err := impl .collectAzureWorkloadIdentityUsage (ctx , pc )
418+ Expect (err ).NotTo (HaveOccurred ())
419+ Expect (useWorkloadIdentity ).To (BeTrue ())
420+ })
421+
422+ It ("returns false when none of the referred object stores use default Azure credentials" , func (ctx SpecContext ) {
423+ ns := "test-ns"
424+ cluster := & cnpgv1.Cluster {ObjectMeta : metav1.ObjectMeta {Name : "c" , Namespace : ns }}
425+ pc := & config.PluginConfiguration {
426+ Cluster : cluster ,
427+ BarmanObjectName : "primary-store" ,
428+ }
429+ primaryStore := & barmancloudv1.ObjectStore {
430+ ObjectMeta : metav1.ObjectMeta {Name : pc .BarmanObjectName , Namespace : ns },
431+ Spec : barmancloudv1.ObjectStoreSpec {
432+ Configuration : barmanapi.BarmanObjectStoreConfiguration {
433+ BarmanCredentials : barmanapi.BarmanCredentials {
434+ Azure : & barmanapi.AzureCredentials {InheritFromAzureAD : true },
435+ },
436+ },
437+ },
438+ }
439+ cli := buildClientFunc (primaryStore ).Build ()
440+
441+ impl := LifecycleImplementation {Client : cli }
442+ useWorkloadIdentity , err := impl .collectAzureWorkloadIdentityUsage (ctx , pc )
443+ Expect (err ).NotTo (HaveOccurred ())
444+ Expect (useWorkloadIdentity ).To (BeFalse ())
445+ })
446+ })
447+ })
448+
449+ var _ = Describe ("reconcilePodSpec" , func () {
450+ It ("injects the Azure federated token volume and env when workload identity is enabled" , func () {
451+ cluster := & cnpgv1.Cluster {ObjectMeta : metav1.ObjectMeta {Name : "cluster-1" , Namespace : "ns-1" }}
452+ spec := & corev1.PodSpec {
453+ Containers : []corev1.Container {
454+ {
455+ Name : "postgres" ,
456+ Env : []corev1.EnvVar {
457+ {Name : "AZURE_CLIENT_ID" , Value : "client-id" },
458+ },
459+ },
460+ },
461+ }
462+
463+ err := reconcilePodSpec (
464+ cluster ,
465+ spec ,
466+ "postgres" ,
467+ corev1.Container {Args : []string {"instance" }},
468+ sidecarConfiguration {useAzureWorkloadIdentity : true },
469+ )
470+ Expect (err ).NotTo (HaveOccurred ())
471+ Expect (spec .Volumes ).To (ContainElement (HaveField ("Name" , azureFederatedTokenVolumeName )))
472+ Expect (spec .InitContainers ).To (HaveLen (1 ))
473+ Expect (spec .InitContainers [0 ].Env ).To (ContainElement (corev1.EnvVar {
474+ Name : "AZURE_FEDERATED_TOKEN_FILE" ,
475+ Value : azureFederatedTokenFilePath ,
476+ }))
477+ Expect (spec .InitContainers [0 ].Env ).To (ContainElement (corev1.EnvVar {
478+ Name : "AZURE_CLIENT_ID" ,
479+ Value : "client-id" ,
480+ }))
481+ Expect (spec .InitContainers [0 ].VolumeMounts ).To (ContainElement (corev1.VolumeMount {
482+ Name : azureFederatedTokenVolumeName ,
483+ MountPath : azureFederatedTokenMountPath ,
484+ ReadOnly : true ,
485+ }))
486+ })
487+
488+ It ("does not override an existing federated token file env" , func () {
489+ cluster := & cnpgv1.Cluster {ObjectMeta : metav1.ObjectMeta {Name : "cluster-1" , Namespace : "ns-1" }}
490+ spec := & corev1.PodSpec {
491+ Containers : []corev1.Container {
492+ {
493+ Name : "postgres" ,
494+ Env : []corev1.EnvVar {
495+ {Name : "AZURE_FEDERATED_TOKEN_FILE" , Value : "/custom/token" },
496+ },
497+ },
498+ },
499+ }
500+
501+ err := reconcilePodSpec (
502+ cluster ,
503+ spec ,
504+ "postgres" ,
505+ corev1.Container {Args : []string {"instance" }},
506+ sidecarConfiguration {useAzureWorkloadIdentity : true },
507+ )
508+ Expect (err ).NotTo (HaveOccurred ())
509+ Expect (spec .InitContainers ).To (HaveLen (1 ))
510+ Expect (spec .InitContainers [0 ].Env ).To (ContainElement (corev1.EnvVar {
511+ Name : "AZURE_FEDERATED_TOKEN_FILE" ,
512+ Value : "/custom/token" ,
513+ }))
514+ Expect (spec .InitContainers [0 ].Env ).NotTo (ContainElement (corev1.EnvVar {
515+ Name : "AZURE_FEDERATED_TOKEN_FILE" ,
516+ Value : azureFederatedTokenFilePath ,
517+ }))
518+ })
390519})
391520
392521var _ = Describe ("Volume utilities" , func () {
0 commit comments