[v11.2.x] Azure Monitor: Add a feature flag to toggle user auth for Azure Monitor only (#97565)

* Azure Monitor: Add a feature flag to toggle user auth for Azure Monitor only (#96858)

* Azure Monitor: Add a feature flag to toggle user auth for Azure Monitor only

* Fix condition for userIdentityEnabled

* Re-add removed test

* Remove unused prop

* Refactor onAuthTypeChange in AzureCredentialsForm

* Add frontend unit tests

* Lint

(cherry picked from commit b898a4540d)

# Conflicts:
#	docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md
#	packages/grafana-data/src/types/featureToggles.gen.ts
#	pkg/services/featuremgmt/registry.go
#	pkg/services/featuremgmt/toggles_gen.csv
#	pkg/services/featuremgmt/toggles_gen.go
#	pkg/services/featuremgmt/toggles_gen.json

* Update test

* Missing import

---------

Co-authored-by: Adam Yeats <16296989+adamyeats@users.noreply.github.com>
This commit is contained in:
Andreas Christou
2024-12-10 11:20:26 +00:00
committed by GitHub
co-authored by Adam Yeats
parent 86573d4266
commit 7693dde11b
13 changed files with 150 additions and 22 deletions
+7
View File
@@ -1379,6 +1379,13 @@ var (
Owner: grafanaAppPlatformSquad,
RequiresRestart: true,
},
{
Name: "azureMonitorEnableUserAuth",
Description: "Enables user auth for Azure Monitor datasource only",
Stage: FeatureStageGeneralAvailability,
Owner: grafanaPartnerPluginsSquad,
Expression: "true", // Enabled by default for now
},
}
)
+1
View File
@@ -181,3 +181,4 @@ bodyScrolling,preview,@grafana/grafana-frontend-platform,false,false,true
cloudwatchMetricInsightsCrossAccount,preview,@grafana/aws-datasources,false,false,true
prometheusAzureOverrideAudience,deprecated,@grafana/partner-datasources,false,false,false
dataplaneAggregator,experimental,@grafana/grafana-app-platform-squad,false,true,false
azureMonitorEnableUserAuth,GA,@grafana/partner-datasources,false,false,false
1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
181 cloudwatchMetricInsightsCrossAccount preview @grafana/aws-datasources false false true
182 prometheusAzureOverrideAudience deprecated @grafana/partner-datasources false false false
183 dataplaneAggregator experimental @grafana/grafana-app-platform-squad false true false
184 azureMonitorEnableUserAuth GA @grafana/partner-datasources false false false
+4
View File
@@ -734,4 +734,8 @@ const (
// FlagDataplaneAggregator
// Enable grafana dataplane aggregator
FlagDataplaneAggregator = "dataplaneAggregator"
// FlagAzureMonitorEnableUserAuth
// Enables user auth for Azure Monitor datasource only
FlagAzureMonitorEnableUserAuth = "azureMonitorEnableUserAuth"
)
+13
View File
@@ -502,6 +502,19 @@
"codeowner": "@grafana/aws-datasources"
}
},
{
"metadata": {
"name": "azureMonitorEnableUserAuth",
"resourceVersion": "1733495779155",
"creationTimestamp": "2024-12-06T14:36:19Z"
},
"spec": {
"description": "Enables user auth for Azure Monitor datasource only",
"stage": "GA",
"codeowner": "@grafana/partner-datasources",
"expression": "true"
}
},
{
"metadata": {
"name": "azureMonitorPrometheusExemplars",
+5
View File
@@ -10,6 +10,7 @@ import (
"net/http"
"strconv"
"github.com/grafana/grafana-azure-sdk-go/v2/azcredentials"
"github.com/grafana/grafana-azure-sdk-go/v2/azsettings"
"github.com/grafana/grafana-azure-sdk-go/v2/azusercontext"
"github.com/grafana/grafana-plugin-sdk-go/backend"
@@ -116,6 +117,10 @@ func NewInstanceSettings(clientProvider *httpclient.Provider, executors map[stri
return nil, err
}
if credentials.AzureAuthType() == azcredentials.AzureAuthCurrentUserIdentity && !backend.GrafanaConfigFromContext(ctx).FeatureToggles().IsEnabled("azureMonitorEnableUserAuth") {
return nil, backend.DownstreamError(errors.New("current user authentication is not enabled for azure monitor"))
}
model := types.DatasourceInfo{
Credentials: credentials,
Settings: azMonitorSettings,
+39 -6
View File
@@ -16,6 +16,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/experimental/featuretoggles"
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/types"
@@ -58,9 +59,29 @@ func TestNewInstanceSettings(t *testing.T) {
tests := []struct {
name string
settings backend.DataSourceInstanceSettings
expectedModel types.DatasourceInfo
expectedModel *types.DatasourceInfo
Err require.ErrorAssertionFunc
setupContext func(ctx context.Context) context.Context
}{
{
name: "current user authentication disabled by feature toggle",
settings: backend.DataSourceInstanceSettings{
JSONData: []byte(`{"azureAuthType":"currentuser"}`),
DecryptedSecureJSONData: map[string]string{},
ID: 60,
},
expectedModel: nil,
Err: func(t require.TestingT, err error, _ ...interface{}) {
require.Error(t, err)
require.Contains(t, err.Error(), "current user authentication is not enabled for azure monitor")
},
setupContext: func(ctx context.Context) context.Context {
featureToggles := backend.NewGrafanaCfg(map[string]string{
featuretoggles.EnabledFeatures: "", // No enabled features
})
return backend.WithGrafanaConfig(ctx, featureToggles)
},
},
{
name: "creates an instance",
settings: backend.DataSourceInstanceSettings{
@@ -68,7 +89,7 @@ func TestNewInstanceSettings(t *testing.T) {
DecryptedSecureJSONData: map[string]string{"key": "value"},
ID: 40,
},
expectedModel: types.DatasourceInfo{
expectedModel: &types.DatasourceInfo{
Credentials: &azcredentials.AzureManagedIdentityCredentials{},
Settings: types.AzureMonitorSettings{},
Routes: testRoutes,
@@ -86,7 +107,7 @@ func TestNewInstanceSettings(t *testing.T) {
DecryptedSecureJSONData: map[string]string{"clientSecret": "secret"},
ID: 50,
},
expectedModel: types.DatasourceInfo{
expectedModel: &types.DatasourceInfo{
Credentials: &azcredentials.AzureClientSecretCredentials{
AzureCloud: "AzureCustomizedCloud",
ClientSecret: "secret",
@@ -116,11 +137,23 @@ func TestNewInstanceSettings(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
if tt.setupContext != nil {
ctx = tt.setupContext(ctx)
}
factory := NewInstanceSettings(&httpclient.Provider{}, map[string]azDatasourceExecutor{}, log.DefaultLogger)
instance, err := factory(context.Background(), tt.settings)
instance, err := factory(ctx, tt.settings)
tt.Err(t, err)
if !cmp.Equal(instance, tt.expectedModel) {
t.Errorf("Unexpected instance: %v", cmp.Diff(instance, tt.expectedModel))
if tt.expectedModel == nil {
require.Nil(t, instance, "Expected instance to be nil")
} else {
require.NotNil(t, instance, "Expected instance to be created")
if !cmp.Equal(instance, *tt.expectedModel) {
t.Errorf("Unexpected instance: %v", cmp.Diff(instance, *tt.expectedModel))
}
}
})
}