Plugins: Include Azure settings as a part of Grafana config sent in plugin requests (#79342)

* Add Azure settings and update tests

* Filter by plugin ID

* Add forward settings config variable

* Update line

* Add tests

* Update so that data sources are fully defined in config

* Update SDK and test

* Fix lint

* Update docs/sources/setup-grafana/configure-grafana/_index.md

Co-authored-by: Andrew Hackmann <5140848+bossinc@users.noreply.github.com>

* Remove unnecessary if

---------

Co-authored-by: Andrew Hackmann <5140848+bossinc@users.noreply.github.com>
This commit is contained in:
Andreas Christou
2023-12-14 11:48:22 +00:00
committed by GitHub
co-authored by Andrew Hackmann
parent 31d79c0502
commit f3cdb44898
9 changed files with 228 additions and 45 deletions
+52 -35
View File
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"os"
"slices"
"sort"
"strconv"
"strings"
@@ -98,7 +99,7 @@ func (s *Service) Get(ctx context.Context, p *plugins.Plugin) []string {
}
// GetConfigMap returns a map of configuration that should be passed in a plugin request.
func (s *Service) GetConfigMap(ctx context.Context, _ string, _ *auth.ExternalService) map[string]string {
func (s *Service) GetConfigMap(ctx context.Context, pluginID string, _ *auth.ExternalService) map[string]string {
m := make(map[string]string)
if s.cfg.GrafanaAppURL != "" {
@@ -144,40 +145,56 @@ func (s *Service) GetConfigMap(ctx context.Context, _ string, _ *auth.ExternalSe
m[proxy.PluginSecureSocksProxyServerName] = s.cfg.ProxySettings.ServerName
}
// TODO add support via plugin SDK
//azureSettings := s.cfg.Azure
//if azureSettings != nil {
// if azureSettings.Cloud != "" {
// m[azsettings.AzureCloud] = azureSettings.Cloud
// }
//
// if azureSettings.ManagedIdentityEnabled {
// m[azsettings.ManagedIdentityEnabled] = "true"
//
// if azureSettings.ManagedIdentityClientId != "" {
// m[azsettings.ManagedIdentityClientID] = azureSettings.ManagedIdentityClientId
// }
// }
//
// if azureSettings.UserIdentityEnabled {
// m[azsettings.UserIdentityEnabled] = "true"
//
// if azureSettings.UserIdentityTokenEndpoint != nil {
// if azureSettings.UserIdentityTokenEndpoint.TokenUrl != "" {
// m[azsettings.UserIdentityTokenURL] = azureSettings.UserIdentityTokenEndpoint.TokenUrl
// }
// if azureSettings.UserIdentityTokenEndpoint.ClientId != "" {
// m[azsettings.UserIdentityClientID] = azureSettings.UserIdentityTokenEndpoint.ClientId
// }
// if azureSettings.UserIdentityTokenEndpoint.ClientSecret != "" {
// m[azsettings.UserIdentityClientSecret] = azureSettings.UserIdentityTokenEndpoint.ClientSecret
// }
// if azureSettings.UserIdentityTokenEndpoint.UsernameAssertion {
// m[azsettings.UserIdentityAssertion] = "username"
// }
// }
// }
//}
// Settings here will be extracted by grafana-azure-sdk-go from the plugin context
azureSettings := s.cfg.Azure
if azureSettings != nil && slices.Contains[[]string, string](azureSettings.ForwardSettingsPlugins, pluginID) {
if azureSettings.Cloud != "" {
m[azsettings.AzureCloud] = azureSettings.Cloud
}
if azureSettings.ManagedIdentityEnabled {
m[azsettings.ManagedIdentityEnabled] = "true"
if azureSettings.ManagedIdentityClientId != "" {
m[azsettings.ManagedIdentityClientID] = azureSettings.ManagedIdentityClientId
}
}
if azureSettings.UserIdentityEnabled {
m[azsettings.UserIdentityEnabled] = "true"
if azureSettings.UserIdentityTokenEndpoint != nil {
if azureSettings.UserIdentityTokenEndpoint.TokenUrl != "" {
m[azsettings.UserIdentityTokenURL] = azureSettings.UserIdentityTokenEndpoint.TokenUrl
}
if azureSettings.UserIdentityTokenEndpoint.ClientId != "" {
m[azsettings.UserIdentityClientID] = azureSettings.UserIdentityTokenEndpoint.ClientId
}
if azureSettings.UserIdentityTokenEndpoint.ClientSecret != "" {
m[azsettings.UserIdentityClientSecret] = azureSettings.UserIdentityTokenEndpoint.ClientSecret
}
if azureSettings.UserIdentityTokenEndpoint.UsernameAssertion {
m[azsettings.UserIdentityAssertion] = "username"
}
}
}
if azureSettings.WorkloadIdentityEnabled {
m[azsettings.WorkloadIdentityEnabled] = "true"
if azureSettings.WorkloadIdentitySettings != nil {
if azureSettings.WorkloadIdentitySettings.ClientId != "" {
m[azsettings.WorkloadIdentityClientID] = azureSettings.WorkloadIdentitySettings.ClientId
}
if azureSettings.WorkloadIdentitySettings.TenantId != "" {
m[azsettings.WorkloadIdentityTenantID] = azureSettings.WorkloadIdentitySettings.TenantId
}
if azureSettings.WorkloadIdentitySettings.TokenFile != "" {
m[azsettings.WorkloadIdentityTokenFile] = azureSettings.WorkloadIdentitySettings.TokenFile
}
}
}
}
// TODO add support via plugin SDK
//ps := getPluginSettings(pluginID, s.cfg)
+114
View File
@@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana-azure-sdk-go/azsettings"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/auth"
"github.com/grafana/grafana/pkg/plugins/config"
@@ -598,6 +599,45 @@ func TestInitializer_featureToggleEnvVar(t *testing.T) {
})
}
func TestInitalizer_azureEnvVars(t *testing.T) {
t.Run("backend datasource with azure settings", func(t *testing.T) {
p := &plugins.Plugin{}
envVarsProvider := NewProvider(&config.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: "mock_user_identity_token_url",
ClientId: "mock_user_identity_client_id",
ClientSecret: "mock_user_identity_client_secret",
UsernameAssertion: true,
},
},
}, nil)
envVars := envVarsProvider.Get(context.Background(), p)
assert.ElementsMatch(t, []string{"GF_VERSION=", "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_TOKEN_URL=mock_user_identity_token_url",
"GFAZPL_USER_IDENTITY_CLIENT_ID=mock_user_identity_client_id",
"GFAZPL_USER_IDENTITY_CLIENT_SECRET=mock_user_identity_client_secret",
"GFAZPL_USER_IDENTITY_ASSERTION=username",
}, envVars)
})
}
func TestService_GetConfigMap(t *testing.T) {
tcs := []struct {
name string
@@ -730,3 +770,77 @@ func TestService_GetConfigMap_appURL(t *testing.T) {
require.Equal(t, map[string]string{"GF_APP_URL": "https://myorg.com/"}, s.GetConfigMap(context.Background(), "", nil))
})
}
func TestService_GetConfigMap_azure(t *testing.T) {
azSettings := &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: "mock_user_identity_token_url",
ClientId: "mock_user_identity_client_id",
ClientSecret: "mock_user_identity_client_secret",
UsernameAssertion: true,
},
ForwardSettingsPlugins: []string{"grafana-azure-monitor-datasource", "prometheus", "grafana-azure-data-explorer-datasource", "mssql"},
}
t.Run("uses the azure settings for an Azure plugin", func(t *testing.T) {
s := &Service{
cfg: &config.Cfg{
Azure: azSettings,
},
}
require.Equal(t, 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_TOKEN_URL": "mock_user_identity_token_url",
"GFAZPL_USER_IDENTITY_CLIENT_ID": "mock_user_identity_client_id",
"GFAZPL_USER_IDENTITY_CLIENT_SECRET": "mock_user_identity_client_secret",
"GFAZPL_USER_IDENTITY_ASSERTION": "username",
}, s.GetConfigMap(context.Background(), "grafana-azure-monitor-datasource", nil))
})
t.Run("does not use the azure settings for a non-Azure plugin", func(t *testing.T) {
s := &Service{
cfg: &config.Cfg{
Azure: azSettings,
},
}
require.Equal(t, map[string]string{}, s.GetConfigMap(context.Background(), "", nil))
})
t.Run("uses the azure settings for a non-Azure user-specified plugin", func(t *testing.T) {
azSettings.ForwardSettingsPlugins = append(azSettings.ForwardSettingsPlugins, "test-datasource")
s := &Service{
cfg: &config.Cfg{
Azure: azSettings,
},
}
require.Equal(t, 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_TOKEN_URL": "mock_user_identity_token_url",
"GFAZPL_USER_IDENTITY_CLIENT_ID": "mock_user_identity_client_id",
"GFAZPL_USER_IDENTITY_CLIENT_SECRET": "mock_user_identity_client_secret",
"GFAZPL_USER_IDENTITY_ASSERTION": "username",
}, s.GetConfigMap(context.Background(), "test-datasource", nil))
})
}