grafana/pkg/services/pluginsintegration/pluginconfig/envvars.go
Dave Henderson 6262c56132
chore(perf): Pre-allocate where possible (enable prealloc linter) (#88952)
* 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>
2024-06-14 14:16:36 -04:00

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)
}