140 lines
5.2 KiB
Python
140 lines
5.2 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
from app.minio_provisioning import default_namespace, policy_json_for_backend
|
|
|
|
|
|
def _client(tmp_path, monkeypatch) -> TestClient:
|
|
monkeypatch.setenv("AUTHZ_DATA_DIR", str(tmp_path))
|
|
monkeypatch.setenv("AUTHZ_PRIVATE_KEY_PATH", str(tmp_path / "signing_key.pem"))
|
|
monkeypatch.setenv("AUTHZ_INTERNAL_TOKEN", "test-internal-token")
|
|
import app.main as main
|
|
|
|
main = importlib.reload(main)
|
|
return TestClient(main.app)
|
|
|
|
|
|
def _register_backend(client: TestClient) -> None:
|
|
response = client.post(
|
|
"/backends/register",
|
|
json={"backend_id": "alice", "name": "Alice", "base_url": "http://alice.local"},
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
|
|
def test_minio_settings_round_trip_with_masked_public_read(tmp_path, monkeypatch) -> None:
|
|
with _client(tmp_path, monkeypatch) as client:
|
|
_register_backend(client)
|
|
saved = client.post(
|
|
"/backends/alice/settings/minio",
|
|
json={
|
|
"endpoint": "minio.local:9000",
|
|
"access_key": "alice-access",
|
|
"secret_key": "alice-secret",
|
|
"bucket": "beaver-user-files",
|
|
"namespace": "users/alice",
|
|
"secure": True,
|
|
"region": "us-east-1",
|
|
},
|
|
)
|
|
public = client.get("/backends/alice/settings/minio")
|
|
internal = client.get(
|
|
"/internal/backends/alice/settings/minio",
|
|
headers={"Authorization": "Bearer test-internal-token"},
|
|
)
|
|
|
|
assert saved.status_code == 200
|
|
assert saved.json()["configured"] is True
|
|
assert saved.json()["endpoint"] == "minio.local:9000"
|
|
assert saved.json()["secret_key_masked"] is True
|
|
assert "secret_key" not in saved.json()
|
|
assert public.status_code == 200
|
|
assert public.json()["access_key"] == "alice-access"
|
|
assert public.json()["bucket"] == "beaver-user-files"
|
|
assert public.json()["namespace"] == "users/alice"
|
|
assert public.json()["secret_key_masked"] is True
|
|
assert "secret_key" not in public.json()
|
|
assert internal.status_code == 200
|
|
assert internal.json()["secret_key"] == "alice-secret"
|
|
assert internal.json()["bucket"] == "beaver-user-files"
|
|
assert internal.json()["namespace"] == "users/alice"
|
|
|
|
|
|
def test_minio_settings_preserve_secret_on_masked_update(tmp_path, monkeypatch) -> None:
|
|
with _client(tmp_path, monkeypatch) as client:
|
|
_register_backend(client)
|
|
first = client.post(
|
|
"/backends/alice/settings/minio",
|
|
json={
|
|
"endpoint": "minio.local:9000",
|
|
"access_key": "alice-access",
|
|
"secret_key": "alice-secret",
|
|
"bucket": "beaver-user-files",
|
|
"namespace": "users/alice",
|
|
},
|
|
)
|
|
updated = client.post(
|
|
"/backends/alice/settings/minio",
|
|
json={
|
|
"endpoint": "minio2.local:9000",
|
|
"access_key": "alice-access-2",
|
|
"secret_key": "",
|
|
"bucket": "beaver-user-files",
|
|
"namespace": "users/alice-v2",
|
|
},
|
|
)
|
|
internal = client.get(
|
|
"/internal/backends/alice/settings/minio",
|
|
headers={"Authorization": "Bearer test-internal-token"},
|
|
)
|
|
|
|
assert first.status_code == 200
|
|
assert updated.status_code == 200
|
|
assert updated.json()["endpoint"] == "minio2.local:9000"
|
|
assert updated.json()["namespace"] == "users/alice-v2"
|
|
assert internal.status_code == 200
|
|
assert internal.json()["secret_key"] == "alice-secret"
|
|
assert internal.json()["bucket"] == "beaver-user-files"
|
|
assert internal.json()["namespace"] == "users/alice-v2"
|
|
|
|
|
|
def test_minio_settings_delete_and_missing_behavior(tmp_path, monkeypatch) -> None:
|
|
with _client(tmp_path, monkeypatch) as client:
|
|
_register_backend(client)
|
|
missing_public = client.get("/backends/alice/settings/minio")
|
|
missing_internal = client.get(
|
|
"/internal/backends/alice/settings/minio",
|
|
headers={"Authorization": "Bearer test-internal-token"},
|
|
)
|
|
client.post(
|
|
"/backends/alice/settings/minio",
|
|
json={
|
|
"endpoint": "minio.local:9000",
|
|
"access_key": "alice-access",
|
|
"secret_key": "alice-secret",
|
|
"bucket": "beaver-user-files",
|
|
"namespace": "users/alice",
|
|
},
|
|
)
|
|
deleted = client.delete("/backends/alice/settings/minio")
|
|
after_delete = client.get("/backends/alice/settings/minio")
|
|
|
|
assert missing_public.status_code == 200
|
|
assert missing_public.json() == {"configured": False}
|
|
assert missing_internal.status_code == 404
|
|
assert deleted.status_code == 200
|
|
assert deleted.json() == {"ok": True}
|
|
assert after_delete.status_code == 200
|
|
assert after_delete.json() == {"configured": False}
|
|
|
|
|
|
def test_minio_namespace_policy_is_scoped_to_backend_prefix() -> None:
|
|
policy = policy_json_for_backend(backend_id="alice", bucket="beaver-user-files")
|
|
|
|
assert default_namespace("alice") == "users/alice"
|
|
assert "arn:aws:s3:::beaver-user-files/users/alice/*" in policy
|
|
assert "users/bob" not in policy
|