Azure: Use SSO settings in plugin context (#112058)
* Bump grafana-azure-sdk-go * Set override values * Add Azure settings helper covering SSO cases * Ensure Azure settings are correctly created - Add mock for sso settings service - Add tests - Update wire * Minor improvements * Test updates * Move fake implementation * add interface to limit leakage * rename * work sync * Fix wire * Add fake provider * Update tests * Actually fix the workspace * More go dependency fixes * Update tests * Update workspace, again * Add missing tests * Fix dependencies * These dependencies.. * More dependency things * Okay now dependencies really are fixed * Lint * Update pkg/services/pluginsintegration/pluginconfig/request.go Co-authored-by: Misi <mgyongyosi@users.noreply.github.com> --------- Co-authored-by: Will Browne <wbrowne@tcd.ie> Co-authored-by: Misi <mgyongyosi@users.noreply.github.com>
This commit is contained in:
co-authored by
Misi
Will Browne
parent
59459560c2
commit
fa9d6be255
@@ -0,0 +1,66 @@
|
||||
package pluginconfig
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana-azure-sdk-go/v2/azsettings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsso"
|
||||
)
|
||||
|
||||
// mergeAzureSettings merges the Azure AD settings from the SSO settings DB with the Azure AD settings from the config.
|
||||
// Azure AD settings can be changed via the UI or SSO settings API
|
||||
// They can also be overridden in the [azure] config section
|
||||
// The order of precedence is:
|
||||
// 1. [azure] config section (if the override flag is set)
|
||||
// 2. SSO settings from the DB (if they exist)
|
||||
// 3. [auth.azuread] config section (if enabled)
|
||||
func mergeAzureSettings(currSettings *azsettings.AzureSettings, azureAdSettings *pluginsso.Settings) *azsettings.AzureSettings {
|
||||
if azureAdSettings != nil {
|
||||
settings := azureAdSettings.Values
|
||||
tokenEndpointSettings := currSettings.UserIdentityTokenEndpoint
|
||||
if tokenEndpointSettings == nil {
|
||||
tokenEndpointSettings = &azsettings.TokenEndpointSettings{}
|
||||
currSettings.UserIdentityTokenEndpoint = tokenEndpointSettings
|
||||
}
|
||||
|
||||
tokenUrl, ok := settings["token_url"].(string)
|
||||
if ok {
|
||||
if !currSettings.UserIdentityTokenEndpoint.TokenUrlOverride {
|
||||
currSettings.UserIdentityTokenEndpoint.TokenUrl = tokenUrl
|
||||
}
|
||||
}
|
||||
clientAuth, ok := settings["client_authentication"].(string)
|
||||
if ok {
|
||||
if !currSettings.UserIdentityTokenEndpoint.ClientAuthenticationOverride {
|
||||
if clientAuth != "none" {
|
||||
currSettings.UserIdentityTokenEndpoint.ClientAuthentication = clientAuth
|
||||
}
|
||||
}
|
||||
}
|
||||
clientId, ok := settings["client_id"].(string)
|
||||
if ok {
|
||||
if !currSettings.UserIdentityTokenEndpoint.ClientIdOverride {
|
||||
currSettings.UserIdentityTokenEndpoint.ClientId = clientId
|
||||
}
|
||||
}
|
||||
clientSecret, ok := settings["client_secret"].(string)
|
||||
if ok {
|
||||
if !currSettings.UserIdentityTokenEndpoint.ClientSecretOverride {
|
||||
currSettings.UserIdentityTokenEndpoint.ClientSecret = clientSecret
|
||||
}
|
||||
}
|
||||
managedIdentityClientId, ok := settings["managed_identity_client_id"].(string)
|
||||
if ok {
|
||||
if !currSettings.UserIdentityTokenEndpoint.ManagedIdentityClientIdOverride {
|
||||
currSettings.UserIdentityTokenEndpoint.ManagedIdentityClientId = managedIdentityClientId
|
||||
}
|
||||
}
|
||||
federatedCredentialAudience, ok := settings["federated_credential_audience"].(string)
|
||||
if ok {
|
||||
if !currSettings.UserIdentityTokenEndpoint.FederatedCredentialAudienceOverride {
|
||||
currSettings.UserIdentityTokenEndpoint.FederatedCredentialAudience = federatedCredentialAudience
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currSettings
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package pluginconfig
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana-azure-sdk-go/v2/azsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsso"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetAzureSettings(t *testing.T) {
|
||||
t.Run("no Azure settings input", func(t *testing.T) {
|
||||
result := mergeAzureSettings(nil, nil)
|
||||
|
||||
assert.Nil(t, result)
|
||||
})
|
||||
|
||||
t.Run("no SSO settings or override settings", func(t *testing.T) {
|
||||
currSettings := &azsettings.AzureSettings{
|
||||
UserIdentityTokenEndpoint: &azsettings.TokenEndpointSettings{
|
||||
TokenUrl: "original-token-url",
|
||||
ClientAuthentication: "original-auth",
|
||||
ClientId: "original-client-id",
|
||||
ClientSecret: "original-client-secret",
|
||||
},
|
||||
}
|
||||
|
||||
azureAdSettings := &pluginsso.Settings{
|
||||
Values: map[string]any{},
|
||||
}
|
||||
|
||||
result := mergeAzureSettings(currSettings, azureAdSettings)
|
||||
|
||||
assert.Equal(t, "original-token-url", result.UserIdentityTokenEndpoint.TokenUrl)
|
||||
assert.Equal(t, "original-auth", result.UserIdentityTokenEndpoint.ClientAuthentication)
|
||||
assert.Equal(t, "original-client-id", result.UserIdentityTokenEndpoint.ClientId)
|
||||
assert.Equal(t, "original-client-secret", result.UserIdentityTokenEndpoint.ClientSecret)
|
||||
})
|
||||
|
||||
t.Run("with SSO settings but no overrides", func(t *testing.T) {
|
||||
currSettings := &azsettings.AzureSettings{
|
||||
UserIdentityTokenEndpoint: &azsettings.TokenEndpointSettings{
|
||||
TokenUrl: "original-token-url",
|
||||
ClientAuthentication: "original-auth",
|
||||
ClientId: "original-client-id",
|
||||
ClientSecret: "original-client-secret",
|
||||
ManagedIdentityClientId: "original-managed-id",
|
||||
FederatedCredentialAudience: "original-audience",
|
||||
TokenUrlOverride: false,
|
||||
ClientAuthenticationOverride: false,
|
||||
ClientIdOverride: false,
|
||||
ClientSecretOverride: false,
|
||||
ManagedIdentityClientIdOverride: false,
|
||||
FederatedCredentialAudienceOverride: false,
|
||||
},
|
||||
}
|
||||
|
||||
azureAdSettings := &pluginsso.Settings{
|
||||
Values: map[string]any{
|
||||
"token_url": "sso-token-url",
|
||||
"client_authentication": "sso-auth",
|
||||
"client_id": "sso-client-id",
|
||||
"client_secret": "sso-client-secret",
|
||||
"managed_identity_client_id": "sso-managed-id",
|
||||
"federated_credential_audience": "sso-audience",
|
||||
},
|
||||
}
|
||||
|
||||
result := mergeAzureSettings(currSettings, azureAdSettings)
|
||||
|
||||
assert.Equal(t, "sso-token-url", result.UserIdentityTokenEndpoint.TokenUrl)
|
||||
assert.Equal(t, "sso-auth", result.UserIdentityTokenEndpoint.ClientAuthentication)
|
||||
assert.Equal(t, "sso-client-id", result.UserIdentityTokenEndpoint.ClientId)
|
||||
assert.Equal(t, "sso-client-secret", result.UserIdentityTokenEndpoint.ClientSecret)
|
||||
assert.Equal(t, "sso-managed-id", result.UserIdentityTokenEndpoint.ManagedIdentityClientId)
|
||||
assert.Equal(t, "sso-audience", result.UserIdentityTokenEndpoint.FederatedCredentialAudience)
|
||||
})
|
||||
|
||||
t.Run("with both overrides and SSO settings", func(t *testing.T) {
|
||||
currSettings := &azsettings.AzureSettings{
|
||||
UserIdentityTokenEndpoint: &azsettings.TokenEndpointSettings{
|
||||
TokenUrl: "override-token-url",
|
||||
ClientAuthentication: "override-auth",
|
||||
ClientId: "override-client-id",
|
||||
ClientSecret: "override-client-secret",
|
||||
ManagedIdentityClientId: "override-managed-id",
|
||||
FederatedCredentialAudience: "override-audience",
|
||||
TokenUrlOverride: true,
|
||||
ClientAuthenticationOverride: true,
|
||||
ClientIdOverride: true,
|
||||
ClientSecretOverride: true,
|
||||
ManagedIdentityClientIdOverride: true,
|
||||
FederatedCredentialAudienceOverride: true,
|
||||
},
|
||||
}
|
||||
|
||||
azureAdSettings := &pluginsso.Settings{
|
||||
Values: map[string]any{
|
||||
"token_url": "sso-token-url",
|
||||
"client_authentication": "sso-auth",
|
||||
"client_id": "sso-client-id",
|
||||
"client_secret": "sso-client-secret",
|
||||
"managed_identity_client_id": "sso-managed-id",
|
||||
"federated_credential_audience": "sso-audience",
|
||||
},
|
||||
}
|
||||
|
||||
result := mergeAzureSettings(currSettings, azureAdSettings)
|
||||
|
||||
// Should keep override values, not SSO values
|
||||
assert.Equal(t, "override-token-url", result.UserIdentityTokenEndpoint.TokenUrl)
|
||||
assert.Equal(t, "override-auth", result.UserIdentityTokenEndpoint.ClientAuthentication)
|
||||
assert.Equal(t, "override-client-id", result.UserIdentityTokenEndpoint.ClientId)
|
||||
assert.Equal(t, "override-client-secret", result.UserIdentityTokenEndpoint.ClientSecret)
|
||||
assert.Equal(t, "override-managed-id", result.UserIdentityTokenEndpoint.ManagedIdentityClientId)
|
||||
assert.Equal(t, "override-audience", result.UserIdentityTokenEndpoint.FederatedCredentialAudience)
|
||||
})
|
||||
|
||||
t.Run("client authentication 'none' should be ignored", func(t *testing.T) {
|
||||
currSettings := &azsettings.AzureSettings{
|
||||
UserIdentityTokenEndpoint: &azsettings.TokenEndpointSettings{
|
||||
ClientAuthentication: "original-auth",
|
||||
ClientAuthenticationOverride: false,
|
||||
},
|
||||
}
|
||||
|
||||
azureAdSettings := &pluginsso.Settings{
|
||||
Values: map[string]any{
|
||||
"client_authentication": "none",
|
||||
},
|
||||
}
|
||||
|
||||
result := mergeAzureSettings(currSettings, azureAdSettings)
|
||||
|
||||
assert.Equal(t, "original-auth", result.UserIdentityTokenEndpoint.ClientAuthentication)
|
||||
})
|
||||
|
||||
t.Run("non-string values should be ignored", func(t *testing.T) {
|
||||
currSettings := &azsettings.AzureSettings{
|
||||
UserIdentityTokenEndpoint: &azsettings.TokenEndpointSettings{
|
||||
TokenUrl: "original-token-url",
|
||||
ClientId: "original-client-id",
|
||||
TokenUrlOverride: false,
|
||||
ClientIdOverride: false,
|
||||
},
|
||||
}
|
||||
|
||||
azureAdSettings := &pluginsso.Settings{
|
||||
Values: map[string]any{
|
||||
"token_url": 12345,
|
||||
"client_id": []string{"array", "value"},
|
||||
},
|
||||
}
|
||||
|
||||
result := mergeAzureSettings(currSettings, azureAdSettings)
|
||||
|
||||
assert.Equal(t, "original-token-url", result.UserIdentityTokenEndpoint.TokenUrl)
|
||||
assert.Equal(t, "original-client-id", result.UserIdentityTokenEndpoint.ClientId)
|
||||
})
|
||||
|
||||
t.Run("Nil UserIdentityTokenEndpoint should not panic", func(t *testing.T) {
|
||||
currSettings := &azsettings.AzureSettings{
|
||||
UserIdentityTokenEndpoint: nil,
|
||||
}
|
||||
|
||||
azureAdSettings := &pluginsso.Settings{
|
||||
Values: map[string]any{
|
||||
"token_url": "sso-token-url",
|
||||
},
|
||||
}
|
||||
|
||||
require.NotPanics(t, func() {
|
||||
mergeAzureSettings(currSettings, azureAdSettings)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Empty SSO settings map", func(t *testing.T) {
|
||||
currSettings := &azsettings.AzureSettings{
|
||||
UserIdentityTokenEndpoint: &azsettings.TokenEndpointSettings{
|
||||
TokenUrl: "original-token-url",
|
||||
ClientAuthentication: "original-auth",
|
||||
ClientId: "original-client-id",
|
||||
},
|
||||
}
|
||||
|
||||
azureAdSettings := &pluginsso.Settings{
|
||||
Values: map[string]any{},
|
||||
}
|
||||
|
||||
result := mergeAzureSettings(currSettings, azureAdSettings)
|
||||
|
||||
assert.Equal(t, "original-token-url", result.UserIdentityTokenEndpoint.TokenUrl)
|
||||
assert.Equal(t, "original-auth", result.UserIdentityTokenEndpoint.ClientAuthentication)
|
||||
assert.Equal(t, "original-client-id", result.UserIdentityTokenEndpoint.ClientId)
|
||||
})
|
||||
}
|
||||
@@ -13,23 +13,27 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/proxy"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/envvars"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsso"
|
||||
)
|
||||
|
||||
var _ envvars.Provider = (*EnvVarsProvider)(nil)
|
||||
|
||||
type EnvVarsProvider struct {
|
||||
cfg *PluginInstanceCfg
|
||||
license plugins.Licensing
|
||||
logger log.Logger
|
||||
cfg *PluginInstanceCfg
|
||||
license plugins.Licensing
|
||||
logger log.Logger
|
||||
ssoSettings pluginsso.SettingsProvider
|
||||
}
|
||||
|
||||
func NewEnvVarsProvider(cfg *PluginInstanceCfg, license plugins.Licensing) *EnvVarsProvider {
|
||||
func NewEnvVarsProvider(cfg *PluginInstanceCfg, license plugins.Licensing, ssoSettings pluginsso.SettingsProvider) *EnvVarsProvider {
|
||||
return &EnvVarsProvider{
|
||||
cfg: cfg,
|
||||
license: license,
|
||||
logger: log.New("plugins.envvars"),
|
||||
cfg: cfg,
|
||||
license: license,
|
||||
logger: log.New("plugins.envvars"),
|
||||
ssoSettings: ssoSettings,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +67,7 @@ func (p *EnvVarsProvider) PluginEnvVars(ctx context.Context, plugin *plugins.Plu
|
||||
hostEnv = append(hostEnv, p.featureToggleEnableVars(ctx)...)
|
||||
hostEnv = append(hostEnv, p.awsEnvVars(plugin.PluginID())...)
|
||||
hostEnv = append(hostEnv, p.secureSocksProxyEnvVars()...)
|
||||
hostEnv = append(hostEnv, azsettings.WriteToEnvStr(p.cfg.Azure)...)
|
||||
hostEnv = append(hostEnv, azsettings.WriteToEnvStr(p.getAzureSettings())...)
|
||||
hostEnv = append(hostEnv, p.tracingEnvVars(plugin)...)
|
||||
hostEnv = append(hostEnv, p.pluginSettingsEnvVars(plugin.PluginID())...)
|
||||
|
||||
@@ -189,3 +193,15 @@ func (p *EnvVarsProvider) envVar(key, value string) string {
|
||||
}
|
||||
return fmt.Sprintf("%s=%s", key, value)
|
||||
}
|
||||
|
||||
func (p *EnvVarsProvider) getAzureSettings() *azsettings.AzureSettings {
|
||||
azureSettings := p.cfg.Azure
|
||||
if azureSettings == nil {
|
||||
azureSettings = &azsettings.AzureSettings{}
|
||||
}
|
||||
azureAdSettings, err := p.ssoSettings.GetForProvider(context.Background(), social.AzureADProviderName)
|
||||
if err != nil {
|
||||
p.logger.Error("Failed to get SSO settings", "error", err)
|
||||
}
|
||||
return mergeAzureSettings(azureSettings, azureAdSettings)
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func TestPluginEnvVarsProvider_PluginEnvVars(t *testing.T) {
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
}
|
||||
|
||||
provider := NewEnvVarsProvider(cfg, licensing)
|
||||
provider := NewEnvVarsProvider(cfg, licensing, &fakeSSOSettingsProvider{})
|
||||
envVars := provider.PluginEnvVars(context.Background(), p)
|
||||
assert.Len(t, envVars, 6)
|
||||
assert.Equal(t, "GF_VERSION=", envVars[0])
|
||||
@@ -77,7 +77,7 @@ func TestPluginEnvVarsProvider_skipHostEnvVars(t *testing.T) {
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
provider := NewEnvVarsProvider(pCfg, nil)
|
||||
provider := NewEnvVarsProvider(pCfg, nil, &fakeSSOSettingsProvider{})
|
||||
envVars := provider.PluginEnvVars(context.Background(), p)
|
||||
|
||||
// We want to test that the envvars.Provider does not add any of the host env vars.
|
||||
@@ -93,7 +93,7 @@ func TestPluginEnvVarsProvider_skipHostEnvVars(t *testing.T) {
|
||||
cfg := setting.NewCfg()
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
provider := NewEnvVarsProvider(pCfg, nil)
|
||||
provider := NewEnvVarsProvider(pCfg, nil, &fakeSSOSettingsProvider{})
|
||||
|
||||
t.Run("should populate allowed host env vars", func(t *testing.T) {
|
||||
// Set all allowed variables
|
||||
@@ -418,7 +418,7 @@ func TestPluginEnvVarsProvider_tracingEnvironmentVariables(t *testing.T) {
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
p := NewEnvVarsProvider(tc.cfg, nil)
|
||||
p := NewEnvVarsProvider(tc.cfg, nil, &fakeSSOSettingsProvider{})
|
||||
envVars := p.PluginEnvVars(context.Background(), tc.plugin)
|
||||
tc.exp(t, envVars)
|
||||
})
|
||||
@@ -473,7 +473,7 @@ func TestPluginEnvVarsProvider_authEnvVars(t *testing.T) {
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
provider := NewEnvVarsProvider(pCfg, nil)
|
||||
provider := NewEnvVarsProvider(pCfg, nil, &fakeSSOSettingsProvider{})
|
||||
envVars := provider.PluginEnvVars(context.Background(), p)
|
||||
assert.Equal(t, "GF_VERSION=", envVars[0])
|
||||
assert.Equal(t, "GF_APP_URL=https://myorg.com/", envVars[1])
|
||||
@@ -521,7 +521,7 @@ func TestPluginEnvVarsProvider_awsEnvVars(t *testing.T) {
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
}
|
||||
|
||||
provider := NewEnvVarsProvider(cfg, nil)
|
||||
provider := NewEnvVarsProvider(cfg, nil, &fakeSSOSettingsProvider{})
|
||||
envVars := provider.PluginEnvVars(context.Background(), p)
|
||||
assert.ElementsMatch(t, tc.expected, envVars)
|
||||
}
|
||||
@@ -540,7 +540,7 @@ func TestPluginEnvVarsProvider_featureToggleEnvVar(t *testing.T) {
|
||||
Features: featuremgmt.WithFeatures(expectedFeatures[0], true, expectedFeatures[1], true),
|
||||
}
|
||||
|
||||
p := NewEnvVarsProvider(cfg, nil)
|
||||
p := NewEnvVarsProvider(cfg, nil, &fakeSSOSettingsProvider{})
|
||||
envVars := p.PluginEnvVars(context.Background(), &plugins.Plugin{})
|
||||
assert.Equal(t, 2, len(envVars))
|
||||
|
||||
@@ -591,7 +591,7 @@ func TestPluginEnvVarsProvider_azureEnvVars(t *testing.T) {
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
provider := NewEnvVarsProvider(pCfg, nil)
|
||||
provider := NewEnvVarsProvider(pCfg, nil, &fakeSSOSettingsProvider{})
|
||||
envVars := provider.PluginEnvVars(context.Background(), &plugins.Plugin{})
|
||||
assert.ElementsMatch(t, []string{"GF_VERSION=", "GFAZPL_AZURE_CLOUD=AzureCloud", "GFAZPL_AZURE_AUTH_ENABLED=true",
|
||||
"GFAZPL_MANAGED_IDENTITY_ENABLED=true",
|
||||
@@ -608,4 +608,113 @@ func TestPluginEnvVarsProvider_azureEnvVars(t *testing.T) {
|
||||
"GFAZPL_USER_IDENTITY_ASSERTION=username",
|
||||
}, envVars)
|
||||
})
|
||||
|
||||
t.Run("sets user token endpoint settings from SSO settings for an Azure plugin", func(t *testing.T) {
|
||||
cfg := &setting.Cfg{
|
||||
Raw: ini.Empty(),
|
||||
Azure: &azsettings.AzureSettings{
|
||||
AzureAuthEnabled: true,
|
||||
Cloud: azsettings.AzurePublic,
|
||||
ManagedIdentityEnabled: true,
|
||||
ManagedIdentityClientId: "mock_managed_identity_client_id",
|
||||
WorkloadIdentityEnabled: true,
|
||||
WorkloadIdentitySettings: &azsettings.WorkloadIdentitySettings{
|
||||
TenantId: "mock_workload_identity_tenant_id",
|
||||
ClientId: "mock_workload_identity_client_id",
|
||||
TokenFile: "mock_workload_identity_token_file",
|
||||
},
|
||||
UserIdentityEnabled: true,
|
||||
UserIdentityFallbackCredentialsEnabled: true,
|
||||
UserIdentityTokenEndpoint: &azsettings.TokenEndpointSettings{
|
||||
TokenUrl: "mock_user_identity_token_url",
|
||||
ClientId: "mock_user_identity_client_id",
|
||||
ClientSecret: "mock_user_identity_client_secret",
|
||||
UsernameAssertion: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
provider := NewEnvVarsProvider(pCfg, nil, &fakeSSOSettingsProvider{
|
||||
GetForProviderFunc: getAzureSSOSettings,
|
||||
})
|
||||
envVars := provider.PluginEnvVars(context.Background(), &plugins.Plugin{})
|
||||
assert.ElementsMatch(t, []string{"GF_VERSION=", "GFAZPL_AZURE_CLOUD=AzureCloud", "GFAZPL_AZURE_AUTH_ENABLED=true",
|
||||
"GFAZPL_MANAGED_IDENTITY_ENABLED=true",
|
||||
"GFAZPL_MANAGED_IDENTITY_CLIENT_ID=mock_managed_identity_client_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_ENABLED=true",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_TENANT_ID=mock_workload_identity_tenant_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_CLIENT_ID=mock_workload_identity_client_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_TOKEN_FILE=mock_workload_identity_token_file",
|
||||
"GFAZPL_USER_IDENTITY_ENABLED=true",
|
||||
"GFAZPL_USER_IDENTITY_FALLBACK_SERVICE_CREDENTIALS_ENABLED=true",
|
||||
"GFAZPL_USER_IDENTITY_TOKEN_URL=sso_user_identity_token_url",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_AUTHENTICATION=sso_user_client_authentication",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_ID=sso_user_identity_client_id",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_SECRET=sso_user_identity_client_secret",
|
||||
"GFAZPL_USER_IDENTITY_MANAGED_IDENTITY_CLIENT_ID=sso_user_identity_managed_identity_client_id",
|
||||
"GFAZPL_USER_IDENTITY_FEDERATED_CREDENTIAL_AUDIENCE=sso_user_identity_federated_credential_audience",
|
||||
"GFAZPL_USER_IDENTITY_ASSERTION=username",
|
||||
}, envVars)
|
||||
})
|
||||
|
||||
t.Run("does not use SSO settings if overrides have been set for an Azure plugin", func(t *testing.T) {
|
||||
cfg := &setting.Cfg{
|
||||
Raw: ini.Empty(),
|
||||
Azure: &azsettings.AzureSettings{
|
||||
AzureAuthEnabled: true,
|
||||
Cloud: azsettings.AzurePublic,
|
||||
ManagedIdentityEnabled: true,
|
||||
ManagedIdentityClientId: "mock_managed_identity_client_id",
|
||||
WorkloadIdentityEnabled: true,
|
||||
WorkloadIdentitySettings: &azsettings.WorkloadIdentitySettings{
|
||||
TenantId: "mock_workload_identity_tenant_id",
|
||||
ClientId: "mock_workload_identity_client_id",
|
||||
TokenFile: "mock_workload_identity_token_file",
|
||||
},
|
||||
UserIdentityEnabled: true,
|
||||
UserIdentityFallbackCredentialsEnabled: true,
|
||||
UserIdentityTokenEndpoint: &azsettings.TokenEndpointSettings{
|
||||
TokenUrl: "override_user_identity_token_url",
|
||||
TokenUrlOverride: true,
|
||||
ClientAuthentication: "override_user_client_authentication",
|
||||
ClientAuthenticationOverride: true,
|
||||
ClientId: "override_user_identity_client_id",
|
||||
ClientIdOverride: true,
|
||||
ClientSecret: "override_user_identity_client_secret",
|
||||
ClientSecretOverride: true,
|
||||
ManagedIdentityClientId: "override_user_identity_managed_identity_client_id",
|
||||
ManagedIdentityClientIdOverride: true,
|
||||
FederatedCredentialAudience: "override_user_identity_federated_credential_audience",
|
||||
FederatedCredentialAudienceOverride: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
provider := NewEnvVarsProvider(pCfg, nil, &fakeSSOSettingsProvider{
|
||||
GetForProviderFunc: getAzureSSOSettings,
|
||||
})
|
||||
envVars := provider.PluginEnvVars(context.Background(), &plugins.Plugin{})
|
||||
assert.ElementsMatch(t, []string{"GF_VERSION=", "GFAZPL_AZURE_CLOUD=AzureCloud", "GFAZPL_AZURE_AUTH_ENABLED=true",
|
||||
"GFAZPL_MANAGED_IDENTITY_ENABLED=true",
|
||||
"GFAZPL_MANAGED_IDENTITY_CLIENT_ID=mock_managed_identity_client_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_ENABLED=true",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_TENANT_ID=mock_workload_identity_tenant_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_CLIENT_ID=mock_workload_identity_client_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_TOKEN_FILE=mock_workload_identity_token_file",
|
||||
"GFAZPL_USER_IDENTITY_ENABLED=true",
|
||||
"GFAZPL_USER_IDENTITY_FALLBACK_SERVICE_CREDENTIALS_ENABLED=true",
|
||||
"GFAZPL_USER_IDENTITY_TOKEN_URL=override_user_identity_token_url",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_AUTHENTICATION=override_user_client_authentication",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_ID=override_user_identity_client_id",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_SECRET=override_user_identity_client_secret",
|
||||
"GFAZPL_USER_IDENTITY_MANAGED_IDENTITY_CLIENT_ID=override_user_identity_managed_identity_client_id",
|
||||
"GFAZPL_USER_IDENTITY_FEDERATED_CREDENTIAL_AUDIENCE=override_user_identity_federated_credential_audience",
|
||||
}, envVars)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,11 +9,14 @@ import (
|
||||
|
||||
"github.com/grafana/grafana-aws-sdk/pkg/awsds"
|
||||
"github.com/grafana/grafana-azure-sdk-go/v2/azsettings"
|
||||
"github.com/grafana/grafana/pkg/plugins/auth"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/proxy"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/experimental/featuretoggles"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/plugins/auth"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsso"
|
||||
)
|
||||
|
||||
var _ PluginRequestConfigProvider = (*RequestConfigProvider)(nil)
|
||||
@@ -23,12 +26,16 @@ type PluginRequestConfigProvider interface {
|
||||
}
|
||||
|
||||
type RequestConfigProvider struct {
|
||||
cfg *PluginInstanceCfg
|
||||
cfg *PluginInstanceCfg
|
||||
ssoSettings pluginsso.SettingsProvider
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
func NewRequestConfigProvider(cfg *PluginInstanceCfg) *RequestConfigProvider {
|
||||
func NewRequestConfigProvider(cfg *PluginInstanceCfg, ssoSettings pluginsso.SettingsProvider) *RequestConfigProvider {
|
||||
return &RequestConfigProvider{
|
||||
cfg: cfg,
|
||||
cfg: cfg,
|
||||
ssoSettings: ssoSettings,
|
||||
logger: log.New("pluginrequestconfig"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,8 +96,19 @@ func (s *RequestConfigProvider) PluginRequestConfig(ctx context.Context, pluginI
|
||||
if s.cfg.AzureAuthEnabled {
|
||||
m[azsettings.AzureAuthEnabled] = strconv.FormatBool(s.cfg.AzureAuthEnabled)
|
||||
}
|
||||
|
||||
azureSettings := s.cfg.Azure
|
||||
if azureSettings != nil && slices.Contains[[]string, string](azureSettings.ForwardSettingsPlugins, pluginID) {
|
||||
if azureSettings == nil {
|
||||
azureSettings = &azsettings.AzureSettings{}
|
||||
}
|
||||
|
||||
if slices.Contains(azureSettings.ForwardSettingsPlugins, pluginID) {
|
||||
azureAdSettings, err := s.ssoSettings.GetForProvider(ctx, social.AzureADProviderName)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get SSO settings", "error", err)
|
||||
}
|
||||
azureSettings = mergeAzureSettings(azureSettings, azureAdSettings)
|
||||
|
||||
if azureSettings.Cloud != "" {
|
||||
m[azsettings.AzureCloud] = azureSettings.Cloud
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins/auth"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsso"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -19,7 +20,7 @@ func TestRequestConfigProvider_PluginRequestConfig_Defaults(t *testing.T) {
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.Equal(t, map[string]string{
|
||||
"GF_SQL_MAX_OPEN_CONNS_DEFAULT": "0",
|
||||
"GF_SQL_MAX_IDLE_CONNS_DEFAULT": "0",
|
||||
@@ -133,7 +134,7 @@ func TestRequestConfigProvider_PluginRequestConfig(t *testing.T) {
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
p := NewRequestConfigProvider(tc.cfg)
|
||||
p := NewRequestConfigProvider(tc.cfg, &fakeSSOSettingsProvider{})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), tc.expected)
|
||||
})
|
||||
}
|
||||
@@ -168,7 +169,7 @@ func TestRequestConfigProvider_PluginRequestConfig_featureToggles(t *testing.T)
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), tc.features)
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), tc.expectedConfig)
|
||||
}
|
||||
})
|
||||
@@ -182,7 +183,7 @@ func TestRequestConfigProvider_PluginRequestConfig_appURL(t *testing.T) {
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), map[string]string{"GF_APP_URL": "https://myorg.com/"})
|
||||
})
|
||||
}
|
||||
@@ -198,7 +199,7 @@ func TestRequestConfigProvider_PluginRequestConfig_SQL(t *testing.T) {
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), map[string]string{
|
||||
"GF_SQL_ROW_LIMIT": "23",
|
||||
"GF_SQL_MAX_OPEN_CONNS_DEFAULT": "24",
|
||||
@@ -216,7 +217,7 @@ func TestRequestConfigProvider_PluginRequestConfig_SQL(t *testing.T) {
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.Equal(t, map[string]string{
|
||||
"GF_SQL_MAX_OPEN_CONNS_DEFAULT": "0",
|
||||
"GF_SQL_MAX_IDLE_CONNS_DEFAULT": "0",
|
||||
@@ -233,7 +234,7 @@ func TestRequestConfigProvider_PluginRequestConfig_concurrentQueryCount(t *testi
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), map[string]string{"GF_CONCURRENT_QUERY_COUNT": "42"})
|
||||
})
|
||||
|
||||
@@ -242,7 +243,7 @@ func TestRequestConfigProvider_PluginRequestConfig_concurrentQueryCount(t *testi
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.NotContains(t, p.PluginRequestConfig(context.Background(), "", nil), "GF_CONCURRENT_QUERY_COUNT")
|
||||
})
|
||||
|
||||
@@ -253,7 +254,7 @@ func TestRequestConfigProvider_PluginRequestConfig_concurrentQueryCount(t *testi
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.NotContains(t, p.PluginRequestConfig(context.Background(), "", nil), "GF_CONCURRENT_QUERY_COUNT")
|
||||
})
|
||||
}
|
||||
@@ -265,7 +266,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azureAuthEnabled(t *testing.T
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
}
|
||||
|
||||
p := NewRequestConfigProvider(cfg)
|
||||
p := NewRequestConfigProvider(cfg, &fakeSSOSettingsProvider{})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), map[string]string{"GFAZPL_AZURE_AUTH_ENABLED": "true"})
|
||||
})
|
||||
|
||||
@@ -274,7 +275,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azureAuthEnabled(t *testing.T
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
}
|
||||
|
||||
p := NewRequestConfigProvider(cfg)
|
||||
p := NewRequestConfigProvider(cfg, &fakeSSOSettingsProvider{})
|
||||
require.NotContains(t, p.PluginRequestConfig(context.Background(), "", nil), "GFAZPL_AZURE_AUTH_ENABLED")
|
||||
})
|
||||
|
||||
@@ -284,7 +285,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azureAuthEnabled(t *testing.T
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
}
|
||||
|
||||
p := NewRequestConfigProvider(cfg)
|
||||
p := NewRequestConfigProvider(cfg, &fakeSSOSettingsProvider{})
|
||||
require.NotContains(t, p.PluginRequestConfig(context.Background(), "", nil), "GFAZPL_AZURE_AUTH_ENABLED")
|
||||
})
|
||||
}
|
||||
@@ -322,7 +323,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azure(t *testing.T) {
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "grafana-azure-monitor-datasource", nil), map[string]string{
|
||||
"GFAZPL_AZURE_CLOUD": "AzureCloud", "GFAZPL_MANAGED_IDENTITY_ENABLED": "true",
|
||||
"GFAZPL_MANAGED_IDENTITY_CLIENT_ID": "mock_managed_identity_client_id",
|
||||
@@ -356,7 +357,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azure(t *testing.T) {
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "grafana-azure-monitor-datasource", nil), map[string]string{
|
||||
"GFAZPL_AZURE_CLOUD": "AzureCloud", "GFAZPL_MANAGED_IDENTITY_ENABLED": "true",
|
||||
"GFAZPL_MANAGED_IDENTITY_CLIENT_ID": "mock_managed_identity_client_id",
|
||||
@@ -384,7 +385,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azure(t *testing.T) {
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
m := p.PluginRequestConfig(context.Background(), "", nil)
|
||||
require.NotContains(t, m, "GFAZPL_AZURE_CLOUD")
|
||||
require.NotContains(t, m, "GFAZPL_MANAGED_IDENTITY_ENABLED")
|
||||
@@ -413,7 +414,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azure(t *testing.T) {
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "test-datasource", nil), map[string]string{
|
||||
"GFAZPL_AZURE_CLOUD": "AzureCloud", "GFAZPL_MANAGED_IDENTITY_ENABLED": "true",
|
||||
"GFAZPL_MANAGED_IDENTITY_CLIENT_ID": "mock_managed_identity_client_id",
|
||||
@@ -433,6 +434,108 @@ func TestRequestConfigProvider_PluginRequestConfig_azure(t *testing.T) {
|
||||
"GFAZPL_AZURE_ENTRA_PASSWORD_CREDENTIALS_ENABLED": "true",
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("sets user token endpoint settings from SSO settings for an Azure plugin", func(t *testing.T) {
|
||||
cfg := setting.NewCfg()
|
||||
cfg.Azure = azSettings
|
||||
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{
|
||||
GetForProviderFunc: getAzureSSOSettings,
|
||||
})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "grafana-azure-monitor-datasource", nil), map[string]string{
|
||||
"GFAZPL_AZURE_CLOUD": "AzureCloud", "GFAZPL_MANAGED_IDENTITY_ENABLED": "true",
|
||||
"GFAZPL_MANAGED_IDENTITY_CLIENT_ID": "mock_managed_identity_client_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_ENABLED": "true",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_TENANT_ID": "mock_workload_identity_tenant_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_CLIENT_ID": "mock_workload_identity_client_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_TOKEN_FILE": "mock_workload_identity_token_file",
|
||||
"GFAZPL_USER_IDENTITY_ENABLED": "true",
|
||||
"GFAZPL_USER_IDENTITY_FALLBACK_SERVICE_CREDENTIALS_ENABLED": "true",
|
||||
"GFAZPL_USER_IDENTITY_TOKEN_URL": "sso_user_identity_token_url",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_AUTHENTICATION": "sso_user_client_authentication",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_ID": "sso_user_identity_client_id",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_SECRET": "sso_user_identity_client_secret",
|
||||
"GFAZPL_USER_IDENTITY_MANAGED_IDENTITY_CLIENT_ID": "sso_user_identity_managed_identity_client_id",
|
||||
"GFAZPL_USER_IDENTITY_FEDERATED_CREDENTIAL_AUDIENCE": "sso_user_identity_federated_credential_audience",
|
||||
"GFAZPL_USER_IDENTITY_ASSERTION": "username",
|
||||
"GFAZPL_AZURE_ENTRA_PASSWORD_CREDENTIALS_ENABLED": "true",
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("does not use SSO settings if overrides have been set for an Azure plugin", func(t *testing.T) {
|
||||
cfg := setting.NewCfg()
|
||||
cfg.Azure = &azsettings.AzureSettings{
|
||||
Cloud: azsettings.AzurePublic,
|
||||
ManagedIdentityEnabled: true,
|
||||
ManagedIdentityClientId: "mock_managed_identity_client_id",
|
||||
WorkloadIdentityEnabled: true,
|
||||
WorkloadIdentitySettings: &azsettings.WorkloadIdentitySettings{
|
||||
TenantId: "mock_workload_identity_tenant_id",
|
||||
ClientId: "mock_workload_identity_client_id",
|
||||
TokenFile: "mock_workload_identity_token_file",
|
||||
},
|
||||
UserIdentityEnabled: true,
|
||||
UserIdentityTokenEndpoint: &azsettings.TokenEndpointSettings{
|
||||
TokenUrl: "override_user_identity_token_url",
|
||||
TokenUrlOverride: true,
|
||||
ClientAuthentication: "override_user_client_authentication",
|
||||
ClientAuthenticationOverride: true,
|
||||
ClientId: "override_user_identity_client_id",
|
||||
ClientIdOverride: true,
|
||||
ClientSecret: "override_user_identity_client_secret",
|
||||
ClientSecretOverride: true,
|
||||
ManagedIdentityClientId: "override_user_identity_managed_identity_client_id",
|
||||
ManagedIdentityClientIdOverride: true,
|
||||
FederatedCredentialAudience: "override_user_identity_federated_credential_audience",
|
||||
FederatedCredentialAudienceOverride: true,
|
||||
UsernameAssertion: true,
|
||||
},
|
||||
UserIdentityFallbackCredentialsEnabled: true,
|
||||
ForwardSettingsPlugins: []string{"grafana-azure-monitor-datasource", "prometheus", "grafana-azure-data-explorer-datasource", "mssql", "grafana-azureprometheus-datasource"},
|
||||
AzureEntraPasswordCredentialsEnabled: true,
|
||||
}
|
||||
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{
|
||||
GetForProviderFunc: getAzureSSOSettings,
|
||||
})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "grafana-azure-monitor-datasource", nil), map[string]string{
|
||||
"GFAZPL_AZURE_CLOUD": "AzureCloud", "GFAZPL_MANAGED_IDENTITY_ENABLED": "true",
|
||||
"GFAZPL_MANAGED_IDENTITY_CLIENT_ID": "mock_managed_identity_client_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_ENABLED": "true",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_TENANT_ID": "mock_workload_identity_tenant_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_CLIENT_ID": "mock_workload_identity_client_id",
|
||||
"GFAZPL_WORKLOAD_IDENTITY_TOKEN_FILE": "mock_workload_identity_token_file",
|
||||
"GFAZPL_USER_IDENTITY_ENABLED": "true",
|
||||
"GFAZPL_USER_IDENTITY_FALLBACK_SERVICE_CREDENTIALS_ENABLED": "true",
|
||||
"GFAZPL_USER_IDENTITY_TOKEN_URL": "override_user_identity_token_url",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_AUTHENTICATION": "override_user_client_authentication",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_ID": "override_user_identity_client_id",
|
||||
"GFAZPL_USER_IDENTITY_CLIENT_SECRET": "override_user_identity_client_secret",
|
||||
"GFAZPL_USER_IDENTITY_MANAGED_IDENTITY_CLIENT_ID": "override_user_identity_managed_identity_client_id",
|
||||
"GFAZPL_USER_IDENTITY_FEDERATED_CREDENTIAL_AUDIENCE": "override_user_identity_federated_credential_audience",
|
||||
"GFAZPL_USER_IDENTITY_ASSERTION": "username",
|
||||
"GFAZPL_AZURE_ENTRA_PASSWORD_CREDENTIALS_ENABLED": "true",
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func getAzureSSOSettings(ctx context.Context, provider string) (*pluginsso.Settings, error) {
|
||||
return &pluginsso.Settings{
|
||||
Values: map[string]any{
|
||||
"token_url": "sso_user_identity_token_url",
|
||||
"client_authentication": "sso_user_client_authentication",
|
||||
"client_id": "sso_user_identity_client_id",
|
||||
"client_secret": "sso_user_identity_client_secret",
|
||||
"managed_identity_client_id": "sso_user_identity_managed_identity_client_id",
|
||||
"federated_credential_audience": "sso_user_identity_federated_credential_audience",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestRequestConfigProvider_PluginRequestConfig_aws(t *testing.T) {
|
||||
@@ -447,7 +550,7 @@ func TestRequestConfigProvider_PluginRequestConfig_aws(t *testing.T) {
|
||||
cfg.AWSListMetricsPageLimit = "100"
|
||||
cfg.AWSForwardSettingsPlugins = []string{"cloudwatch", "prometheus", "elasticsearch"}
|
||||
|
||||
p := NewRequestConfigProvider(cfg)
|
||||
p := NewRequestConfigProvider(cfg, &fakeSSOSettingsProvider{})
|
||||
|
||||
t.Run("uses the aws settings for an AWS plugin", func(t *testing.T) {
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "cloudwatch", nil), map[string]string{
|
||||
@@ -471,7 +574,7 @@ func TestRequestConfigProvider_PluginRequestConfig_aws(t *testing.T) {
|
||||
t.Run("uses the aws settings for a non-aws user-specified plugin", func(t *testing.T) {
|
||||
cfg.AWSForwardSettingsPlugins = append(cfg.AWSForwardSettingsPlugins, "test-datasource")
|
||||
|
||||
p = NewRequestConfigProvider(cfg)
|
||||
p = NewRequestConfigProvider(cfg, &fakeSSOSettingsProvider{})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "test-datasource", nil), map[string]string{
|
||||
"AWS_AUTH_AssumeRoleEnabled": "false",
|
||||
"AWS_AUTH_AllowedAuthProviders": "grafana_assume_role,keys",
|
||||
@@ -489,9 +592,20 @@ func TestRequestConfigProvider_PluginRequestConfig_appClientSecret(t *testing.T)
|
||||
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
|
||||
require.NoError(t, err)
|
||||
|
||||
p := NewRequestConfigProvider(pCfg)
|
||||
p := NewRequestConfigProvider(pCfg, &fakeSSOSettingsProvider{})
|
||||
require.Subset(t, p.PluginRequestConfig(context.Background(), "", &auth.ExternalService{
|
||||
ClientSecret: "mysecret",
|
||||
}), map[string]string{backend.AppClientSecret: "mysecret"})
|
||||
})
|
||||
}
|
||||
|
||||
type fakeSSOSettingsProvider struct {
|
||||
GetForProviderFunc func(ctx context.Context, provider string) (*pluginsso.Settings, error)
|
||||
}
|
||||
|
||||
func (m *fakeSSOSettingsProvider) GetForProvider(ctx context.Context, provider string) (*pluginsso.Settings, error) {
|
||||
if m.GetForProviderFunc != nil {
|
||||
return m.GetForProviderFunc(ctx, provider)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user