feat(auth): enhance token validation and internal access control

Refactor the `Whoami` handler to validate token metadata (status, expiration,
revocation) against Redis before database lookup, ensuring consistency with
balancer logic. Add `allow_ips`, `deny_ips`, and `expires_at` fields to
authentication responses.

Update internal middleware to support explicit anonymous access configuration
and harden security for unconfigured tokens.

Remove legacy fallback logic for master keys without digests.

BREAKING CHANGE: Internal endpoints now reject requests by default if no stats token is configured. To allow unauthenticated access, set `internal.allow_anonymous` to true.
BREAKING CHANGE: Support for legacy master keys without stored digests has been removed.
This commit is contained in:
zenfun
2026-01-03 16:04:04 +08:00
parent 295faa8e01
commit 4cd9b66a84
5 changed files with 93 additions and 57 deletions

View File

@@ -71,7 +71,8 @@ type QuotaConfig struct {
}
type InternalConfig struct {
StatsToken string
StatsToken string
AllowAnonymous bool
}
type SyncOutboxConfig struct {
@@ -115,6 +116,7 @@ func Load() (*Config, error) {
v.SetDefault("model_registry.timeout_seconds", 30)
v.SetDefault("quota.reset_interval_seconds", 300)
v.SetDefault("internal.stats_token", "")
v.SetDefault("internal.allow_anonymous", false)
v.SetDefault("sync_outbox.enabled", true)
v.SetDefault("sync_outbox.interval_seconds", 5)
v.SetDefault("sync_outbox.batch_size", 200)
@@ -151,6 +153,7 @@ func Load() (*Config, error) {
_ = v.BindEnv("model_registry.timeout_seconds", "EZ_MODEL_REGISTRY_TIMEOUT_SECONDS")
_ = v.BindEnv("quota.reset_interval_seconds", "EZ_QUOTA_RESET_INTERVAL_SECONDS")
_ = v.BindEnv("internal.stats_token", "EZ_INTERNAL_STATS_TOKEN")
_ = v.BindEnv("internal.allow_anonymous", "EZ_INTERNAL_ALLOW_ANON")
_ = v.BindEnv("sync_outbox.enabled", "EZ_SYNC_OUTBOX_ENABLED")
_ = v.BindEnv("sync_outbox.interval_seconds", "EZ_SYNC_OUTBOX_INTERVAL_SECONDS")
_ = v.BindEnv("sync_outbox.batch_size", "EZ_SYNC_OUTBOX_BATCH_SIZE")
@@ -216,7 +219,8 @@ func Load() (*Config, error) {
ResetIntervalSeconds: v.GetInt("quota.reset_interval_seconds"),
},
Internal: InternalConfig{
StatsToken: v.GetString("internal.stats_token"),
StatsToken: v.GetString("internal.stats_token"),
AllowAnonymous: v.GetBool("internal.allow_anonymous"),
},
SyncOutbox: SyncOutboxConfig{
Enabled: v.GetBool("sync_outbox.enabled"),