Azure: Settings for Azure AD Workload Identity (#75283)

* Settings for Azure AD Workload Identity

* Update dependency on Grafana Azure SDK

* Documentation

* Fix JS code

* Cleanup Prometheus backend code

* Making prettier happy
pull/75552/head
Sergey Kostrukov 2 years ago committed by GitHub
parent 969e6a17ba
commit 3ee40d3a5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      conf/defaults.ini
  2. 18
      conf/sample.ini
  3. 26
      docs/sources/setup-grafana/configure-grafana/_index.md
  4. 2
      go.mod
  5. 4
      go.sum
  6. 2
      packages/grafana-runtime/src/config.ts
  7. 7
      pkg/api/dtos/frontend_settings.go
  8. 7
      pkg/api/frontendsettings.go
  9. 18
      pkg/setting/setting_azure.go
  10. 25
      pkg/tsdb/prometheus/azureauth/azure.go
  11. 9
      public/app/plugins/datasource/mssql/azureauth/AzureAuth.testMocks.ts

@ -846,6 +846,24 @@ managed_identity_enabled = false
# Should be set for user-assigned identity and should be empty for system-assigned identity
managed_identity_client_id =
# Specifies whether Azure AD Workload Identity authentication should be enabled in datasources that support it
# For more documentation on Azure AD Workload Identity, review this documentation:
# https://azure.github.io/azure-workload-identity/docs/
# Disabled by default, needs to be explicitly enabled
workload_identity_enabled = false
# Tenant ID of the Azure AD Workload Identity
# Allows to override default tenant ID of the Azure AD identity associated with the Kubernetes service account
workload_identity_tenant_id =
# Client ID of the Azure AD Workload Identity
# Allows to override default client ID of the Azure AD identity associated with the Kubernetes service account
workload_identity_client_id =
# Custom path to token file for the Azure AD Workload Identity
# Allows to set a custom path to the projected service account token file
workload_identity_token_file =
# Specifies whether user identity authentication (on behalf of currently signed-in user) should be enabled in datasources
# that support it (requires AAD authentication)
# Disabled by default, needs to be explicitly enabled

@ -799,6 +799,24 @@
# Should be set for user-assigned identity and should be empty for system-assigned identity
;managed_identity_client_id =
# Specifies whether Azure AD Workload Identity authentication should be enabled in datasources that support it
# For more documentation on Azure AD Workload Identity, review this documentation:
# https://azure.github.io/azure-workload-identity/docs/
# Disabled by default, needs to be explicitly enabled
;workload_identity_enabled = false
# Tenant ID of the Azure AD Workload Identity
# Allows to override default tenant ID of the Azure AD identity associated with the Kubernetes service account
;workload_identity_tenant_id =
# Client ID of the Azure AD Workload Identity
# Allows to override default client ID of the Azure AD identity associated with the Kubernetes service account
;workload_identity_client_id =
# Custom path to token file for the Azure AD Workload Identity
# Allows to set a custom path to the projected service account token file
;workload_identity_token_file =
# Specifies whether user identity authentication (on behalf of currently signed-in user) should be enabled in datasources
# that support it (requires AAD authentication)
# Disabled by default, needs to be explicitly enabled

@ -1158,6 +1158,32 @@ The client ID to use for user-assigned managed identity.
Should be set for user-assigned identity and should be empty for system-assigned identity.
### workload_identity_enabled
Specifies whether Azure AD Workload Identity authentication should be enabled in datasources that support it.
For more documentation on Azure AD Workload Identity, review [Azure AD Workload Identity](https://azure.github.io/azure-workload-identity/docs/) documentation.
Disabled by default, needs to be explicitly enabled.
### workload_identity_tenant_id
Tenant ID of the Azure AD Workload Identity.
Allows to override default tenant ID of the Azure AD identity associated with the Kubernetes service account.
### workload_identity_client_id
Client ID of the Azure AD Workload Identity.
Allows to override default client ID of the Azure AD identity associated with the Kubernetes service account.
### workload_identity_token_file
Custom path to token file for the Azure AD Workload Identity.
Allows to set a custom path to the projected service account token file.
### user_identity_enabled
Specifies whether user identity authentication (on behalf of currently signed-in user) should be enabled in datasources that support it (requires AAD authentication).

@ -62,7 +62,7 @@ require (
github.com/grafana/alerting v0.0.0-20230918125844-e60d564786c9 // @grafana/alerting-squad-backend
github.com/grafana/cuetsy v0.1.10 // @grafana/grafana-as-code
github.com/grafana/grafana-aws-sdk v0.19.1 // @grafana/aws-datasources
github.com/grafana/grafana-azure-sdk-go v1.8.1 // @grafana/backend-platform
github.com/grafana/grafana-azure-sdk-go v1.9.0 // @grafana/backend-platform
github.com/grafana/grafana-plugin-sdk-go v0.177.0 // @grafana/plugins-platform-backend
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // @grafana/backend-platform
github.com/hashicorp/go-hclog v1.5.0 // @grafana/plugins-platform-backend

@ -1799,8 +1799,8 @@ github.com/grafana/grafana-apiserver v0.0.0-20230713001719-88a9ed41992d h1:fjc6v
github.com/grafana/grafana-apiserver v0.0.0-20230713001719-88a9ed41992d/go.mod h1:2g9qGdCeU6x/69QAs82WM52bwBUT5/CBaBD0I94+txU=
github.com/grafana/grafana-aws-sdk v0.19.1 h1:5GBiOv2AgdyjwlgAX+dtgPtXU4FgMTD9rfQUPQseEpQ=
github.com/grafana/grafana-aws-sdk v0.19.1/go.mod h1:ntq2NDH12Y2Fkbc6fozpF8kYsJM9k6KNr+Xfo5w3/iM=
github.com/grafana/grafana-azure-sdk-go v1.8.1 h1:UgzOc7Qv1P0EJhijn71g9eT1xqujI3nwbhw+OIarBYE=
github.com/grafana/grafana-azure-sdk-go v1.8.1/go.mod h1:1vBa0KOl+/Kcm7V888OyMXDSFncmek14q7XhEkrcSaA=
github.com/grafana/grafana-azure-sdk-go v1.9.0 h1:4JRwlqgUtPRAQSoiV4DFZDQ3lbNsauHqj9kC6SMR9Ak=
github.com/grafana/grafana-azure-sdk-go v1.9.0/go.mod h1:1vBa0KOl+/Kcm7V888OyMXDSFncmek14q7XhEkrcSaA=
github.com/grafana/grafana-google-sdk-go v0.1.0 h1:LKGY8z2DSxKjYfr2flZsWgTRTZ6HGQbTqewE3JvRaNA=
github.com/grafana/grafana-google-sdk-go v0.1.0/go.mod h1:Vo2TKWfDVmNTELBUM+3lkrZvFtBws0qSZdXhQxRdJrE=
github.com/grafana/grafana-plugin-sdk-go v0.94.0/go.mod h1:3VXz4nCv6wH5SfgB3mlW39s+c+LetqSCjFj7xxPC5+M=

@ -21,6 +21,7 @@ import {
export interface AzureSettings {
cloud?: string;
managedIdentityEnabled: boolean;
workloadIdentityEnabled: boolean;
userIdentityEnabled: boolean;
}
@ -124,6 +125,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
awsAssumeRoleEnabled = false;
azure: AzureSettings = {
managedIdentityEnabled: false,
workloadIdentityEnabled: false,
userIdentityEnabled: false,
};
caching = {

@ -44,9 +44,10 @@ type FrontendSettingsLicenseInfoDTO struct {
}
type FrontendSettingsAzureDTO struct {
Cloud string `json:"cloud"`
ManagedIdentityEnabled bool `json:"managedIdentityEnabled"`
UserIdentityEnabled bool `json:"userIdentityEnabled"`
Cloud string `json:"cloud"`
ManagedIdentityEnabled bool `json:"managedIdentityEnabled"`
WorkloadIdentityEnabled bool `json:"workloadIdentityEnabled"`
UserIdentityEnabled bool `json:"userIdentityEnabled"`
}
type FrontendSettingsCachingDTO struct {

@ -206,9 +206,10 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
SupportBundlesEnabled: isSupportBundlesEnabled(hs),
Azure: dtos.FrontendSettingsAzureDTO{
Cloud: hs.Cfg.Azure.Cloud,
ManagedIdentityEnabled: hs.Cfg.Azure.ManagedIdentityEnabled,
UserIdentityEnabled: hs.Cfg.Azure.UserIdentityEnabled,
Cloud: hs.Cfg.Azure.Cloud,
ManagedIdentityEnabled: hs.Cfg.Azure.ManagedIdentityEnabled,
WorkloadIdentityEnabled: hs.Cfg.Azure.WorkloadIdentityEnabled,
UserIdentityEnabled: hs.Cfg.Azure.UserIdentityEnabled,
},
Caching: dtos.FrontendSettingsCachingDTO{

@ -17,6 +17,24 @@ func (cfg *Cfg) readAzureSettings() {
azureSettings.ManagedIdentityEnabled = azureSection.Key("managed_identity_enabled").MustBool(false)
azureSettings.ManagedIdentityClientId = azureSection.Key("managed_identity_client_id").String()
// Workload Identity authentication
if azureSection.Key("workload_identity_enabled").MustBool(false) {
azureSettings.WorkloadIdentityEnabled = true
workloadIdentitySettings := &azsettings.WorkloadIdentitySettings{}
if val := azureSection.Key("workload_identity_tenant_id").String(); val != "" {
workloadIdentitySettings.TenantId = val
}
if val := azureSection.Key("workload_identity_client_id").String(); val != "" {
workloadIdentitySettings.ClientId = val
}
if val := azureSection.Key("workload_identity_token_file").String(); val != "" {
workloadIdentitySettings.TokenFile = val
}
azureSettings.WorkloadIdentitySettings = workloadIdentitySettings
}
// User Identity authentication
if azureSection.Key("user_identity_enabled").MustBool(false) {
azureSettings.UserIdentityEnabled = true

@ -77,7 +77,7 @@ func getOverriddenScopes(jsonData map[string]any) ([]string, error) {
func getPrometheusScopes(settings *azsettings.AzureSettings, credentials azcredentials.AzureCredentials) ([]string, error) {
// Extract cloud from credentials
azureCloud, err := getAzureCloudFromCredentials(settings, credentials)
azureCloud, err := azcredentials.GetAzureCloud(settings, credentials)
if err != nil {
return nil, err
}
@ -90,26 +90,3 @@ func getPrometheusScopes(settings *azsettings.AzureSettings, credentials azcrede
return scopes, nil
}
}
// To be part of grafana-azure-sdk-go
func getAzureCloudFromCredentials(settings *azsettings.AzureSettings, credentials azcredentials.AzureCredentials) (string, error) {
switch c := credentials.(type) {
case *azcredentials.AzureManagedIdentityCredentials:
// In case of managed identity, the cloud is always same as where Grafana is hosted
return getDefaultAzureCloud(settings), nil
case *azcredentials.AzureClientSecretCredentials:
return c.AzureCloud, nil
default:
err := fmt.Errorf("the Azure credentials of type '%s' not supported by Prometheus datasource", c.AzureAuthType())
return "", err
}
}
// To be part of grafana-azure-sdk-go
func getDefaultAzureCloud(settings *azsettings.AzureSettings) string {
cloudName := settings.Cloud
if cloudName == "" {
return azsettings.AzurePublic
}
return cloudName
}

@ -4,11 +4,16 @@ import { GrafanaBootConfig } from '@grafana/runtime';
import { AzureAuthSecureJSONDataType, AzureAuthJSONDataType, AzureAuthType } from '../types';
export const configWithManagedIdentityEnabled: Partial<GrafanaBootConfig> = {
azure: { managedIdentityEnabled: true, userIdentityEnabled: false },
azure: { managedIdentityEnabled: true, workloadIdentityEnabled: false, userIdentityEnabled: false },
};
export const configWithManagedIdentityDisabled: Partial<GrafanaBootConfig> = {
azure: { managedIdentityEnabled: false, userIdentityEnabled: false, cloud: 'AzureCloud' },
azure: {
managedIdentityEnabled: false,
workloadIdentityEnabled: false,
userIdentityEnabled: false,
cloud: 'AzureCloud',
},
};
export const dataSourceSettingsWithMsiCredentials: Partial<

Loading…
Cancel
Save