fix: fail closed on an unwritable audit log, bound the rate limiter and harden startup
The audit logger is opened at startup (exit 2 on failure) and obtained before every call, which is refused with audit_unavailable otherwise. Audit records only take validated path and sudo values and use the request id as correlation id. The rate limiter evicts idle keys, caps tracked keys, audits the first excess per key and window and uses the settings passed to the app. FORWARDED_ALLOW_IPS is now a setting, and startup warns about a missing host allow-list and unavailable OAuth.
This commit is contained in:
1 parent
a3222d5ebe
commit
cf3d2e17d3
16 files changed
+532
-115
No files matched your search
@@ -128,6 +128,7 @@ class Settings(BaseSettings):
|
||||
mcp_bearer_token: SecretStr | None = Field(default=None)
|
||||
public_base_url: str | None = Field(default=None)
|
||||
allowed_hosts: Annotated[list[str], NoDecode] = Field(default_factory=list)
|
||||
forwarded_allow_ips: str = Field(default="127.0.0.1")
|
||||
|
||||
# Per-user OAuth (HTTP only)
|
||||
oauth_enabled: bool = Field(default=False)
|
||||
@@ -199,6 +200,28 @@ class Settings(BaseSettings):
|
||||
raise ValueError("PUBLIC_BASE_URL must use https unless the host is loopback")
|
||||
return normalized
|
||||
|
||||
@field_validator("forwarded_allow_ips", mode="before")
|
||||
@classmethod
|
||||
def _validate_forwarded_allow_ips(cls, value: Any) -> Any:
|
||||
"""Accept ``*`` or a comma list of IP addresses and networks (blank means the default)."""
|
||||
if not isinstance(value, str):
|
||||
return value
|
||||
items = [item.strip() for item in value.split(",") if item.strip()]
|
||||
if not items:
|
||||
return "127.0.0.1"
|
||||
if "*" in items and len(items) > 1:
|
||||
raise ValueError("FORWARDED_ALLOW_IPS: '*' cannot be combined with other entries")
|
||||
for item in items:
|
||||
if item == "*":
|
||||
continue
|
||||
try:
|
||||
ipaddress.ip_network(item, strict=False)
|
||||
except ValueError:
|
||||
raise ValueError(
|
||||
"FORWARDED_ALLOW_IPS must be '*' or a comma list of IP addresses or networks"
|
||||
) from None
|
||||
return ",".join(items)
|
||||
|
||||
@field_validator("mcp_path")
|
||||
@classmethod
|
||||
def _validate_mcp_path(cls, value: str) -> str:
|
||||
|
||||
Reference in new issue
Block a user