Security(Go): Login rate limit + WS origin allowlist + REST bearer auth
This commit is contained in:
@@ -611,6 +611,27 @@ func parsePorts(portStr string) ([]int, error) {
|
||||
return ports, nil
|
||||
}
|
||||
|
||||
// splitCSV splits a comma-separated env-var value into trimmed, non-empty
|
||||
// entries. Returns nil for an empty input so callers can keep the natural
|
||||
// "no value → no restriction" semantics with a single nil check.
|
||||
func splitCSV(s string) []string {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
parts := strings.Split(s, ",")
|
||||
out := make([]string, 0, len(parts))
|
||||
for _, p := range parts {
|
||||
p = strings.TrimSpace(p)
|
||||
if p != "" {
|
||||
out = append(out, p)
|
||||
}
|
||||
}
|
||||
if len(out) == 0 {
|
||||
return nil
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Parse command line flags
|
||||
portStr := flag.String("port", "6543", "Server listen ports (semicolon-separated, e.g. 6543;6544;6545)")
|
||||
@@ -733,9 +754,33 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Web-UI hardening knobs for public-HTTPS deployment.
|
||||
//
|
||||
// YAMA_WEB_ALLOWED_ORIGINS: comma-separated Origin allowlist (e.g.
|
||||
// "https://yama.example.com,https://yama-mobile.example.com").
|
||||
// Empty (default) → only same-origin WS upgrades accepted, which
|
||||
// is correct when the web UI and WS endpoint share a host.
|
||||
//
|
||||
// Login rate limits are hard-coded at sensible defaults for the
|
||||
// small-user web UI: 10 attempts / minute per IP, 5 / 15 min per
|
||||
// username. The handler also injects a 250 ms delay on every failure
|
||||
// so online brute force is impractical even within budget.
|
||||
allowedOrigins := splitCSV(os.Getenv("YAMA_WEB_ALLOWED_ORIGINS"))
|
||||
trustProxy := os.Getenv("YAMA_WEB_TRUST_PROXY") == "1"
|
||||
if trustProxy {
|
||||
log.Info("Trusting X-Forwarded-For for client IP — make sure a reverse proxy is in front")
|
||||
}
|
||||
webCfg := web.Config{
|
||||
AllowedOrigins: allowedOrigins,
|
||||
LoginIPLimit: wsauth.NewRateLimiter(10, time.Minute),
|
||||
LoginUserLimit: wsauth.NewRateLimiter(5, 15*time.Minute),
|
||||
TrustForwardedFor: trustProxy,
|
||||
}
|
||||
|
||||
// Start HTTP server for web UI. Hub gives it read-only access to the
|
||||
// device registry; the authenticator owns user accounts and session tokens.
|
||||
httpSrv := web.New(*httpPort, log.WithPrefix("Web"), deviceHub, webAuth)
|
||||
httpSrv := web.New(*httpPort, log.WithPrefix("Web"), deviceHub, webAuth).
|
||||
WithConfig(webCfg)
|
||||
if err := httpSrv.Start(); err != nil {
|
||||
log.Fatal("Failed to start HTTP server: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user