This commit is contained in:
Mateusz Gruszczyński committed 2026-10-25 17:45:57 +01:00
1 parent bd077754a9
commit ed7e3377c1
40 files changed
+1764 -365

No files matched your search

+465 -68
View File
@@ -2,7 +2,7 @@
"openapi": "3.0.3",
"info": {
"title": "RustProxy Administration API",
"version": "0.34.12",
"version": "0.34.13",
"description": "Administration API for the active panel origin. Sign in through the panel; the same-origin HttpOnly cookie authenticates all private operations. Mutations also require the exact Origin, X-RustProxy-Request: 1 and a session-bound X-CSRF-Token. Loopback HTTP is the default; Settings can enable HTTPS before using a non-loopback administration bind. This document contains no live configuration or credentials. Object schemas marked extensible are summaries: full configuration validation is authoritative in Rust. The API also permits explicitly scoped GeneralApiBearer tokens on a narrow route allowlist, with RO/RW and source CIDR checks; API-token management and Prometheus-token management are browser-session-only."
},
"servers": [
@@ -1025,11 +1025,22 @@
},
"description": "Named PHP-FPM configurations reusable by Web Services."
},
"global_security": {
"$ref": "#/components/schemas/GlobalSecurity"
},
"user_agent_blocking": {
"$ref": "#/components/schemas/UserAgentBlocking"
"deprecated": true,
"writeOnly": true,
"description": "Migration-only input for full configuration imports from older installations. The live GET response and canonical saved configuration use global_security.user_agent_blocking instead. Conflicting legacy and nested policies are rejected.",
"allOf": [
{
"$ref": "#/components/schemas/UserAgentBlocking"
}
]
}
},
"additionalProperties": true
"additionalProperties": false,
"description": "The canonical global User-Agent policy lives at global_security.user_agent_blocking; the old root-level key is accepted only as a migration input, not returned by this API."
},
"Envelope": {
"type": "object",
@@ -1797,10 +1808,10 @@
"expected_revision": {
"type": "integer",
"format": "int64",
"description": "Revision returned by the latest GET /api/config."
"description": "Current revision from GET /api/config or GET /api/config/{section}."
},
"value": {
"description": "Complete value of the selected configuration section. This is a section replacement, not a merge patch."
"description": "Complete value of the selected configuration section. This is a section replacement, not a merge patch. Read GET /api/config/{section} first, then return its complete `value` with edits. Even an empty array is a full replacement of that collection."
}
},
"additionalProperties": false,
@@ -7585,6 +7596,135 @@
}
},
"additionalProperties": false
},
"GlobalSecurity": {
"type": "object",
"description": "One atomic global HTTP security configuration for all public HTTP hosts. Includes User-Agent blocking, country/IP restrictions, methods, request Content-Type, shared rate limiting and response security headers. Individual policies default off. Old top-level user_agent_blocking in an imported full config is migrated at validation time; conflicting old and new values are rejected.",
"additionalProperties": false,
"properties": {
"country_access": {
"$ref": "#/components/schemas/CountryAccess"
},
"acl": {
"allOf": [
{
"$ref": "#/components/schemas/Acl"
}
],
"nullable": true,
"description": "Optional global client IP/CIDR and allow-only DNS ACL; null disables this layer."
},
"method_policy": {
"$ref": "#/components/schemas/MethodPolicy"
},
"content_type_policy": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean",
"default": false
},
"blocked": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 64,
"description": "Blocked MIME types, e.g. application/json, image/*."
}
}
},
"rate_limit": {
"$ref": "#/components/schemas/VhostRateLimit"
},
"security_headers": {
"type": "object",
"additionalProperties": false,
"properties": {
"hsts": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean",
"default": false
},
"max_age_seconds": {
"type": "integer",
"minimum": 0,
"maximum": 63072000,
"default": 31536000
},
"include_subdomains": {
"type": "boolean",
"default": false
},
"preload": {
"type": "boolean",
"default": false
}
}
},
"nosniff": {
"type": "boolean",
"default": false
},
"frame_options": {
"type": "string",
"enum": [
"preserve",
"deny",
"sameorigin"
],
"default": "preserve"
},
"referrer_policy": {
"type": "string",
"nullable": true,
"maxLength": 8192
},
"content_security_policy": {
"type": "string",
"nullable": true,
"maxLength": 8192
},
"permissions_policy": {
"type": "string",
"nullable": true,
"maxLength": 8192
}
}
},
"user_agent_blocking": {
"$ref": "#/components/schemas/UserAgentBlocking"
}
},
"required": [
"user_agent_blocking"
]
},
"ConfigSectionRead": {
"type": "object",
"description": "Read one whole configuration section with the same value format accepted by PUT. It does not contain storage metadata or unrelated sections.",
"additionalProperties": false,
"properties": {
"revision": {
"type": "integer",
"format": "int64"
},
"section": {
"type": "string"
},
"value": {
"description": "Serialized complete value for the requested section. The format is identical to PUT /api/config/{section}. See x-rustproxy-section-fields on the operation for section-to-Config mapping."
}
},
"required": [
"revision",
"section",
"value"
]
}
}
},
@@ -9813,66 +9953,6 @@
]
}
},
"/api/geoip/update": {
"post": {
"summary": "Check, download and hot-reload GeoIP country databases now",
"description": "Download the configured direct GeoIP source(s), optionally verify publisher SHA-256 values, validate the selected CSV/MMDB format, atomically publish changed files and hot-reload future GeoIP lookups.",
"tags": [
"Settings"
],
"operationId": "post_api_geoip_update",
"responses": {
"200": {
"description": "GeoIP check completed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GeoIpUpdateResult"
}
}
}
},
"401": {
"description": "Authentication required or revoked",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Host, origin or CSRF validation failed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"502": {
"description": "Publisher check, download, validation or reload failed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"security": [
{
"AdminSession": []
},
{
"GeneralApiBearer": []
}
]
}
},
"/api/cache/purge": {
"post": {
"summary": "Purge all cache entries or one vhost",
@@ -10644,9 +10724,19 @@
}
}
}
},
"404": {
"description": "Unknown or removed configuration section",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"description": "Preferred UI/control-plane save path. Replaces only the selected section while preserving every other section from the current revision. This is not a merge patch. Cache identity is independent from the global configuration revision: logging, listeners, TLS inventory, metrics and administration saves do not purge cached objects. Changes which can alter origin requests or cached responses (cache/transform/response/forwarding/vhosts) rotate the cache compatibility identity and purge incompatible hot/cold objects. Supported section names include docker-agents, vhosts, redirects, not_found_hosts, streams, listeners, http2, tls, pages, cache, transform, logging, forwarding, headers, prometheus, geoip, administration, acl-profiles, host-policies and response.",
"description": "Replaces the named section in one revision-checked, validated, durable configuration update; unrelated sections are preserved. This is a full section replacement, not a merge/patch. Use GET /api/config/{section} to read the exact value shape before PUT. logging requires {logging, error_log}; response requires {server_header, diagnostic_headers, compression}; global-security requires one GlobalSecurity object containing user_agent_blocking. The legacy standalone user-agent-blocking section and standalone error_log are not writable. Global revision conflicts return 409, even for writes to different sections; retry after fetching a new revision. PUT returns the complete updated {revision, config} envelope so the UI can refresh all sections. Origin-dependent cache policy changes still invalidate incompatible cached objects; unrelated logging/listener/administration updates do not purge the cache. See x-rustproxy-section-fields for canonical JSON field mapping.",
"parameters": [
{
"name": "section",
@@ -10671,11 +10761,13 @@
"tls",
"vhosts",
"redirects",
"not_found_hosts",
"not-found-hosts",
"streams",
"acl-profiles",
"host-policies",
"user-agent-blocking"
"global-security",
"web-services",
"php-fpm-profiles"
]
},
"description": "Configuration section to replace."
@@ -10705,6 +10797,9 @@
{
"AdminSession": [],
"CsrfToken": []
},
{
"GeneralApiBearer": []
}
],
"requestBody": {
@@ -10716,6 +10811,248 @@
}
}
}
},
"x-rustproxy-section-fields": {
"listeners": [
"listeners"
],
"docker-agents": [
"docker_agents"
],
"http2": [
"http2"
],
"pages": [
"pages"
],
"cache": [
"cache"
],
"transform": [
"transform"
],
"forwarding": [
"forwarding"
],
"headers": [
"headers"
],
"prometheus": [
"prometheus"
],
"geoip": [
"geoip_updates"
],
"administration": [
"administration"
],
"tls": [
"tls"
],
"vhosts": [
"vhosts"
],
"web-services": [
"web_services"
],
"php-fpm-profiles": [
"php_fpm_profiles"
],
"redirects": [
"redirects"
],
"not-found-hosts": [
"not_found_hosts"
],
"streams": [
"streams"
],
"acl-profiles": [
"acl_profiles"
],
"host-policies": [
"host_policies"
],
"response": [
"server_header",
"diagnostic_headers",
"compression"
],
"logging": [
"logging",
"error_log"
],
"global-security": [
"global_security"
]
}
},
"get": {
"summary": "Read one revisioned configuration section",
"description": "Returns {revision, section, value}. The value is the complete canonical section payload accepted by PUT /api/config/{section}, not a partial patch. logging groups logging + error_log, response groups the three response controls, and global-security contains user_agent_blocking and all other global security rules. No storage paths are returned by this endpoint. See x-rustproxy-section-fields for the exact Config property mapping of all supported names.",
"tags": [
"Configuration"
],
"operationId": "get_api_config_section",
"parameters": [
{
"name": "section",
"in": "path",
"required": true,
"schema": {
"type": "string",
"enum": [
"listeners",
"docker-agents",
"response",
"pages",
"cache",
"transform",
"logging",
"forwarding",
"headers",
"prometheus",
"geoip",
"administration",
"http2",
"tls",
"vhosts",
"redirects",
"not-found-hosts",
"streams",
"acl-profiles",
"host-policies",
"global-security",
"web-services",
"php-fpm-profiles"
]
},
"description": "Exactly one supported configuration section."
}
],
"responses": {
"200": {
"description": "Section value and current global revision",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConfigSectionRead"
}
}
}
},
"401": {
"description": "Authentication required",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden by Host or token policy",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Unknown or removed configuration section",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"security": [
{
"AdminSession": []
},
{
"GeneralApiBearer": []
}
],
"x-rustproxy-section-fields": {
"listeners": [
"listeners"
],
"docker-agents": [
"docker_agents"
],
"http2": [
"http2"
],
"pages": [
"pages"
],
"cache": [
"cache"
],
"transform": [
"transform"
],
"forwarding": [
"forwarding"
],
"headers": [
"headers"
],
"prometheus": [
"prometheus"
],
"geoip": [
"geoip_updates"
],
"administration": [
"administration"
],
"tls": [
"tls"
],
"vhosts": [
"vhosts"
],
"web-services": [
"web_services"
],
"php-fpm-profiles": [
"php_fpm_profiles"
],
"redirects": [
"redirects"
],
"not-found-hosts": [
"not_found_hosts"
],
"streams": [
"streams"
],
"acl-profiles": [
"acl_profiles"
],
"host-policies": [
"host_policies"
],
"response": [
"server_header",
"diagnostic_headers",
"compression"
],
"logging": [
"logging",
"error_log"
],
"global-security": [
"global_security"
]
}
}
},
@@ -13905,6 +14242,66 @@
}
]
}
},
"/api/config/geoip/update": {
"post": {
"summary": "Update GeoIP data using saved geoip configuration now",
"description": "Manually start a GeoIP data refresh using the already-saved settings at GET/PUT /api/config/geoip. This is an operational POST, not a configuration PUT and it does not increment the configuration revision. Downloads configured GeoIP sources, verifies optional SHA-256 checksums, checks CSV/MMDB, atomically publishes changed databases and hot-reloads future lookups. Save any edited GeoIP settings before calling this action. The response is GeoIpUpdateResult; a failed external fetch returns 502 and existing usable data remains untouched.",
"tags": [
"Configuration"
],
"operationId": "post_api_config_geoip_update",
"responses": {
"200": {
"description": "GeoIP check completed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GeoIpUpdateResult"
}
}
}
},
"401": {
"description": "Authentication required or revoked",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Host, origin or CSRF validation failed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"502": {
"description": "Publisher check, download, validation or reload failed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"security": [
{
"AdminSession": []
},
{
"GeneralApiBearer": []
}
]
}
}
},
"tags": []