@@ -25,6 +25,12 @@ type ServerConfig struct {
2525 Whitelist []string `yaml:"whitelist"`
2626}
2727
28+ type LogConfig struct {
29+ Operator string `yaml:"operator"`
30+ URL string `yaml:"url"`
31+ Description string `yaml:"description"`
32+ }
33+
2834type Config struct {
2935 Webserver struct {
3036 ServerConfig `yaml:",inline"`
@@ -39,6 +45,9 @@ type Config struct {
3945 MetricsURL string `yaml:"metrics_url"`
4046 ExposeSystemMetrics bool `yaml:"expose_system_metrics"`
4147 }
48+ General struct {
49+ AdditionalLogs []LogConfig `yaml:"additional_logs"`
50+ }
4251}
4352
4453// ReadConfig reads the config file and returns a filled Config struct.
@@ -53,14 +62,14 @@ func ReadConfig(configPath string) (Config, error) {
5362 if ! validateConfig (conf ) {
5463 log .Fatalln ("Invalid config" )
5564 }
56- AppConfig = conf
65+ AppConfig = * conf
5766
58- return conf , nil
67+ return * conf , nil
5968}
6069
6170// parseConfigFromFile reads the config file as bytes and passes it to parseConfigFromBytes.
6271// It returns a filled Config struct.
63- func parseConfigFromFile (configFile string ) (Config , error ) {
72+ func parseConfigFromFile (configFile string ) (* Config , error ) {
6473 if configFile == "" {
6574 configFile = "config.yml"
6675 }
@@ -69,7 +78,7 @@ func parseConfigFromFile(configFile string) (Config, error) {
6978 absPath , err := filepath .Abs (configFile )
7079 if err != nil {
7180 log .Printf ("Couldn't convert to absolute path: '%s'\n " , configFile )
72- return Config {}, err
81+ return & Config {}, err
7382 }
7483
7584 if _ , statErr := os .Stat (absPath ); os .IsNotExist (statErr ) {
@@ -84,45 +93,46 @@ func parseConfigFromFile(configFile string) (Config, error) {
8493 absPath += ".yaml"
8594 default :
8695 log .Printf ("Config file '%s' does not have a valid extension\n " , configFile )
87- return Config {}, statErr
96+ return & Config {}, statErr
8897 }
8998
9099 if _ , secondStatErr := os .Stat (absPath ); os .IsNotExist (secondStatErr ) {
91100 log .Printf ("Config file '%s' does not exist\n " , absPath )
92- return Config {}, secondStatErr
101+ return & Config {}, secondStatErr
93102 }
94103 }
95104 log .Printf ("File '%s' exists\n " , absPath )
96105
97106 yamlFileContent , readErr := os .ReadFile (absPath )
98107 if readErr != nil {
99- return Config {}, readErr
108+ return & Config {}, readErr
100109 }
101110
102111 conf , parseErr := parseConfigFromBytes (yamlFileContent )
103112 if parseErr != nil {
104- return Config {}, parseErr
113+ return & Config {}, parseErr
105114 }
106115
107116 return conf , nil
108117}
109118
110119// parseConfigFromBytes parses the config bytes and returns a filled Config struct.
111- func parseConfigFromBytes (data []byte ) (Config , error ) {
120+ func parseConfigFromBytes (data []byte ) (* Config , error ) {
112121 var config Config
113122
114123 err := yaml .Unmarshal (data , & config )
115124 if err != nil {
116- return config , err
125+ return & config , err
117126 }
118127
119- return config , nil
128+ return & config , nil
120129}
121130
122131// validateConfig validates the config values and sets defaults for missing values.
123- func validateConfig (config Config ) bool {
132+ func validateConfig (config * Config ) bool {
124133 // Still matches invalid IP addresses but good enough for detecting completely wrong formats
125- URLRegex := regexp .MustCompile (`^(/[a-zA-Z0-9\-._]+)+$` )
134+ URLPathRegex := regexp .MustCompile (`^(/[a-zA-Z0-9\-._]+)+$` )
135+ URLRegex := regexp .MustCompile (`^https?://[a-zA-Z0-9\-._]+(:[0-9]+)?(/[a-zA-Z0-9\-._]+)*$` )
126136
127137 // Check webserver config
128138 if config .Webserver .ListenAddr == "" || net .ParseIP (config .Webserver .ListenAddr ) == nil {
@@ -135,17 +145,17 @@ func validateConfig(config Config) bool {
135145 return false
136146 }
137147
138- if config .Webserver .FullURL == "" || ! URLRegex .MatchString (config .Webserver .FullURL ) {
148+ if config .Webserver .FullURL == "" || ! URLPathRegex .MatchString (config .Webserver .FullURL ) {
139149 log .Println ("Webhook full URL is not set or does not match pattern '/...'" )
140150 config .Webserver .FullURL = "/full-stream"
141151 }
142152
143- if config .Webserver .LiteURL == "" || ! URLRegex .MatchString (config .Webserver .FullURL ) {
153+ if config .Webserver .LiteURL == "" || ! URLPathRegex .MatchString (config .Webserver .FullURL ) {
144154 log .Println ("Webhook lite URL is not set or does not match pattern '/...'" )
145155 config .Webserver .LiteURL = "/"
146156 }
147157
148- if config .Webserver .DomainsOnlyURL == "" || ! URLRegex .MatchString (config .Webserver .DomainsOnlyURL ) {
158+ if config .Webserver .DomainsOnlyURL == "" || ! URLPathRegex .MatchString (config .Webserver .DomainsOnlyURL ) {
149159 log .Println ("Webhook domains only URL is not set or does not match pattern '/...'" )
150160 config .Webserver .FullURL = "/domains-only"
151161 }
@@ -187,5 +197,19 @@ func validateConfig(config Config) bool {
187197 }
188198 }
189199
200+ var validLogs []LogConfig
201+ if len (config .General .AdditionalLogs ) > 0 {
202+ for _ , ctLog := range config .General .AdditionalLogs {
203+ if ! URLRegex .MatchString (ctLog .URL ) {
204+ log .Println ("Ignoring invalid additional log URL: " , ctLog .URL )
205+ continue
206+ }
207+
208+ validLogs = append (validLogs , ctLog )
209+ }
210+ }
211+
212+ config .General .AdditionalLogs = validLogs
213+
190214 return true
191215}
0 commit comments