// Package secrets provides functionality. package secrets import ( "log" "os" "path/filepath" "github.com/go-yaml/yaml" "rocketgit.ru/rsmon/worker/config/application" _ "rocketgit.ru/rsmon/worker/config/env" // Import to ensure .env is loaded before reading env vars ) const envTest = "test" // SecretsBase provides functionality. type SecretsBase struct { URL string `yaml:"url"` InfluxToken string `yaml:"influx_token"` WorkerAdminSecret string `yaml:"worker_admin_secret"` } // SecretsCrypto provides functionality. type SecretsCrypto struct { SessionKey string `yaml:"session_key"` CsrfKey string `yaml:"csrf_key"` Pepper string `yaml:"pepper"` } // SecretsCrm provides functionality. type SecretsCrm struct { URL string `yaml:"url"` IngressToken string `yaml:"ingress_token"` } // SecretsData provides functionality. type SecretsData struct { Base *SecretsBase `yaml:"base"` Crypto *SecretsCrypto `yaml:"crypto"` Crm *SecretsCrm `yaml:"crm"` } var ( // Data provides functionality. Data SecretsData // Base provides functionality. Base *SecretsBase // Crypto provides cryptography configuration. Crypto *SecretsCrypto // Crm provides CRM configuration. Crm *SecretsCrm ) func envFirst(keys ...string) string { for _, key := range keys { if value := os.Getenv(key); value != "" { return value } } return "" } func buildSecretsFromEnv() SecretsData { baseURL := envFirst("BASE_URL", "APP_BASE_URL") if baseURL == "" { baseURL = "http://localhost:7401" } sessionKey := envFirst("SESSION_KEY") pepper := envFirst("PEPPER") csrfKey := envFirst("CSRF_KEY") return SecretsData{ Base: &SecretsBase{ URL: baseURL, InfluxToken: envFirst("INFLUX_TOKEN"), WorkerAdminSecret: envFirst("WORKER_ADMIN_SECRET", "RSMON_ADMIN_SECRET"), }, Crypto: &SecretsCrypto{ SessionKey: sessionKey, CsrfKey: csrfKey, Pepper: pepper, }, Crm: &SecretsCrm{ URL: envFirst("CRM_URL", "SENSEI_CRM_URL"), IngressToken: envFirst("CRM_INGRESS_TOKEN", "SENSEI_CRM_INGRESS_TOKEN"), }, } } func assign(data SecretsData) { Data = data Base = Data.Base Crypto = Data.Crypto Crm = Data.Crm } func init() { var err error // Try multiple paths for secrets.yml cwd := os.Getenv("CWD") if cwd == "" { cwd = "." } // Possible paths to check - try relative to CWD and from module root paths := []string{ filepath.Join(cwd, "config", "secrets.yml"), "config/secrets.yml", "../../config/secrets.yml", "../../../config/secrets.yml", "../../../../config/secrets.yml", } var dat []byte for _, path := range paths { dat, err = os.ReadFile(path) if err == nil { break } } // If we're in test mode and no secrets file found, use defaults // Check multiple test indicators since init() order is unpredictable isTest := os.Getenv("RSMON_ENV") == envTest || os.Getenv("GO_ENV") == envTest || os.Getenv("CI") == "true" || application.Env == envTest if err != nil && isTest { log.Println("No secrets.yml found in test environment, using defaults") // Set default values for test environment Base = &SecretsBase{ URL: "http://localhost:7401", InfluxToken: "", WorkerAdminSecret: "test-secret", } Crypto = &SecretsCrypto{ SessionKey: "abc", CsrfKey: "bGludXhoaW50LmNvbQo=", Pepper: "abc", } Crm = &SecretsCrm{URL: "", IngressToken: ""} assign(SecretsData{ Base: Base, Crypto: Crypto, Crm: Crm, }) return } if err != nil { log.Println("No secrets.yml found, using environment variables") assign(buildSecretsFromEnv()) return } var AllSecrets map[string]SecretsData err = yaml.Unmarshal(dat, &AllSecrets) if err != nil { panic(err) } env := application.Env if env == "" { env = "development" } assign(AllSecrets[env]) }