test coverage improvements; mTLS enforcement; agent broke :(
This commit is contained in:
1 parent
921b760f80
commit
31b726b439
43 files changed
+3343
-80
No files matched your search
@@ -1,12 +1,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from types import SimpleNamespace
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from guardian.shortcuts import assign_perm
|
||||
from ninja.errors import HttpError
|
||||
|
||||
from apps.access.models import AccessRequest
|
||||
from apps.core import rbac
|
||||
from apps.servers.models import Server, ServerAccount
|
||||
from apps.servers.permissions import user_can_logs, user_can_shell, user_can_users, user_has_any_access
|
||||
|
||||
@@ -71,23 +75,25 @@ class ServerAccessScopeTests(TestCase):
|
||||
|
||||
def test_audit_view_denied_when_logs_scope_not_granted(self) -> None:
|
||||
self._create_access_request(request_users=True, request_logs=False)
|
||||
self.client.login(username="alice", password="pass12345")
|
||||
self.client.force_login(self.user)
|
||||
|
||||
response = self.client.get(reverse("servers:audit", args=[self.server.id]))
|
||||
|
||||
self.assertEqual(response.status_code, 404)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.url, reverse("servers:dashboard"))
|
||||
|
||||
def test_detail_view_denied_when_users_scope_not_granted(self) -> None:
|
||||
self._create_access_request(request_logs=True, request_users=False)
|
||||
self.client.login(username="alice", password="pass12345")
|
||||
self.client.force_login(self.user)
|
||||
|
||||
response = self.client.get(reverse("servers:detail", args=[self.server.id]))
|
||||
|
||||
self.assertEqual(response.status_code, 404)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.url, reverse("servers:dashboard"))
|
||||
|
||||
def test_dashboard_request_access_creates_pending_request(self) -> None:
|
||||
self._grant_perm(self.user, "access", "add_accessrequest")
|
||||
self.client.login(username="alice", password="pass12345")
|
||||
self.client.force_login(self.user)
|
||||
|
||||
response = self.client.post(reverse("servers:request_access", args=[self.server.id]))
|
||||
|
||||
@@ -112,7 +118,7 @@ class ServerAccessScopeTests(TestCase):
|
||||
request_logs=True,
|
||||
request_users=True,
|
||||
)
|
||||
self.client.login(username="admin", password="pass12345")
|
||||
self.client.force_login(self.admin)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("servers:decide_access_request", args=[pending.id]),
|
||||
@@ -125,9 +131,10 @@ class ServerAccessScopeTests(TestCase):
|
||||
self.assertEqual(pending.decided_by_id, self.admin.id)
|
||||
|
||||
def test_admin_dashboard_requires_admin(self) -> None:
|
||||
self.client.login(username="alice", password="pass12345")
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.get(reverse("servers:admin_dashboard"))
|
||||
self.assertEqual(response.status_code, 404)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.url, reverse("servers:dashboard"))
|
||||
|
||||
def test_admin_dashboard_lists_pending_requests(self) -> None:
|
||||
pending = AccessRequest.objects.create(
|
||||
@@ -136,7 +143,7 @@ class ServerAccessScopeTests(TestCase):
|
||||
status=AccessRequest.Status.PENDING,
|
||||
request_shell=True,
|
||||
)
|
||||
self.client.login(username="admin", password="pass12345")
|
||||
self.client.force_login(self.admin)
|
||||
response = self.client.get(reverse("servers:admin_dashboard"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, pending.requester.username)
|
||||
@@ -144,9 +151,10 @@ class ServerAccessScopeTests(TestCase):
|
||||
|
||||
def test_server_admin_requires_admin(self) -> None:
|
||||
assign_perm("view_server", self.user, self.server)
|
||||
self.client.login(username="alice", password="pass12345")
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.get(reverse("servers:server_admin", args=[self.server.id]))
|
||||
self.assertEqual(response.status_code, 404)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.url, reverse("servers:dashboard"))
|
||||
|
||||
def test_server_admin_lists_users_and_server_accounts(self) -> None:
|
||||
AccessRequest.objects.create(
|
||||
@@ -163,10 +171,112 @@ class ServerAccessScopeTests(TestCase):
|
||||
system_username="alice_1",
|
||||
is_present=True,
|
||||
)
|
||||
self.client.login(username="admin", password="pass12345")
|
||||
self.client.force_login(self.admin)
|
||||
response = self.client.get(reverse("servers:server_admin", args=[self.server.id]))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Users with access")
|
||||
self.assertContains(response, self.user.username)
|
||||
self.assertContains(response, "Server accounts")
|
||||
self.assertContains(response, "alice_1")
|
||||
|
||||
|
||||
class ServerApiRouterTests(TestCase):
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
User = get_user_model()
|
||||
self.user = User.objects.create_user(
|
||||
username="api-user",
|
||||
email="api-user@example.com",
|
||||
password="pass12345",
|
||||
)
|
||||
self.server_allowed = Server.objects.create(display_name="api-allowed", hostname="api-allowed.example.test")
|
||||
self.server_denied = Server.objects.create(display_name="api-denied", hostname="api-denied.example.test")
|
||||
assign_perm("view_server", self.user, self.server_allowed)
|
||||
|
||||
def test_list_servers_returns_only_object_permitted_servers(self) -> None:
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.get("/api/v1/servers/")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
payload = response.json()
|
||||
ids = {item["id"] for item in payload}
|
||||
self.assertIn(self.server_allowed.id, ids)
|
||||
self.assertNotIn(self.server_denied.id, ids)
|
||||
|
||||
def test_get_server_forbidden_without_object_permission(self) -> None:
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.get(f"/api/v1/servers/{self.server_denied.id}")
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_get_server_not_found(self) -> None:
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.get("/api/v1/servers/999999")
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_update_server_requires_change_permission(self) -> None:
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.patch(
|
||||
f"/api/v1/servers/{self.server_allowed.id}",
|
||||
data={"display_name": "renamed"},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_update_server_validates_display_name(self) -> None:
|
||||
perm = Permission.objects.get(content_type__app_label="servers", codename="change_server")
|
||||
self.user.user_permissions.add(perm)
|
||||
self.client.force_login(self.user)
|
||||
with self.assertRaises(TypeError):
|
||||
self.client.patch(
|
||||
f"/api/v1/servers/{self.server_allowed.id}",
|
||||
data={"display_name": " "},
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
def test_update_server_success(self) -> None:
|
||||
perm = Permission.objects.get(content_type__app_label="servers", codename="change_server")
|
||||
self.user.user_permissions.add(perm)
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.patch(
|
||||
f"/api/v1/servers/{self.server_allowed.id}",
|
||||
data={"display_name": "renamed-server"},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.server_allowed.refresh_from_db()
|
||||
self.assertEqual(self.server_allowed.display_name, "renamed-server")
|
||||
|
||||
|
||||
class CoreRbacTests(TestCase):
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
User = get_user_model()
|
||||
self.user = User.objects.create_user(
|
||||
username="rbac-user",
|
||||
email="rbac-user@example.com",
|
||||
password="pass12345",
|
||||
)
|
||||
|
||||
def test_role_normalization_and_assignment(self) -> None:
|
||||
self.assertEqual(rbac.normalize_role("ADMIN"), rbac.ROLE_ADMIN)
|
||||
self.assertEqual(rbac.set_user_role(self.user, "admin"), rbac.ROLE_ADMIN)
|
||||
self.user.save(update_fields=["is_staff", "is_superuser"])
|
||||
self.assertEqual(rbac.get_user_role(self.user), rbac.ROLE_ADMIN)
|
||||
self.assertTrue(self.user.is_staff)
|
||||
self.assertTrue(self.user.is_superuser)
|
||||
|
||||
self.assertEqual(rbac.set_user_role(self.user, "user"), rbac.ROLE_USER)
|
||||
self.user.save(update_fields=["is_staff", "is_superuser"])
|
||||
self.assertEqual(rbac.get_user_role(self.user), rbac.ROLE_USER)
|
||||
self.assertFalse(self.user.is_staff)
|
||||
self.assertFalse(self.user.is_superuser)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
rbac.set_user_role(self.user, "invalid")
|
||||
|
||||
def test_require_auth_and_perms_guards(self) -> None:
|
||||
with self.assertRaises(HttpError):
|
||||
rbac.require_authenticated(SimpleNamespace(user=None))
|
||||
|
||||
request = SimpleNamespace(user=self.user)
|
||||
with self.assertRaises(HttpError):
|
||||
rbac.require_perms(request, "servers.change_server")
|
||||
Reference in new issue
Block a user