Files
go2rtc/internal/app/secrets.go
T

129 lines
2.5 KiB
Go

package app
import (
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/AlexxIT/go2rtc/pkg/yaml"
)
var secrets [][]byte
var templateRegex = regexp.MustCompile(`\{\{\s*([^\}]+)\s*\}\}`)
func ResolveSecrets(template string) string {
if !templateRegex.MatchString(template) {
return template
}
var secretsMap map[string]interface{}
LoadSecret(&secretsMap)
// ex template: rtsp://{{ my_camera.username }}:{{ my_camera.password }}@192.168.178.1:554/stream
result := templateRegex.ReplaceAllStringFunc(template, func(match string) string {
varName := strings.TrimSpace(templateRegex.FindStringSubmatch(match)[1])
pathParts := strings.Split(varName, ".")
value := getNestedValue(secretsMap, pathParts)
if value != nil {
return stringify(value)
}
return ""
})
return result
}
func LoadSecret(v any) {
for _, data := range secrets {
if err := yaml.Unmarshal(data, v); err != nil {
Logger.Warn().Err(err).Send()
}
}
}
func PatchSecret(path []string, value any) error {
if SecretPath == "" {
return errors.New("secret file disabled")
}
// empty config is OK
b, _ := os.ReadFile(SecretPath)
b, err := yaml.Patch(b, path, value)
if err != nil {
return err
}
if err := os.WriteFile(SecretPath, b, 0644); err == nil {
secrets = [][]byte{b}
}
return err
}
func initSecret(secret string) {
if secret == "" {
secret = "go2rtc.secrets"
}
SecretPath = secret
if SecretPath != "" {
if !filepath.IsAbs(SecretPath) {
if cwd, err := os.Getwd(); err == nil {
SecretPath = filepath.Join(cwd, SecretPath)
}
}
Info["secret_path"] = SecretPath
}
}
func getNestedValue(m map[string]interface{}, path []string) interface{} {
if len(path) == 0 || m == nil {
return nil
}
key := path[0]
value, exists := m[key]
if !exists {
return nil
}
if len(path) == 1 {
return value
}
// Für verschachtelte Maps
switch nextMap := value.(type) {
case map[string]interface{}:
return getNestedValue(nextMap, path[1:])
case map[interface{}]interface{}:
// Konvertiere map[interface{}]interface{} zu map[string]interface{}
stringMap := make(map[string]interface{})
for k, v := range nextMap {
if keyStr, ok := k.(string); ok {
stringMap[keyStr] = v
}
}
return getNestedValue(stringMap, path[1:])
default:
return nil
}
}
func stringify(value interface{}) string {
switch v := value.(type) {
case string:
return v
case int, int64, float64, bool:
return fmt.Sprintf("%v", v)
default:
return ""
}
}