Publish curated Unraid-AppOps-Gateway source from 034c9f844d2455850ba37b31379b7edaa786583e
This commit is contained in:
1 parent
c61fbfd87f
commit
1a54836efc
101 files changed
+4973
-1298
No files matched your search
@@ -40,83 +40,10 @@ def _request(headers: list[tuple[bytes, bytes]] | None = None, client_host: str
|
||||
return Request({"type": "http", "method": "POST", "path": "/api/actions/plan", "headers": headers or [], "client": (client_host, 12345)})
|
||||
|
||||
|
||||
def test_operator_boundary_protects_mutations_and_accepts_valid_token():
|
||||
def test_human_boundary_rejects_anonymous_and_legacy_tokens(monkeypatch):
|
||||
from backend.app.core import security
|
||||
from backend.app.core.config import settings
|
||||
|
||||
previous = (settings.operator_auth_required, settings.operator_token, security.settings.operator_auth_required, security.settings.operator_token)
|
||||
settings.operator_auth_required = True
|
||||
settings.operator_token = "test-operator-boundary-token"
|
||||
security.settings.operator_auth_required = True
|
||||
security.settings.operator_token = "test-operator-boundary-token"
|
||||
try:
|
||||
with pytest.raises(HTTPException) as missing:
|
||||
security.require_operator_request(_request())
|
||||
assert missing.value.status_code == 401
|
||||
request = _request([(b"x-appops-operator-token", b"test-operator-boundary-token")])
|
||||
assert security.require_operator_request(request) == "operator"
|
||||
finally:
|
||||
settings.operator_auth_required, settings.operator_token, security.settings.operator_auth_required, security.settings.operator_token = previous
|
||||
|
||||
|
||||
def test_disabled_operator_boundary_ignores_stale_configured_token():
|
||||
from backend.app.core import security
|
||||
from backend.app.core.config import settings
|
||||
|
||||
previous = (settings.operator_auth_required, settings.operator_token)
|
||||
settings.operator_auth_required = False
|
||||
settings.operator_token = "stale-operator-token-that-no-longer-unlocks"
|
||||
try:
|
||||
assert security.require_operator_request(_request()) == "private_unlocked"
|
||||
assert security.operator_session_status(_request()) == {
|
||||
"authorized": True,
|
||||
"mode": "private",
|
||||
"identity": None,
|
||||
}
|
||||
finally:
|
||||
settings.operator_auth_required, settings.operator_token = previous
|
||||
|
||||
|
||||
def test_operator_boundary_accepts_allowed_authentik_account_only_from_trusted_proxy():
|
||||
from backend.app.core import security
|
||||
from backend.app.core.config import settings
|
||||
|
||||
previous = (
|
||||
settings.operator_auth_required,
|
||||
settings.operator_token,
|
||||
settings.operator_proxy_auth_enabled,
|
||||
settings.operator_proxy_trusted_networks,
|
||||
settings.operator_proxy_users,
|
||||
settings.operator_proxy_groups,
|
||||
)
|
||||
settings.operator_auth_required = True
|
||||
settings.operator_token = "fallback-operator-token-value"
|
||||
settings.operator_proxy_auth_enabled = True
|
||||
settings.operator_proxy_trusted_networks = ["203.0.113.0/16"]
|
||||
settings.operator_proxy_users = ["example-host"]
|
||||
settings.operator_proxy_groups = ["appops-operators"]
|
||||
headers = [(b"x-authentik-username", b"example-host"), (b"x-authentik-groups", b"users|appops-operators")]
|
||||
try:
|
||||
assert security.require_operator_request(_request(headers, "203.0.113.8")) == "authentik:example-host"
|
||||
assert security.operator_session_status(_request(headers, "203.0.113.8")) == {
|
||||
"authorized": True,
|
||||
"mode": "account",
|
||||
"identity": "example-host",
|
||||
}
|
||||
assert security.require_operator_request(_request(headers + [(b"x-appops-operator-token", b"stale-token")], "203.0.113.8")) == "authentik:example-host"
|
||||
with pytest.raises(HTTPException) as spoofed:
|
||||
security.require_operator_request(_request(headers, "198.18.10.20"))
|
||||
assert spoofed.value.status_code == 401
|
||||
denied_headers = [(b"x-authentik-username", b"someone-else"), (b"x-authentik-groups", b"users")]
|
||||
monkeypatch.setenv("APPOPS_REQUIRE_OPERATOR_AUTH", "false")
|
||||
for headers in [[], [(b"x-appops-operator-token", b"legacy-token")]]:
|
||||
with pytest.raises(HTTPException) as denied:
|
||||
security.require_operator_request(_request(denied_headers, "203.0.113.8"))
|
||||
security.require_operator_request(_request(headers))
|
||||
assert denied.value.status_code == 401
|
||||
finally:
|
||||
(
|
||||
settings.operator_auth_required,
|
||||
settings.operator_token,
|
||||
settings.operator_proxy_auth_enabled,
|
||||
settings.operator_proxy_trusted_networks,
|
||||
settings.operator_proxy_users,
|
||||
settings.operator_proxy_groups,
|
||||
) = previous
|
||||
Reference in new issue
Block a user