Files
Jakub Zych 79fd705680 feat(11-03): re-authorize every Centrifugo subscribe through a namespace registry
- lighthouse: Registry of namespace authorizers (Result, Allowed, Denied),
  ParseChannel, ChannelID with PHP (int)-cast semantics (PHPInt, pinned by
  a php -r table test), FormatChannels, WithClientID/ClientID
- centrifugo: ProxyHandler (constant-time X-Centrifugo-Secret, HTTP 200
  generic deny, info [] on allow, presence allow/override merge, 64 KiB
  body cap) mounted as the ServerToServer subscribe route
- README: proxy contract, registry and channel rules
2026-09-30 12:29:09 +02:00

85 lines
2.6 KiB
Go

// Package centrifugo is the Centrifugo driver of lighthouse: an HTTP API
// client, a connection and subscription token issuer, and the subscribe
// proxy handler. Import it for its side effect to register the
// "centrifugo" realtime.driver.
package centrifugo
import (
"net/netip"
"strings"
"time"
"git.golem15.com/golem15/summercms/modules/compass"
"git.golem15.com/golem15/summercms/modules/lighthouse"
"git.golem15.com/golem15/summercms/modules/surf"
)
// Default values of the realtime.centrifugo.* keys.
const (
DefaultAPIURL = "http://127.0.0.1:8001/api"
DefaultTokenTTL = 3600 * time.Second
DefaultWSURL = "/ws"
DefaultTokenPath = "/api/realtime/token"
DefaultSubscribePath = "/api/realtime/subscribe"
)
// Config is the realtime.centrifugo.* configuration.
type Config struct {
// APIURL is the Centrifugo HTTP API base, without a trailing method.
APIURL string
// APIKey authenticates publishes; empty disables them.
APIKey string
// TokenSecret signs connection and subscription tokens (HS256); empty
// makes the token route answer 503.
TokenSecret string
// TokenTTL is the lifetime of issued tokens.
TokenTTL time.Duration
// WSURL is the WebSocket URL the client connects to.
WSURL string
// ProxySecret is the X-Centrifugo-Secret header value the subscribe
// proxy expects; empty denies every subscribe.
ProxySecret string
// TokenPath and SubscribePath are the mounted route paths.
TokenPath string
SubscribePath string
// TrustedProxies are the http.trusted_proxies used to log the client IP
// of a denied subscribe.
TrustedProxies []netip.Prefix
}
// LoadConfig reads realtime.centrifugo.* from c, filling the defaults.
// token_ttl is an integer number of seconds or a duration string.
func LoadConfig(c *compass.Config) Config {
cfg := Config{
APIURL: DefaultAPIURL,
TokenTTL: DefaultTokenTTL,
WSURL: DefaultWSURL,
TokenPath: DefaultTokenPath,
SubscribePath: DefaultSubscribePath,
}
if c == nil {
return cfg
}
str := func(key string) string { return strings.TrimSpace(c.String("realtime.centrifugo." + key)) }
if v := str("api_url"); v != "" {
cfg.APIURL = strings.TrimSuffix(v, "/")
}
cfg.APIKey = str("api_key")
cfg.TokenSecret = str("token_secret")
cfg.ProxySecret = str("proxy_secret")
if d := lighthouse.DurationSetting(c, "realtime.centrifugo.token_ttl"); d > 0 {
cfg.TokenTTL = d
}
if v := str("ws_url"); v != "" {
cfg.WSURL = v
}
if v := str("token_path"); v != "" {
cfg.TokenPath = v
}
if v := str("subscribe_path"); v != "" {
cfg.SubscribePath = v
}
cfg.TrustedProxies = surf.TrustedProxies(c)
return cfg
}