diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 86f1b333e..ee5b39a47 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -382,6 +382,14 @@ LOGIN_URL = '/{}login/'.format(BASE_PATH) CSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS +# Exclude potentially sensitive models from wildcard view exemption. These may still be exempted +# by specifying the model individually in the EXEMPT_VIEW_PERMISSIONS configuration parameter. +EXEMPT_EXCLUDE_MODELS = ( + ('auth', 'group'), + ('auth', 'user'), + ('users', 'objectpermission'), +) + # # Caching # diff --git a/netbox/users/tests/test_api.py b/netbox/users/tests/test_api.py index 42c5a3e03..1cd5892e9 100644 --- a/netbox/users/tests/test_api.py +++ b/netbox/users/tests/test_api.py @@ -128,17 +128,3 @@ class ObjectPermissionTest(APIViewTestCases.APIViewTestCase): 'constraints': {'name': 'TEST6'}, }, ] - - @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) - def test_list_objects_anonymous(self): - # Endpoint should never be exposed via EXEMPT_VIEW_PERMISSIONS - url = self._get_list_url() - with disable_warnings('django.request'): - self.assertHttpStatus(self.client.get(url, **self.header), status.HTTP_403_FORBIDDEN) - - @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) - def test_get_object_anonymous(self): - # Endpoint should never be exposed via EXEMPT_VIEW_PERMISSIONS - url = self._get_detail_url(self._get_queryset().first()) - with disable_warnings('django.request'): - self.assertHttpStatus(self.client.get(url, **self.header), status.HTTP_403_FORBIDDEN) diff --git a/netbox/utilities/permissions.py b/netbox/utilities/permissions.py index 0321fc6a7..b6bddcf61 100644 --- a/netbox/utilities/permissions.py +++ b/netbox/utilities/permissions.py @@ -1,12 +1,6 @@ from django.conf import settings from django.contrib.contenttypes.models import ContentType -# Exclude potentially sensitive models from wild view exemption. These may still be exempted -# by specifying the model individually in the EXEMPT_VIEW_PERMISSIONS configuration parameter. -EXEMPT_EXCLUDE_MODELS = ( - ('users', 'objectpermission'), -) - def get_permission_for_model(model, action): """ @@ -70,7 +64,7 @@ def permission_is_exempt(name): if action == 'view': if ( # All models (excluding those in EXEMPT_EXCLUDE_MODELS) are exempt from view permission enforcement - '*' in settings.EXEMPT_VIEW_PERMISSIONS and (app_label, model_name) not in EXEMPT_EXCLUDE_MODELS + '*' in settings.EXEMPT_VIEW_PERMISSIONS and (app_label, model_name) not in settings.EXEMPT_EXCLUDE_MODELS ) or ( # This specific model is exempt from view permission enforcement f'{app_label}.{model_name}' in settings.EXEMPT_VIEW_PERMISSIONS diff --git a/netbox/utilities/testing/api.py b/netbox/utilities/testing/api.py index f46bcae35..bf6ebd7ff 100644 --- a/netbox/utilities/testing/api.py +++ b/netbox/utilities/testing/api.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.urls import reverse @@ -62,8 +63,13 @@ class APIViewTestCases: GET a single object as an unauthenticated user. """ url = self._get_detail_url(self._get_queryset().first()) - response = self.client.get(url, **self.header) - self.assertHttpStatus(response, status.HTTP_200_OK) + if (self.model._meta.app_label, self.model._meta.model_name) in settings.EXEMPT_EXCLUDE_MODELS: + # Models listed in EXEMPT_EXCLUDE_MODELS should not be accessible to anonymous users + with disable_warnings('django.request'): + self.assertHttpStatus(self.client.get(url, **self.header), status.HTTP_403_FORBIDDEN) + else: + response = self.client.get(url, **self.header) + self.assertHttpStatus(response, status.HTTP_200_OK) @override_settings(EXEMPT_VIEW_PERMISSIONS=[]) def test_get_object_without_permission(self): @@ -111,10 +117,14 @@ class APIViewTestCases: GET a list of objects as an unauthenticated user. """ url = self._get_list_url() - response = self.client.get(url, **self.header) - - self.assertHttpStatus(response, status.HTTP_200_OK) - self.assertEqual(len(response.data['results']), self._get_queryset().count()) + if (self.model._meta.app_label, self.model._meta.model_name) in settings.EXEMPT_EXCLUDE_MODELS: + # Models listed in EXEMPT_EXCLUDE_MODELS should not be accessible to anonymous users + with disable_warnings('django.request'): + self.assertHttpStatus(self.client.get(url, **self.header), status.HTTP_403_FORBIDDEN) + else: + response = self.client.get(url, **self.header) + self.assertHttpStatus(response, status.HTTP_200_OK) + self.assertEqual(len(response.data['results']), self._get_queryset().count()) @override_settings(EXEMPT_VIEW_PERMISSIONS=[]) def test_list_objects_brief(self):