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
This commit is contained in:
Adam Yeats
2024-11-27 14:01:54 +00:00
committed by GitHub
parent d18cdae3e2
commit b898a4540d
13 changed files with 151 additions and 22 deletions
+7
View File
@@ -1666,6 +1666,13 @@ var (
Owner: grafanaAlertingSquad,
Expression: "true", // enabled by default
},
{
Name: "azureMonitorEnableUserAuth",
Description: "Enables user auth for Azure Monitor datasource only",
Stage: FeatureStageGeneralAvailability,
Owner: grafanaPartnerPluginsSquad,
Expression: "true", // Enabled by default for now
},
{
Name: "alertingNotificationsStepMode",
Description: "Enables simplified step mode in the notifications section",
+1
View File
@@ -222,4 +222,5 @@ crashDetection,experimental,@grafana/observability-traces-and-profiling,false,fa
jaegerBackendMigration,experimental,@grafana/oss-big-tent,false,false,false
reportingUseRawTimeRange,preview,@grafana/sharing-squad,false,false,false
alertingUIOptimizeReducer,GA,@grafana/alerting-squad,false,false,true
azureMonitorEnableUserAuth,GA,@grafana/partner-datasources,false,false,false
alertingNotificationsStepMode,experimental,@grafana/alerting-squad,false,false,true
1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
222 jaegerBackendMigration experimental @grafana/oss-big-tent false false false
223 reportingUseRawTimeRange preview @grafana/sharing-squad false false false
224 alertingUIOptimizeReducer GA @grafana/alerting-squad false false true
225 azureMonitorEnableUserAuth GA @grafana/partner-datasources false false false
226 alertingNotificationsStepMode experimental @grafana/alerting-squad false false true
+4
View File
@@ -899,6 +899,10 @@ const (
// Enables removing the reducer from the alerting UI when creating a new alert rule and using instant query
FlagAlertingUIOptimizeReducer = "alertingUIOptimizeReducer"
// FlagAzureMonitorEnableUserAuth
// Enables user auth for Azure Monitor datasource only
FlagAzureMonitorEnableUserAuth = "azureMonitorEnableUserAuth"
// FlagAlertingNotificationsStepMode
// Enables simplified step mode in the notifications section
FlagAlertingNotificationsStepMode = "alertingNotificationsStepMode"
+16
View File
@@ -660,6 +660,22 @@
"expression": "false"
}
},
{
"metadata": {
"name": "azureMonitorEnableUserAuth",
"resourceVersion": "1732189410576",
"creationTimestamp": "2024-11-21T11:42:29Z",
"annotations": {
"grafana.app/updatedTimestamp": "2024-11-21 11:43:30.576196 +0000 UTC"
}
},
"spec": {
"description": "Enables user auth for Azure Monitor datasource only",
"stage": "GA",
"codeowner": "@grafana/partner-datasources",
"expression": "true"
}
},
{
"metadata": {
"name": "azureMonitorLogLimit",
+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"
@@ -139,6 +140,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
@@ -17,6 +17,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"
@@ -59,9 +60,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{
@@ -69,7 +90,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,
@@ -87,7 +108,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",
@@ -117,11 +138,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))
}
}
})
}