Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions dojo/announcement/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@
from django.utils.translation import gettext
from django.utils.translation import gettext_lazy as _

from dojo.authorization.authorization_decorators import (
user_is_configuration_authorized,
)
from dojo.forms import AnnouncementCreateForm, AnnouncementRemoveForm
from dojo.models import Announcement, UserAnnouncement
from dojo.utils import add_breadcrumb

logger = logging.getLogger(__name__)


@user_is_configuration_authorized("dojo.change_announcement")
def configure_announcement(request):
remove = False
if request.method == "GET":
Expand Down
16 changes: 9 additions & 7 deletions dojo/api_v2/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@
import dojo.finding.helper as finding_helper
import dojo.risk_acceptance.helper as ra_helper
from dojo.authorization.authorization import user_has_permission
from dojo.authorization.models import (
Dojo_Group_Member,
Global_Role,
Product_Group,
Product_Member,
Product_Type_Group,
Product_Type_Member,
Role,
)
from dojo.authorization.roles_permissions import Permissions
from dojo.celery_dispatch import dojo_dispatch_task
from dojo.endpoint.utils import endpoint_filter, endpoint_meta_import
Expand Down Expand Up @@ -59,7 +68,6 @@
Cred_User,
Development_Environment,
Dojo_Group,
Dojo_Group_Member,
Dojo_User,
DojoMeta,
Endpoint,
Expand All @@ -73,7 +81,6 @@
Finding_Group,
Finding_Template,
General_Survey,
Global_Role,
Language_Type,
Languages,
Network_Locations,
Expand All @@ -82,15 +89,10 @@
Notes,
Product,
Product_API_Scan_Configuration,
Product_Group,
Product_Member,
Product_Type,
Product_Type_Group,
Product_Type_Member,
Question,
Regulation,
Risk_Acceptance,
Role,
SLA_Configuration,
Sonarqube_Issue,
Sonarqube_Issue_Transition,
Expand Down
18 changes: 10 additions & 8 deletions dojo/api_v2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,21 @@
mixins as dojo_mixins,
)
from dojo.api_v2 import (
permissions,
prefetch,
serializers,
)
from dojo.api_v2.prefetch.prefetcher import _Prefetcher
from dojo.authorization import api_permissions as permissions
from dojo.authorization.authorization import user_has_permission_or_403
from dojo.authorization.models import (
Dojo_Group_Member,
Global_Role,
Product_Group,
Product_Member,
Product_Type_Group,
Product_Type_Member,
Role,
)
from dojo.authorization.roles_permissions import Permissions
from dojo.celery_dispatch import dojo_dispatch_task
from dojo.cred.queries import get_authorized_cred_mappings
Expand Down Expand Up @@ -100,7 +109,6 @@
Cred_User,
Development_Environment,
Dojo_Group,
Dojo_Group_Member,
Dojo_User,
DojoMeta,
Endpoint,
Expand All @@ -112,7 +120,6 @@
Finding,
Finding_Template,
General_Survey,
Global_Role,
Language_Type,
Languages,
Network_Locations,
Expand All @@ -121,15 +128,10 @@
Notes,
Product,
Product_API_Scan_Configuration,
Product_Group,
Product_Member,
Product_Type,
Product_Type_Group,
Product_Type_Member,
Question,
Regulation,
Risk_Acceptance,
Role,
SLA_Configuration,
Sonarqube_Issue,
Sonarqube_Issue_Transition,
Expand Down
6 changes: 4 additions & 2 deletions dojo/asset/api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field

from dojo.authorization.models import (
Product_Group,
Product_Member,
)
from dojo.filters import (
CharFieldFilterANDExpression,
CharFieldInFilter,
Expand All @@ -16,8 +20,6 @@
from dojo.models import (
Product,
Product_API_Scan_Configuration,
Product_Group,
Product_Member,
)

labels = get_labels()
Expand Down
6 changes: 4 additions & 2 deletions dojo/asset/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@

from dojo.api_v2.serializers import ProductMetaSerializer, TagListSerializerField
from dojo.authorization.authorization import user_has_permission
from dojo.authorization.models import (
Product_Group,
Product_Member,
)
from dojo.authorization.roles_permissions import Permissions
from dojo.models import (
Dojo_User,
Product,
Product_API_Scan_Configuration,
Product_Group,
Product_Member,
)
from dojo.organization.api.serializers import RelatedOrganizationField
from dojo.product.queries import get_authorized_products
Expand Down
9 changes: 6 additions & 3 deletions dojo/asset/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from rest_framework.response import Response

import dojo.api_v2.mixins as dojo_mixins
from dojo.api_v2 import permissions, prefetch
from dojo.api_v2 import prefetch
from dojo.api_v2.serializers import ReportGenerateOptionSerializer, ReportGenerateSerializer
from dojo.api_v2.views import PrefetchDojoModelViewSet, report_generate, schema_with_prefetch
from dojo.asset.api import serializers
Expand All @@ -16,12 +16,15 @@
AssetGroupFilterSet,
AssetMemberFilterSet,
)
from dojo.authorization import api_permissions as permissions
from dojo.authorization.models import (
Product_Group,
Product_Member,
)
from dojo.authorization.roles_permissions import Permissions
from dojo.models import (
Product,
Product_API_Scan_Configuration,
Product_Group,
Product_Member,
)
from dojo.product.queries import (
get_authorized_product_api_scan_configurations,
Expand Down
11 changes: 11 additions & 0 deletions dojo/authorization/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Import query_registrations to trigger RBAC filter registration at startup
from dojo.authorization import query_registrations # noqa: F401
from dojo.authorization.authorization import ( # noqa: F401
user_has_configuration_permission,
user_has_global_permission,
user_has_global_permission_or_403,
user_has_permission,
user_has_permission_or_403,
user_is_superuser_or_global_owner,
)
from dojo.authorization.roles_permissions import Permissions, Roles # noqa: F401
Original file line number Diff line number Diff line change
Expand Up @@ -1285,3 +1285,41 @@ class UserHasConfigurationPermissionSuperuser(

def has_permission(self, request, view):
return super().has_permission(request, view)


class LocationFindingReferencePermission(permissions.BasePermission):
def has_permission(self, request, view):
return check_post_permission(
request,
Finding,
"finding",
Permissions.Finding_Edit,
)

def has_object_permission(self, request, view, obj):
return check_object_permission(
request,
obj.finding,
Permissions.Finding_View,
Permissions.Finding_Edit,
Permissions.Finding_Edit,
)


class LocationProductReferencePermission(permissions.BasePermission):
def has_permission(self, request, view):
return check_post_permission(
request,
Product,
"product",
Permissions.Product_Edit,
)

def has_object_permission(self, request, view, obj):
return check_object_permission(
request,
obj.product,
Permissions.Product_View,
Permissions.Product_Edit,
Permissions.Product_Edit,
)
12 changes: 7 additions & 5 deletions dojo/authorization/authorization.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
from django.core.exceptions import PermissionDenied
from django.db.models import Model, QuerySet

from dojo.authorization.models import (
Dojo_Group_Member,
Product_Group,
Product_Member,
Product_Type_Group,
Product_Type_Member,
)
from dojo.authorization.roles_permissions import (
Permissions,
Roles,
Expand All @@ -12,7 +19,6 @@
App_Analysis,
Cred_Mapping,
Dojo_Group,
Dojo_Group_Member,
Dojo_User,
Endpoint,
Engagement,
Expand All @@ -21,11 +27,7 @@
Languages,
Product,
Product_API_Scan_Configuration,
Product_Group,
Product_Member,
Product_Type,
Product_Type_Group,
Product_Type_Member,
Risk_Acceptance,
Stub_Finding,
Test,
Expand Down
50 changes: 50 additions & 0 deletions dojo/authorization/middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404

from dojo.authorization.authorization import (
user_has_configuration_permission,
user_has_global_permission_or_403,
user_has_permission_or_403,
)
from dojo.authorization.url_permissions import URL_PERMISSIONS


class AuthorizationMiddleware:
def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
return self.get_response(request)

def process_view(self, request, view_func, view_args, view_kwargs):
# Skip API paths -- DRF has its own permission classes
if request.path.startswith("/api/"):
return

resolver_match = request.resolver_match
if resolver_match is None:
return

url_name = resolver_match.url_name
checks = URL_PERMISSIONS.get(url_name)
if not checks:
return

for check in checks:
check_type = check[0]
if check_type == "global":
_, permission = check
user_has_global_permission_or_403(request.user, permission)
elif check_type == "config":
_, permission = check
if not user_has_configuration_permission(request.user, permission):
raise PermissionDenied
elif check_type == "object":
_, model, permission, arg_name = check
lookup_value = view_kwargs.get(arg_name)
if lookup_value is None:
continue # kwarg not present, skip this check
obj = get_object_or_404(model, pk=lookup_value)
user_has_permission_or_403(request.user, obj, permission)

return
68 changes: 68 additions & 0 deletions dojo/authorization/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from django.db import models
from django.utils.translation import gettext_lazy as _


class Role(models.Model):
name = models.CharField(max_length=255, unique=True)
is_owner = models.BooleanField(default=False)

class Meta:
app_label = "dojo"
ordering = ("name",)

def __str__(self):
return self.name


class Dojo_Group_Member(models.Model):
group = models.ForeignKey("dojo.Dojo_Group", on_delete=models.CASCADE)
user = models.ForeignKey("dojo.Dojo_User", on_delete=models.CASCADE)
role = models.ForeignKey(Role, on_delete=models.CASCADE, help_text=_("This role determines the permissions of the user to manage the group."), verbose_name=_("Group role"))

class Meta:
app_label = "dojo"


class Global_Role(models.Model):
user = models.OneToOneField("dojo.Dojo_User", null=True, blank=True, on_delete=models.CASCADE)
group = models.OneToOneField("dojo.Dojo_Group", null=True, blank=True, on_delete=models.CASCADE)
role = models.ForeignKey(Role, on_delete=models.CASCADE, null=True, blank=True, help_text=_("The global role will be applied to all product types and products."), verbose_name=_("Global role"))

class Meta:
app_label = "dojo"


class Product_Member(models.Model):
product = models.ForeignKey("dojo.Product", on_delete=models.CASCADE)
user = models.ForeignKey("dojo.Dojo_User", on_delete=models.CASCADE)
role = models.ForeignKey(Role, on_delete=models.CASCADE)

class Meta:
app_label = "dojo"


class Product_Group(models.Model):
product = models.ForeignKey("dojo.Product", on_delete=models.CASCADE)
group = models.ForeignKey("dojo.Dojo_Group", on_delete=models.CASCADE)
role = models.ForeignKey(Role, on_delete=models.CASCADE)

class Meta:
app_label = "dojo"


class Product_Type_Member(models.Model):
product_type = models.ForeignKey("dojo.Product_Type", on_delete=models.CASCADE)
user = models.ForeignKey("dojo.Dojo_User", on_delete=models.CASCADE)
role = models.ForeignKey(Role, on_delete=models.CASCADE)

class Meta:
app_label = "dojo"


class Product_Type_Group(models.Model):
product_type = models.ForeignKey("dojo.Product_Type", on_delete=models.CASCADE)
group = models.ForeignKey("dojo.Dojo_Group", on_delete=models.CASCADE)
role = models.ForeignKey(Role, on_delete=models.CASCADE)

class Meta:
app_label = "dojo"
Loading
Loading