mirror of
https://github.com/grafana/grafana.git
synced 2024-11-27 19:30:36 -06:00
6945f1c483
* provide public getter for config template variable regex * add code comment * Add documentation on assertion_name_mapping templates * Add missing piece of SAML documentation while I'm in here. * Update docs/sources/enterprise/saml/configure-saml.md Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com> * Add a bit more documentation on error handling. Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com>
155 lines
3.2 KiB
Go
155 lines
3.2 KiB
Go
package setting
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"regexp"
|
|
"sort"
|
|
"strings"
|
|
|
|
"gopkg.in/ini.v1"
|
|
)
|
|
|
|
type Expander interface {
|
|
SetupExpander(file *ini.File) error
|
|
Expand(string) (string, error)
|
|
}
|
|
|
|
type registeredExpander struct {
|
|
name string
|
|
priority int64
|
|
expander Expander
|
|
}
|
|
|
|
var expanders = []registeredExpander{
|
|
{
|
|
name: "env",
|
|
priority: -10,
|
|
expander: envExpander{},
|
|
},
|
|
{
|
|
name: "file",
|
|
priority: -5,
|
|
expander: fileExpander{},
|
|
},
|
|
}
|
|
|
|
func AddExpander(name string, priority int64, e Expander) {
|
|
expanders = append(expanders, registeredExpander{
|
|
name: name,
|
|
priority: priority,
|
|
expander: e,
|
|
})
|
|
}
|
|
|
|
var regex = regexp.MustCompile(`\$(|__\w+){([^}]+)}`)
|
|
|
|
// Slightly hacky function to avoid code duplication. If this is eventually called in multiple places, consider refactoring or potentially adding more general helper functions to this package
|
|
func GetExpanderRegex() *regexp.Regexp {
|
|
return regex
|
|
}
|
|
|
|
func expandConfig(file *ini.File) error {
|
|
sort.Slice(expanders, func(i, j int) bool {
|
|
return expanders[i].priority < expanders[j].priority
|
|
})
|
|
|
|
for _, expander := range expanders {
|
|
err := expander.expander.SetupExpander(file)
|
|
if err != nil {
|
|
return fmt.Errorf("got error during initilazation of expander '%s': %w", expander.name, err)
|
|
}
|
|
|
|
for _, section := range file.Sections() {
|
|
for _, key := range section.Keys() {
|
|
updated, err := applyExpander(key.Value(), expander)
|
|
if err != nil {
|
|
return fmt.Errorf("got error while expanding %s.%s with expander '%s': %w",
|
|
section.Name(),
|
|
key.Name(),
|
|
expander.name,
|
|
err)
|
|
}
|
|
|
|
key.SetValue(updated)
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ExpandVar(s string) (string, error) {
|
|
for _, expander := range expanders {
|
|
var err error
|
|
s, err = applyExpander(s, expander)
|
|
if err != nil {
|
|
return "", fmt.Errorf("got error while expanding expander %s: %w", expander.name, err)
|
|
}
|
|
}
|
|
return s, nil
|
|
}
|
|
|
|
func applyExpander(s string, e registeredExpander) (string, error) {
|
|
matches := regex.FindAllStringSubmatch(s, -1)
|
|
|
|
for _, match := range matches {
|
|
if len(match) < 3 {
|
|
return "", fmt.Errorf("regex error, got %d results back for match, expected 3", len(match))
|
|
}
|
|
|
|
_, isEnv := e.expander.(envExpander)
|
|
if match[1] == "__"+e.name || (match[1] == "" && isEnv) {
|
|
updated, err := e.expander.Expand(match[2])
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
s = strings.Replace(s, match[0], updated, 1)
|
|
}
|
|
}
|
|
|
|
return s, nil
|
|
}
|
|
|
|
type envExpander struct {
|
|
}
|
|
|
|
func (e envExpander) SetupExpander(file *ini.File) error {
|
|
return nil
|
|
}
|
|
|
|
func (e envExpander) Expand(s string) (string, error) {
|
|
envValue := os.Getenv(s)
|
|
|
|
// if env variable is hostname and it is empty use os.Hostname as default
|
|
if s == "HOSTNAME" && envValue == "" {
|
|
return os.Hostname()
|
|
}
|
|
|
|
return os.Getenv(s), nil
|
|
}
|
|
|
|
type fileExpander struct {
|
|
}
|
|
|
|
func (e fileExpander) SetupExpander(file *ini.File) error {
|
|
return nil
|
|
}
|
|
|
|
func (e fileExpander) Expand(s string) (string, error) {
|
|
_, err := os.Stat(s)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// nolint:gosec
|
|
// We can ignore the gosec G304 warning on this one because `s` comes from configuration section keys
|
|
f, err := ioutil.ReadFile(s)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return strings.TrimSpace(string(f)), nil
|
|
}
|