mirror of
https://github.com/grafana/grafana.git
synced 2025-01-16 11:42:35 -06:00
6262c56132
* chore(perf): Pre-allocate where possible (enable prealloc linter) Signed-off-by: Dave Henderson <dave.henderson@grafana.com> * fix TestAlertManagers_buildRedactedAMs Signed-off-by: Dave Henderson <dave.henderson@grafana.com> * prealloc a slice that appeared after rebase Signed-off-by: Dave Henderson <dave.henderson@grafana.com> --------- Signed-off-by: Dave Henderson <dave.henderson@grafana.com>
192 lines
6.4 KiB
Go
192 lines
6.4 KiB
Go
package pluginconfig
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/grafana/grafana-aws-sdk/pkg/awsds"
|
|
"github.com/grafana/grafana-azure-sdk-go/v2/azsettings"
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend/proxy"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/plugins"
|
|
"github.com/grafana/grafana/pkg/plugins/envvars"
|
|
)
|
|
|
|
var _ envvars.Provider = (*EnvVarsProvider)(nil)
|
|
|
|
type EnvVarsProvider struct {
|
|
cfg *PluginInstanceCfg
|
|
license plugins.Licensing
|
|
logger log.Logger
|
|
}
|
|
|
|
func NewEnvVarsProvider(cfg *PluginInstanceCfg, license plugins.Licensing) *EnvVarsProvider {
|
|
return &EnvVarsProvider{
|
|
cfg: cfg,
|
|
license: license,
|
|
logger: log.New("plugins.envvars"),
|
|
}
|
|
}
|
|
|
|
func (p *EnvVarsProvider) PluginEnvVars(ctx context.Context, plugin *plugins.Plugin) []string {
|
|
hostEnv := []string{
|
|
p.envVar("GF_VERSION", p.cfg.GrafanaVersion),
|
|
}
|
|
|
|
if p.license != nil {
|
|
hostEnv = append(
|
|
hostEnv,
|
|
p.envVar("GF_EDITION", p.license.Edition()),
|
|
p.envVar("GF_ENTERPRISE_LICENSE_PATH", p.license.Path()),
|
|
p.envVar("GF_ENTERPRISE_APP_URL", p.license.AppURL()),
|
|
)
|
|
hostEnv = append(hostEnv, p.license.Environment()...)
|
|
}
|
|
|
|
if plugin.ExternalService != nil {
|
|
hostEnv = append(
|
|
hostEnv,
|
|
p.envVar("GF_APP_URL", p.cfg.GrafanaAppURL),
|
|
p.envVar("GF_PLUGIN_APP_CLIENT_ID", plugin.ExternalService.ClientID),
|
|
p.envVar("GF_PLUGIN_APP_CLIENT_SECRET", plugin.ExternalService.ClientSecret),
|
|
)
|
|
if plugin.ExternalService.PrivateKey != "" {
|
|
hostEnv = append(hostEnv, p.envVar("GF_PLUGIN_APP_PRIVATE_KEY", plugin.ExternalService.PrivateKey))
|
|
}
|
|
}
|
|
|
|
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, p.tracingEnvVars(plugin)...)
|
|
hostEnv = append(hostEnv, p.pluginSettingsEnvVars(plugin.PluginID())...)
|
|
|
|
// If SkipHostEnvVars is enabled, get some allowed variables from the current process and pass
|
|
// them down to the plugin. If the flag is not set, do not add anything else because ALL env vars
|
|
// from the current process (os.Environ()) will be forwarded to the plugin's process by go-plugin
|
|
if plugin.SkipHostEnvVars {
|
|
hostEnv = append(hostEnv, envvars.PermittedHostEnvVars()...)
|
|
}
|
|
|
|
return hostEnv
|
|
}
|
|
|
|
func (p *EnvVarsProvider) featureToggleEnableVars(ctx context.Context) []string {
|
|
var variables []string // an array is used for consistency and keep the logic simpler for no features case
|
|
|
|
if p.cfg.Features == nil {
|
|
return variables
|
|
}
|
|
|
|
enabledFeatures := p.cfg.Features.GetEnabled(ctx)
|
|
if len(enabledFeatures) > 0 {
|
|
features := make([]string, 0, len(enabledFeatures))
|
|
for feat := range enabledFeatures {
|
|
features = append(features, feat)
|
|
}
|
|
variables = append(variables, p.envVar("GF_INSTANCE_FEATURE_TOGGLES_ENABLE", strings.Join(features, ",")))
|
|
}
|
|
|
|
return variables
|
|
}
|
|
|
|
func (p *EnvVarsProvider) awsEnvVars(pluginID string) []string {
|
|
if !slices.Contains[[]string, string](p.cfg.AWSForwardSettingsPlugins, pluginID) {
|
|
return []string{}
|
|
}
|
|
|
|
var variables []string
|
|
if !p.cfg.AWSAssumeRoleEnabled {
|
|
variables = append(variables, p.envVar(awsds.AssumeRoleEnabledEnvVarKeyName, "false"))
|
|
}
|
|
if len(p.cfg.AWSAllowedAuthProviders) > 0 {
|
|
variables = append(variables, p.envVar(awsds.AllowedAuthProvidersEnvVarKeyName, strings.Join(p.cfg.AWSAllowedAuthProviders, ",")))
|
|
}
|
|
if p.cfg.AWSExternalId != "" {
|
|
variables = append(variables, p.envVar(awsds.GrafanaAssumeRoleExternalIdKeyName, p.cfg.AWSExternalId))
|
|
}
|
|
if p.cfg.AWSSessionDuration != "" {
|
|
variables = append(variables, p.envVar(awsds.SessionDurationEnvVarKeyName, p.cfg.AWSSessionDuration))
|
|
}
|
|
if p.cfg.AWSListMetricsPageLimit != "" {
|
|
variables = append(variables, p.envVar(awsds.ListMetricsPageLimitKeyName, p.cfg.AWSListMetricsPageLimit))
|
|
}
|
|
|
|
return variables
|
|
}
|
|
|
|
func (p *EnvVarsProvider) secureSocksProxyEnvVars() []string {
|
|
if p.cfg.ProxySettings.Enabled {
|
|
return []string{
|
|
// nolint:staticcheck
|
|
p.envVar(proxy.PluginSecureSocksProxyClientCertFilePathEnvVarName, p.cfg.ProxySettings.ClientCertFilePath),
|
|
// nolint:staticcheck
|
|
p.envVar(proxy.PluginSecureSocksProxyClientKeyFilePathEnvVarName, p.cfg.ProxySettings.ClientKeyFilePath),
|
|
// nolint:staticcheck
|
|
p.envVar(proxy.PluginSecureSocksProxyRootCACertFilePathsEnvVarName, strings.Join(p.cfg.ProxySettings.RootCAFilePaths, " ")),
|
|
// nolint:staticcheck
|
|
p.envVar(proxy.PluginSecureSocksProxyAddressEnvVarName, p.cfg.ProxySettings.ProxyAddress),
|
|
// nolint:staticcheck
|
|
p.envVar(proxy.PluginSecureSocksProxyServerNameEnvVarName, p.cfg.ProxySettings.ServerName),
|
|
// nolint:staticcheck
|
|
p.envVar(proxy.PluginSecureSocksProxyEnabledEnvVarName, strconv.FormatBool(p.cfg.ProxySettings.Enabled)),
|
|
// nolint:staticcheck
|
|
p.envVar(proxy.PluginSecureSocksProxyAllowInsecureEnvVarName, strconv.FormatBool(p.cfg.ProxySettings.AllowInsecure)),
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *EnvVarsProvider) tracingEnvVars(plugin *plugins.Plugin) []string {
|
|
if !p.cfg.Tracing.IsEnabled() {
|
|
return nil
|
|
}
|
|
|
|
vars := []string{
|
|
p.envVar("GF_INSTANCE_OTLP_ADDRESS", p.cfg.Tracing.OpenTelemetry.Address),
|
|
p.envVar("GF_INSTANCE_OTLP_PROPAGATION", p.cfg.Tracing.OpenTelemetry.Propagation),
|
|
p.envVar("GF_INSTANCE_OTLP_SAMPLER_TYPE", p.cfg.Tracing.OpenTelemetry.Sampler),
|
|
fmt.Sprintf("GF_INSTANCE_OTLP_SAMPLER_PARAM=%.6f", p.cfg.Tracing.OpenTelemetry.SamplerParam),
|
|
p.envVar("GF_INSTANCE_OTLP_SAMPLER_REMOTE_URL", p.cfg.Tracing.OpenTelemetry.SamplerRemoteURL),
|
|
}
|
|
if plugin.Info.Version != "" {
|
|
vars = append(vars, fmt.Sprintf("GF_PLUGIN_VERSION=%s", plugin.Info.Version))
|
|
}
|
|
return vars
|
|
}
|
|
|
|
func (p *EnvVarsProvider) pluginSettingsEnvVars(pluginID string) []string {
|
|
const customConfigPrefix = "GF_PLUGIN"
|
|
|
|
pluginSettings := p.cfg.PluginSettings[pluginID]
|
|
|
|
env := make([]string, 0, len(pluginSettings))
|
|
for k, v := range pluginSettings {
|
|
if k == "path" || strings.ToLower(k) == "id" {
|
|
continue
|
|
}
|
|
|
|
key := fmt.Sprintf("%s_%s", customConfigPrefix, strings.ToUpper(k))
|
|
if value := os.Getenv(key); value != "" {
|
|
v = value
|
|
}
|
|
|
|
env = append(env, fmt.Sprintf("%s=%s", key, v))
|
|
}
|
|
|
|
return env
|
|
}
|
|
|
|
func (p *EnvVarsProvider) envVar(key, value string) string {
|
|
if strings.Contains(value, "\x00") {
|
|
p.logger.Error("Variable with key '%s' contains NUL", key)
|
|
}
|
|
return fmt.Sprintf("%s=%s", key, value)
|
|
}
|