From dafc416783d4a08eee07d95e7022088f969e15ee Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 2 Mar 2022 20:48:43 +0800 Subject: [PATCH] Fix rbac (#7728) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf: 重命名 signal handlers * fix: 修复 ticket processor 问题 * perf: 修改 ticket 处理人api * fix: 修复创建系统账号bug * fix: 升级celery_beat==2.2.1和flower==1.0.0;修改celery进程启动参数先后顺序 * perf: 修改 authentication token * fix: 修复上传权限bug * fix: 登录页面增加i18n切换; * fix: 系统角色删除限制 * perf: 修改一下 permissions tree * perf: 生成 i18n * perf: 修改一点点 Co-authored-by: ibuler Co-authored-by: feng626 <1304903146@qq.com> Co-authored-by: Jiangjie.Bai --- apps/assets/api/cmd_filter.py | 2 +- apps/assets/apps.py | 4 +- apps/assets/models/asset.py | 4 +- .../__init__.py | 0 .../asset.py | 0 .../authbook.py | 0 .../common.py | 0 .../node_assets_amount.py | 0 .../node_assets_mapping.py | 0 .../system_user.py | 0 apps/audits/apps.py | 2 +- ...{signals_handler.py => signal_handlers.py} | 0 apps/authentication/api/connection_token.py | 16 +- apps/authentication/apps.py | 2 +- .../migrations/0007_connectiontoken.py | 12 +- .../migrations/0008_auto_20220217_2135.py | 21 - .../migrations/0008_superconnectiontoken.py | 25 + apps/authentication/models.py | 11 +- apps/authentication/serializers.py | 14 +- ...signals_handlers.py => signal_handlers.py} | 0 .../templates/authentication/login.html | 27 + .../management/commands/expire_caches.py | 2 +- .../management/commands/services/command.py | 2 +- .../commands/services/services/celery_base.py | 5 +- .../commands/services/services/flower.py | 3 +- apps/jumpserver/context_processor.py | 2 +- apps/jumpserver/urls.py | 3 +- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 582 ++++++++++-------- apps/notifications/apps.py | 2 +- ...{signals_handler.py => signal_handlers.py} | 0 apps/notifications/ws.py | 2 +- apps/ops/apps.py | 4 +- apps/ops/notifications.py | 2 +- ...{signals_handler.py => signal_handlers.py} | 0 apps/orgs/apps.py | 4 +- .../__init__.py | 0 .../cache.py | 0 .../common.py | 0 apps/perms/apps.py | 4 +- .../serializers/application/permission.py | 2 +- .../__init__.py | 0 .../app_permission.py | 0 .../asset_permission.py | 0 .../refresh_perms.py | 0 apps/rbac/api/rolebinding.py | 16 +- apps/rbac/const.py | 10 +- apps/rbac/models/permission.py | 193 +----- apps/rbac/permissions.py | 1 + apps/rbac/tree.py | 387 ++++++++++++ apps/settings/apps.py | 2 +- ...{signals_handler.py => signal_handlers.py} | 0 apps/terminal/apps.py | 2 +- .../migrations/0047_auto_20220302_1951.py | 17 + apps/terminal/models/replay.py | 1 + ...{signals_handler.py => signal_handlers.py} | 0 apps/tickets/api/super_ticket.py | 11 +- apps/tickets/apps.py | 2 +- apps/tickets/models/ticket.py | 7 +- apps/tickets/serializers/super_ticket.py | 13 +- .../__init__.py | 0 .../comment.py | 0 .../ticket.py | 0 apps/users/apps.py | 2 +- apps/users/serializers/user.py | 4 +- ...{signals_handler.py => signal_handlers.py} | 0 jms | 10 +- requirements/requirements.txt | 4 +- utils/start_celery_beat.py | 3 +- 69 files changed, 929 insertions(+), 519 deletions(-) rename apps/assets/{signals_handler => signal_handlers}/__init__.py (100%) rename apps/assets/{signals_handler => signal_handlers}/asset.py (100%) rename apps/assets/{signals_handler => signal_handlers}/authbook.py (100%) rename apps/assets/{signals_handler => signal_handlers}/common.py (100%) rename apps/assets/{signals_handler => signal_handlers}/node_assets_amount.py (100%) rename apps/assets/{signals_handler => signal_handlers}/node_assets_mapping.py (100%) rename apps/assets/{signals_handler => signal_handlers}/system_user.py (100%) rename apps/audits/{signals_handler.py => signal_handlers.py} (100%) delete mode 100644 apps/authentication/migrations/0008_auto_20220217_2135.py create mode 100644 apps/authentication/migrations/0008_superconnectiontoken.py rename apps/authentication/{signals_handlers.py => signal_handlers.py} (100%) rename apps/notifications/{signals_handler.py => signal_handlers.py} (100%) rename apps/ops/{signals_handler.py => signal_handlers.py} (100%) rename apps/orgs/{signals_handler => signal_handlers}/__init__.py (100%) rename apps/orgs/{signals_handler => signal_handlers}/cache.py (100%) rename apps/orgs/{signals_handler => signal_handlers}/common.py (100%) rename apps/perms/{signals_handler => signal_handlers}/__init__.py (100%) rename apps/perms/{signals_handler => signal_handlers}/app_permission.py (100%) rename apps/perms/{signals_handler => signal_handlers}/asset_permission.py (100%) rename apps/perms/{signals_handler => signal_handlers}/refresh_perms.py (100%) create mode 100644 apps/rbac/tree.py rename apps/settings/{signals_handler.py => signal_handlers.py} (100%) create mode 100644 apps/terminal/migrations/0047_auto_20220302_1951.py rename apps/terminal/{signals_handler.py => signal_handlers.py} (100%) rename apps/tickets/{signals_handler => signal_handlers}/__init__.py (100%) rename apps/tickets/{signals_handler => signal_handlers}/comment.py (100%) rename apps/tickets/{signals_handler => signal_handlers}/ticket.py (100%) rename apps/users/{signals_handler.py => signal_handlers.py} (100%) diff --git a/apps/assets/api/cmd_filter.py b/apps/assets/api/cmd_filter.py index c9fad91a0..dcb2d77c9 100644 --- a/apps/assets/api/cmd_filter.py +++ b/apps/assets/api/cmd_filter.py @@ -53,7 +53,7 @@ class CommandConfirmAPI(CreateAPIView): run_command=self.serializer.data.get('run_command'), session=self.serializer.session, cmd_filter_rule=self.serializer.cmd_filter_rule, - org_id=self.serializer.org.id + org_id=self.serializer.org.id, ) return ticket diff --git a/apps/assets/apps.py b/apps/assets/apps.py index 5b44e2e92..e1bb43544 100644 --- a/apps/assets/apps.py +++ b/apps/assets/apps.py @@ -6,11 +6,11 @@ from django.apps import AppConfig class AssetsConfig(AppConfig): name = 'assets' - verbose_name = _('Assets') + verbose_name = _('App assets') def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def ready(self): super().ready() - from . import signals_handler + from . import signal_handlers diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index 905b70aa5..b0872ad0d 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -355,6 +355,6 @@ class Asset(AbsConnectivity, AbsHardwareInfo, ProtocolsMixin, NodesRelationMixin verbose_name = _("Asset") ordering = ["hostname", ] permissions = [ - ('test_assetconnectivity', 'Can test asset connectivity'), - ('push_assetsystemuser', 'Can push system user to asset'), + ('test_assetconnectivity', _('Can test asset connectivity')), + ('push_assetsystemuser', _('Can push system user to asset')), ] diff --git a/apps/assets/signals_handler/__init__.py b/apps/assets/signal_handlers/__init__.py similarity index 100% rename from apps/assets/signals_handler/__init__.py rename to apps/assets/signal_handlers/__init__.py diff --git a/apps/assets/signals_handler/asset.py b/apps/assets/signal_handlers/asset.py similarity index 100% rename from apps/assets/signals_handler/asset.py rename to apps/assets/signal_handlers/asset.py diff --git a/apps/assets/signals_handler/authbook.py b/apps/assets/signal_handlers/authbook.py similarity index 100% rename from apps/assets/signals_handler/authbook.py rename to apps/assets/signal_handlers/authbook.py diff --git a/apps/assets/signals_handler/common.py b/apps/assets/signal_handlers/common.py similarity index 100% rename from apps/assets/signals_handler/common.py rename to apps/assets/signal_handlers/common.py diff --git a/apps/assets/signals_handler/node_assets_amount.py b/apps/assets/signal_handlers/node_assets_amount.py similarity index 100% rename from apps/assets/signals_handler/node_assets_amount.py rename to apps/assets/signal_handlers/node_assets_amount.py diff --git a/apps/assets/signals_handler/node_assets_mapping.py b/apps/assets/signal_handlers/node_assets_mapping.py similarity index 100% rename from apps/assets/signals_handler/node_assets_mapping.py rename to apps/assets/signal_handlers/node_assets_mapping.py diff --git a/apps/assets/signals_handler/system_user.py b/apps/assets/signal_handlers/system_user.py similarity index 100% rename from apps/assets/signals_handler/system_user.py rename to apps/assets/signal_handlers/system_user.py diff --git a/apps/audits/apps.py b/apps/audits/apps.py index e66faa467..904739ec7 100644 --- a/apps/audits/apps.py +++ b/apps/audits/apps.py @@ -9,6 +9,6 @@ class AuditsConfig(AppConfig): verbose_name = _('Audits') def ready(self): - from . import signals_handler + from . import signal_handlers if settings.SYSLOG_ENABLE: post_save.connect(signals_handler.on_audits_log_create) diff --git a/apps/audits/signals_handler.py b/apps/audits/signal_handlers.py similarity index 100% rename from apps/audits/signals_handler.py rename to apps/audits/signal_handlers.py diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 3712bdf51..47ce04ece 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -302,16 +302,26 @@ class SecretDetailMixin: user=user, system_user=system_user, expired_at=expired_at, actions=actions ) + cmd_filter_kwargs = { + 'system_user_id': system_user.id, + 'user_id': user.id, + } if asset: asset_detail = self._get_asset_secret_detail(asset) system_user.load_asset_more_auth(asset.id, user.username, user.id) data['type'] = 'asset' data.update(asset_detail) + cmd_filter_kwargs['asset_id'] = asset.id else: app_detail = self._get_application_secret_detail(app) system_user.load_app_more_auth(app.id, user.username, user.id) data['type'] = 'application' data.update(app_detail) + cmd_filter_kwargs['application_id'] = app.id + + from assets.models import CommandFilterRule + cmd_filter_rules = CommandFilterRule.get_queryset(**cmd_filter_kwargs) + data['cmd_filter_rules'] = cmd_filter_rules serializer = self.get_serializer(data) return Response(data=serializer.data, status=200) @@ -350,8 +360,10 @@ class UserConnectionTokenViewSet( return True def create_token(self, user, asset, application, system_user, ttl=5 * 60): - if not self.request.user.is_superuser and user != self.request.user: - raise PermissionDenied('Only super user can create user token') + # 再次强调一下权限 + perm_required = 'authentication.add_superconnectiontoken' + if user != self.request.user and not self.request.user.has_perm(perm_required): + raise PermissionDenied('Only can create user token') self.check_resource_permission(user, asset, application, system_user) token = random_string(36) secret = random_string(16) diff --git a/apps/authentication/apps.py b/apps/authentication/apps.py index 527c54871..6516ed70e 100644 --- a/apps/authentication/apps.py +++ b/apps/authentication/apps.py @@ -7,7 +7,7 @@ class AuthenticationConfig(AppConfig): verbose_name = _('Authentication') def ready(self): - from . import signals_handlers + from . import signal_handlers from . import notifications super().ready() diff --git a/apps/authentication/migrations/0007_connectiontoken.py b/apps/authentication/migrations/0007_connectiontoken.py index c017c5d76..86341ff5b 100644 --- a/apps/authentication/migrations/0007_connectiontoken.py +++ b/apps/authentication/migrations/0007_connectiontoken.py @@ -19,8 +19,14 @@ class Migration(migrations.Migration): ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ], - options={ - 'permissions': [('add_superconnectiontoken', 'Can add super connection token'), ('view_connectiontokensecret', 'Can view connect token secret')], - }, + options={'verbose_name': 'Connection token'}, + ), + migrations.AlterModelOptions( + name='accesskey', + options={'verbose_name': 'Access key'}, + ), + migrations.AlterModelOptions( + name='ssotoken', + options={'verbose_name': 'SSO token'}, ), ] diff --git a/apps/authentication/migrations/0008_auto_20220217_2135.py b/apps/authentication/migrations/0008_auto_20220217_2135.py deleted file mode 100644 index 3f6b55248..000000000 --- a/apps/authentication/migrations/0008_auto_20220217_2135.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-17 13:35 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0007_connectiontoken'), - ] - - operations = [ - migrations.AlterModelOptions( - name='accesskey', - options={'verbose_name': 'Access key'}, - ), - migrations.AlterModelOptions( - name='ssotoken', - options={'verbose_name': 'SSO token'}, - ), - ] diff --git a/apps/authentication/migrations/0008_superconnectiontoken.py b/apps/authentication/migrations/0008_superconnectiontoken.py new file mode 100644 index 000000000..82e956a24 --- /dev/null +++ b/apps/authentication/migrations/0008_superconnectiontoken.py @@ -0,0 +1,25 @@ +# Generated by Django 3.1.14 on 2022-03-02 11:53 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0007_connectiontoken'), + ] + + operations = [ + migrations.CreateModel( + name='SuperConnectionToken', + fields=[ + ], + options={ + 'verbose_name': 'Super connection token', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('authentication.connectiontoken',), + ), + ] diff --git a/apps/authentication/models.py b/apps/authentication/models.py index f263973fa..7e407a1dd 100644 --- a/apps/authentication/models.py +++ b/apps/authentication/models.py @@ -58,7 +58,10 @@ class ConnectionToken(models.JMSBaseModel): # Todo: add connection token 可能要授权给 普通用户, 或者放开就行 class Meta: - permissions = [ - ('add_superconnectiontoken', _('Can add super connection token')), - ('view_connectiontokensecret', _('Can view connect token secret')) - ] + verbose_name = _('Connection token') + + +class SuperConnectionToken(ConnectionToken): + class Meta: + proxy = True + verbose_name = _("Super connection token") diff --git a/apps/authentication/serializers.py b/apps/authentication/serializers.py index 678b7763b..f6661ba38 100644 --- a/apps/authentication/serializers.py +++ b/apps/authentication/serializers.py @@ -5,7 +5,7 @@ from rest_framework import serializers from common.utils import get_object_or_none from users.models import User -from assets.models import Asset, SystemUser, Gateway, Domain +from assets.models import Asset, SystemUser, Gateway, Domain, CommandFilterRule from applications.models import Application from users.serializers import UserProfileSerializer from assets.serializers import ProtocolsField @@ -200,6 +200,17 @@ class ConnectionTokenDomainSerializer(serializers.ModelSerializer): fields = ['id', 'name', 'gateways'] +class ConnectionTokenFilterRuleSerializer(serializers.ModelSerializer): + + class Meta: + model = CommandFilterRule + fields = [ + 'id', 'type', 'content', 'ignore_case', 'pattern', + 'priority', 'action', + 'date_created', + ] + + class ConnectionTokenSecretSerializer(serializers.Serializer): id = serializers.CharField(read_only=True) secret = serializers.CharField(read_only=True) @@ -209,6 +220,7 @@ class ConnectionTokenSecretSerializer(serializers.Serializer): remote_app = ConnectionTokenRemoteAppSerializer(read_only=True) application = ConnectionTokenApplicationSerializer(read_only=True) system_user = ConnectionTokenSystemUserSerializer(read_only=True) + cmd_filter_rules = ConnectionTokenFilterRuleSerializer(many=True) domain = ConnectionTokenDomainSerializer(read_only=True) gateway = ConnectionTokenGatewaySerializer(read_only=True) actions = ActionsField() diff --git a/apps/authentication/signals_handlers.py b/apps/authentication/signal_handlers.py similarity index 100% rename from apps/authentication/signals_handlers.py rename to apps/authentication/signal_handlers.py diff --git a/apps/authentication/templates/authentication/login.html b/apps/authentication/templates/authentication/login.html index b74217cee..3e24aa610 100644 --- a/apps/authentication/templates/authentication/login.html +++ b/apps/authentication/templates/authentication/login.html @@ -115,10 +115,21 @@ .mfa-div { width: 100%; } + + .login-page-language { + margin-right: -11px !important; + padding-top: 12px !important; + padding-left: 0 !important; + padding-bottom: 8px !important; + color: #666 !important; + font-weight: 350 !important; + min-height: auto !important; + } +