diff --git a/apps/accounts/api/account/account.py b/apps/accounts/api/account/account.py index ecf014b55..8cfeeec8c 100644 --- a/apps/accounts/api/account/account.py +++ b/apps/accounts/api/account/account.py @@ -9,8 +9,9 @@ from accounts.filters import AccountFilterSet from accounts.mixins import AccountRecordViewLogMixin from accounts.models import Account from assets.models import Asset, Node +from authentication.permissions import UserConfirmation, ConfirmType from common.api.mixin import ExtraFilterFieldsMixin -from common.permissions import UserConfirmation, ConfirmType, IsValidUser +from common.permissions import IsValidUser from orgs.mixins.api import OrgBulkModelViewSet from rbac.permissions import RBACPermission diff --git a/apps/accounts/api/account/template.py b/apps/accounts/api/account/template.py index 57d577b46..4493cb227 100644 --- a/apps/accounts/api/account/template.py +++ b/apps/accounts/api/account/template.py @@ -8,8 +8,8 @@ from accounts.mixins import AccountRecordViewLogMixin from accounts.models import AccountTemplate from accounts.tasks import template_sync_related_accounts from assets.const import Protocol +from authentication.permissions import UserConfirmation, ConfirmType from common.drf.filters import BaseFilterSet -from common.permissions import UserConfirmation, ConfirmType from orgs.mixins.api import OrgBulkModelViewSet from rbac.permissions import RBACPermission diff --git a/apps/authentication/api/access_key.py b/apps/authentication/api/access_key.py index 86551953a..66026102c 100644 --- a/apps/authentication/api/access_key.py +++ b/apps/authentication/api/access_key.py @@ -5,8 +5,8 @@ from django.utils.translation import gettext as _ from rest_framework import serializers from rest_framework.response import Response +from authentication.permissions import UserConfirmation from common.api import JMSModelViewSet -from common.permissions import UserConfirmation from rbac.permissions import RBACPermission from ..const import ConfirmType from ..serializers import AccessKeySerializer diff --git a/apps/authentication/api/confirm.py b/apps/authentication/api/confirm.py index 92792d72d..4bd8d2c72 100644 --- a/apps/authentication/api/confirm.py +++ b/apps/authentication/api/confirm.py @@ -7,7 +7,8 @@ from rest_framework import status from rest_framework.generics import RetrieveAPIView, CreateAPIView from rest_framework.response import Response -from common.permissions import IsValidUser, UserConfirmation +from authentication.permissions import UserConfirmation +from common.permissions import IsValidUser from ..const import ConfirmType from ..serializers import ConfirmSerializer diff --git a/apps/authentication/api/dingtalk.py b/apps/authentication/api/dingtalk.py index 66f5a1d8c..ad3bd26b1 100644 --- a/apps/authentication/api/dingtalk.py +++ b/apps/authentication/api/dingtalk.py @@ -4,8 +4,9 @@ from rest_framework.views import APIView from authentication import errors from authentication.const import ConfirmType +from authentication.permissions import UserConfirmation from common.api import RoleUserMixin, RoleAdminMixin -from common.permissions import UserConfirmation, IsValidUser +from common.permissions import IsValidUser from common.utils import get_logger from users.models import User diff --git a/apps/authentication/api/feishu.py b/apps/authentication/api/feishu.py index 336552087..cf95bb6ea 100644 --- a/apps/authentication/api/feishu.py +++ b/apps/authentication/api/feishu.py @@ -4,12 +4,13 @@ from rest_framework.views import APIView from authentication import errors from authentication.const import ConfirmType +from authentication.permissions import UserConfirmation from common.api import RoleUserMixin, RoleAdminMixin -from common.permissions import UserConfirmation, IsValidUser +from common.permissions import IsValidUser from common.utils import get_logger from users.models import User -logger = get_logger(__file__) +logger = get_logger(__name__) class FeiShuQRUnBindBase(APIView): diff --git a/apps/authentication/api/wecom.py b/apps/authentication/api/wecom.py index 82476157b..6dcfe539c 100644 --- a/apps/authentication/api/wecom.py +++ b/apps/authentication/api/wecom.py @@ -4,8 +4,9 @@ from rest_framework.views import APIView from authentication import errors from authentication.const import ConfirmType +from authentication.permissions import UserConfirmation from common.api import RoleUserMixin, RoleAdminMixin -from common.permissions import UserConfirmation, IsValidUser +from common.permissions import IsValidUser from common.utils import get_logger from users.models import User diff --git a/apps/authentication/permissions.py b/apps/authentication/permissions.py new file mode 100644 index 000000000..e49f72796 --- /dev/null +++ b/apps/authentication/permissions.py @@ -0,0 +1,58 @@ +import time + +from django.conf import settings +from rest_framework import permissions + +from authentication.const import ConfirmType +from authentication.models import ConnectionToken +from common.exceptions import UserConfirmRequired +from common.permissions import IsValidUser +from common.utils import get_object_or_none +from orgs.utils import tmp_to_root_org + + +class UserConfirmation(permissions.BasePermission): + ttl = 60 * 5 + min_level = 1 + confirm_type = 'relogin' + + def has_permission(self, request, view): + if not settings.SECURITY_VIEW_AUTH_NEED_MFA: + return True + + confirm_level = request.session.get('CONFIRM_LEVEL') + confirm_time = request.session.get('CONFIRM_TIME') + ttl = self.get_ttl() + if not confirm_level or not confirm_time or \ + confirm_level < self.min_level or \ + confirm_time < time.time() - ttl: + raise UserConfirmRequired(code=self.confirm_type) + return True + + def get_ttl(self): + if self.confirm_type == ConfirmType.MFA: + ttl = settings.SECURITY_MFA_VERIFY_TTL + else: + ttl = self.ttl + return ttl + + @classmethod + def require(cls, confirm_type=ConfirmType.RELOGIN, ttl=60 * 5): + min_level = ConfirmType.values.index(confirm_type) + 1 + name = 'UserConfirmationLevel{}TTL{}'.format(min_level, ttl) + return type(name, (cls,), {'min_level': min_level, 'ttl': ttl, 'confirm_type': confirm_type}) + + +class IsValidUserOrConnectionToken(IsValidUser): + def has_permission(self, request, view): + return super().has_permission(request, view) \ + or self.is_valid_connection_token(request) + + @staticmethod + def is_valid_connection_token(request): + token_id = request.query_params.get('token') + if not token_id: + return False + with tmp_to_root_org(): + token = get_object_or_none(ConnectionToken, id=token_id) + return token and token.is_valid diff --git a/apps/authentication/views/dingtalk.py b/apps/authentication/views/dingtalk.py index c23827ca1..fcff66527 100644 --- a/apps/authentication/views/dingtalk.py +++ b/apps/authentication/views/dingtalk.py @@ -13,7 +13,7 @@ from authentication import errors from authentication.const import ConfirmType from authentication.mixins import AuthMixin from authentication.notifications import OAuthBindMessage -from common.permissions import UserConfirmation +from authentication.permissions import UserConfirmation from common.sdk.im.dingtalk import URL, DingTalk from common.utils import get_logger from common.utils.common import get_request_ip diff --git a/apps/authentication/views/feishu.py b/apps/authentication/views/feishu.py index ec483cdd4..5be872987 100644 --- a/apps/authentication/views/feishu.py +++ b/apps/authentication/views/feishu.py @@ -11,7 +11,7 @@ from rest_framework.permissions import AllowAny, IsAuthenticated from authentication.const import ConfirmType from authentication.notifications import OAuthBindMessage -from common.permissions import UserConfirmation +from authentication.permissions import UserConfirmation from common.sdk.im.feishu import URL, FeiShu from common.utils import get_logger from common.utils.common import get_request_ip diff --git a/apps/authentication/views/wecom.py b/apps/authentication/views/wecom.py index 7bb56202c..7bc814d3f 100644 --- a/apps/authentication/views/wecom.py +++ b/apps/authentication/views/wecom.py @@ -13,7 +13,7 @@ from authentication import errors from authentication.const import ConfirmType from authentication.mixins import AuthMixin from authentication.notifications import OAuthBindMessage -from common.permissions import UserConfirmation +from authentication.permissions import UserConfirmation from common.sdk.im.wecom import URL from common.sdk.im.wecom import WeCom from common.utils import get_logger diff --git a/apps/common/permissions.py b/apps/common/permissions.py index 742759e1d..ee2e24a8b 100644 --- a/apps/common/permissions.py +++ b/apps/common/permissions.py @@ -5,12 +5,6 @@ import time from django.conf import settings from rest_framework import permissions -from authentication.const import ConfirmType -from authentication.models import ConnectionToken -from common.exceptions import UserConfirmRequired -from common.utils import get_object_or_none -from orgs.utils import tmp_to_root_org - class IsValidUser(permissions.IsAuthenticated): """Allows access to valid user, is active and not expired""" @@ -20,21 +14,6 @@ class IsValidUser(permissions.IsAuthenticated): and request.user.is_valid -class IsValidUserOrConnectionToken(IsValidUser): - def has_permission(self, request, view): - return super().has_permission(request, view) \ - or self.is_valid_connection_token(request) - - @staticmethod - def is_valid_connection_token(request): - token_id = request.query_params.get('token') - if not token_id: - return False - with tmp_to_root_org(): - token = get_object_or_none(ConnectionToken, id=token_id) - return token and token.is_valid - - class OnlySuperUser(IsValidUser): def has_permission(self, request, view): return super().has_permission(request, view) \ @@ -56,38 +35,6 @@ class WithBootstrapToken(permissions.BasePermission): return settings.BOOTSTRAP_TOKEN == request_bootstrap_token -class UserConfirmation(permissions.BasePermission): - ttl = 60 * 5 - min_level = 1 - confirm_type = ConfirmType.RELOGIN - - def has_permission(self, request, view): - if not settings.SECURITY_VIEW_AUTH_NEED_MFA: - return True - - confirm_level = request.session.get('CONFIRM_LEVEL') - confirm_time = request.session.get('CONFIRM_TIME') - ttl = self.get_ttl() - if not confirm_level or not confirm_time or \ - confirm_level < self.min_level or \ - confirm_time < time.time() - ttl: - raise UserConfirmRequired(code=self.confirm_type) - return True - - def get_ttl(self): - if self.confirm_type == ConfirmType.MFA: - ttl = settings.SECURITY_MFA_VERIFY_TTL - else: - ttl = self.ttl - return ttl - - @classmethod - def require(cls, confirm_type=ConfirmType.RELOGIN, ttl=60 * 5): - min_level = ConfirmType.values.index(confirm_type) + 1 - name = 'UserConfirmationLevel{}TTL{}'.format(min_level, ttl) - return type(name, (cls,), {'min_level': min_level, 'ttl': ttl, 'confirm_type': confirm_type}) - - class ServiceAccountSignaturePermission(permissions.BasePermission): def has_permission(self, request, view): from authentication.models import AccessKey diff --git a/apps/settings/api/public.py b/apps/settings/api/public.py index f2628a5d4..85c56bdbf 100644 --- a/apps/settings/api/public.py +++ b/apps/settings/api/public.py @@ -2,7 +2,7 @@ from django.conf import settings from rest_framework import generics from rest_framework.permissions import AllowAny -from common.permissions import IsValidUserOrConnectionToken +from authentication.permissions import IsValidUserOrConnectionToken from common.utils import get_logger, lazyproperty from common.utils.timezone import local_now from jumpserver.utils import has_valid_xpack_license, get_xpack_license_info diff --git a/apps/terminal/api/component/endpoint.py b/apps/terminal/api/component/endpoint.py index e2eeaf548..b40aba9aa 100644 --- a/apps/terminal/api/component/endpoint.py +++ b/apps/terminal/api/component/endpoint.py @@ -6,8 +6,8 @@ from rest_framework.request import Request from rest_framework.response import Response from assets.models import Asset +from authentication.permissions import IsValidUserOrConnectionToken from common.api import JMSBulkModelViewSet -from common.permissions import IsValidUserOrConnectionToken from orgs.utils import tmp_to_root_org from terminal import serializers from terminal.models import Session, Endpoint, EndpointRule diff --git a/apps/users/api/profile.py b/apps/users/api/profile.py index 727c87314..974fc136c 100644 --- a/apps/users/api/profile.py +++ b/apps/users/api/profile.py @@ -5,7 +5,7 @@ from rest_framework import generics from rest_framework.permissions import IsAuthenticated from authentication.models import ConnectionToken -from common.permissions import IsValidUserOrConnectionToken +from authentication.permissions import IsValidUserOrConnectionToken from common.utils import get_object_or_none from orgs.utils import tmp_to_root_org from users.notifications import ( diff --git a/utils/add_china_db_platform.py b/utils/add_china_db_platform.py new file mode 100644 index 000000000..1a0d855bb --- /dev/null +++ b/utils/add_china_db_platform.py @@ -0,0 +1,8 @@ +#!/usr/bin/python +# +databases = [ + { + 'name': 'TiDB', + 'type': 'mysql', + } +]