fix: fix rbac to dev (#7636)

* feat: 添加 RBAC 应用模块

* feat: 添加 RBAC Model、API

* feat: 添加 RBAC Model、API 2

* feat: 添加 RBAC Model、API 3

* feat: 添加 RBAC Model、API 4

* feat: RBAC

* feat: RBAC

* feat: RBAC

* feat: RBAC

* feat: RBAC

* feat: RBAC 整理权限位

* feat: RBAC 整理权限位2

* feat: RBAC 整理权限位2

* feat: RBAC 整理权限位

* feat: RBAC 添加默认角色

* feat: RBAC 添加迁移文件;迁移用户角色->用户角色绑定

* feat: RBAC 添加迁移文件;迁移用户角色->用户角色绑定

* feat: RBAC 修改用户模块API

* feat: RBAC 添加组织模块迁移文件 & 修改组织模块API

* feat: RBAC 添加组织模块迁移文件 & 修改组织模块API

* feat: RBAC 修改用户角色属性的使用

* feat: RBAC No.1

* xxx

* perf: 暂存

* perf: ...

* perf(rbac): 添加 perms 到 profile serializer 中

* stash

* perf: 使用init

* perf: 修改migrations

* perf: rbac

* stash

* stash

* pref: 修改rbac

* stash it

* stash: 先去修复其他bug

* perf: 修改 role 添加 users

* pref: 修改 RBAC Model

* feat: 添加权限的 tree api

* stash: 暂存一下

* stash: 暂存一下

* perf: 修改 model verbose name

* feat: 添加model各种 verbose name

* perf: 生成 migrations

* perf: 优化权限位

* perf: 添加迁移脚本

* feat: 添加组织角色迁移

* perf: 添加迁移脚本

* stash

* perf: 添加migrateion

* perf: 暂存一下

* perf: 修改rbac

* perf: stash it

* fix: 迁移冲突

* fix: 迁移冲突

* perf: 暂存一下

* perf: 修改 rbac 逻辑

* stash: 暂存一下

* perf: 修改内置角色

* perf: 解决 root 组织的问题

* perf: stash it

* perf: 优化 rbac

* perf: 优化 rolebinding 处理

* perf: 完成用户离开组织的问题

* perf: 暂存一下

* perf: 修改翻译

* perf: 去掉了 IsSuperUser

* perf: IsAppUser 去掉完成

* perf: 修改 connection token 的权限

* perf: 去掉导入的问题

* perf: perms define 格式,修改 app 用户 的全新啊

* perf: 修改 permission

* perf: 去掉一些 org admin

* perf: 去掉部分 org admin

* perf: 再去掉点 org admin role

* perf: 再去掉部分 org admin

* perf: user 角色搜索

* perf: 去掉很多 js

* perf: 添加权限位

* perf: 修改权限

* perf: 去掉一个 todo

* merge: with dev

* fix: 修复冲突

Co-authored-by: Bai <bugatti_it@163.com>
Co-authored-by: Michael Bai <baijiangjie@gmail.com>
Co-authored-by: ibuler <ibuler@qq.com>
This commit is contained in:
fit2bot
2022-02-17 20:13:31 +08:00
committed by GitHub
parent b088362ae3
commit e259d2a9e9
263 changed files with 3049 additions and 62465 deletions

View File

@@ -9,10 +9,9 @@ from rest_framework.fields import DateTimeField
from rest_framework.response import Response
from django.template import loader
from terminal.models import CommandStorage, Session
from terminal.models import CommandStorage, Session, Command
from terminal.filters import CommandFilter
from orgs.utils import current_org
from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor, IsAppUser
from common.drf.api import JMSBulkModelViewSet
from common.utils import get_logger
from terminal.serializers import InsecureCommandAlertSerializer
@@ -29,7 +28,6 @@ __all__ = ['CommandViewSet', 'CommandExportApi', 'InsecureCommandAlertAPI']
class CommandQueryMixin:
command_store = get_command_storage()
permission_classes = [IsOrgAdminOrAppUser | IsOrgAuditor]
filterset_fields = [
"asset", "system_user", "user", "session", "risk_level",
"input"
@@ -105,9 +103,9 @@ class CommandViewSet(JMSBulkModelViewSet):
"""
command_store = get_command_storage()
permission_classes = [IsOrgAdminOrAppUser | IsOrgAuditor]
serializer_class = SessionCommandSerializer
filterset_class = CommandFilter
model = Command
ordering_fields = ('timestamp', )
def merge_all_storage_list(self, request, *args, **kwargs):
@@ -191,6 +189,9 @@ class CommandViewSet(JMSBulkModelViewSet):
class CommandExportApi(CommandQueryMixin, generics.ListAPIView):
serializer_class = SessionCommandSerializer
rbac_perms = {
'list': 'terminal.view_command'
}
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
@@ -210,8 +211,10 @@ class CommandExportApi(CommandQueryMixin, generics.ListAPIView):
class InsecureCommandAlertAPI(generics.CreateAPIView):
permission_classes = [IsAppUser]
serializer_class = InsecureCommandAlertSerializer
rbac_perms = {
'POST': 'terminal.add_command'
}
def post(self, request, *args, **kwargs):
serializer = InsecureCommandAlertSerializer(data=request.data, many=True)

View File

@@ -13,16 +13,15 @@ from rest_framework.response import Response
from rest_framework.decorators import action
from common.utils import data_to_json
from .. import utils
from common.const.http import GET
from common.utils import get_logger, get_object_or_none
from common.mixins.api import AsyncApiMixin
from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor, IsAppUser
from common.drf.filters import DatetimeRangeFilter
from common.drf.renders import PassthroughRenderer
from orgs.mixins.api import OrgBulkModelViewSet
from orgs.utils import tmp_to_root_org, tmp_to_org
from users.models import User
from .. import utils
from ..utils import find_session_replay_local, download_session_replay
from ..models import Session
from .. import serializers
@@ -41,15 +40,18 @@ class SessionViewSet(OrgBulkModelViewSet):
'default': serializers.SessionSerializer,
'display': serializers.SessionDisplaySerializer,
}
permission_classes = (IsOrgAdminOrAppUser,)
search_fields = [
"user", "asset", "system_user", "remote_addr", "protocol", "is_finished", 'login_from',
"user", "asset", "system_user", "remote_addr",
"protocol", "is_finished", 'login_from',
]
filterset_fields = search_fields + ['terminal']
date_range_filter_fields = [
('date_start', ('date_from', 'date_to'))
]
extra_filter_backends = [DatetimeRangeFilter]
rbac_perms = {
'download': ['terminal.download_sessionreplay']
}
@staticmethod
def prepare_offline_file(session, local_path):
@@ -103,17 +105,15 @@ class SessionViewSet(OrgBulkModelViewSet):
serializer.validated_data["terminal"] = self.request.user.terminal
return super().perform_create(serializer)
def get_permissions(self):
if self.request.method.lower() in ['get', 'options']:
self.permission_classes = (IsOrgAdminOrAppUser | IsOrgAuditor,)
return super().get_permissions()
class SessionReplayViewSet(AsyncApiMixin, viewsets.ViewSet):
serializer_class = serializers.ReplaySerializer
permission_classes = (IsOrgAdminOrAppUser | IsOrgAuditor,)
session = None
download_cache_key = "SESSION_REPLAY_DOWNLOAD_{}"
session = None
rbac_perms = {
'create': 'terminal.upload_session',
'retrieve': 'terminal.download_session',
}
def create(self, request, *args, **kwargs):
session_id = kwargs.get('pk')
@@ -175,8 +175,13 @@ class SessionReplayViewSet(AsyncApiMixin, viewsets.ViewSet):
class SessionJoinValidateAPI(views.APIView):
permission_classes = (IsAppUser,)
"""
监控用
"""
serializer_class = serializers.SessionJoinValidateSerializer
rbac_perms = {
'POST': 'terminal.validate_sessionactionperm'
}
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data)
@@ -199,11 +204,12 @@ class SessionJoinValidateAPI(views.APIView):
if not user:
msg = _('User does not exist: {}'.format(user_id))
return Response({'ok': False, 'msg': msg}, status=401)
with tmp_to_org(session.org):
if is_session_approver(session_id, user_id):
return Response({'ok': True, 'msg': ''}, status=200)
if not user.admin_or_audit_orgs:
if not user.has_perm('terminal.monitor_session'):
msg = _('User does not have permission')
return Response({'ok': False, 'msg': msg}, status=401)

View File

@@ -3,8 +3,9 @@ from rest_framework.decorators import action
from rest_framework.response import Response
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from common.permissions import IsAppUser, IsSuperUser
from common.const.http import PATCH
from common.permissions import IsValidUser
from orgs.mixins.api import OrgModelViewSet
from .. import serializers, models
@@ -13,21 +14,22 @@ __all__ = ['SessionSharingViewSet', 'SessionJoinRecordsViewSet']
class SessionSharingViewSet(OrgModelViewSet):
serializer_class = serializers.SessionSharingSerializer
permission_classes = (IsAppUser | IsSuperUser, )
search_fields = ('session', 'creator', 'is_active', 'expired_time')
filterset_fields = search_fields
model = models.SessionSharing
rbac_perms = {
'create': 'terminal.add_supersessionsharing',
}
def get_permissions(self):
if self.request.method.lower() in ['post']:
self.permission_classes = (IsAppUser,)
return super().get_permissions()
def get_queryset(self):
queryset = models.SessionSharing.objects.filter(creator=self.request.user)
return queryset
def create(self, request, *args, **kwargs):
def dispatch(self, request, *args, **kwargs):
if not settings.SECURITY_SESSION_SHARE:
detail = _('Secure session sharing settings is disabled')
raise MethodNotAllowed(self.action, detail=detail)
return super().create(request, *args, **kwargs)
return super().dispatch(request, *args, **kwargs)
def destroy(self, request, *args, **kwargs):
raise MethodNotAllowed(self.action)
@@ -35,7 +37,6 @@ class SessionSharingViewSet(OrgModelViewSet):
class SessionJoinRecordsViewSet(OrgModelViewSet):
serializer_class = serializers.SessionJoinRecordSerializer
permission_classes = (IsAppUser | IsSuperUser, )
search_fields = (
'sharing', 'session', 'joiner', 'date_joined', 'date_left',
'login_from', 'is_success', 'is_finished'
@@ -43,11 +44,6 @@ class SessionJoinRecordsViewSet(OrgModelViewSet):
filterset_fields = search_fields
model = models.SessionJoinRecord
def get_permissions(self):
if self.request.method.lower() in ['post']:
self.permission_classes = (IsAppUser,)
return super().get_permissions()
def create(self, request, *args, **kwargs):
try:
response = super().create(request, *args, **kwargs)

View File

@@ -4,10 +4,9 @@
import logging
from django.shortcuts import get_object_or_404
from rest_framework import viewsets, generics
from rest_framework.views import Response
from rest_framework.views import Response
from rest_framework import status
from common.permissions import IsAppUser, IsOrgAdminOrAppUser, IsSuperUser
from ..models import Terminal, Status, Session
from .. import serializers
from ..utils import TypedComponentsStatusMetricsUtil
@@ -15,16 +14,12 @@ from ..utils import TypedComponentsStatusMetricsUtil
logger = logging.getLogger(__file__)
__all__ = [
'StatusViewSet',
'ComponentsMetricsAPIView',
]
__all__ = ['StatusViewSet', 'ComponentsMetricsAPIView']
class StatusViewSet(viewsets.ModelViewSet):
queryset = Status.objects.all()
serializer_class = serializers.StatusSerializer
permission_classes = (IsOrgAdminOrAppUser,)
session_serializer_class = serializers.SessionSerializer
task_serializer_class = serializers.TaskSerializer
@@ -53,15 +48,12 @@ class StatusViewSet(viewsets.ModelViewSet):
serializer.validated_data["terminal"] = self.request.user.terminal
return super().perform_create(serializer)
def get_permissions(self):
if self.action == "create":
self.permission_classes = (IsAppUser,)
return super().get_permissions()
class ComponentsMetricsAPIView(generics.GenericAPIView):
""" 返回汇总组件指标数据 """
permission_classes = (IsSuperUser,)
rbac_perms = {
'GET': 'terminal.view_terminal'
}
def get(self, request, *args, **kwargs):
util = TypedComponentsStatusMetricsUtil()

View File

@@ -10,7 +10,6 @@ from django_filters import utils
from terminal import const
from common.const.http import GET
from common.permissions import IsSuperUser, IsOrgAuditor
from terminal.filters import CommandStorageFilter, CommandFilter, CommandFilterForStorageTree
from ..models import CommandStorage, ReplayStorage
from ..serializers import CommandStorageSerializer, ReplayStorageSerializer
@@ -39,10 +38,12 @@ class CommandStorageViewSet(BaseStorageViewSetMixin, viewsets.ModelViewSet):
search_fields = ('name', 'type')
queryset = CommandStorage.objects.all()
serializer_class = CommandStorageSerializer
permission_classes = (IsSuperUser,)
filterset_class = CommandStorageFilter
rbac_perms = {
'tree': 'terminal.view_commandstorage'
}
@action(methods=[GET], detail=False, permission_classes=(IsOrgAuditor, ), filterset_class=CommandFilterForStorageTree)
@action(methods=[GET], detail=False, filterset_class=CommandFilterForStorageTree)
def tree(self, request: Request):
storage_qs = self.get_queryset().exclude(name='null')
storages_with_count = []
@@ -107,12 +108,9 @@ class ReplayStorageViewSet(BaseStorageViewSetMixin, viewsets.ModelViewSet):
search_fields = filterset_fields
queryset = ReplayStorage.objects.all()
serializer_class = ReplayStorageSerializer
permission_classes = (IsSuperUser,)
class BaseStorageTestConnectiveMixin:
permission_classes = (IsSuperUser,)
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
try:

View File

@@ -7,7 +7,6 @@ from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from common.utils import get_object_or_none
from common.permissions import IsOrgAdminOrAppUser
from ..models import Session, Task
from .. import serializers
from terminal.utils import is_session_approver
@@ -22,7 +21,6 @@ class TaskViewSet(BulkModelViewSet):
queryset = Task.objects.all()
serializer_class = serializers.TaskSerializer
filterset_fields = ('is_finished',)
permission_classes = (IsOrgAdminOrAppUser,)
def kill_sessions(session_ids, user):
@@ -42,13 +40,10 @@ def kill_sessions(session_ids, user):
class KillSessionAPI(APIView):
permission_classes = (IsOrgAdminOrAppUser,)
def post(self, request, *args, **kwargs):
session_ids = request.data
user = request.user
validated_session = kill_sessions(session_ids, user)
return Response({"ok": validated_session})
model = Task
rbac_perms = {
'POST': 'terminal.terminate_session'
}
class KillSessionForTicketAPI(APIView):

View File

@@ -8,13 +8,12 @@ from rest_framework import generics
from rest_framework.views import APIView, Response
from rest_framework import status
from django.conf import settings
from django_filters import rest_framework as filters
from django.utils.translation import gettext_lazy as _
from common.exceptions import JMSException
from common.drf.api import JMSBulkModelViewSet
from common.utils import get_object_or_none
from common.permissions import IsAppUser, IsSuperUser, WithBootstrapToken
from common.permissions import WithBootstrapToken
from ..models import Terminal
from .. import serializers
from .. import exceptions
@@ -29,7 +28,6 @@ logger = logging.getLogger(__file__)
class TerminalViewSet(JMSBulkModelViewSet):
queryset = Terminal.objects.filter(is_deleted=False)
serializer_class = serializers.TerminalSerializer
permission_classes = (IsSuperUser,)
filterset_fields = ['name', 'remote_addr', 'type']
custom_filter_fields = ['status']
@@ -86,7 +84,9 @@ class TerminalViewSet(JMSBulkModelViewSet):
class TerminalConfig(APIView):
permission_classes = (IsAppUser,)
rbac_perms = {
'GET': 'view_terminalconfig'
}
def get(self, request):
config = request.user.terminal.config