Plugins: Expose ExternalService in request config (#85187)

This commit is contained in:
Andres Martinez Gotor 2024-04-03 09:22:34 +02:00 committed by GitHub
parent 1522499c4a
commit 9c7237891c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 50 additions and 25 deletions

View File

@ -1,6 +1,10 @@
package pluginconfig
import "context"
import (
"context"
"github.com/grafana/grafana/pkg/plugins/auth"
)
var _ PluginRequestConfigProvider = (*FakePluginRequestConfigProvider)(nil)
@ -11,6 +15,6 @@ func NewFakePluginRequestConfigProvider() *FakePluginRequestConfigProvider {
}
// PluginRequestConfig returns a map of configuration that should be passed in a plugin request.
func (s *FakePluginRequestConfigProvider) PluginRequestConfig(ctx context.Context, pluginID string) map[string]string {
func (s *FakePluginRequestConfigProvider) PluginRequestConfig(ctx context.Context, pluginID string, externalService *auth.ExternalService) map[string]string {
return map[string]string{}
}

View File

@ -9,6 +9,7 @@ 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"
@ -18,7 +19,7 @@ import (
var _ PluginRequestConfigProvider = (*RequestConfigProvider)(nil)
type PluginRequestConfigProvider interface {
PluginRequestConfig(ctx context.Context, pluginID string) map[string]string
PluginRequestConfig(ctx context.Context, pluginID string, externalService *auth.ExternalService) map[string]string
}
type RequestConfigProvider struct {
@ -33,7 +34,7 @@ func NewRequestConfigProvider(cfg *PluginInstanceCfg) *RequestConfigProvider {
// PluginRequestConfig returns a map of configuration that should be passed in a plugin request.
// nolint:gocyclo
func (s *RequestConfigProvider) PluginRequestConfig(ctx context.Context, pluginID string) map[string]string {
func (s *RequestConfigProvider) PluginRequestConfig(ctx context.Context, pluginID string, externalService *auth.ExternalService) map[string]string {
m := make(map[string]string)
if s.cfg.GrafanaAppURL != "" {
@ -160,5 +161,9 @@ func (s *RequestConfigProvider) PluginRequestConfig(ctx context.Context, pluginI
m[awsds.SigV4VerboseLoggingEnvVarKeyName] = strconv.FormatBool(s.cfg.SigV4VerboseLogging)
}
if externalService != nil {
m[backend.AppClientSecret] = externalService.ClientSecret
}
return m
}

View File

@ -7,7 +7,9 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana-azure-sdk-go/v2/azsettings"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins/auth"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/setting"
)
@ -22,7 +24,7 @@ func TestRequestConfigProvider_PluginRequestConfig_Defaults(t *testing.T) {
"GF_SQL_MAX_OPEN_CONNS_DEFAULT": "0",
"GF_SQL_MAX_IDLE_CONNS_DEFAULT": "0",
"GF_SQL_MAX_CONN_LIFETIME_SECONDS_DEFAULT": "0",
}, p.PluginRequestConfig(context.Background(), ""))
}, p.PluginRequestConfig(context.Background(), "", nil))
}
func TestRequestConfigProvider_PluginRequestConfig(t *testing.T) {
@ -132,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)
require.Subset(t, p.PluginRequestConfig(context.Background(), ""), tc.expected)
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), tc.expected)
})
}
}
@ -167,7 +169,7 @@ func TestRequestConfigProvider_PluginRequestConfig_featureToggles(t *testing.T)
require.NoError(t, err)
p := NewRequestConfigProvider(pCfg)
require.Subset(t, p.PluginRequestConfig(context.Background(), ""), tc.expectedConfig)
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), tc.expectedConfig)
}
})
}
@ -181,7 +183,7 @@ func TestRequestConfigProvider_PluginRequestConfig_appURL(t *testing.T) {
require.NoError(t, err)
p := NewRequestConfigProvider(pCfg)
require.Subset(t, p.PluginRequestConfig(context.Background(), ""), map[string]string{"GF_APP_URL": "https://myorg.com/"})
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), map[string]string{"GF_APP_URL": "https://myorg.com/"})
})
}
@ -197,7 +199,7 @@ func TestRequestConfigProvider_PluginRequestConfig_SQL(t *testing.T) {
require.NoError(t, err)
p := NewRequestConfigProvider(pCfg)
require.Subset(t, p.PluginRequestConfig(context.Background(), ""), map[string]string{
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), map[string]string{
"GF_SQL_ROW_LIMIT": "23",
"GF_SQL_MAX_OPEN_CONNS_DEFAULT": "24",
"GF_SQL_MAX_IDLE_CONNS_DEFAULT": "25",
@ -219,7 +221,7 @@ func TestRequestConfigProvider_PluginRequestConfig_SQL(t *testing.T) {
"GF_SQL_MAX_OPEN_CONNS_DEFAULT": "0",
"GF_SQL_MAX_IDLE_CONNS_DEFAULT": "0",
"GF_SQL_MAX_CONN_LIFETIME_SECONDS_DEFAULT": "0",
}, p.PluginRequestConfig(context.Background(), ""))
}, p.PluginRequestConfig(context.Background(), "", nil))
})
}
@ -232,7 +234,7 @@ func TestRequestConfigProvider_PluginRequestConfig_concurrentQueryCount(t *testi
require.NoError(t, err)
p := NewRequestConfigProvider(pCfg)
require.Subset(t, p.PluginRequestConfig(context.Background(), ""), map[string]string{"GF_CONCURRENT_QUERY_COUNT": "42"})
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), map[string]string{"GF_CONCURRENT_QUERY_COUNT": "42"})
})
t.Run("Doesn't set the concurrent query count if it is not in the config", func(t *testing.T) {
@ -241,7 +243,7 @@ func TestRequestConfigProvider_PluginRequestConfig_concurrentQueryCount(t *testi
require.NoError(t, err)
p := NewRequestConfigProvider(pCfg)
require.NotContains(t, p.PluginRequestConfig(context.Background(), ""), "GF_CONCURRENT_QUERY_COUNT")
require.NotContains(t, p.PluginRequestConfig(context.Background(), "", nil), "GF_CONCURRENT_QUERY_COUNT")
})
t.Run("Doesn't set the concurrent query count if it is zero", func(t *testing.T) {
@ -252,7 +254,7 @@ func TestRequestConfigProvider_PluginRequestConfig_concurrentQueryCount(t *testi
require.NoError(t, err)
p := NewRequestConfigProvider(pCfg)
require.NotContains(t, p.PluginRequestConfig(context.Background(), ""), "GF_CONCURRENT_QUERY_COUNT")
require.NotContains(t, p.PluginRequestConfig(context.Background(), "", nil), "GF_CONCURRENT_QUERY_COUNT")
})
}
@ -264,7 +266,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azureAuthEnabled(t *testing.T
}
p := NewRequestConfigProvider(cfg)
require.Subset(t, p.PluginRequestConfig(context.Background(), ""), map[string]string{"GFAZPL_AZURE_AUTH_ENABLED": "true"})
require.Subset(t, p.PluginRequestConfig(context.Background(), "", nil), map[string]string{"GFAZPL_AZURE_AUTH_ENABLED": "true"})
})
t.Run("Doesn't set the azureAuthEnabled if it is not in the config", func(t *testing.T) {
@ -273,7 +275,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azureAuthEnabled(t *testing.T
}
p := NewRequestConfigProvider(cfg)
require.NotContains(t, p.PluginRequestConfig(context.Background(), ""), "GFAZPL_AZURE_AUTH_ENABLED")
require.NotContains(t, p.PluginRequestConfig(context.Background(), "", nil), "GFAZPL_AZURE_AUTH_ENABLED")
})
t.Run("Doesn't set the azureAuthEnabled if it is false", func(t *testing.T) {
@ -283,7 +285,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azureAuthEnabled(t *testing.T
}
p := NewRequestConfigProvider(cfg)
require.NotContains(t, p.PluginRequestConfig(context.Background(), ""), "GFAZPL_AZURE_AUTH_ENABLED")
require.NotContains(t, p.PluginRequestConfig(context.Background(), "", nil), "GFAZPL_AZURE_AUTH_ENABLED")
})
}
@ -317,7 +319,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azure(t *testing.T) {
require.NoError(t, err)
p := NewRequestConfigProvider(pCfg)
require.Subset(t, p.PluginRequestConfig(context.Background(), "grafana-azure-monitor-datasource"), map[string]string{
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",
@ -341,7 +343,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azure(t *testing.T) {
require.NoError(t, err)
p := NewRequestConfigProvider(pCfg)
m := p.PluginRequestConfig(context.Background(), "")
m := p.PluginRequestConfig(context.Background(), "", nil)
require.NotContains(t, m, "GFAZPL_AZURE_CLOUD")
require.NotContains(t, m, "GFAZPL_MANAGED_IDENTITY_ENABLED")
require.NotContains(t, m, "GFAZPL_MANAGED_IDENTITY_CLIENT_ID")
@ -366,7 +368,7 @@ func TestRequestConfigProvider_PluginRequestConfig_azure(t *testing.T) {
require.NoError(t, err)
p := NewRequestConfigProvider(pCfg)
require.Subset(t, p.PluginRequestConfig(context.Background(), "test-datasource"), map[string]string{
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",
"GFAZPL_WORKLOAD_IDENTITY_ENABLED": "true",
@ -398,7 +400,7 @@ func TestRequestConfigProvider_PluginRequestConfig_aws(t *testing.T) {
p := NewRequestConfigProvider(cfg)
t.Run("uses the aws settings for an AWS plugin", func(t *testing.T) {
require.Subset(t, p.PluginRequestConfig(context.Background(), "cloudwatch"), map[string]string{
require.Subset(t, p.PluginRequestConfig(context.Background(), "cloudwatch", nil), map[string]string{
"AWS_AUTH_AssumeRoleEnabled": "false",
"AWS_AUTH_AllowedAuthProviders": "grafana_assume_role,keys",
"AWS_AUTH_EXTERNAL_ID": "mock_external_id",
@ -408,7 +410,7 @@ func TestRequestConfigProvider_PluginRequestConfig_aws(t *testing.T) {
})
t.Run("does not use the aws settings for a non-aws plugin", func(t *testing.T) {
m := p.PluginRequestConfig(context.Background(), "")
m := p.PluginRequestConfig(context.Background(), "", nil)
require.NotContains(t, m, "AWS_AUTH_AssumeRoleEnabled")
require.NotContains(t, m, "AWS_AUTH_AllowedAuthProviders")
require.NotContains(t, m, "AWS_AUTH_EXTERNAL_ID")
@ -420,7 +422,7 @@ func TestRequestConfigProvider_PluginRequestConfig_aws(t *testing.T) {
cfg.AWSForwardSettingsPlugins = append(cfg.AWSForwardSettingsPlugins, "test-datasource")
p = NewRequestConfigProvider(cfg)
require.Subset(t, p.PluginRequestConfig(context.Background(), "test-datasource"), map[string]string{
require.Subset(t, p.PluginRequestConfig(context.Background(), "test-datasource", nil), map[string]string{
"AWS_AUTH_AssumeRoleEnabled": "false",
"AWS_AUTH_AllowedAuthProviders": "grafana_assume_role,keys",
"AWS_AUTH_EXTERNAL_ID": "mock_external_id",
@ -429,3 +431,17 @@ func TestRequestConfigProvider_PluginRequestConfig_aws(t *testing.T) {
})
})
}
func TestRequestConfigProvider_PluginRequestConfig_appClientSecret(t *testing.T) {
t.Run("Uses the configured app URL", func(t *testing.T) {
cfg := setting.NewCfg()
pCfg, err := ProvidePluginInstanceConfig(cfg, setting.ProvideProvider(cfg), featuremgmt.WithFeatures())
require.NoError(t, err)
p := NewRequestConfigProvider(pCfg)
require.Subset(t, p.PluginRequestConfig(context.Background(), "", &auth.ExternalService{
ClientSecret: "mysecret",
}), map[string]string{backend.AppClientSecret: "mysecret"})
})
}

View File

@ -82,7 +82,7 @@ func (p *Provider) Get(ctx context.Context, pluginID string, user identity.Reque
pCtx.AppInstanceSettings = appSettings
}
settings := p.pluginRequestConfigProvider.PluginRequestConfig(ctx, pluginID)
settings := p.pluginRequestConfigProvider.PluginRequestConfig(ctx, pluginID, plugin.ExternalService)
pCtx.GrafanaConfig = backend.NewGrafanaCfg(settings)
ua, err := useragent.New(p.cfg.BuildVersion, runtime.GOOS, runtime.GOARCH)
@ -119,7 +119,7 @@ func (p *Provider) GetWithDataSource(ctx context.Context, pluginID string, user
}
pCtx.DataSourceInstanceSettings = datasourceSettings
settings := p.pluginRequestConfigProvider.PluginRequestConfig(ctx, pluginID)
settings := p.pluginRequestConfigProvider.PluginRequestConfig(ctx, pluginID, plugin.ExternalService)
pCtx.GrafanaConfig = backend.NewGrafanaCfg(settings)
ua, err := useragent.New(p.cfg.BuildVersion, runtime.GOOS, runtime.GOARCH)
@ -167,7 +167,7 @@ func (p *Provider) PluginContextForDataSource(ctx context.Context, datasourceSet
pCtx.DataSourceInstanceSettings = datasourceSettings
settings := p.pluginRequestConfigProvider.PluginRequestConfig(ctx, pluginID)
settings := p.pluginRequestConfigProvider.PluginRequestConfig(ctx, pluginID, plugin.ExternalService)
pCtx.GrafanaConfig = backend.NewGrafanaCfg(settings)
ua, err := useragent.New(p.cfg.BuildVersion, runtime.GOOS, runtime.GOARCH)