improve secret vars and parse url with secrets
This commit is contained in:
@@ -18,14 +18,6 @@ func LoadConfig(v any) {
|
||||
}
|
||||
}
|
||||
|
||||
func LoadSecret(v any) {
|
||||
for _, data := range secrets {
|
||||
if err := yaml.Unmarshal(data, v); err != nil {
|
||||
Logger.Warn().Err(err).Send()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func PatchConfig(path []string, value any) error {
|
||||
if ConfigPath == "" {
|
||||
return errors.New("config file disabled")
|
||||
@@ -42,27 +34,6 @@ func PatchConfig(path []string, value any) error {
|
||||
return os.WriteFile(ConfigPath, b, 0644)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
type flagConfig []string
|
||||
|
||||
func (c *flagConfig) String() string {
|
||||
@@ -75,7 +46,6 @@ func (c *flagConfig) Set(value string) error {
|
||||
}
|
||||
|
||||
var configs [][]byte
|
||||
var secrets [][]byte
|
||||
|
||||
func initConfig(confs flagConfig) {
|
||||
if confs == nil {
|
||||
@@ -116,23 +86,6 @@ func initConfig(confs flagConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
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 parseConfString(s string) []byte {
|
||||
i := strings.IndexByte(s, '=')
|
||||
if i < 0 {
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
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 ""
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/AlexxIT/go2rtc/internal/app"
|
||||
"github.com/AlexxIT/go2rtc/pkg/core"
|
||||
)
|
||||
|
||||
@@ -46,7 +47,8 @@ func GetProducer(url string) (core.Producer, error) {
|
||||
}
|
||||
|
||||
if handler, ok := handlers[scheme]; ok {
|
||||
return handler(url)
|
||||
parsedURL := ParseURL(url)
|
||||
return handler(parsedURL)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,3 +97,7 @@ func GetConsumer(url string) (core.Consumer, func(), error) {
|
||||
|
||||
return nil, nil, errors.New("streams: unsupported scheme: " + url)
|
||||
}
|
||||
|
||||
func ParseURL(url string) string {
|
||||
return app.ResolveSecrets(url)
|
||||
}
|
||||
Reference in New Issue
Block a user