
* core: initial app entitlements Signed-off-by: Jens Langhammer <jens@goauthentik.io> * base off of pbm Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add tests and oauth2 Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add to proxy Signed-off-by: Jens Langhammer <jens@goauthentik.io> * rewrite to use bindings Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make policy bindings form and list more customizable Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * double fix Signed-off-by: Jens Langhammer <jens@goauthentik.io> * refine permissions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add missing rbac modal to app entitlements Signed-off-by: Jens Langhammer <jens@goauthentik.io> * separate scope for app entitlements Signed-off-by: Jens Langhammer <jens@goauthentik.io> * include entitlements mapping in proxy Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add API validation to prevent policies from being bound to entitlements Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make preview Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add initial docs Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix Signed-off-by: Jens Langhammer <jens@goauthentik.io> * remove duplicate docs Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
154 lines
6.2 KiB
Python
154 lines
6.2 KiB
Python
"""Test Application Entitlements API"""
|
|
|
|
from django.urls import reverse
|
|
from guardian.shortcuts import assign_perm
|
|
from rest_framework.test import APITestCase
|
|
|
|
from authentik.core.models import Application, ApplicationEntitlement, Group
|
|
from authentik.core.tests.utils import create_test_admin_user, create_test_flow, create_test_user
|
|
from authentik.lib.generators import generate_id
|
|
from authentik.policies.dummy.models import DummyPolicy
|
|
from authentik.policies.models import PolicyBinding
|
|
from authentik.providers.oauth2.models import OAuth2Provider
|
|
|
|
|
|
class TestApplicationEntitlements(APITestCase):
|
|
"""Test application entitlements"""
|
|
|
|
def setUp(self) -> None:
|
|
self.user = create_test_user()
|
|
self.other_user = create_test_user()
|
|
self.provider = OAuth2Provider.objects.create(
|
|
name="test",
|
|
authorization_flow=create_test_flow(),
|
|
)
|
|
self.app: Application = Application.objects.create(
|
|
name=generate_id(),
|
|
slug=generate_id(),
|
|
provider=self.provider,
|
|
)
|
|
|
|
def test_user(self):
|
|
"""Test user-direct assignment"""
|
|
ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id())
|
|
PolicyBinding.objects.create(target=ent, user=self.user, order=0)
|
|
ents = self.user.app_entitlements(self.app)
|
|
self.assertEqual(len(ents), 1)
|
|
self.assertEqual(ents[0].name, ent.name)
|
|
|
|
def test_group(self):
|
|
"""Test direct group"""
|
|
group = Group.objects.create(name=generate_id())
|
|
self.user.ak_groups.add(group)
|
|
ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id())
|
|
PolicyBinding.objects.create(target=ent, group=group, order=0)
|
|
ents = self.user.app_entitlements(self.app)
|
|
self.assertEqual(len(ents), 1)
|
|
self.assertEqual(ents[0].name, ent.name)
|
|
|
|
def test_group_indirect(self):
|
|
"""Test indirect group"""
|
|
parent = Group.objects.create(name=generate_id())
|
|
group = Group.objects.create(name=generate_id(), parent=parent)
|
|
self.user.ak_groups.add(group)
|
|
ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id())
|
|
PolicyBinding.objects.create(target=ent, group=parent, order=0)
|
|
ents = self.user.app_entitlements(self.app)
|
|
self.assertEqual(len(ents), 1)
|
|
self.assertEqual(ents[0].name, ent.name)
|
|
|
|
def test_negate_user(self):
|
|
"""Test with negate flag"""
|
|
ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id())
|
|
PolicyBinding.objects.create(target=ent, user=self.other_user, order=0, negate=True)
|
|
ents = self.user.app_entitlements(self.app)
|
|
self.assertEqual(len(ents), 1)
|
|
self.assertEqual(ents[0].name, ent.name)
|
|
|
|
def test_negate_group(self):
|
|
"""Test with negate flag"""
|
|
other_group = Group.objects.create(name=generate_id())
|
|
ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id())
|
|
PolicyBinding.objects.create(target=ent, group=other_group, order=0, negate=True)
|
|
ents = self.user.app_entitlements(self.app)
|
|
self.assertEqual(len(ents), 1)
|
|
self.assertEqual(ents[0].name, ent.name)
|
|
|
|
def test_api_perms_global(self):
|
|
"""Test API creation with global permissions"""
|
|
assign_perm("authentik_core.add_applicationentitlement", self.user)
|
|
assign_perm("authentik_core.view_application", self.user)
|
|
self.client.force_login(self.user)
|
|
res = self.client.post(
|
|
reverse("authentik_api:applicationentitlement-list"),
|
|
data={
|
|
"name": generate_id(),
|
|
"app": self.app.pk,
|
|
},
|
|
)
|
|
self.assertEqual(res.status_code, 201)
|
|
|
|
def test_api_perms_scoped(self):
|
|
"""Test API creation with scoped permissions"""
|
|
assign_perm("authentik_core.add_applicationentitlement", self.user)
|
|
assign_perm("authentik_core.view_application", self.user, self.app)
|
|
self.client.force_login(self.user)
|
|
res = self.client.post(
|
|
reverse("authentik_api:applicationentitlement-list"),
|
|
data={
|
|
"name": generate_id(),
|
|
"app": self.app.pk,
|
|
},
|
|
)
|
|
self.assertEqual(res.status_code, 201)
|
|
|
|
def test_api_perms_missing(self):
|
|
"""Test API creation with no permissions"""
|
|
assign_perm("authentik_core.add_applicationentitlement", self.user)
|
|
self.client.force_login(self.user)
|
|
res = self.client.post(
|
|
reverse("authentik_api:applicationentitlement-list"),
|
|
data={
|
|
"name": generate_id(),
|
|
"app": self.app.pk,
|
|
},
|
|
)
|
|
self.assertEqual(res.status_code, 400)
|
|
self.assertJSONEqual(res.content, {"app": ["User does not have access to application."]})
|
|
|
|
def test_api_bindings_policy(self):
|
|
"""Test that API doesn't allow policies to be bound to this"""
|
|
ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id())
|
|
policy = DummyPolicy.objects.create(name=generate_id())
|
|
admin = create_test_admin_user()
|
|
self.client.force_login(admin)
|
|
response = self.client.post(
|
|
reverse("authentik_api:policybinding-list"),
|
|
data={
|
|
"target": ent.pbm_uuid,
|
|
"policy": policy.pk,
|
|
"order": 0,
|
|
},
|
|
)
|
|
self.assertJSONEqual(
|
|
response.content.decode(),
|
|
{"non_field_errors": ["One of 'group', 'user' must be set."]},
|
|
)
|
|
|
|
def test_api_bindings_group(self):
|
|
"""Test that API doesn't allow policies to be bound to this"""
|
|
ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id())
|
|
group = Group.objects.create(name=generate_id())
|
|
admin = create_test_admin_user()
|
|
self.client.force_login(admin)
|
|
response = self.client.post(
|
|
reverse("authentik_api:policybinding-list"),
|
|
data={
|
|
"target": ent.pbm_uuid,
|
|
"group": group.pk,
|
|
"order": 0,
|
|
},
|
|
)
|
|
self.assertEqual(response.status_code, 201)
|
|
self.assertTrue(PolicyBinding.objects.filter(target=ent.pbm_uuid).exists())
|