From 610f8121930e89d5f983de4e3c5e948d6975ce1b Mon Sep 17 00:00:00 2001 From: Paul Yu Date: Mon, 4 Mar 2024 02:02:50 -0800 Subject: [PATCH] Add support for cross tenant authentication azure workload identity TriggerAuthentication (#5517) Signed-off-by: Paul Yu Signed-off-by: Paul Yu Signed-off-by: Jorge Turrado Ferrero Co-authored-by: Jorge Turrado Ferrero --- CHANGELOG.md | 1 + .../v1alpha1/triggerauthentication_types.go | 27 +++- .../v1alpha1/triggerauthentication_webhook.go | 12 +- .../triggerauthentication_webhook_test.go | 127 +++++++++++++++--- apis/keda/v1alpha1/zz_generated.deepcopy.go | 15 +++ ...keda.sh_clustertriggerauthentications.yaml | 40 ++++++ .../bases/keda.sh_triggerauthentications.yaml | 40 ++++++ .../azure/azure_aad_workload_identity.go | 61 ++++++--- pkg/scalers/azure/azure_app_insights.go | 2 +- pkg/scalers/azure/azure_azidentity_chain.go | 4 +- pkg/scalers/azure/azure_data_explorer.go | 2 +- pkg/scalers/azure/azure_eventhub.go | 2 +- ...e_managed_prometheus_http_round_tripper.go | 2 +- pkg/scalers/azure/azure_monitor.go | 2 +- pkg/scalers/azure/azure_storage.go | 2 +- pkg/scalers/azure_log_analytics_scaler.go | 2 +- pkg/scalers/azure_pipelines_scaler.go | 2 +- pkg/scalers/azure_servicebus_scaler.go | 2 +- pkg/scalers/rabbitmq_scaler.go | 9 +- .../resolver/aws_secretmanager_handler.go | 4 +- .../resolver/azure_keyvault_handler.go | 2 +- pkg/scaling/resolver/scale_resolvers.go | 4 +- 22 files changed, 300 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d8989558be..de429fa370a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ Here is an overview of all new **experimental** features: - **General**: Add command-line flag in Adapter to allow override of gRPC Authority Header ([#5449](https://github.com/kedacore/keda/issues/5449)) - **General**: Add OPENTELEMETRY flag in e2e test YAML ([#5375](https://github.com/kedacore/keda/issues/5375)) +- **General**: Add support for cross tenant/cloud authentication when using Azure Workload Identity for TriggerAuthentication ([#5441](https://github.com/kedacore/keda/issues/5441)) ### Fixes diff --git a/apis/keda/v1alpha1/triggerauthentication_types.go b/apis/keda/v1alpha1/triggerauthentication_types.go index 61d1c19d65f..e81e9ee3ede 100644 --- a/apis/keda/v1alpha1/triggerauthentication_types.go +++ b/apis/keda/v1alpha1/triggerauthentication_types.go @@ -141,11 +141,22 @@ const ( type AuthPodIdentity struct { // +kubebuilder:validation:Enum=azure;azure-workload;gcp;aws;aws-eks;aws-kiam Provider PodIdentityProvider `json:"provider"` + // +optional IdentityID *string `json:"identityId"` + + // +optional + // Set identityTenantId to override the default Azure tenant id. If this is set, then the IdentityID must also be set + IdentityTenantID *string `json:"identityTenantId"` + // +optional + // Set identityAuthorityHost to override the default Azure authority host. If this is set, then the IdentityTenantID must also be set + IdentityAuthorityHost *string `json:"identityAuthorityHost"` + + // +kubebuilder:validation:Optional // RoleArn sets the AWS RoleArn to be used. Mutually exclusive with IdentityOwner - RoleArn string `json:"roleArn"` + RoleArn *string `json:"roleArn"` + // +kubebuilder:validation:Enum=keda;workload // +optional // IdentityOwner configures which identity has to be used during auto discovery, keda or the scaled workload. Mutually exclusive with roleArn @@ -159,6 +170,20 @@ func (a *AuthPodIdentity) GetIdentityID() string { return *a.IdentityID } +func (a *AuthPodIdentity) GetIdentityTenantID() string { + if a.IdentityTenantID == nil { + return "" + } + return *a.IdentityTenantID +} + +func (a *AuthPodIdentity) GetIdentityAuthorityHost() string { + if a.IdentityAuthorityHost == nil { + return "" + } + return *a.IdentityAuthorityHost +} + func (a *AuthPodIdentity) IsWorkloadIdentityOwner() bool { if a.IdentityOwner == nil { return false diff --git a/apis/keda/v1alpha1/triggerauthentication_webhook.go b/apis/keda/v1alpha1/triggerauthentication_webhook.go index df77bbc1e18..f77452e2473 100644 --- a/apis/keda/v1alpha1/triggerauthentication_webhook.go +++ b/apis/keda/v1alpha1/triggerauthentication_webhook.go @@ -116,10 +116,18 @@ func validateSpec(spec *TriggerAuthenticationSpec) (admission.Warnings, error) { switch spec.PodIdentity.Provider { case PodIdentityProviderAzure, PodIdentityProviderAzureWorkload: if spec.PodIdentity.IdentityID != nil && *spec.PodIdentity.IdentityID == "" { - return nil, fmt.Errorf("identityid of PodIdentity should not be empty. If it's set, identityId has to be different than \"\"") + return nil, fmt.Errorf("identityId of PodIdentity should not be empty. If it's set, identityId has to be different than \"\"") + } + + if spec.PodIdentity.IdentityAuthorityHost != nil && *spec.PodIdentity.IdentityAuthorityHost != "" { + if spec.PodIdentity.IdentityTenantID == nil || *spec.PodIdentity.IdentityTenantID == "" { + return nil, fmt.Errorf("identityTenantID of PodIdentity should not be nil or empty when identityAuthorityHost of PodIdentity is set") + } + } else if spec.PodIdentity.IdentityTenantID != nil && *spec.PodIdentity.IdentityTenantID == "" { + return nil, fmt.Errorf("identityTenantId of PodIdentity should not be empty. If it's set, identityTenantId has to be different than \"\"") } case PodIdentityProviderAws: - if spec.PodIdentity.RoleArn != "" && spec.PodIdentity.IsWorkloadIdentityOwner() { + if spec.PodIdentity.RoleArn != nil && *spec.PodIdentity.RoleArn != "" && spec.PodIdentity.IsWorkloadIdentityOwner() { return nil, fmt.Errorf("roleArn of PodIdentity can't be set if KEDA isn't identityOwner") } default: diff --git a/apis/keda/v1alpha1/triggerauthentication_webhook_test.go b/apis/keda/v1alpha1/triggerauthentication_webhook_test.go index 44ea8ed762c..8c984915ba8 100644 --- a/apis/keda/v1alpha1/triggerauthentication_webhook_test.go +++ b/apis/keda/v1alpha1/triggerauthentication_webhook_test.go @@ -30,7 +30,7 @@ var _ = It("validate triggerauthentication when IdentityID is nil, roleArn is em err := k8sClient.Create(context.Background(), namespace) Expect(err).ToNot(HaveOccurred()) - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, "", nil, nil) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, nil, nil, nil, nil, nil) ta := createTriggerAuthentication("nilidentityidta", namespaceName, "TriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -44,7 +44,7 @@ var _ = It("validate triggerauthentication when IdentityID is empty", func() { Expect(err).ToNot(HaveOccurred()) identityID := "" - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, "", &identityID, nil) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, nil, &identityID, nil, nil, nil) ta := createTriggerAuthentication("emptyidentityidta", namespaceName, "TriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -58,20 +58,98 @@ var _ = It("validate triggerauthentication when IdentityID is not empty", func() Expect(err).ToNot(HaveOccurred()) identityID := "12345" - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, "", &identityID, nil) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, nil, &identityID, nil, nil, nil) ta := createTriggerAuthentication("identityidta", namespaceName, "TriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) }).ShouldNot(HaveOccurred()) }) +var _ = It("validate triggerauthentication when IdentityTenantID is not nil and not empty", func() { + namespaceName := "identitytenantidta" + namespace := createNamespace(namespaceName) + err := k8sClient.Create(context.Background(), namespace) + Expect(err).ToNot(HaveOccurred()) + + identityID := "12345" + identityTenantID := "12345" + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzureWorkload, nil, &identityID, &identityTenantID, nil, nil) + ta := createTriggerAuthentication("identitytenantidta", namespaceName, "TriggerAuthentication", spec) + Eventually(func() error { + return k8sClient.Create(context.Background(), ta) + }).ShouldNot(HaveOccurred()) +}) + +var _ = It("validate triggerauthentication when IdentityTenantID is not nil but empty", func() { + namespaceName := "emptyidentitytenantidta" + namespace := createNamespace(namespaceName) + err := k8sClient.Create(context.Background(), namespace) + Expect(err).ToNot(HaveOccurred()) + + identityID := "12345" + identityTenantID := "" + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzureWorkload, nil, &identityID, &identityTenantID, nil, nil) + ta := createTriggerAuthentication("emptyidentitytenantidta", namespaceName, "TriggerAuthentication", spec) + Eventually(func() error { + return k8sClient.Create(context.Background(), ta) + }).Should(HaveOccurred()) +}) + +var _ = It("validate triggerauthentication when IdentityAuthorityHost is not nil and not empty and IdentityTenantID is not nil and not empty", func() { + namespaceName := "identityauthorityhostta" + namespace := createNamespace(namespaceName) + err := k8sClient.Create(context.Background(), namespace) + Expect(err).ToNot(HaveOccurred()) + + identityID := "12345" + identityTenantID := "12345" + identityAuthorityHost := "12345" + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzureWorkload, nil, &identityID, &identityTenantID, &identityAuthorityHost, nil) + ta := createTriggerAuthentication("identityauthorityhostta", namespaceName, "TriggerAuthentication", spec) + Eventually(func() error { + return k8sClient.Create(context.Background(), ta) + }).ShouldNot(HaveOccurred()) +}) + +var _ = It("validate triggerauthentication when IdentityAuthorityHost is not nil and not empty and IdentityTenantID is nil", func() { + namespaceName := "niltenantidentityauthorityhostta" + namespace := createNamespace(namespaceName) + err := k8sClient.Create(context.Background(), namespace) + Expect(err).ToNot(HaveOccurred()) + + identityID := "12345" + identityAuthorityHost := "12345" + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzureWorkload, nil, &identityID, nil, &identityAuthorityHost, nil) + ta := createTriggerAuthentication("niltenantidentityauthorityhostta", namespaceName, "TriggerAuthentication", spec) + Eventually(func() error { + return k8sClient.Create(context.Background(), ta) + }).Should(HaveOccurred()) +}) + +var _ = It("validate triggerauthentication when IdentityAuthorityHost is not nil and not empty and IdentityTenantID is not nil but empty", func() { + namespaceName := "emptytenantidentityauthorityhostta" + namespace := createNamespace(namespaceName) + err := k8sClient.Create(context.Background(), namespace) + Expect(err).ToNot(HaveOccurred()) + + identityID := "12345" + identityTenantID := "" + identityAuthorityHost := "12345" + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzureWorkload, nil, &identityID, &identityTenantID, &identityAuthorityHost, nil) + ta := createTriggerAuthentication("emptytenantidentityauthorityhostta", namespaceName, "TriggerAuthentication", spec) + Eventually(func() error { + return k8sClient.Create(context.Background(), ta) + }).Should(HaveOccurred()) +}) + var _ = It("validate triggerauthentication when RoleArn is not empty and IdentityOwner is nil", func() { namespaceName := "rolearn" namespace := createNamespace(namespaceName) err := k8sClient.Create(context.Background(), namespace) Expect(err).ToNot(HaveOccurred()) - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, "Helo", nil, nil) + roleArn := "Hello" + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, &roleArn, nil, nil, nil, nil) ta := createTriggerAuthentication("identityidta", namespaceName, "TriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -84,8 +162,9 @@ var _ = It("validate triggerauthentication when RoleArn is not empty and Identit err := k8sClient.Create(context.Background(), namespace) Expect(err).ToNot(HaveOccurred()) + roleArn := "Hello" identityOwner := kedaString - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, "Helo", nil, &identityOwner) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, &roleArn, nil, nil, nil, &identityOwner) ta := createTriggerAuthentication("identityidta", namespaceName, "TriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -98,8 +177,9 @@ var _ = It("validate triggerauthentication when RoleArn is not empty and Identit err := k8sClient.Create(context.Background(), namespace) Expect(err).ToNot(HaveOccurred()) + roleArn := "Hello" identityOwner := workloadString - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, "Helo", nil, &identityOwner) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, &roleArn, nil, nil, nil, &identityOwner) ta := createTriggerAuthentication("identityidta", namespaceName, "TriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -113,7 +193,7 @@ var _ = It("validate triggerauthentication when RoleArn is empty and IdentityOwn Expect(err).ToNot(HaveOccurred()) identityOwner := kedaString - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, "", nil, &identityOwner) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, nil, nil, nil, nil, &identityOwner) ta := createTriggerAuthentication("identityidta", namespaceName, "TriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -127,7 +207,7 @@ var _ = It("validate triggerauthentication when RoleArn is not empty and Identit Expect(err).ToNot(HaveOccurred()) identityOwner := workloadString - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, "", nil, &identityOwner) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, nil, nil, nil, nil, &identityOwner) ta := createTriggerAuthentication("identityidta", namespaceName, "TriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -140,7 +220,7 @@ var _ = It("validate clustertriggerauthentication when IdentityID is nil", func( err := k8sClient.Create(context.Background(), namespace) Expect(err).ToNot(HaveOccurred()) - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, "", nil, nil) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, nil, nil, nil, nil, nil) ta := createTriggerAuthentication("clusternilidentityidta", namespaceName, "ClusterTriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -154,7 +234,7 @@ var _ = It("validate clustertriggerauthentication when IdentityID is empty", fun Expect(err).ToNot(HaveOccurred()) identityID := "" - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, "", &identityID, nil) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, nil, &identityID, nil, nil, nil) ta := createTriggerAuthentication("clusteremptyidentityidta", namespaceName, "ClusterTriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -168,7 +248,7 @@ var _ = It("validate clustertriggerauthentication when IdentityID is not empty", Expect(err).ToNot(HaveOccurred()) identityID := "12345" - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, "", &identityID, nil) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAzure, nil, &identityID, nil, nil, nil) ta := createTriggerAuthentication("clusteridentityidta", namespaceName, "ClusterTriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -181,7 +261,8 @@ var _ = It("validate clustertriggerauthentication when RoleArn is not empty and err := k8sClient.Create(context.Background(), namespace) Expect(err).ToNot(HaveOccurred()) - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, "Helo", nil, nil) + roleArn := "Hello" + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, &roleArn, nil, nil, nil, nil) ta := createTriggerAuthentication("clusteridentityidta", namespaceName, "ClusterTriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -194,8 +275,9 @@ var _ = It("validate clustertriggerauthentication when RoleArn is not empty and err := k8sClient.Create(context.Background(), namespace) Expect(err).ToNot(HaveOccurred()) + roleArn := "Hello" identityOwner := kedaString - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, "Helo", nil, &identityOwner) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, &roleArn, nil, nil, nil, &identityOwner) ta := createTriggerAuthentication("clusteridentityidta", namespaceName, "ClusterTriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -208,8 +290,9 @@ var _ = It("validate clustertriggerauthentication when RoleArn is not empty and err := k8sClient.Create(context.Background(), namespace) Expect(err).ToNot(HaveOccurred()) + roleArn := "Hello" identityOwner := workloadString - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, "Helo", nil, &identityOwner) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, &roleArn, nil, nil, nil, &identityOwner) ta := createTriggerAuthentication("clusteridentityidta", namespaceName, "ClusterTriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -223,7 +306,7 @@ var _ = It("validate clustertriggerauthentication when RoleArn is empty and Iden Expect(err).ToNot(HaveOccurred()) identityOwner := kedaString - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, "", nil, &identityOwner) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, nil, nil, nil, nil, &identityOwner) ta := createTriggerAuthentication("clusteridentityidta", namespaceName, "ClusterTriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) @@ -237,20 +320,22 @@ var _ = It("validate clustertriggerauthentication when RoleArn is not empty and Expect(err).ToNot(HaveOccurred()) identityOwner := workloadString - spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, "", nil, &identityOwner) + spec := createTriggerAuthenticationSpecWithPodIdentity(PodIdentityProviderAws, nil, nil, nil, nil, &identityOwner) ta := createTriggerAuthentication("clusteridentityidta", namespaceName, "TriggerAuthentication", spec) Eventually(func() error { return k8sClient.Create(context.Background(), ta) }).ShouldNot(HaveOccurred()) }) -func createTriggerAuthenticationSpecWithPodIdentity(provider PodIdentityProvider, roleArn string, identityID, identityOwner *string) TriggerAuthenticationSpec { +func createTriggerAuthenticationSpecWithPodIdentity(provider PodIdentityProvider, roleArn, identityID, identityTenantID, identityAuthorityHost, identityOwner *string) TriggerAuthenticationSpec { return TriggerAuthenticationSpec{ PodIdentity: &AuthPodIdentity{ - Provider: provider, - IdentityID: identityID, - RoleArn: roleArn, - IdentityOwner: identityOwner, + Provider: provider, + IdentityID: identityID, + IdentityTenantID: identityTenantID, + IdentityAuthorityHost: identityAuthorityHost, + RoleArn: roleArn, + IdentityOwner: identityOwner, }, } } diff --git a/apis/keda/v1alpha1/zz_generated.deepcopy.go b/apis/keda/v1alpha1/zz_generated.deepcopy.go index 46af93efa0e..a144aeb07d3 100755 --- a/apis/keda/v1alpha1/zz_generated.deepcopy.go +++ b/apis/keda/v1alpha1/zz_generated.deepcopy.go @@ -85,6 +85,21 @@ func (in *AuthPodIdentity) DeepCopyInto(out *AuthPodIdentity) { *out = new(string) **out = **in } + if in.IdentityTenantID != nil { + in, out := &in.IdentityTenantID, &out.IdentityTenantID + *out = new(string) + **out = **in + } + if in.IdentityAuthorityHost != nil { + in, out := &in.IdentityAuthorityHost, &out.IdentityAuthorityHost + *out = new(string) + **out = **in + } + if in.RoleArn != nil { + in, out := &in.RoleArn, &out.RoleArn + *out = new(string) + **out = **in + } if in.IdentityOwner != nil { in, out := &in.IdentityOwner, &out.IdentityOwner *out = new(string) diff --git a/config/crd/bases/keda.sh_clustertriggerauthentications.yaml b/config/crd/bases/keda.sh_clustertriggerauthentications.yaml index 05c21c07497..159de1bbda1 100644 --- a/config/crd/bases/keda.sh_clustertriggerauthentications.yaml +++ b/config/crd/bases/keda.sh_clustertriggerauthentications.yaml @@ -138,6 +138,11 @@ spec: AuthPodIdentity allows users to select the platform native identity mechanism properties: + identityAuthorityHost: + description: Set identityAuthorityHost to override the default + Azure authority host. If this is set, then the IdentityTenantID + must also be set + type: string identityId: type: string identityOwner: @@ -148,6 +153,11 @@ spec: - keda - workload type: string + identityTenantId: + description: Set identityTenantId to override the default + Azure tenant id. If this is set, then the IdentityID must + also be set + type: string provider: description: PodIdentityProvider contains the list of providers enum: @@ -237,6 +247,11 @@ spec: AuthPodIdentity allows users to select the platform native identity mechanism properties: + identityAuthorityHost: + description: Set identityAuthorityHost to override the default + Azure authority host. If this is set, then the IdentityTenantID + must also be set + type: string identityId: type: string identityOwner: @@ -247,6 +262,11 @@ spec: - keda - workload type: string + identityTenantId: + description: Set identityTenantId to override the default + Azure tenant id. If this is set, then the IdentityID must + also be set + type: string provider: description: PodIdentityProvider contains the list of providers enum: @@ -350,6 +370,11 @@ spec: AuthPodIdentity allows users to select the platform native identity mechanism properties: + identityAuthorityHost: + description: Set identityAuthorityHost to override the default + Azure authority host. If this is set, then the IdentityTenantID + must also be set + type: string identityId: type: string identityOwner: @@ -360,6 +385,11 @@ spec: - keda - workload type: string + identityTenantId: + description: Set identityTenantId to override the default + Azure tenant id. If this is set, then the IdentityID must + also be set + type: string provider: description: PodIdentityProvider contains the list of providers enum: @@ -466,6 +496,11 @@ spec: AuthPodIdentity allows users to select the platform native identity mechanism properties: + identityAuthorityHost: + description: Set identityAuthorityHost to override the default + Azure authority host. If this is set, then the IdentityTenantID + must also be set + type: string identityId: type: string identityOwner: @@ -476,6 +511,11 @@ spec: - keda - workload type: string + identityTenantId: + description: Set identityTenantId to override the default Azure + tenant id. If this is set, then the IdentityID must also be + set + type: string provider: description: PodIdentityProvider contains the list of providers enum: diff --git a/config/crd/bases/keda.sh_triggerauthentications.yaml b/config/crd/bases/keda.sh_triggerauthentications.yaml index 6bb8748c429..6c8dbef0cf2 100644 --- a/config/crd/bases/keda.sh_triggerauthentications.yaml +++ b/config/crd/bases/keda.sh_triggerauthentications.yaml @@ -137,6 +137,11 @@ spec: AuthPodIdentity allows users to select the platform native identity mechanism properties: + identityAuthorityHost: + description: Set identityAuthorityHost to override the default + Azure authority host. If this is set, then the IdentityTenantID + must also be set + type: string identityId: type: string identityOwner: @@ -147,6 +152,11 @@ spec: - keda - workload type: string + identityTenantId: + description: Set identityTenantId to override the default + Azure tenant id. If this is set, then the IdentityID must + also be set + type: string provider: description: PodIdentityProvider contains the list of providers enum: @@ -236,6 +246,11 @@ spec: AuthPodIdentity allows users to select the platform native identity mechanism properties: + identityAuthorityHost: + description: Set identityAuthorityHost to override the default + Azure authority host. If this is set, then the IdentityTenantID + must also be set + type: string identityId: type: string identityOwner: @@ -246,6 +261,11 @@ spec: - keda - workload type: string + identityTenantId: + description: Set identityTenantId to override the default + Azure tenant id. If this is set, then the IdentityID must + also be set + type: string provider: description: PodIdentityProvider contains the list of providers enum: @@ -349,6 +369,11 @@ spec: AuthPodIdentity allows users to select the platform native identity mechanism properties: + identityAuthorityHost: + description: Set identityAuthorityHost to override the default + Azure authority host. If this is set, then the IdentityTenantID + must also be set + type: string identityId: type: string identityOwner: @@ -359,6 +384,11 @@ spec: - keda - workload type: string + identityTenantId: + description: Set identityTenantId to override the default + Azure tenant id. If this is set, then the IdentityID must + also be set + type: string provider: description: PodIdentityProvider contains the list of providers enum: @@ -465,6 +495,11 @@ spec: AuthPodIdentity allows users to select the platform native identity mechanism properties: + identityAuthorityHost: + description: Set identityAuthorityHost to override the default + Azure authority host. If this is set, then the IdentityTenantID + must also be set + type: string identityId: type: string identityOwner: @@ -475,6 +510,11 @@ spec: - keda - workload type: string + identityTenantId: + description: Set identityTenantId to override the default Azure + tenant id. If this is set, then the IdentityID must also be + set + type: string provider: description: PodIdentityProvider contains the list of providers enum: diff --git a/pkg/scalers/azure/azure_aad_workload_identity.go b/pkg/scalers/azure/azure_aad_workload_identity.go index e8d4ac89549..06be2f09c97 100644 --- a/pkg/scalers/azure/azure_aad_workload_identity.go +++ b/pkg/scalers/azure/azure_aad_workload_identity.go @@ -41,28 +41,40 @@ const ( azureClientIDEnv = "AZURE_CLIENT_ID" azureTenantIDEnv = "AZURE_TENANT_ID" azureFederatedTokenFileEnv = "AZURE_FEDERATED_TOKEN_FILE" - azureAuthrityHostEnv = "AZURE_AUTHORITY_HOST" + azureAuthorityHostEnv = "AZURE_AUTHORITY_HOST" ) var DefaultClientID string -var TenantID string +var DefaultTenantID string var TokenFilePath string -var AuthorityHost string +var DefaultAuthorityHost string func init() { DefaultClientID = os.Getenv(azureClientIDEnv) - TenantID = os.Getenv(azureTenantIDEnv) + DefaultTenantID = os.Getenv(azureTenantIDEnv) TokenFilePath = os.Getenv(azureFederatedTokenFileEnv) - AuthorityHost = os.Getenv(azureAuthrityHostEnv) + DefaultAuthorityHost = os.Getenv(azureAuthorityHostEnv) } // GetAzureADWorkloadIdentityToken returns the AADToken for resource -func GetAzureADWorkloadIdentityToken(ctx context.Context, identityID, resource string) (AADToken, error) { +func GetAzureADWorkloadIdentityToken(ctx context.Context, identityID, identityTenantID, identityAuthorityHost, resource string) (AADToken, error) { clientID := DefaultClientID + tenantID := DefaultTenantID + authorityHost := DefaultAuthorityHost + if identityID != "" { clientID = identityID } + if identityTenantID != "" { + tenantID = identityTenantID + + // override the authority host only if provided and tenant id is provided + if identityAuthorityHost != "" { + authorityHost = identityAuthorityHost + } + } + signedAssertion, err := readJWTFromFileSystem(TokenFilePath) if err != nil { return AADToken{}, fmt.Errorf("error reading service account token - %w", err) @@ -77,7 +89,7 @@ func GetAzureADWorkloadIdentityToken(ctx context.Context, identityID, resource s }) confidentialClient, err := confidential.New( - fmt.Sprintf("%s%s/oauth2/token", AuthorityHost, TenantID), + fmt.Sprintf("%s%s/oauth2/token", authorityHost, tenantID), clientID, cred, ) @@ -117,26 +129,31 @@ func getScopedResource(resource string) string { } type ADWorkloadIdentityConfig struct { - ctx context.Context - IdentityID string - Resource string + ctx context.Context + IdentityID string + IdentityTenantID string + IdentityAuthorityHost string + Resource string } -func NewAzureADWorkloadIdentityConfig(ctx context.Context, identityID, resource string) auth.AuthorizerConfig { - return ADWorkloadIdentityConfig{ctx: ctx, IdentityID: identityID, Resource: resource} +func NewAzureADWorkloadIdentityConfig(ctx context.Context, identityID, identityTenantID, identityAuthorityHost, resource string) auth.AuthorizerConfig { + return ADWorkloadIdentityConfig{ctx: ctx, IdentityID: identityID, IdentityTenantID: identityTenantID, IdentityAuthorityHost: identityAuthorityHost, Resource: resource} } // Authorizer implements the auth.AuthorizerConfig interface func (aadWiConfig ADWorkloadIdentityConfig) Authorizer() (autorest.Authorizer, error) { return autorest.NewBearerAuthorizer(NewAzureADWorkloadIdentityTokenProvider( - aadWiConfig.ctx, aadWiConfig.IdentityID, aadWiConfig.Resource)), nil + aadWiConfig.ctx, aadWiConfig.IdentityID, aadWiConfig.IdentityTenantID, aadWiConfig.IdentityAuthorityHost, aadWiConfig.Resource)), nil } -func NewADWorkloadIdentityCredential(identityID string) (*azidentity.WorkloadIdentityCredential, error) { +func NewADWorkloadIdentityCredential(identityID, identityTenantID string) (*azidentity.WorkloadIdentityCredential, error) { options := &azidentity.WorkloadIdentityCredentialOptions{} if identityID != "" { options.ClientID = identityID } + if identityTenantID != "" { + options.TenantID = identityTenantID + } return azidentity.NewWorkloadIdentityCredential(options) } @@ -144,14 +161,16 @@ func NewADWorkloadIdentityCredential(identityID string) (*azidentity.WorkloadIde // The OAuthTokenProvider interface is used by the BearerAuthorizer to get the token when preparing the HTTP Header. // The Refresher interface is used by the BearerAuthorizer to refresh the token. type ADWorkloadIdentityTokenProvider struct { - ctx context.Context - IdentityID string - Resource string - aadToken AADToken + ctx context.Context + IdentityID string + IdentityTenantID string + IdentityAuthorityHost string + Resource string + aadToken AADToken } -func NewAzureADWorkloadIdentityTokenProvider(ctx context.Context, identityID, resource string) *ADWorkloadIdentityTokenProvider { - return &ADWorkloadIdentityTokenProvider{ctx: ctx, IdentityID: identityID, Resource: resource} +func NewAzureADWorkloadIdentityTokenProvider(ctx context.Context, identityID, identityTenantID, identityAuthorityHost, resource string) *ADWorkloadIdentityTokenProvider { + return &ADWorkloadIdentityTokenProvider{ctx: ctx, IdentityID: identityID, IdentityTenantID: identityTenantID, IdentityAuthorityHost: identityAuthorityHost, Resource: resource} } // OAuthToken is for implementing the adal.OAuthTokenProvider interface. It returns the current access token. @@ -165,7 +184,7 @@ func (wiTokenProvider *ADWorkloadIdentityTokenProvider) Refresh() error { return nil } - aadToken, err := GetAzureADWorkloadIdentityToken(wiTokenProvider.ctx, wiTokenProvider.IdentityID, wiTokenProvider.Resource) + aadToken, err := GetAzureADWorkloadIdentityToken(wiTokenProvider.ctx, wiTokenProvider.IdentityID, wiTokenProvider.IdentityTenantID, wiTokenProvider.IdentityAuthorityHost, wiTokenProvider.Resource) if err != nil { return err } diff --git a/pkg/scalers/azure/azure_app_insights.go b/pkg/scalers/azure/azure_app_insights.go index 461d61a2cf9..0ce57b6d9eb 100644 --- a/pkg/scalers/azure/azure_app_insights.go +++ b/pkg/scalers/azure/azure_app_insights.go @@ -72,7 +72,7 @@ func getAuthConfig(ctx context.Context, info AppInsightsInfo, podIdentity kedav1 config.ClientID = podIdentity.GetIdentityID() return config case kedav1alpha1.PodIdentityProviderAzureWorkload: - return NewAzureADWorkloadIdentityConfig(ctx, podIdentity.GetIdentityID(), info.AppInsightsResourceURL) + return NewAzureADWorkloadIdentityConfig(ctx, podIdentity.GetIdentityID(), podIdentity.GetIdentityTenantID(), podIdentity.GetIdentityAuthorityHost(), info.AppInsightsResourceURL) } return nil } diff --git a/pkg/scalers/azure/azure_azidentity_chain.go b/pkg/scalers/azure/azure_azidentity_chain.go index d23841ab60a..0396c235a42 100644 --- a/pkg/scalers/azure/azure_azidentity_chain.go +++ b/pkg/scalers/azure/azure_azidentity_chain.go @@ -10,7 +10,7 @@ import ( "github.com/kedacore/keda/v2/apis/keda/v1alpha1" ) -func NewChainedCredential(logger logr.Logger, identityID string, podIdentity v1alpha1.PodIdentityProvider) (*azidentity.ChainedTokenCredential, error) { +func NewChainedCredential(logger logr.Logger, identityID, identityTenantID string, podIdentity v1alpha1.PodIdentityProvider) (*azidentity.ChainedTokenCredential, error) { var creds []azcore.TokenCredential // Used for local debug based on az-cli user @@ -42,7 +42,7 @@ func NewChainedCredential(logger logr.Logger, identityID string, podIdentity v1a creds = append(creds, msiCred) } case v1alpha1.PodIdentityProviderAzureWorkload: - wiCred, err := NewADWorkloadIdentityCredential(identityID) + wiCred, err := NewADWorkloadIdentityCredential(identityID, identityTenantID) if err != nil { logger.Error(err, "error starting azure workload-identity token provider") } else { diff --git a/pkg/scalers/azure/azure_data_explorer.go b/pkg/scalers/azure/azure_data_explorer.go index 7b187436372..db5e1295213 100644 --- a/pkg/scalers/azure/azure_data_explorer.go +++ b/pkg/scalers/azure/azure_data_explorer.go @@ -91,7 +91,7 @@ func getDataExplorerAuthConfig(metadata *DataExplorerMetadata) (*kusto.Connectio case kedav1alpha1.PodIdentityProviderAzure, kedav1alpha1.PodIdentityProviderAzureWorkload: azureDataExplorerLogger.V(1).Info(fmt.Sprintf("Creating Azure Data Explorer Client using podIdentity %s", metadata.PodIdentity.Provider)) - creds, chainedErr := NewChainedCredential(azureDataExplorerLogger, metadata.PodIdentity.GetIdentityID(), metadata.PodIdentity.Provider) + creds, chainedErr := NewChainedCredential(azureDataExplorerLogger, metadata.PodIdentity.GetIdentityID(), metadata.PodIdentity.GetIdentityTenantID(), metadata.PodIdentity.Provider) if chainedErr != nil { return nil, chainedErr } diff --git a/pkg/scalers/azure/azure_eventhub.go b/pkg/scalers/azure/azure_eventhub.go index d4ca34b879c..0ff4e347521 100644 --- a/pkg/scalers/azure/azure_eventhub.go +++ b/pkg/scalers/azure/azure_eventhub.go @@ -68,7 +68,7 @@ func GetEventHubClient(ctx context.Context, info EventHubInfo) (*eventhub.Hub, e // User wants to use AAD Workload Identity env := azure.Environment{ActiveDirectoryEndpoint: info.ActiveDirectoryEndpoint, ServiceBusEndpointSuffix: info.ServiceBusEndpointSuffix} hubEnvOptions := eventhub.HubWithEnvironment(env) - provider := NewAzureADWorkloadIdentityTokenProvider(ctx, info.PodIdentity.GetIdentityID(), info.EventHubResourceURL) + provider := NewAzureADWorkloadIdentityTokenProvider(ctx, info.PodIdentity.GetIdentityID(), info.PodIdentity.GetIdentityTenantID(), info.PodIdentity.GetIdentityAuthorityHost(), info.EventHubResourceURL) return eventhub.NewHub(info.Namespace, info.EventHubName, provider, hubEnvOptions) } diff --git a/pkg/scalers/azure/azure_managed_prometheus_http_round_tripper.go b/pkg/scalers/azure/azure_managed_prometheus_http_round_tripper.go index 33dc15dbb85..40cc65b9f2d 100644 --- a/pkg/scalers/azure/azure_managed_prometheus_http_round_tripper.go +++ b/pkg/scalers/azure/azure_managed_prometheus_http_round_tripper.go @@ -37,7 +37,7 @@ func TryAndGetAzureManagedPrometheusHTTPRoundTripper(logger logr.Logger, podIden return nil, fmt.Errorf("trigger metadata cannot be nil") } - chainedCred, err := NewChainedCredential(logger, podIdentity.GetIdentityID(), podIdentity.Provider) + chainedCred, err := NewChainedCredential(logger, podIdentity.GetIdentityID(), podIdentity.GetIdentityTenantID(), podIdentity.Provider) if err != nil { return nil, err } diff --git a/pkg/scalers/azure/azure_monitor.go b/pkg/scalers/azure/azure_monitor.go index 0ed25ff561c..d7bfe2281e6 100644 --- a/pkg/scalers/azure/azure_monitor.go +++ b/pkg/scalers/azure/azure_monitor.go @@ -93,7 +93,7 @@ func createMetricsClient(ctx context.Context, info MonitorInfo, podIdentity keda authConfig = config case kedav1alpha1.PodIdentityProviderAzureWorkload: - authConfig = NewAzureADWorkloadIdentityConfig(ctx, podIdentity.GetIdentityID(), info.AzureResourceManagerEndpoint) + authConfig = NewAzureADWorkloadIdentityConfig(ctx, podIdentity.GetIdentityID(), podIdentity.GetIdentityTenantID(), podIdentity.GetIdentityAuthorityHost(), info.AzureResourceManagerEndpoint) } authorizer, _ := authConfig.Authorizer() diff --git a/pkg/scalers/azure/azure_storage.go b/pkg/scalers/azure/azure_storage.go index d8f09d2f2ee..0c63e065f17 100644 --- a/pkg/scalers/azure/azure_storage.go +++ b/pkg/scalers/azure/azure_storage.go @@ -227,7 +227,7 @@ func parseAccessTokenAndEndpoint(ctx context.Context, httpClient util.HTTPDoer, case kedav1alpha1.PodIdentityProviderAzure: token, err = GetAzureADPodIdentityToken(ctx, httpClient, podIdentity.GetIdentityID(), storageResource) case kedav1alpha1.PodIdentityProviderAzureWorkload: - token, err = GetAzureADWorkloadIdentityToken(ctx, podIdentity.GetIdentityID(), storageResource) + token, err = GetAzureADWorkloadIdentityToken(ctx, podIdentity.GetIdentityID(), podIdentity.GetIdentityTenantID(), podIdentity.GetIdentityAuthorityHost(), storageResource) } if err != nil { diff --git a/pkg/scalers/azure_log_analytics_scaler.go b/pkg/scalers/azure_log_analytics_scaler.go index b07abdacf57..7cae83735c9 100644 --- a/pkg/scalers/azure_log_analytics_scaler.go +++ b/pkg/scalers/azure_log_analytics_scaler.go @@ -477,7 +477,7 @@ func (s *azureLogAnalyticsScaler) getAuthorizationToken(ctx context.Context) (to switch s.metadata.podIdentity.Provider { case kedav1alpha1.PodIdentityProviderAzureWorkload: - aadToken, err := azure.GetAzureADWorkloadIdentityToken(ctx, s.metadata.podIdentity.GetIdentityID(), s.metadata.logAnalyticsResourceURL) + aadToken, err := azure.GetAzureADWorkloadIdentityToken(ctx, s.metadata.podIdentity.GetIdentityID(), s.metadata.podIdentity.GetIdentityTenantID(), s.metadata.podIdentity.GetIdentityAuthorityHost(), s.metadata.logAnalyticsResourceURL) if err != nil { return tokenData{}, nil } diff --git a/pkg/scalers/azure_pipelines_scaler.go b/pkg/scalers/azure_pipelines_scaler.go index 8413642e68e..6bdf5c3fdec 100644 --- a/pkg/scalers/azure_pipelines_scaler.go +++ b/pkg/scalers/azure_pipelines_scaler.go @@ -194,7 +194,7 @@ func getAuthMethod(logger logr.Logger, config *scalersconfig.ScalerConfig) (stri case "", kedav1alpha1.PodIdentityProviderNone: return "", nil, kedav1alpha1.AuthPodIdentity{}, fmt.Errorf("no personalAccessToken given or PodIdentity provider configured") case kedav1alpha1.PodIdentityProviderAzure, kedav1alpha1.PodIdentityProviderAzureWorkload: - cred, err := azure.NewChainedCredential(logger, config.PodIdentity.GetIdentityID(), config.PodIdentity.Provider) + cred, err := azure.NewChainedCredential(logger, config.PodIdentity.GetIdentityID(), config.PodIdentity.GetIdentityTenantID(), config.PodIdentity.Provider) if err != nil { return "", nil, kedav1alpha1.AuthPodIdentity{}, err } diff --git a/pkg/scalers/azure_servicebus_scaler.go b/pkg/scalers/azure_servicebus_scaler.go index b3ee21614c2..18973b71459 100755 --- a/pkg/scalers/azure_servicebus_scaler.go +++ b/pkg/scalers/azure_servicebus_scaler.go @@ -298,7 +298,7 @@ func (s *azureServiceBusScaler) getServiceBusAdminClient() (*admin.Client, error case "", kedav1alpha1.PodIdentityProviderNone: client, err = admin.NewClientFromConnectionString(s.metadata.connection, nil) case kedav1alpha1.PodIdentityProviderAzure, kedav1alpha1.PodIdentityProviderAzureWorkload: - creds, chainedErr := azure.NewChainedCredential(s.logger, s.podIdentity.GetIdentityID(), s.podIdentity.Provider) + creds, chainedErr := azure.NewChainedCredential(s.logger, s.podIdentity.GetIdentityID(), s.podIdentity.GetIdentityTenantID(), s.podIdentity.Provider) if chainedErr != nil { return nil, chainedErr } diff --git a/pkg/scalers/rabbitmq_scaler.go b/pkg/scalers/rabbitmq_scaler.go index 9681ff8f932..4e8cf3c2b5e 100644 --- a/pkg/scalers/rabbitmq_scaler.go +++ b/pkg/scalers/rabbitmq_scaler.go @@ -91,8 +91,10 @@ type rabbitMQMetadata struct { unsafeSsl bool // token provider for azure AD - workloadIdentityClientID string - workloadIdentityResource string + workloadIdentityClientID string + workloadIdentityTenantID string + workloadIdentityAuthorityHost string + workloadIdentityResource string } type queueInfo struct { @@ -244,6 +246,7 @@ func parseRabbitMQMetadata(config *scalersconfig.ScalerConfig) (*rabbitMQMetadat if config.PodIdentity.Provider == v1alpha1.PodIdentityProviderAzureWorkload { if config.AuthParams["workloadIdentityResource"] != "" { meta.workloadIdentityClientID = config.PodIdentity.GetIdentityID() + meta.workloadIdentityTenantID = config.PodIdentity.GetIdentityTenantID() meta.workloadIdentityResource = config.AuthParams["workloadIdentityResource"] } } @@ -510,7 +513,7 @@ func getJSON(ctx context.Context, s *rabbitMQScaler, url string) (queueInfo, err if s.metadata.workloadIdentityResource != "" { if s.azureOAuth == nil { - s.azureOAuth = azure.NewAzureADWorkloadIdentityTokenProvider(ctx, s.metadata.workloadIdentityClientID, s.metadata.workloadIdentityResource) + s.azureOAuth = azure.NewAzureADWorkloadIdentityTokenProvider(ctx, s.metadata.workloadIdentityClientID, s.metadata.workloadIdentityTenantID, s.metadata.workloadIdentityAuthorityHost, s.metadata.workloadIdentityResource) } err = s.azureOAuth.Refresh() diff --git a/pkg/scaling/resolver/aws_secretmanager_handler.go b/pkg/scaling/resolver/aws_secretmanager_handler.go index a85e0974601..3d10ba2e1e5 100644 --- a/pkg/scaling/resolver/aws_secretmanager_handler.go +++ b/pkg/scaling/resolver/aws_secretmanager_handler.go @@ -92,8 +92,8 @@ func (ash *AwsSecretManagerHandler) Initialize(ctx context.Context, client clien return fmt.Errorf("error resolving role arn for aws: %w", err) } ash.awsMetadata.AwsRoleArn = awsRoleArn - } else if ash.secretManager.PodIdentity.RoleArn != "" { - ash.awsMetadata.AwsRoleArn = ash.secretManager.PodIdentity.RoleArn + } else if ash.secretManager.PodIdentity.RoleArn != nil { + ash.awsMetadata.AwsRoleArn = *ash.secretManager.PodIdentity.RoleArn } default: return fmt.Errorf("pod identity provider %s not supported", podIdentity.Provider) diff --git a/pkg/scaling/resolver/azure_keyvault_handler.go b/pkg/scaling/resolver/azure_keyvault_handler.go index f7fe36544c2..3abd02f7ba6 100644 --- a/pkg/scaling/resolver/azure_keyvault_handler.go +++ b/pkg/scaling/resolver/azure_keyvault_handler.go @@ -137,7 +137,7 @@ func (vh *AzureKeyVaultHandler) getAuthConfig(ctx context.Context, client client return config, nil case kedav1alpha1.PodIdentityProviderAzureWorkload: - return azure.NewAzureADWorkloadIdentityConfig(ctx, podIdentity.GetIdentityID(), keyVaultResourceURL), nil + return azure.NewAzureADWorkloadIdentityConfig(ctx, podIdentity.GetIdentityID(), podIdentity.GetIdentityTenantID(), podIdentity.GetIdentityAuthorityHost(), keyVaultResourceURL), nil default: return nil, fmt.Errorf("key vault does not support pod identity provider - %s", podIdentity.Provider) } diff --git a/pkg/scaling/resolver/scale_resolvers.go b/pkg/scaling/resolver/scale_resolvers.go index 23c4ff8195c..3aa4ae28a29 100644 --- a/pkg/scaling/resolver/scale_resolvers.go +++ b/pkg/scaling/resolver/scale_resolvers.go @@ -187,12 +187,12 @@ func ResolveAuthRefAndPodIdentity(ctx context.Context, client client.Client, log } switch podIdentity.Provider { case kedav1alpha1.PodIdentityProviderAws: - if podIdentity.RoleArn != "" { + if podIdentity.RoleArn != nil { if podIdentity.IsWorkloadIdentityOwner() { return nil, kedav1alpha1.AuthPodIdentity{Provider: kedav1alpha1.PodIdentityProviderNone}, fmt.Errorf("roleArn can't be set if KEDA isn't identity owner, current value: '%s'", *podIdentity.IdentityOwner) } - authParams["awsRoleArn"] = podIdentity.RoleArn + authParams["awsRoleArn"] = *podIdentity.RoleArn } if podIdentity.IsWorkloadIdentityOwner() { value, err := resolveServiceAccountAnnotation(ctx, client, podTemplateSpec.Spec.ServiceAccountName, namespace, kedav1alpha1.PodIdentityAnnotationEKS, true)