aboutsummaryrefslogtreecommitdiff
path: root/internal/config
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-01-20 16:15:50 -0800
committerFuwn <[email protected]>2026-01-20 16:15:50 -0800
commitb147654b8aed7005760017f604aae58637ac7767 (patch)
tree77cad60fc8eff8bd6c18a9846307e02bf1d6ba32 /internal/config
parentfeat: Add all remaining monitor options to group defaults (diff)
downloadkaze-b147654b8aed7005760017f604aae58637ac7767.tar.xz
kaze-b147654b8aed7005760017f604aae58637ac7767.zip
feat: Add API access control (public/private/authenticated)
Add configurable access control for /api/* endpoints: - public: Anyone can access (default, backwards compatible) - private: API endpoints return 403 Forbidden - authenticated: Requires API key via X-API-Key header or ?api_key= param Config example: api: access: authenticated keys: - "secret-key-1" - "secret-key-2"
Diffstat (limited to 'internal/config')
-rw-r--r--internal/config/config.go29
1 files changed, 29 insertions, 0 deletions
diff --git a/internal/config/config.go b/internal/config/config.go
index d82fee0..5f05b96 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -15,10 +15,22 @@ type Config struct {
Server ServerConfig `yaml:"server"`
Storage StorageConfig `yaml:"storage"`
Display DisplayConfig `yaml:"display"`
+ API APIConfig `yaml:"api"`
Groups []GroupConfig `yaml:"groups"`
Incidents []IncidentConfig `yaml:"incidents"`
}
+// APIConfig contains settings for the JSON API endpoints
+type APIConfig struct {
+ // Access controls who can access /api/* endpoints:
+ // "public" - Anyone can access (default)
+ // "private" - API endpoints are disabled (return 403)
+ // "authenticated" - Requires API key via X-API-Key header or ?api_key= query param
+ Access string `yaml:"access"`
+ // Keys is a list of valid API keys (only used when access is "authenticated")
+ Keys []string `yaml:"keys"`
+}
+
// DisplayConfig contains display/UI settings
type DisplayConfig struct {
// TickMode controls how history is aggregated: ping, minute, hour, day
@@ -241,6 +253,11 @@ func (c *Config) applyDefaults() {
c.Display.Scale = 2.0
}
+ // Apply API defaults
+ if c.API.Access == "" {
+ c.API.Access = "public"
+ }
+
// Apply group defaults
for i := range c.Groups {
grp := &c.Groups[i]
@@ -456,6 +473,18 @@ func (c *Config) validate() error {
return fmt.Errorf("tick_count must be between 1 and 200, got %d", c.Display.TickCount)
}
+ // Validate API config
+ switch c.API.Access {
+ case "", "public", "private", "authenticated":
+ // Valid modes ("" defaults to "public")
+ default:
+ return fmt.Errorf("invalid api.access %q (must be public, private, or authenticated)", c.API.Access)
+ }
+
+ if c.API.Access == "authenticated" && len(c.API.Keys) == 0 {
+ return fmt.Errorf("api.access is 'authenticated' but no api.keys provided")
+ }
+
return nil
}