From 11e538d417d7ff07b3d9156e55135eb1e76f628f Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 13 Jul 2022 11:31:53 +0800 Subject: [PATCH 001/104] =?UTF-8?q?fix:=20=E5=B7=A5=E5=8D=95=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E5=AE=A1=E6=89=B9=E4=B8=8D=E6=94=AF=E6=8C=81=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E8=B5=84=E4=BA=A7=20(#8582)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/tickets/handlers/base.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/tickets/handlers/base.py b/apps/tickets/handlers/base.py index c48ce350b..81341ce8e 100644 --- a/apps/tickets/handlers/base.py +++ b/apps/tickets/handlers/base.py @@ -64,9 +64,14 @@ class BaseHandler: diff_context = {} if state != TicketState.approved: return diff_context + if self.ticket.type not in [TicketType.apply_asset, TicketType.apply_application]: return diff_context + # 企业微信,钉钉审批不做diff + if not hasattr(self.ticket, 'old_rel_snapshot'): + return diff_context + old_rel_snapshot = self.ticket.old_rel_snapshot current_rel_snapshot = self.ticket.get_local_snapshot() diff = set(current_rel_snapshot.items()) - set(old_rel_snapshot.items()) From 2abca3959745eb45e302d9ad377efa4aa403aa83 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 13 Jul 2022 15:48:55 +0800 Subject: [PATCH 002/104] fix: ticket bug (#8584) Co-authored-by: feng626 <1304903146@qq.com> --- apps/tickets/api/ticket.py | 3 ++- apps/tickets/migrations/0016_auto_20220609_1758.py | 4 ++-- apps/tickets/serializers/ticket/ticket.py | 9 ++++++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/tickets/api/ticket.py b/apps/tickets/api/ticket.py index ee6b76534..1df3506c1 100644 --- a/apps/tickets/api/ticket.py +++ b/apps/tickets/api/ticket.py @@ -29,7 +29,8 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet): serializer_class = serializers.TicketDisplaySerializer serializer_classes = { 'list': serializers.TicketListSerializer, - 'open': serializers.TicketApplySerializer + 'open': serializers.TicketApplySerializer, + 'approve': serializers.TicketApproveSerializer } model = Ticket perm_model = Ticket diff --git a/apps/tickets/migrations/0016_auto_20220609_1758.py b/apps/tickets/migrations/0016_auto_20220609_1758.py index ecf1c85fd..e5e6f61ce 100644 --- a/apps/tickets/migrations/0016_auto_20220609_1758.py +++ b/apps/tickets/migrations/0016_auto_20220609_1758.py @@ -139,7 +139,7 @@ class Migration(migrations.Migration): ('ticket_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tickets.ticket')), - ('apply_permission_name', models.CharField(max_length=128, verbose_name='Apply name')), + ('apply_permission_name', models.CharField(max_length=128, verbose_name='Permission name')), ('apply_actions', models.IntegerField( choices=[(255, 'All'), (1, 'Connect'), (2, 'Upload file'), (4, 'Download file'), (6, 'Upload download'), (8, 'Clipboard copy'), (16, 'Clipboard paste'), @@ -162,7 +162,7 @@ class Migration(migrations.Migration): ('ticket_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tickets.ticket')), - ('apply_permission_name', models.CharField(max_length=128, verbose_name='Apply name')), + ('apply_permission_name', models.CharField(max_length=128, verbose_name='Permission name')), ('apply_category', models.CharField(choices=[('db', 'Database'), ('remote_app', 'Remote app'), ('cloud', 'Cloud')], max_length=16, verbose_name='Category')), diff --git a/apps/tickets/serializers/ticket/ticket.py b/apps/tickets/serializers/ticket/ticket.py index facf3fcec..a0760e4d0 100644 --- a/apps/tickets/serializers/ticket/ticket.py +++ b/apps/tickets/serializers/ticket/ticket.py @@ -9,7 +9,7 @@ from tickets.models import Ticket, TicketFlow from tickets.const import TicketType __all__ = [ - 'TicketDisplaySerializer', 'TicketApplySerializer', 'TicketListSerializer' + 'TicketDisplaySerializer', 'TicketApplySerializer', 'TicketListSerializer', 'TicketApproveSerializer' ] @@ -59,6 +59,13 @@ class TicketDisplaySerializer(TicketSerializer): read_only_fields = fields +class TicketApproveSerializer(TicketSerializer): + class Meta: + model = Ticket + fields = TicketSerializer.Meta.fields + read_only_fields = fields + + class TicketApplySerializer(TicketSerializer): org_id = serializers.CharField( required=True, max_length=36, allow_blank=True, label=_("Organization") From ce2f6fdc8485d4ee16a65bad0e04504ccc2e8518 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 13 Jul 2022 16:29:05 +0800 Subject: [PATCH 003/104] =?UTF-8?q?feat:=20Endpoint=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=20oracle=20=E7=89=88=E6=9C=AC=20(#8585)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Endpoint 支持 oracle 版本 * feat: Endpoint 支持 oracle 版本 * feat: Endpoint 支持 oracle 版本 Co-authored-by: Jiangjie.Bai --- apps/applications/const.py | 6 + apps/applications/models/application.py | 15 +++ .../attrs/application_type/oracle.py | 6 + apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 126 ++++++++++-------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 122 ++++++++++------- apps/terminal/api/endpoint.py | 48 ++++--- .../migrations/0052_auto_20220713_1417.py | 25 ++++ apps/terminal/models/endpoint.py | 6 + apps/terminal/serializers/endpoint.py | 12 ++ 11 files changed, 248 insertions(+), 126 deletions(-) create mode 100644 apps/terminal/migrations/0052_auto_20220713_1417.py diff --git a/apps/applications/const.py b/apps/applications/const.py index 313477c25..4e0d2fe50 100644 --- a/apps/applications/const.py +++ b/apps/applications/const.py @@ -83,3 +83,9 @@ class AppType(models.TextChoices): if AppCategory.is_xpack(category): return True return tp in ['oracle', 'postgresql', 'sqlserver'] + + +class OracleVersion(models.TextChoices): + version_11g = '11g', '11g' + version_12c = '12c', '12c' + version_other = 'other', _('Other') diff --git a/apps/applications/models/application.py b/apps/applications/models/application.py index af1e27c2d..1644ab1d5 100644 --- a/apps/applications/models/application.py +++ b/apps/applications/models/application.py @@ -10,6 +10,7 @@ from common.mixins import CommonModelMixin from common.tree import TreeNode from common.utils import is_uuid from assets.models import Asset, SystemUser +from ..const import OracleVersion from ..utils import KubernetesTree from .. import const @@ -214,6 +215,8 @@ class ApplicationTreeNodeMixin: class Application(CommonModelMixin, OrgModelMixin, ApplicationTreeNodeMixin): + APP_TYPE = const.AppType + name = models.CharField(max_length=128, verbose_name=_('Name')) category = models.CharField( max_length=16, choices=const.AppCategory.choices, verbose_name=_('Category') @@ -255,6 +258,9 @@ class Application(CommonModelMixin, OrgModelMixin, ApplicationTreeNodeMixin): def category_db(self): return self.category == const.AppCategory.db.value + def is_type(self, tp): + return self.type == tp + def get_rdp_remote_app_setting(self): from applications.serializers.attrs import get_serializer_class_by_application_type if not self.category_remote_app: @@ -298,6 +304,15 @@ class Application(CommonModelMixin, OrgModelMixin, ApplicationTreeNodeMixin): target_ip = self.attrs.get('host') return target_ip + def get_target_protocol_for_oracle(self): + """ Oracle 类型需要单独处理,因为要携带版本号 """ + if not self.is_type(self.APP_TYPE.oracle): + return + version = self.attrs.get('version', OracleVersion.version_other) + if version == OracleVersion.version_other: + return + return 'oracle_%s' % version + class ApplicationUser(SystemUser): class Meta: diff --git a/apps/applications/serializers/attrs/application_type/oracle.py b/apps/applications/serializers/attrs/application_type/oracle.py index c87c4904d..94cfaa319 100644 --- a/apps/applications/serializers/attrs/application_type/oracle.py +++ b/apps/applications/serializers/attrs/application_type/oracle.py @@ -2,9 +2,15 @@ from rest_framework import serializers from django.utils.translation import ugettext_lazy as _ from ..application_category import DBSerializer +from applications.const import OracleVersion __all__ = ['OracleSerializer'] class OracleSerializer(DBSerializer): + version = serializers.ChoiceField( + choices=OracleVersion.choices, default=OracleVersion.version_other, + allow_null=True, label=_('Version'), + help_text=_('Magnus currently supports only 11g and 12c connections') + ) port = serializers.IntegerField(default=1521, label=_('Port'), allow_null=True) diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 6d3f88208..789260264 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:326eef1f3134c1500a6641c6616a9d509befd5db42ead551fe5ca01b3e0273c0 -size 128150 +oid sha256:4d5cc27fc996896f8cba5773c99de59ff854f7ef1ae8c470d5c74bb6b371e6ed +size 128472 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 9205fb974..254383a50 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-12 17:58+0800\n" +"POT-Creation-Date: 2022-07-13 16:25+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -23,13 +23,13 @@ msgid "Acls" msgstr "Acls" #: acls/models/base.py:25 acls/serializers/login_asset_acl.py:47 -#: applications/models/application.py:217 assets/models/asset.py:138 +#: applications/models/application.py:220 assets/models/asset.py:138 #: assets/models/base.py:175 assets/models/cluster.py:18 #: assets/models/cmd_filter.py:27 assets/models/domain.py:23 #: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24 #: orgs/models.py:65 perms/models/base.py:83 rbac/models/role.py:29 #: settings/models.py:29 settings/serializers/sms.py:6 -#: terminal/models/endpoint.py:10 terminal/models/endpoint.py:82 +#: terminal/models/endpoint.py:10 terminal/models/endpoint.py:88 #: terminal/models/storage.py:26 terminal/models/task.py:16 #: terminal/models/terminal.py:100 users/forms/profile.py:33 #: users/models/group.py:15 users/models/user.py:661 @@ -38,12 +38,12 @@ msgid "Name" msgstr "名前" #: acls/models/base.py:27 assets/models/cmd_filter.py:84 -#: assets/models/user.py:251 terminal/models/endpoint.py:85 +#: assets/models/user.py:251 terminal/models/endpoint.py:91 msgid "Priority" msgstr "優先順位" #: acls/models/base.py:28 assets/models/cmd_filter.py:84 -#: assets/models/user.py:251 terminal/models/endpoint.py:86 +#: assets/models/user.py:251 terminal/models/endpoint.py:92 msgid "1-100, the lower the value will be match first" msgstr "1-100、低い値は最初に一致します" @@ -53,7 +53,7 @@ msgstr "1-100、低い値は最初に一致します" msgid "Active" msgstr "アクティブ" -#: acls/models/base.py:32 applications/models/application.py:230 +#: acls/models/base.py:32 applications/models/application.py:233 #: assets/models/asset.py:143 assets/models/asset.py:231 #: assets/models/backup.py:54 assets/models/base.py:180 #: assets/models/cluster.py:29 assets/models/cmd_filter.py:48 @@ -61,7 +61,7 @@ msgstr "アクティブ" #: assets/models/domain.py:65 assets/models/group.py:23 #: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:68 #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 -#: terminal/models/endpoint.py:21 terminal/models/endpoint.py:92 +#: terminal/models/endpoint.py:23 terminal/models/endpoint.py:98 #: terminal/models/storage.py:29 terminal/models/terminal.py:114 #: tickets/models/comment.py:32 tickets/models/ticket/general.py:288 #: users/models/group.py:16 users/models/user.py:698 @@ -157,7 +157,7 @@ msgstr "コンマ区切り文字列の形式。* はすべて一致すること #: acls/serializers/login_asset_acl.py:51 assets/models/base.py:176 #: assets/models/gathered_user.py:15 audits/models.py:121 #: authentication/forms.py:25 authentication/forms.py:27 -#: authentication/models.py:245 +#: authentication/models.py:253 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 #: ops/models/adhoc.py:159 users/forms/profile.py:32 users/models/user.py:659 @@ -185,7 +185,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 -#: settings/serializers/terminal.py:8 terminal/serializers/endpoint.py:42 +#: settings/serializers/terminal.py:8 terminal/serializers/endpoint.py:54 msgid "IP" msgstr "IP" @@ -241,7 +241,7 @@ msgstr "" msgid "Time Period" msgstr "期間" -#: applications/apps.py:9 applications/models/application.py:63 +#: applications/apps.py:9 applications/models/application.py:64 msgid "Applications" msgstr "アプリケーション" @@ -260,7 +260,11 @@ msgstr "リモートアプリ" msgid "Custom" msgstr "カスタム" -#: applications/models/account.py:12 applications/models/application.py:234 +#: applications/const.py:91 rbac/tree.py:29 +msgid "Other" +msgstr "その他" + +#: applications/models/account.py:12 applications/models/application.py:237 #: assets/models/backup.py:32 assets/models/cmd_filter.py:45 #: authentication/models.py:67 authentication/models.py:95 #: perms/models/application_permission.py:28 @@ -278,8 +282,9 @@ msgstr "アプリケーション" msgid "System user" msgstr "システムユーザー" -#: applications/models/account.py:17 assets/models/authbook.py:21 -#: settings/serializers/auth/cas.py:18 +#: applications/models/account.py:17 +#: applications/serializers/attrs/application_type/oracle.py:13 +#: assets/models/authbook.py:21 settings/serializers/auth/cas.py:18 msgid "Version" msgstr "バージョン" @@ -295,7 +300,7 @@ msgstr "アプリケーションアカウントの秘密を表示できます" msgid "Can change application account secret" msgstr "アプリケーションアカウントの秘密を変更できます" -#: applications/models/application.py:219 +#: applications/models/application.py:222 #: applications/serializers/application.py:99 assets/models/label.py:21 #: perms/models/application_permission.py:21 #: perms/serializers/application/user_permission.py:33 @@ -304,7 +309,7 @@ msgstr "アプリケーションアカウントの秘密を変更できます" msgid "Category" msgstr "カテゴリ" -#: applications/models/application.py:222 +#: applications/models/application.py:225 #: applications/serializers/application.py:101 assets/models/backup.py:49 #: assets/models/cmd_filter.py:82 assets/models/user.py:250 #: authentication/models.py:70 perms/models/application_permission.py:24 @@ -318,21 +323,21 @@ msgstr "カテゴリ" msgid "Type" msgstr "タイプ" -#: applications/models/application.py:226 assets/models/asset.py:217 +#: applications/models/application.py:229 assets/models/asset.py:217 #: assets/models/domain.py:29 assets/models/domain.py:64 msgid "Domain" msgstr "ドメイン" -#: applications/models/application.py:228 xpack/plugins/cloud/models.py:33 +#: applications/models/application.py:231 xpack/plugins/cloud/models.py:33 #: xpack/plugins/cloud/serializers/account.py:60 msgid "Attrs" msgstr "ツールバーの" -#: applications/models/application.py:238 +#: applications/models/application.py:241 msgid "Can match application" msgstr "アプリケーションを一致させることができます" -#: applications/models/application.py:305 +#: applications/models/application.py:320 msgid "Application user" msgstr "アプリケーションユーザー" @@ -397,7 +402,7 @@ msgstr "ホスト" #: applications/serializers/attrs/application_type/mongodb.py:10 #: applications/serializers/attrs/application_type/mysql.py:10 #: applications/serializers/attrs/application_type/mysql_workbench.py:22 -#: applications/serializers/attrs/application_type/oracle.py:10 +#: applications/serializers/attrs/application_type/oracle.py:16 #: applications/serializers/attrs/application_type/pgsql.py:10 #: applications/serializers/attrs/application_type/redis.py:10 #: applications/serializers/attrs/application_type/sqlserver.py:10 @@ -467,6 +472,10 @@ msgstr "Mysql workbench のユーザー名" msgid "Mysql workbench password" msgstr "Mysql workbench パスワード" +#: applications/serializers/attrs/application_type/oracle.py:14 +msgid "Magnus currently supports only 11g and 12c connections" +msgstr "現在、Magnusは11gおよび12cバージョンへの接続のみをサポートしています" + #: applications/serializers/attrs/application_type/vmware_client.py:26 msgid "Vmware username" msgstr "Vmware ユーザー名" @@ -768,7 +777,7 @@ msgstr "失敗しました" msgid "Connectivity" msgstr "接続性" -#: assets/models/base.py:40 authentication/models.py:248 +#: assets/models/base.py:40 authentication/models.py:256 msgid "Date verified" msgstr "確認済みの日付" @@ -1616,7 +1625,7 @@ msgstr "本を飛ばす" msgid "DingTalk" msgstr "DingTalk" -#: audits/signal_handlers.py:56 authentication/models.py:252 +#: audits/signal_handlers.py:56 authentication/models.py:260 msgid "Temporary token" msgstr "仮パスワード" @@ -2106,13 +2115,13 @@ msgstr "期限切れ" msgid "SSO token" msgstr "SSO token" -#: authentication/models.py:72 authentication/models.py:246 +#: authentication/models.py:72 authentication/models.py:254 #: authentication/templates/authentication/_access_key_modal.html:31 #: settings/serializers/auth/radius.py:17 msgid "Secret" msgstr "ひみつ" -#: authentication/models.py:74 authentication/models.py:249 +#: authentication/models.py:74 authentication/models.py:257 #: perms/models/base.py:90 tickets/models/ticket/apply_application.py:26 #: tickets/models/ticket/apply_asset.py:24 users/models/user.py:703 msgid "Date expired" @@ -2130,51 +2139,51 @@ msgstr "接続トークン" msgid "Can view connection token secret" msgstr "接続トークンの秘密を表示できます" -#: authentication/models.py:141 +#: authentication/models.py:149 msgid "Connection token expired at: {}" msgstr "接続トークンの有効期限: {}" -#: authentication/models.py:146 +#: authentication/models.py:154 msgid "User not exists" msgstr "ユーザーは存在しません" -#: authentication/models.py:150 +#: authentication/models.py:158 msgid "User invalid, disabled or expired" msgstr "ユーザーが無効、無効、または期限切れです" -#: authentication/models.py:155 +#: authentication/models.py:163 msgid "System user not exists" msgstr "システムユーザーが存在しません" -#: authentication/models.py:161 +#: authentication/models.py:169 msgid "Asset not exists" msgstr "アセットが存在しません" -#: authentication/models.py:165 +#: authentication/models.py:173 msgid "Asset inactive" msgstr "アセットがアクティブ化されていません" -#: authentication/models.py:172 +#: authentication/models.py:180 msgid "User has no permission to access asset or permission expired" msgstr "" "ユーザーがアセットにアクセスする権限を持っていないか、権限の有効期限が切れて" "います" -#: authentication/models.py:180 +#: authentication/models.py:188 msgid "Application not exists" msgstr "アプリが存在しません" -#: authentication/models.py:187 +#: authentication/models.py:195 msgid "User has no permission to access application or permission expired" msgstr "" "ユーザーがアプリにアクセスする権限を持っていないか、権限の有効期限が切れてい" "ます" -#: authentication/models.py:247 +#: authentication/models.py:255 msgid "Verified" msgstr "確認済み" -#: authentication/models.py:268 +#: authentication/models.py:276 msgid "Super connection token" msgstr "スーパー接続トークン" @@ -2191,7 +2200,11 @@ msgstr "バインディングリマインダー" msgid "Validity" msgstr "有効性" -#: authentication/serializers/connection_token.py:73 +#: authentication/serializers/connection_token.py:24 +msgid "Expired time" +msgstr "期限切れ時間" + +#: authentication/serializers/connection_token.py:74 msgid "Asset or application required" msgstr "アセットまたはアプリが必要" @@ -3009,7 +3022,7 @@ msgstr "組織のリソース ({}) は削除できません" msgid "App organizations" msgstr "アプリ組織" -#: orgs/mixins/models.py:46 orgs/mixins/serializers.py:25 orgs/models.py:80 +#: orgs/mixins/models.py:54 orgs/mixins/serializers.py:25 orgs/models.py:80 #: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:64 @@ -3376,10 +3389,6 @@ msgstr "監査ビュー" msgid "System setting" msgstr "システム設定" -#: rbac/tree.py:29 -msgid "Other" -msgstr "その他" - #: rbac/tree.py:37 msgid "Accounts" msgstr "アカウント" @@ -4678,7 +4687,7 @@ msgstr "" msgid "Offline video player" msgstr "オフラインビデオプレーヤー" -#: terminal/api/endpoint.py:26 +#: terminal/api/endpoint.py:33 msgid "Not found protocol query params" msgstr "プロトコルクエリパラメータが見つかりません" @@ -4851,18 +4860,26 @@ msgstr "PostgreSQL ポート" msgid "Redis Port" msgstr "Redis ポート" -#: terminal/models/endpoint.py:26 terminal/models/endpoint.py:90 -#: terminal/serializers/endpoint.py:45 terminal/serializers/storage.py:38 +#: terminal/models/endpoint.py:21 +msgid "Oracle 11g Port" +msgstr "Oracle 11g ポート" + +#: terminal/models/endpoint.py:22 +msgid "Oracle 12c Port" +msgstr "Oracle 12c ポート" + +#: terminal/models/endpoint.py:28 terminal/models/endpoint.py:96 +#: terminal/serializers/endpoint.py:57 terminal/serializers/storage.py:38 #: terminal/serializers/storage.py:50 terminal/serializers/storage.py:80 #: terminal/serializers/storage.py:90 terminal/serializers/storage.py:98 msgid "Endpoint" msgstr "エンドポイント" -#: terminal/models/endpoint.py:83 +#: terminal/models/endpoint.py:89 msgid "IP group" msgstr "IP グループ" -#: terminal/models/endpoint.py:95 +#: terminal/models/endpoint.py:101 msgid "Endpoint rule" msgstr "エンドポイントルール" @@ -5043,7 +5060,11 @@ msgstr "レベル" msgid "Batch danger command alert" msgstr "一括危険コマンド警告" -#: terminal/serializers/endpoint.py:39 +#: terminal/serializers/endpoint.py:12 +msgid "Oracle port" +msgstr "" + +#: terminal/serializers/endpoint.py:51 msgid "" "If asset IP addresses under different endpoints conflict, use asset labels" msgstr "" @@ -6703,12 +6724,11 @@ msgid "" "all instances and randomly match IP addresses.
Format for comma-" "delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" msgstr "" -"IP範囲に一致するインスタンスのみが同期されます。
" -"インスタンスに複数のIPアドレスが含まれている場合、一致する最初のIPアドレスが作成されたアセットのIPとして使用されます。
" -"デフォルト値の*は、すべてのインスタンスを同期し、IPアドレスをランダムに一致させることを意味します。
" -"形式はコンマ区切りの文字列です。例:192.168.1.0/24,10.1.1.1-10.1.1.20" - - +"IP範囲に一致するインスタンスのみが同期されます。
インスタンスに複数のIPア" +"ドレスが含まれている場合、一致する最初のIPアドレスが作成されたアセットのIPと" +"して使用されます。
デフォルト値の*は、すべてのインスタンスを同期し、IPア" +"ドレスをランダムに一致させることを意味します。
形式はコンマ区切りの文字列" +"です。例:192.168.1.0/24,10.1.1.1-10.1.1.20" #: xpack/plugins/cloud/serializers/task.py:36 msgid "History count" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index dcc55a77c..acdae1731 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1efe7f07b0877357a42a7f93e075c152e2bd8ee7adc20bcab17427a86cce5ed3 -size 105644 +oid sha256:7ee69ce22224f6cae615752c034e495c29d93ed9dbe86767f044d5c0f663b8cc +size 105904 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 1cf1383be..24f5f8ee1 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-12 17:58+0800\n" +"POT-Creation-Date: 2022-07-13 16:25+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -22,13 +22,13 @@ msgid "Acls" msgstr "访问控制" #: acls/models/base.py:25 acls/serializers/login_asset_acl.py:47 -#: applications/models/application.py:217 assets/models/asset.py:138 +#: applications/models/application.py:220 assets/models/asset.py:138 #: assets/models/base.py:175 assets/models/cluster.py:18 #: assets/models/cmd_filter.py:27 assets/models/domain.py:23 #: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24 #: orgs/models.py:65 perms/models/base.py:83 rbac/models/role.py:29 #: settings/models.py:29 settings/serializers/sms.py:6 -#: terminal/models/endpoint.py:10 terminal/models/endpoint.py:82 +#: terminal/models/endpoint.py:10 terminal/models/endpoint.py:88 #: terminal/models/storage.py:26 terminal/models/task.py:16 #: terminal/models/terminal.py:100 users/forms/profile.py:33 #: users/models/group.py:15 users/models/user.py:661 @@ -37,12 +37,12 @@ msgid "Name" msgstr "名称" #: acls/models/base.py:27 assets/models/cmd_filter.py:84 -#: assets/models/user.py:251 terminal/models/endpoint.py:85 +#: assets/models/user.py:251 terminal/models/endpoint.py:91 msgid "Priority" msgstr "优先级" #: acls/models/base.py:28 assets/models/cmd_filter.py:84 -#: assets/models/user.py:251 terminal/models/endpoint.py:86 +#: assets/models/user.py:251 terminal/models/endpoint.py:92 msgid "1-100, the lower the value will be match first" msgstr "优先级可选范围为 1-100 (数值越小越优先)" @@ -52,7 +52,7 @@ msgstr "优先级可选范围为 1-100 (数值越小越优先)" msgid "Active" msgstr "激活中" -#: acls/models/base.py:32 applications/models/application.py:230 +#: acls/models/base.py:32 applications/models/application.py:233 #: assets/models/asset.py:143 assets/models/asset.py:231 #: assets/models/backup.py:54 assets/models/base.py:180 #: assets/models/cluster.py:29 assets/models/cmd_filter.py:48 @@ -60,7 +60,7 @@ msgstr "激活中" #: assets/models/domain.py:65 assets/models/group.py:23 #: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:68 #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 -#: terminal/models/endpoint.py:21 terminal/models/endpoint.py:92 +#: terminal/models/endpoint.py:23 terminal/models/endpoint.py:98 #: terminal/models/storage.py:29 terminal/models/terminal.py:114 #: tickets/models/comment.py:32 tickets/models/ticket/general.py:288 #: users/models/group.py:16 users/models/user.py:698 @@ -156,7 +156,7 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. " #: acls/serializers/login_asset_acl.py:51 assets/models/base.py:176 #: assets/models/gathered_user.py:15 audits/models.py:121 #: authentication/forms.py:25 authentication/forms.py:27 -#: authentication/models.py:245 +#: authentication/models.py:253 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 #: ops/models/adhoc.py:159 users/forms/profile.py:32 users/models/user.py:659 @@ -183,7 +183,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 -#: settings/serializers/terminal.py:8 terminal/serializers/endpoint.py:42 +#: settings/serializers/terminal.py:8 terminal/serializers/endpoint.py:54 msgid "IP" msgstr "IP" @@ -236,7 +236,7 @@ msgstr "" msgid "Time Period" msgstr "时段" -#: applications/apps.py:9 applications/models/application.py:63 +#: applications/apps.py:9 applications/models/application.py:64 msgid "Applications" msgstr "应用管理" @@ -255,7 +255,11 @@ msgstr "远程应用" msgid "Custom" msgstr "自定义" -#: applications/models/account.py:12 applications/models/application.py:234 +#: applications/const.py:91 rbac/tree.py:29 +msgid "Other" +msgstr "其它" + +#: applications/models/account.py:12 applications/models/application.py:237 #: assets/models/backup.py:32 assets/models/cmd_filter.py:45 #: authentication/models.py:67 authentication/models.py:95 #: perms/models/application_permission.py:28 @@ -273,8 +277,9 @@ msgstr "应用程序" msgid "System user" msgstr "系统用户" -#: applications/models/account.py:17 assets/models/authbook.py:21 -#: settings/serializers/auth/cas.py:18 +#: applications/models/account.py:17 +#: applications/serializers/attrs/application_type/oracle.py:13 +#: assets/models/authbook.py:21 settings/serializers/auth/cas.py:18 msgid "Version" msgstr "版本" @@ -290,7 +295,7 @@ msgstr "可以查看应用账号密码" msgid "Can change application account secret" msgstr "可以查看应用账号密码" -#: applications/models/application.py:219 +#: applications/models/application.py:222 #: applications/serializers/application.py:99 assets/models/label.py:21 #: perms/models/application_permission.py:21 #: perms/serializers/application/user_permission.py:33 @@ -299,7 +304,7 @@ msgstr "可以查看应用账号密码" msgid "Category" msgstr "类别" -#: applications/models/application.py:222 +#: applications/models/application.py:225 #: applications/serializers/application.py:101 assets/models/backup.py:49 #: assets/models/cmd_filter.py:82 assets/models/user.py:250 #: authentication/models.py:70 perms/models/application_permission.py:24 @@ -313,21 +318,21 @@ msgstr "类别" msgid "Type" msgstr "类型" -#: applications/models/application.py:226 assets/models/asset.py:217 +#: applications/models/application.py:229 assets/models/asset.py:217 #: assets/models/domain.py:29 assets/models/domain.py:64 msgid "Domain" msgstr "网域" -#: applications/models/application.py:228 xpack/plugins/cloud/models.py:33 +#: applications/models/application.py:231 xpack/plugins/cloud/models.py:33 #: xpack/plugins/cloud/serializers/account.py:60 msgid "Attrs" msgstr "属性" -#: applications/models/application.py:238 +#: applications/models/application.py:241 msgid "Can match application" msgstr "匹配应用" -#: applications/models/application.py:305 +#: applications/models/application.py:320 msgid "Application user" msgstr "应用用户" @@ -392,7 +397,7 @@ msgstr "主机" #: applications/serializers/attrs/application_type/mongodb.py:10 #: applications/serializers/attrs/application_type/mysql.py:10 #: applications/serializers/attrs/application_type/mysql_workbench.py:22 -#: applications/serializers/attrs/application_type/oracle.py:10 +#: applications/serializers/attrs/application_type/oracle.py:16 #: applications/serializers/attrs/application_type/pgsql.py:10 #: applications/serializers/attrs/application_type/redis.py:10 #: applications/serializers/attrs/application_type/sqlserver.py:10 @@ -462,6 +467,10 @@ msgstr "Mysql 工作台 用户名" msgid "Mysql workbench password" msgstr "Mysql 工作台 密码" +#: applications/serializers/attrs/application_type/oracle.py:14 +msgid "Magnus currently supports only 11g and 12c connections" +msgstr "目前 Magnus 只支持连接 11g、12c 版本" + #: applications/serializers/attrs/application_type/vmware_client.py:26 msgid "Vmware username" msgstr "Vmware 用户名" @@ -763,7 +772,7 @@ msgstr "失败" msgid "Connectivity" msgstr "可连接性" -#: assets/models/base.py:40 authentication/models.py:248 +#: assets/models/base.py:40 authentication/models.py:256 msgid "Date verified" msgstr "校验日期" @@ -1604,7 +1613,7 @@ msgstr "飞书" msgid "DingTalk" msgstr "钉钉" -#: audits/signal_handlers.py:56 authentication/models.py:252 +#: audits/signal_handlers.py:56 authentication/models.py:260 msgid "Temporary token" msgstr "临时密码" @@ -2085,13 +2094,13 @@ msgstr "过期时间" msgid "SSO token" msgstr "SSO token" -#: authentication/models.py:72 authentication/models.py:246 +#: authentication/models.py:72 authentication/models.py:254 #: authentication/templates/authentication/_access_key_modal.html:31 #: settings/serializers/auth/radius.py:17 msgid "Secret" msgstr "密钥" -#: authentication/models.py:74 authentication/models.py:249 +#: authentication/models.py:74 authentication/models.py:257 #: perms/models/base.py:90 tickets/models/ticket/apply_application.py:26 #: tickets/models/ticket/apply_asset.py:24 users/models/user.py:703 msgid "Date expired" @@ -2109,47 +2118,47 @@ msgstr "连接令牌" msgid "Can view connection token secret" msgstr "可以查看连接令牌密文" -#: authentication/models.py:141 +#: authentication/models.py:149 msgid "Connection token expired at: {}" msgstr "连接令牌过期: {}" -#: authentication/models.py:146 +#: authentication/models.py:154 msgid "User not exists" msgstr "用户不存在" -#: authentication/models.py:150 +#: authentication/models.py:158 msgid "User invalid, disabled or expired" msgstr "用户无效,已禁用或已过期" -#: authentication/models.py:155 +#: authentication/models.py:163 msgid "System user not exists" msgstr "系统用户不存在" -#: authentication/models.py:161 +#: authentication/models.py:169 msgid "Asset not exists" msgstr "资产不存在" -#: authentication/models.py:165 +#: authentication/models.py:173 msgid "Asset inactive" msgstr "资产未激活" -#: authentication/models.py:172 +#: authentication/models.py:180 msgid "User has no permission to access asset or permission expired" msgstr "用户没有权限访问资产或权限已过期" -#: authentication/models.py:180 +#: authentication/models.py:188 msgid "Application not exists" msgstr "应用不存在" -#: authentication/models.py:187 +#: authentication/models.py:195 msgid "User has no permission to access application or permission expired" msgstr "用户没有权限访问应用或权限已过期" -#: authentication/models.py:247 +#: authentication/models.py:255 msgid "Verified" msgstr "已校验" -#: authentication/models.py:268 +#: authentication/models.py:276 msgid "Super connection token" msgstr "超级连接令牌" @@ -2166,7 +2175,11 @@ msgstr "绑定提醒" msgid "Validity" msgstr "有效" -#: authentication/serializers/connection_token.py:73 +#: authentication/serializers/connection_token.py:24 +msgid "Expired time" +msgstr "过期时间" + +#: authentication/serializers/connection_token.py:74 msgid "Asset or application required" msgstr "资产或应用必填" @@ -2969,7 +2982,7 @@ msgstr "组织存在资源 ({}) 不能被删除" msgid "App organizations" msgstr "组织管理" -#: orgs/mixins/models.py:46 orgs/mixins/serializers.py:25 orgs/models.py:80 +#: orgs/mixins/models.py:54 orgs/mixins/serializers.py:25 orgs/models.py:80 #: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:64 @@ -3333,10 +3346,6 @@ msgstr "审计台" msgid "System setting" msgstr "系统设置" -#: rbac/tree.py:29 -msgid "Other" -msgstr "其它" - #: rbac/tree.py:37 msgid "Accounts" msgstr "账号管理" @@ -4602,7 +4611,7 @@ msgstr "Jmservisor 是在 windows 远程应用发布服务器中用来拉起远 msgid "Offline video player" msgstr "离线录像播放器" -#: terminal/api/endpoint.py:26 +#: terminal/api/endpoint.py:33 msgid "Not found protocol query params" msgstr "" @@ -4775,18 +4784,26 @@ msgstr "PostgreSQL 端口" msgid "Redis Port" msgstr "Redis 端口" -#: terminal/models/endpoint.py:26 terminal/models/endpoint.py:90 -#: terminal/serializers/endpoint.py:45 terminal/serializers/storage.py:38 +#: terminal/models/endpoint.py:21 +msgid "Oracle 11g Port" +msgstr "Oracle 11g 端口" + +#: terminal/models/endpoint.py:22 +msgid "Oracle 12c Port" +msgstr "Oracle 12c 端口" + +#: terminal/models/endpoint.py:28 terminal/models/endpoint.py:96 +#: terminal/serializers/endpoint.py:57 terminal/serializers/storage.py:38 #: terminal/serializers/storage.py:50 terminal/serializers/storage.py:80 #: terminal/serializers/storage.py:90 terminal/serializers/storage.py:98 msgid "Endpoint" msgstr "端点" -#: terminal/models/endpoint.py:83 +#: terminal/models/endpoint.py:89 msgid "IP group" msgstr "IP 组" -#: terminal/models/endpoint.py:95 +#: terminal/models/endpoint.py:101 msgid "Endpoint rule" msgstr "端点规则" @@ -4967,7 +4984,11 @@ msgstr "级别" msgid "Batch danger command alert" msgstr "批量危险命令告警" -#: terminal/serializers/endpoint.py:39 +#: terminal/serializers/endpoint.py:12 +msgid "Oracle port" +msgstr "" + +#: terminal/serializers/endpoint.py:51 msgid "" "If asset IP addresses under different endpoints conflict, use asset labels" msgstr "如果不同端点下的资产 IP 有冲突,使用资产标签实现" @@ -6608,10 +6629,9 @@ msgid "" "all instances and randomly match IP addresses.
Format for comma-" "delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" msgstr "" -"只有匹配到 IP 段的实例会被同步。
" -"如果实例包含多个 IP 地址,那么第一个匹配到的 IP 地址将被用作创建的资产的 IP。
" -"默认值 * 表示同步所有实例和随机匹配 IP 地址。
" -"格式为以逗号分隔的字符串,例如:192.168.1.0/24,10.1.1.1-10.1.1.20" +"只有匹配到 IP 段的实例会被同步。
如果实例包含多个 IP 地址,那么第一个匹配" +"到的 IP 地址将被用作创建的资产的 IP。
默认值 * 表示同步所有实例和随机匹配 " +"IP 地址。
格式为以逗号分隔的字符串,例如:192.168.1.0/24,10.1.1.1-10.1.1.20" #: xpack/plugins/cloud/serializers/task.py:36 msgid "History count" diff --git a/apps/terminal/api/endpoint.py b/apps/terminal/api/endpoint.py index 5e4c7542d..7a9546c5e 100644 --- a/apps/terminal/api/endpoint.py +++ b/apps/terminal/api/endpoint.py @@ -1,6 +1,7 @@ from rest_framework.decorators import action from rest_framework.response import Response from rest_framework import status +from rest_framework.request import Request from common.drf.api import JMSBulkModelViewSet from django.utils.translation import ugettext_lazy as _ from django.shortcuts import get_object_or_404 @@ -18,39 +19,42 @@ __all__ = ['EndpointViewSet', 'EndpointRuleViewSet'] class SmartEndpointViewMixin: get_serializer: callable + request: Request + + # View 处理过程中用的属性 + target_instance: None + target_protocol: None @action(methods=['get'], detail=False, permission_classes=[IsValidUser], url_path='smart') def smart(self, request, *args, **kwargs): - protocol = request.GET.get('protocol') - if not protocol: + self.target_instance = self.get_target_instance() + self.target_protocol = self.get_target_protocol() + if not self.target_protocol: error = _('Not found protocol query params') return Response(data={'error': error}, status=status.HTTP_404_NOT_FOUND) - endpoint = self.match_endpoint(request, protocol) + endpoint = self.match_endpoint() serializer = self.get_serializer(endpoint) return Response(serializer.data) - def match_endpoint(self, request, protocol): - instance = self.get_target_instance(request) - endpoint = self.match_endpoint_by_label(instance, protocol) + def match_endpoint(self): + endpoint = self.match_endpoint_by_label() if not endpoint: - endpoint = self.match_endpoint_by_target_ip(request, instance, protocol) + endpoint = self.match_endpoint_by_target_ip() return endpoint - @staticmethod - def match_endpoint_by_label(instance, protocol): - return Endpoint.match_by_instance_label(instance, protocol) + def match_endpoint_by_label(self): + return Endpoint.match_by_instance_label(self.target_instance, self.target_protocol) - @staticmethod - def match_endpoint_by_target_ip(request, instance, protocol): + def match_endpoint_by_target_ip(self): # 用来方便测试 - target_ip = request.GET.get('target_ip', '') - if not target_ip and callable(getattr(instance, 'get_target_ip', None)): - target_ip = instance.get_target_ip() - endpoint = EndpointRule.match_endpoint(target_ip, protocol, request) + target_ip = self.request.GET.get('target_ip', '') + if not target_ip and callable(getattr(self.target_instance, 'get_target_ip', None)): + target_ip = self.target_instance.get_target_ip() + endpoint = EndpointRule.match_endpoint(target_ip, self.target_protocol, self.request) return endpoint - @staticmethod - def get_target_instance(request): + def get_target_instance(self): + request = self.request asset_id = request.GET.get('asset_id') app_id = request.GET.get('app_id') session_id = request.GET.get('session_id') @@ -77,6 +81,14 @@ class SmartEndpointViewMixin: instance = get_object_or_404(model, pk=pk) return instance + def get_target_protocol(self): + protocol = None + if isinstance(self.target_instance, Application) and self.target_instance.is_type(Application.APP_TYPE.oracle): + protocol = self.target_instance.get_target_protocol_for_oracle() + if not protocol: + protocol = self.request.GET.get('protocol') + return protocol + class EndpointViewSet(SmartEndpointViewMixin, JMSBulkModelViewSet): filterset_fields = ('name', 'host') diff --git a/apps/terminal/migrations/0052_auto_20220713_1417.py b/apps/terminal/migrations/0052_auto_20220713_1417.py new file mode 100644 index 000000000..87ad6ba6a --- /dev/null +++ b/apps/terminal/migrations/0052_auto_20220713_1417.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.12 on 2022-07-13 06:17 + +import common.db.fields +import django.core.validators +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('terminal', '0051_sessionsharing_users'), + ] + + operations = [ + migrations.AddField( + model_name='endpoint', + name='oracle_11g_port', + field=common.db.fields.PortField(default=15211, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='Oracle 11g Port'), + ), + migrations.AddField( + model_name='endpoint', + name='oracle_12c_port', + field=common.db.fields.PortField(default=15212, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='Oracle 12c Port'), + ), + ] diff --git a/apps/terminal/models/endpoint.py b/apps/terminal/models/endpoint.py index b03075abb..083b9c0a1 100644 --- a/apps/terminal/models/endpoint.py +++ b/apps/terminal/models/endpoint.py @@ -18,6 +18,8 @@ class Endpoint(JMSModel): mariadb_port = PortField(default=33061, verbose_name=_('MariaDB Port')) postgresql_port = PortField(default=54320, verbose_name=_('PostgreSQL Port')) redis_port = PortField(default=63790, verbose_name=_('Redis Port')) + oracle_11g_port = PortField(default=15211, verbose_name=_('Oracle 11g Port')) + oracle_12c_port = PortField(default=15212, verbose_name=_('Oracle 12c Port')) comment = models.TextField(default='', blank=True, verbose_name=_('Comment')) default_id = '00000000-0000-0000-0000-000000000001' @@ -32,6 +34,10 @@ class Endpoint(JMSModel): def get_port(self, protocol): return getattr(self, f'{protocol}_port', 0) + def get_oracle_port(self, version): + protocol = f'oracle_{version}' + return self.get_port(protocol) + def is_default(self): return str(self.id) == self.default_id diff --git a/apps/terminal/serializers/endpoint.py b/apps/terminal/serializers/endpoint.py index fa3e71c35..3d8e858ac 100644 --- a/apps/terminal/serializers/endpoint.py +++ b/apps/terminal/serializers/endpoint.py @@ -8,6 +8,8 @@ __all__ = ['EndpointSerializer', 'EndpointRuleSerializer'] class EndpointSerializer(BulkModelSerializer): + # 解决 luna 处理繁琐的问题,oracle_port 返回匹配到的端口 + oracle_port = serializers.SerializerMethodField(label=_('Oracle port')) class Meta: model = Endpoint @@ -17,6 +19,8 @@ class EndpointSerializer(BulkModelSerializer): 'https_port', 'http_port', 'ssh_port', 'rdp_port', 'mysql_port', 'mariadb_port', 'postgresql_port', 'redis_port', + 'oracle_11g_port', 'oracle_12c_port', + 'oracle_port', ] fields = fields_mini + fields_small + [ 'comment', 'date_created', 'date_updated', 'created_by' @@ -30,8 +34,16 @@ class EndpointSerializer(BulkModelSerializer): 'mariadb_port': {'default': 33061}, 'postgresql_port': {'default': 54320}, 'redis_port': {'default': 63790}, + 'oracle_11g_port': {'default': 15211}, + 'oracle_12c_port': {'default': 15212}, } + def get_oracle_port(self, obj: Endpoint): + view = self.context.get('view') + if not view or view.action not in ['smart']: + return 0 + return obj.get_port(view.target_protocol) + class EndpointRuleSerializer(BulkModelSerializer): _ip_group_help_text = '{}
{}'.format( From f0fbc73f73006df71576bd0124fd0a68a121f623 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 7 Jul 2022 16:21:39 +0800 Subject: [PATCH 004/104] =?UTF-8?q?perf:=20=E5=B7=A5=E4=BD=9C=E5=8F=B0?= =?UTF-8?q?=E6=94=AF=E6=8C=81=20root?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/builtin.py | 3 +-- apps/rbac/models/rolebinding.py | 2 +- apps/users/api/user.py | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/rbac/builtin.py b/apps/rbac/builtin.py index 34733dc59..f5b030d2b 100644 --- a/apps/rbac/builtin.py +++ b/apps/rbac/builtin.py @@ -6,7 +6,6 @@ _view_root_perms = ( ('orgs', 'organization', 'view', 'rootorg'), ) -# 工作台也区分组织后再考虑 user_perms = ( ('rbac', 'menupermission', 'view', 'workbench'), ('rbac', 'menupermission', 'view', 'webterminal'), @@ -25,7 +24,7 @@ system_user_perms = ( ('authentication', 'temptoken', 'add,change,view', 'temptoken'), ('authentication', 'accesskey', '*', '*'), ('tickets', 'ticket', 'view', 'ticket'), -) + user_perms +) + user_perms + _view_root_perms _auditor_perms = ( ('rbac', 'menupermission', 'view', 'audit'), diff --git a/apps/rbac/models/rolebinding.py b/apps/rbac/models/rolebinding.py index ded35a278..3caa83622 100644 --- a/apps/rbac/models/rolebinding.py +++ b/apps/rbac/models/rolebinding.py @@ -127,7 +127,7 @@ class RoleBinding(JMSModel): orgs = all_orgs.filter(id__in=org_ids) # 全局组织 - if orgs and perm != 'rbac.view_workbench' and user.has_perm('orgs.view_rootorg'): + if orgs and user.has_perm('orgs.view_rootorg'): orgs = [Organization.root(), *list(orgs)] return orgs diff --git a/apps/users/api/user.py b/apps/users/api/user.py index a5d726fe0..70939f51f 100644 --- a/apps/users/api/user.py +++ b/apps/users/api/user.py @@ -33,7 +33,7 @@ __all__ = [ class UserViewSet(CommonApiMixin, UserQuerysetMixin, SuggestionMixin, BulkModelViewSet): filterset_class = UserFilter - search_fields = ('username', 'email', 'name', 'id', 'source', 'role', 'is_active') + search_fields = ('username', 'email', 'name') serializer_classes = { 'default': UserSerializer, 'suggestion': MiniUserSerializer, From af080fe38d01d518f011b7b175283fc7f83a4ed5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Jul 2022 23:02:12 +0000 Subject: [PATCH 005/104] build(deps): bump django from 3.2.13 to 3.2.14 in /requirements Bumps [django](https://github.com/django/django) from 3.2.13 to 3.2.14. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/3.2.13...3.2.14) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index afe9b7179..75e397656 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -62,7 +62,7 @@ jsonfield2==4.0.0.post0 geoip2==4.5.0 ipip-ipdb==1.6.1 # Django environment -Django==3.2.13 +Django==3.2.14 django-bootstrap3==14.2.0 django-filter==2.4.0 django-formtools==2.2 From f758414844654c39368e40f5cb817bb94d64e025 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 13 Jul 2022 16:54:44 +0800 Subject: [PATCH 006/104] =?UTF-8?q?fix:=20=E5=AE=A1=E6=89=B9=E6=97=B6=20?= =?UTF-8?q?=E6=9D=A5=E7=9D=80=E4=B8=8D=E5=90=8C=E7=BB=84=E7=BB=87=E7=9A=84?= =?UTF-8?q?=E8=B5=84=E4=BA=A7=E6=A0=A1=E9=AA=8C=20(#8586)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/tickets/api/ticket.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/tickets/api/ticket.py b/apps/tickets/api/ticket.py index 1df3506c1..d6e623892 100644 --- a/apps/tickets/api/ticket.py +++ b/apps/tickets/api/ticket.py @@ -77,7 +77,8 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet): partial = kwargs.pop('partial', False) instance = self.get_object() serializer = self.get_serializer(instance, data=request.data, partial=partial) - serializer.is_valid(raise_exception=True) + with tmp_to_root_org(): + serializer.is_valid(raise_exception=True) instance = serializer.save() instance.approve(processor=request.user) return Response('ok') From 4a3d7a85242d0a1014737f997c2b004ede893c36 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 13 Jul 2022 17:13:02 +0800 Subject: [PATCH 007/104] perf: history account model queryset (#8588) Co-authored-by: feng626 <1304903146@qq.com> --- apps/assets/api/account_history.py | 6 +++++- apps/assets/models/authbook.py | 5 ++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/assets/api/account_history.py b/apps/assets/api/account_history.py index 3258dfd48..3feddce91 100644 --- a/apps/assets/api/account_history.py +++ b/apps/assets/api/account_history.py @@ -30,7 +30,11 @@ class AccountHistoryViewSet(AccountViewSet): http_method_names = ['get', 'options'] def get_queryset(self): - queryset = AuthBook.get_queryset(is_history_model=True) + queryset = self.model.objects.all() \ + .annotate(ip=F('asset__ip')) \ + .annotate(hostname=F('asset__hostname')) \ + .annotate(platform=F('asset__platform__name')) \ + .annotate(protocols=F('asset__protocols')) return queryset diff --git a/apps/assets/models/authbook.py b/apps/assets/models/authbook.py index 338c65a3e..a6b52927b 100644 --- a/apps/assets/models/authbook.py +++ b/apps/assets/models/authbook.py @@ -125,9 +125,8 @@ class AuthBook(BaseUser, AbsConnectivity): logger.debug('Update asset admin user: {} {}'.format(self.asset, self.systemuser)) @classmethod - def get_queryset(cls, is_history_model=False): - model = cls.history.model if is_history_model else cls - queryset = model.objects.all() \ + def get_queryset(cls): + queryset = cls.objects.all() \ .annotate(ip=F('asset__ip')) \ .annotate(hostname=F('asset__hostname')) \ .annotate(platform=F('asset__platform__name')) \ From dec8e3459aded0cb62c1d461eb6161e6ff31fea6 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Thu, 14 Jul 2022 10:54:49 +0800 Subject: [PATCH 008/104] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20Oracle=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=20version=20=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E9=BB=98=E8=AE=A4=2012c=20=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: 添加 Oracle 数据库 version 迁移文件默认 12c 版本 --- .../migrations/0022_auto_20220714_1046.py | 23 +++++++++++++++++++ apps/applications/models/application.py | 2 +- .../attrs/application_type/oracle.py | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 apps/applications/migrations/0022_auto_20220714_1046.py diff --git a/apps/applications/migrations/0022_auto_20220714_1046.py b/apps/applications/migrations/0022_auto_20220714_1046.py new file mode 100644 index 000000000..8ecb1cbe6 --- /dev/null +++ b/apps/applications/migrations/0022_auto_20220714_1046.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.12 on 2022-07-14 02:46 + +from django.db import migrations + + +def migrate_db_oracle_version_to_attrs(apps, schema_editor): + db_alias = schema_editor.connection.alias + model = apps.get_model("applications", "Application") + oracles = list(model.objects.using(db_alias).filter(type='oracle')) + for o in oracles: + o.attrs['version'] = '12c' + model.objects.using(db_alias).bulk_update(oracles, ['attrs']) + + +class Migration(migrations.Migration): + + dependencies = [ + ('applications', '0021_auto_20220629_1826'), + ] + + operations = [ + migrations.RunPython(migrate_db_oracle_version_to_attrs) + ] diff --git a/apps/applications/models/application.py b/apps/applications/models/application.py index 1644ab1d5..cc98abaf8 100644 --- a/apps/applications/models/application.py +++ b/apps/applications/models/application.py @@ -308,7 +308,7 @@ class Application(CommonModelMixin, OrgModelMixin, ApplicationTreeNodeMixin): """ Oracle 类型需要单独处理,因为要携带版本号 """ if not self.is_type(self.APP_TYPE.oracle): return - version = self.attrs.get('version', OracleVersion.version_other) + version = self.attrs.get('version', OracleVersion.version_12c) if version == OracleVersion.version_other: return return 'oracle_%s' % version diff --git a/apps/applications/serializers/attrs/application_type/oracle.py b/apps/applications/serializers/attrs/application_type/oracle.py index 94cfaa319..fdc8016d2 100644 --- a/apps/applications/serializers/attrs/application_type/oracle.py +++ b/apps/applications/serializers/attrs/application_type/oracle.py @@ -9,7 +9,7 @@ __all__ = ['OracleSerializer'] class OracleSerializer(DBSerializer): version = serializers.ChoiceField( - choices=OracleVersion.choices, default=OracleVersion.version_other, + choices=OracleVersion.choices, default=OracleVersion.version_12c, allow_null=True, label=_('Version'), help_text=_('Magnus currently supports only 11g and 12c connections') ) From 9967d5241611ff244d8fc4cf52a3b54ecbc3b7e7 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 14 Jul 2022 15:37:00 +0800 Subject: [PATCH 009/104] =?UTF-8?q?perf:=20=E6=9A=82=E6=97=B6=E5=8E=BB?= =?UTF-8?q?=E6=8E=89=E5=8E=86=E5=8F=B2=E8=B4=A6=E5=8F=B7=E6=9D=83=E9=99=90?= =?UTF-8?q?=20(#8594)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/rbac/const.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/rbac/const.py b/apps/rbac/const.py index 20038de19..f8789a110 100644 --- a/apps/rbac/const.py +++ b/apps/rbac/const.py @@ -40,6 +40,10 @@ exclude_permissions = ( ('assets', 'gathereduser', 'add,delete,change', 'gathereduser'), ('assets', 'accountbackupplanexecution', 'delete,change', 'accountbackupplanexecution'), ('assets', 'authbook', 'change', 'authbook'), + # TODO 暂时去掉历史账号的权限 + ('assets', 'authbook', '*', 'assethistoryaccount'), + ('assets', 'authbook', '*', 'assethistoryaccountsecret'), + ('perms', 'userassetgrantedtreenoderelation', '*', '*'), ('perms', 'usergrantedmappingnode', '*', '*'), ('perms', 'permnode', '*', '*'), From 395636296d70b5348ab64cf25de8ac9c906a5371 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Thu, 14 Jul 2022 17:41:14 +0800 Subject: [PATCH 010/104] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5token=20secret=E9=95=BF=E5=BA=A6=E4=B8=BA16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/serializers/connection_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/authentication/serializers/connection_token.py b/apps/authentication/serializers/connection_token.py index 1b639bec6..0e811cbaa 100644 --- a/apps/authentication/serializers/connection_token.py +++ b/apps/authentication/serializers/connection_token.py @@ -61,7 +61,7 @@ class ConnectionTokenSerializer(OrgResourceModelSerializerMixin): system_user = attrs.get('system_user') or '' asset = attrs.get('asset') or '' application = attrs.get('application') or '' - secret = attrs.get('secret') or random_string(64) + secret = attrs.get('secret') or random_string(16) date_expired = attrs.get('date_expired') or ConnectionToken.get_default_date_expired() if isinstance(asset, Asset): From 93537c07a1a3ef3a00c68154114287b08b14c365 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 15 Jul 2022 11:38:50 +0800 Subject: [PATCH 011/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=B7=A5?= =?UTF-8?q?=E5=8D=95=E6=8E=88=E6=9D=83=E7=BB=84=E7=BB=87=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20(#8599)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/tickets/handlers/apply_application.py | 8 +++++--- apps/tickets/handlers/apply_asset.py | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/apps/tickets/handlers/apply_application.py b/apps/tickets/handlers/apply_application.py index 15c76c7e5..5b7712553 100644 --- a/apps/tickets/handlers/apply_application.py +++ b/apps/tickets/handlers/apply_application.py @@ -16,16 +16,18 @@ class Handler(BaseHandler): # permission def _create_application_permission(self): - with tmp_to_root_org(): + org_id = self.ticket.org_id + with tmp_to_org(org_id): application_permission = ApplicationPermission.objects.filter(id=self.ticket.id).first() if application_permission: return application_permission + apply_applications = self.ticket.apply_applications.all() + apply_system_users = self.ticket.apply_system_users.all() + apply_permission_name = self.ticket.apply_permission_name apply_category = self.ticket.apply_category apply_type = self.ticket.apply_type - apply_applications = self.ticket.apply_applications.all() - apply_system_users = self.ticket.apply_system_users.all() apply_date_start = self.ticket.apply_date_start apply_date_expired = self.ticket.apply_date_expired permission_created_by = '{}:{}'.format( diff --git a/apps/tickets/handlers/apply_asset.py b/apps/tickets/handlers/apply_asset.py index 136347782..e9d29697d 100644 --- a/apps/tickets/handlers/apply_asset.py +++ b/apps/tickets/handlers/apply_asset.py @@ -16,15 +16,17 @@ class Handler(BaseHandler): # permission def _create_asset_permission(self): - with tmp_to_root_org(): + org_id = self.ticket.org_id + with tmp_to_org(org_id): asset_permission = AssetPermission.objects.filter(id=self.ticket.id).first() if asset_permission: return asset_permission + apply_nodes = self.ticket.apply_nodes.all() + apply_assets = self.ticket.apply_assets.all() + apply_system_users = self.ticket.apply_system_users.all() + apply_permission_name = self.ticket.apply_permission_name - apply_nodes = self.ticket.apply_nodes.all() - apply_assets = self.ticket.apply_assets.all() - apply_system_users = self.ticket.apply_system_users.all() apply_actions = self.ticket.apply_actions apply_date_start = self.ticket.apply_date_start apply_date_expired = self.ticket.apply_date_expired From 41541a91b9b8c5e61ae88ee07a360bac4a4f079e Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Fri, 15 Jul 2022 14:56:51 +0800 Subject: [PATCH 012/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20public=20?= =?UTF-8?q?=E5=92=8C=20smart=20API=20=E6=9D=83=E9=99=90=E5=8C=85=E5=90=AB?= =?UTF-8?q?=20connection=20token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/permissions.py | 19 +++++++++++++++++++ apps/settings/api/public.py | 8 ++++++-- apps/terminal/api/endpoint.py | 5 +++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/apps/common/permissions.py b/apps/common/permissions.py index 3000b9533..c2d2cf4fa 100644 --- a/apps/common/permissions.py +++ b/apps/common/permissions.py @@ -7,6 +7,9 @@ from rest_framework import permissions from authentication.const import ConfirmType from common.exceptions import UserConfirmRequired +from orgs.utils import tmp_to_root_org +from authentication.models import ConnectionToken +from common.utils import get_object_or_none class IsValidUser(permissions.IsAuthenticated, permissions.BasePermission): @@ -17,6 +20,22 @@ class IsValidUser(permissions.IsAuthenticated, permissions.BasePermission): and request.user.is_valid +class IsValidUserOrConnectionToken(IsValidUser): + + def has_permission(self, request, view): + return super(IsValidUserOrConnectionToken, self).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) \ diff --git a/apps/settings/api/public.py b/apps/settings/api/public.py index 1351fd6cd..161b8002a 100644 --- a/apps/settings/api/public.py +++ b/apps/settings/api/public.py @@ -3,7 +3,11 @@ from rest_framework.permissions import AllowAny, IsAuthenticated from django.conf import settings from jumpserver.utils import has_valid_xpack_license, get_xpack_license_info -from common.utils import get_logger, lazyproperty +from common.utils import get_logger, lazyproperty, get_object_or_none +from authentication.models import ConnectionToken +from orgs.utils import tmp_to_root_org +from common.permissions import IsValidUserOrConnectionToken + from .. import serializers from ..utils import get_interface_setting_or_default @@ -28,7 +32,7 @@ class OpenPublicSettingApi(generics.RetrieveAPIView): class PublicSettingApi(OpenPublicSettingApi): - permission_classes = (IsAuthenticated,) + permission_classes = (IsValidUserOrConnectionToken,) serializer_class = serializers.PrivateSettingSerializer def get_object(self): diff --git a/apps/terminal/api/endpoint.py b/apps/terminal/api/endpoint.py index 7a9546c5e..ca745d412 100644 --- a/apps/terminal/api/endpoint.py +++ b/apps/terminal/api/endpoint.py @@ -9,9 +9,9 @@ from assets.models import Asset from orgs.utils import tmp_to_root_org from applications.models import Application from terminal.models import Session -from common.permissions import IsValidUser from ..models import Endpoint, EndpointRule from .. import serializers +from common.permissions import IsValidUserOrConnectionToken __all__ = ['EndpointViewSet', 'EndpointRuleViewSet'] @@ -25,7 +25,8 @@ class SmartEndpointViewMixin: target_instance: None target_protocol: None - @action(methods=['get'], detail=False, permission_classes=[IsValidUser], url_path='smart') + @action(methods=['get'], detail=False, permission_classes=[IsValidUserOrConnectionToken], + url_path='smart') def smart(self, request, *args, **kwargs): self.target_instance = self.get_target_instance() self.target_protocol = self.get_target_protocol() From 1b1b70e7bdfeb3b64896060d9fcc52b6842d236f Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Fri, 15 Jul 2022 16:30:21 +0800 Subject: [PATCH 013/104] =?UTF-8?q?fix:=20=E5=A4=84=E7=90=86=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E8=B4=A6=E5=8F=B7=E8=84=8F=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0023_auto_20220715_1556.py | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 apps/applications/migrations/0023_auto_20220715_1556.py diff --git a/apps/applications/migrations/0023_auto_20220715_1556.py b/apps/applications/migrations/0023_auto_20220715_1556.py new file mode 100644 index 000000000..03123efab --- /dev/null +++ b/apps/applications/migrations/0023_auto_20220715_1556.py @@ -0,0 +1,48 @@ +# Generated by Django 3.1.14 on 2022-07-15 07:56 +import time +from collections import defaultdict + +from django.db import migrations + + +def migrate_account_dirty_data(apps, schema_editor): + db_alias = schema_editor.connection.alias + account_model = apps.get_model('applications', 'Account') + + count = 0 + bulk_size = 1000 + + while True: + accounts = account_model.objects.using(db_alias) \ + .filter(org_id='')[count:count + bulk_size] + + if not accounts: + break + + accounts = list(accounts) + start = time.time() + for i in accounts: + if i.app: + org_id = i.app.org_id + elif i.systemuser: + org_id = i.systemuser.org_id + else: + org_id = '' + if org_id: + i.org_id = org_id + + account_model.objects.bulk_update(accounts, ['org_id', ]) + print("Update account org is empty: {}-{} using: {:.2f}s".format( + count, count + len(accounts), time.time() - start + )) + count += len(accounts) + + +class Migration(migrations.Migration): + dependencies = [ + ('applications', '0022_auto_20220714_1046'), + ] + + operations = [ + migrations.RunPython(migrate_account_dirty_data), + ] From 4fd82b9946455f2b95b2bb86d8bd1c334e00a1bc Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 15 Jul 2022 17:17:56 +0800 Subject: [PATCH 014/104] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=20(#8602)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/authentication/errors/mfa.py | 10 ++-- apps/locale/ja/LC_MESSAGES/django.po | 72 ++++++++++++++-------------- apps/locale/zh/LC_MESSAGES/django.po | 72 ++++++++++++++-------------- 3 files changed, 79 insertions(+), 75 deletions(-) diff --git a/apps/authentication/errors/mfa.py b/apps/authentication/errors/mfa.py index 4b7f5a57e..288c2060e 100644 --- a/apps/authentication/errors/mfa.py +++ b/apps/authentication/errors/mfa.py @@ -14,23 +14,23 @@ class WeComCodeInvalid(JMSException): class WeComBindAlready(JMSException): - default_code = 'wecom_bind_already' - default_detail = 'WeCom already binded' + default_code = 'wecom_not_bound' + default_detail = _('WeCom is already bound') class WeComNotBound(JMSException): default_code = 'wecom_not_bound' - default_detail = 'WeCom is not bound' + default_detail = _('WeCom is not bound') class DingTalkNotBound(JMSException): default_code = 'dingtalk_not_bound' - default_detail = 'DingTalk is not bound' + default_detail = _('DingTalk is not bound') class FeiShuNotBound(JMSException): default_code = 'feishu_not_bound' - default_detail = 'FeiShu is not bound' + default_detail = _('FeiShu is not bound') class PasswordInvalid(JMSException): diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 254383a50..1ade4540a 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-13 16:25+0800\n" +"POT-Creation-Date: 2022-07-15 17:15+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -89,7 +89,7 @@ msgstr "ログイン確認" #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 #: authentication/models.py:54 authentication/models.py:78 orgs/models.py:214 -#: perms/models/base.py:84 rbac/builtin.py:118 rbac/models/rolebinding.py:41 +#: perms/models/base.py:84 rbac/builtin.py:117 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 #: terminal/models/sharing.py:33 terminal/notifications.py:91 @@ -214,7 +214,7 @@ msgid "Unsupported protocols: {}" msgstr "サポートされていないプロトコル: {}" #: acls/serializers/login_asset_acl.py:98 -#: tickets/serializers/ticket/ticket.py:78 +#: tickets/serializers/ticket/ticket.py:85 msgid "The organization `{}` does not exist" msgstr "組織 '{}'は存在しません" @@ -2002,6 +2002,24 @@ msgstr "電話が設定されていない" msgid "SSO auth closed" msgstr "SSO authは閉鎖されました" +#: authentication/errors/mfa.py:18 authentication/views/wecom.py:80 +msgid "WeCom is already bound" +msgstr "企業の微信はすでにバインドされています" + +#: authentication/errors/mfa.py:23 authentication/views/wecom.py:237 +#: authentication/views/wecom.py:291 +msgid "WeCom is not bound" +msgstr "企業の微信をバインドしていません" + +#: authentication/errors/mfa.py:28 authentication/views/dingtalk.py:242 +#: authentication/views/dingtalk.py:296 +msgid "DingTalk is not bound" +msgstr "DingTalkはバインドされていません" + +#: authentication/errors/mfa.py:33 authentication/views/feishu.py:203 +msgid "FeiShu is not bound" +msgstr "本を飛ばすは拘束されていません" + #: authentication/errors/mfa.py:38 msgid "Your password is invalid" msgstr "パスワードが無効です" @@ -2479,10 +2497,6 @@ msgstr "DingTalkのバインドに成功" msgid "Failed to get user from DingTalk" msgstr "DingTalkからユーザーを取得できませんでした" -#: authentication/views/dingtalk.py:242 authentication/views/dingtalk.py:296 -msgid "DingTalk is not bound" -msgstr "DingTalkはバインドされていません" - #: authentication/views/dingtalk.py:243 authentication/views/dingtalk.py:297 msgid "Please login with a password and then bind the DingTalk" msgstr "パスワードでログインし、DingTalkをバインドしてください" @@ -2511,10 +2525,6 @@ msgstr "本を飛ばすのバインドに成功" msgid "Failed to get user from FeiShu" msgstr "本を飛ばすからユーザーを取得できませんでした" -#: authentication/views/feishu.py:203 -msgid "FeiShu is not bound" -msgstr "本を飛ばすは拘束されていません" - #: authentication/views/feishu.py:204 msgid "Please login with a password and then bind the FeiShu" msgstr "パスワードでログインしてから本を飛ばすをバインドしてください" @@ -2559,10 +2569,6 @@ msgstr "企業微信エラー、システム管理者に連絡してください msgid "WeCom Error" msgstr "企業微信エラー" -#: authentication/views/wecom.py:80 -msgid "WeCom is already bound" -msgstr "企業の微信はすでにバインドされています" - #: authentication/views/wecom.py:163 msgid "WeCom query user failed" msgstr "企業微信ユーザーの問合せに失敗しました" @@ -2579,10 +2585,6 @@ msgstr "企業の微信のバインドに成功" msgid "Failed to get user from WeCom" msgstr "企業の微信からユーザーを取得できませんでした" -#: authentication/views/wecom.py:237 authentication/views/wecom.py:291 -msgid "WeCom is not bound" -msgstr "企業の微信をバインドしていません" - #: authentication/views/wecom.py:238 authentication/views/wecom.py:292 msgid "Please login with a password and then bind the WeCom" msgstr "パスワードでログインしてからWeComをバインドしてください" @@ -3022,10 +3024,10 @@ msgstr "組織のリソース ({}) は削除できません" msgid "App organizations" msgstr "アプリ組織" -#: orgs/mixins/models.py:54 orgs/mixins/serializers.py:25 orgs/models.py:80 +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:80 #: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 -#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:64 +#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 msgid "Organization" msgstr "組織" @@ -3258,27 +3260,27 @@ msgstr "{} 少なくとも1つのシステムロール" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:109 +#: rbac/builtin.py:108 msgid "SystemAdmin" msgstr "システム管理者" -#: rbac/builtin.py:112 +#: rbac/builtin.py:111 msgid "SystemAuditor" msgstr "システム監査人" -#: rbac/builtin.py:115 +#: rbac/builtin.py:114 msgid "SystemComponent" msgstr "システムコンポーネント" -#: rbac/builtin.py:121 +#: rbac/builtin.py:120 msgid "OrgAdmin" msgstr "組織管理者" -#: rbac/builtin.py:124 +#: rbac/builtin.py:123 msgid "OrgAuditor" msgstr "監査員を組織する" -#: rbac/builtin.py:127 +#: rbac/builtin.py:126 msgid "OrgUser" msgstr "組織ユーザー" @@ -4687,7 +4689,7 @@ msgstr "" msgid "Offline video player" msgstr "オフラインビデオプレーヤー" -#: terminal/api/endpoint.py:33 +#: terminal/api/endpoint.py:34 msgid "Not found protocol query params" msgstr "プロトコルクエリパラメータが見つかりません" @@ -5261,7 +5263,7 @@ msgstr "カスタムユーザー" msgid "Ticket already closed" msgstr "チケットはすでに閉じています" -#: tickets/handlers/apply_application.py:35 +#: tickets/handlers/apply_application.py:37 msgid "" "Created by the ticket, ticket title: {}, ticket applicant: {}, ticket " "processor: {}, ticket ID: {}" @@ -5269,7 +5271,7 @@ msgstr "" "チケットによって作成されたチケットタイトル: {}、チケット申請者: {}、チケット" "処理者: {}、チケットID: {}" -#: tickets/handlers/apply_asset.py:35 +#: tickets/handlers/apply_asset.py:37 msgid "" "Created by the ticket ticket title: {} ticket applicant: {} ticket " "processor: {} ticket ID: {}" @@ -5277,19 +5279,19 @@ msgstr "" "チケットのタイトル: {} チケット申請者: {} チケットプロセッサ: {} チケットID: " "{}" -#: tickets/handlers/base.py:79 +#: tickets/handlers/base.py:84 msgid "Change field" msgstr "フィールドを変更" -#: tickets/handlers/base.py:79 +#: tickets/handlers/base.py:84 msgid "Before change" msgstr "変更前" -#: tickets/handlers/base.py:79 +#: tickets/handlers/base.py:84 msgid "After change" msgstr "変更後" -#: tickets/handlers/base.py:91 +#: tickets/handlers/base.py:96 msgid "{} {} the ticket" msgstr "{} {} チケット" @@ -5503,7 +5505,7 @@ msgstr "有効期限は開始日より大きくする必要があります" msgid "Permission named `{}` already exists" msgstr "'{}'という名前の権限は既に存在します" -#: tickets/serializers/ticket/ticket.py:92 +#: tickets/serializers/ticket/ticket.py:99 msgid "The ticket flow `{}` does not exist" msgstr "チケットフロー '{}'が存在しない" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 24f5f8ee1..6f50d5c61 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-13 16:25+0800\n" +"POT-Creation-Date: 2022-07-15 17:15+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -88,7 +88,7 @@ msgstr "登录复核" #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 #: authentication/models.py:54 authentication/models.py:78 orgs/models.py:214 -#: perms/models/base.py:84 rbac/builtin.py:118 rbac/models/rolebinding.py:41 +#: perms/models/base.py:84 rbac/builtin.py:117 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 #: terminal/models/sharing.py:33 terminal/notifications.py:91 @@ -210,7 +210,7 @@ msgid "Unsupported protocols: {}" msgstr "不支持的协议: {}" #: acls/serializers/login_asset_acl.py:98 -#: tickets/serializers/ticket/ticket.py:78 +#: tickets/serializers/ticket/ticket.py:85 msgid "The organization `{}` does not exist" msgstr "组织 `{}` 不存在" @@ -1982,6 +1982,24 @@ msgstr "手机号没有设置" msgid "SSO auth closed" msgstr "SSO 认证关闭了" +#: authentication/errors/mfa.py:18 authentication/views/wecom.py:80 +msgid "WeCom is already bound" +msgstr "企业微信已经绑定" + +#: authentication/errors/mfa.py:23 authentication/views/wecom.py:237 +#: authentication/views/wecom.py:291 +msgid "WeCom is not bound" +msgstr "没有绑定企业微信" + +#: authentication/errors/mfa.py:28 authentication/views/dingtalk.py:242 +#: authentication/views/dingtalk.py:296 +msgid "DingTalk is not bound" +msgstr "钉钉没有绑定" + +#: authentication/errors/mfa.py:33 authentication/views/feishu.py:203 +msgid "FeiShu is not bound" +msgstr "没有绑定飞书" + #: authentication/errors/mfa.py:38 msgid "Your password is invalid" msgstr "您的密码无效" @@ -2445,10 +2463,6 @@ msgstr "绑定 钉钉 成功" msgid "Failed to get user from DingTalk" msgstr "从钉钉获取用户失败" -#: authentication/views/dingtalk.py:242 authentication/views/dingtalk.py:296 -msgid "DingTalk is not bound" -msgstr "钉钉没有绑定" - #: authentication/views/dingtalk.py:243 authentication/views/dingtalk.py:297 msgid "Please login with a password and then bind the DingTalk" msgstr "请使用密码登录,然后绑定钉钉" @@ -2477,10 +2491,6 @@ msgstr "绑定 飞书 成功" msgid "Failed to get user from FeiShu" msgstr "从飞书获取用户失败" -#: authentication/views/feishu.py:203 -msgid "FeiShu is not bound" -msgstr "没有绑定飞书" - #: authentication/views/feishu.py:204 msgid "Please login with a password and then bind the FeiShu" msgstr "请使用密码登录,然后绑定飞书" @@ -2525,10 +2535,6 @@ msgstr "企业微信错误,请联系系统管理员" msgid "WeCom Error" msgstr "企业微信错误" -#: authentication/views/wecom.py:80 -msgid "WeCom is already bound" -msgstr "企业微信已经绑定" - #: authentication/views/wecom.py:163 msgid "WeCom query user failed" msgstr "企业微信查询用户失败" @@ -2545,10 +2551,6 @@ msgstr "绑定 企业微信 成功" msgid "Failed to get user from WeCom" msgstr "从企业微信获取用户失败" -#: authentication/views/wecom.py:237 authentication/views/wecom.py:291 -msgid "WeCom is not bound" -msgstr "没有绑定企业微信" - #: authentication/views/wecom.py:238 authentication/views/wecom.py:292 msgid "Please login with a password and then bind the WeCom" msgstr "请使用密码登录,然后绑定企业微信" @@ -2982,10 +2984,10 @@ msgstr "组织存在资源 ({}) 不能被删除" msgid "App organizations" msgstr "组织管理" -#: orgs/mixins/models.py:54 orgs/mixins/serializers.py:25 orgs/models.py:80 +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:80 #: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 -#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:64 +#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 msgid "Organization" msgstr "组织" @@ -3216,27 +3218,27 @@ msgstr "{} 至少有一个系统角色" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:109 +#: rbac/builtin.py:108 msgid "SystemAdmin" msgstr "系统管理员" -#: rbac/builtin.py:112 +#: rbac/builtin.py:111 msgid "SystemAuditor" msgstr "系统审计员" -#: rbac/builtin.py:115 +#: rbac/builtin.py:114 msgid "SystemComponent" msgstr "系统组件" -#: rbac/builtin.py:121 +#: rbac/builtin.py:120 msgid "OrgAdmin" msgstr "组织管理员" -#: rbac/builtin.py:124 +#: rbac/builtin.py:123 msgid "OrgAuditor" msgstr "组织审计员" -#: rbac/builtin.py:127 +#: rbac/builtin.py:126 msgid "OrgUser" msgstr "组织用户" @@ -4611,7 +4613,7 @@ msgstr "Jmservisor 是在 windows 远程应用发布服务器中用来拉起远 msgid "Offline video player" msgstr "离线录像播放器" -#: terminal/api/endpoint.py:33 +#: terminal/api/endpoint.py:34 msgid "Not found protocol query params" msgstr "" @@ -5183,33 +5185,33 @@ msgstr "自定义用户" msgid "Ticket already closed" msgstr "工单已经关闭" -#: tickets/handlers/apply_application.py:35 +#: tickets/handlers/apply_application.py:37 msgid "" "Created by the ticket, ticket title: {}, ticket applicant: {}, ticket " "processor: {}, ticket ID: {}" msgstr "" "通过工单创建, 工单标题: {}, 工单申请人: {}, 工单处理人: {}, 工单 ID: {}" -#: tickets/handlers/apply_asset.py:35 +#: tickets/handlers/apply_asset.py:37 msgid "" "Created by the ticket ticket title: {} ticket applicant: {} ticket " "processor: {} ticket ID: {}" msgstr "" "通过工单创建, 工单标题: {}, 工单申请人: {}, 工单处理人: {}, 工单 ID: {}" -#: tickets/handlers/base.py:79 +#: tickets/handlers/base.py:84 msgid "Change field" msgstr "变更字段" -#: tickets/handlers/base.py:79 +#: tickets/handlers/base.py:84 msgid "Before change" msgstr "变更前" -#: tickets/handlers/base.py:79 +#: tickets/handlers/base.py:84 msgid "After change" msgstr "变更后" -#: tickets/handlers/base.py:91 +#: tickets/handlers/base.py:96 msgid "{} {} the ticket" msgstr "{} {} 工单" @@ -5423,7 +5425,7 @@ msgstr "过期时间要大于开始时间" msgid "Permission named `{}` already exists" msgstr "授权名称 `{}` 已存在" -#: tickets/serializers/ticket/ticket.py:92 +#: tickets/serializers/ticket/ticket.py:99 msgid "The ticket flow `{}` does not exist" msgstr "工单流程 `{}` 不存在" From 8824b6b54eee6b8707fde5b29fa4007b79d2631f Mon Sep 17 00:00:00 2001 From: fit2cloud Date: Thu, 14 Jul 2022 18:36:20 +0800 Subject: [PATCH 015/104] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3pip=E4=B8=8D?= =?UTF-8?q?=E8=83=BD=E5=AE=89=E8=A3=85psycopg2-binary=E5=92=8Cpymssql?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements/mac_pkg.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/mac_pkg.sh b/requirements/mac_pkg.sh index d93350cbc..e344d75be 100644 --- a/requirements/mac_pkg.sh +++ b/requirements/mac_pkg.sh @@ -3,7 +3,7 @@ BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" PROJECT_DIR=$(dirname "$BASE_DIR") echo "1. 安装依赖" -brew install libtiff libjpeg webp little-cms2 openssl gettext git git-lfs mysql libxml2 libxmlsec1 pkg-config +brew install libtiff libjpeg webp little-cms2 openssl gettext git git-lfs mysql libxml2 libxmlsec1 pkg-config postgresql freetds echo "2. 下载 IP 数据库" ip_db_path="${PROJECT_DIR}/apps/common/utils/geoip/GeoLite2-City.mmdb" From 0eaca0c1cbb81e2eb6ac0793876ba013dbad8607 Mon Sep 17 00:00:00 2001 From: huangzhiwen Date: Fri, 15 Jul 2022 14:54:56 +0800 Subject: [PATCH 016/104] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3mac=20m1=20pip?= =?UTF-8?q?=20install=20pymssql=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements/mac_pkg.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/mac_pkg.sh b/requirements/mac_pkg.sh index e344d75be..5108b36fa 100644 --- a/requirements/mac_pkg.sh +++ b/requirements/mac_pkg.sh @@ -3,7 +3,7 @@ BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" PROJECT_DIR=$(dirname "$BASE_DIR") echo "1. 安装依赖" -brew install libtiff libjpeg webp little-cms2 openssl gettext git git-lfs mysql libxml2 libxmlsec1 pkg-config postgresql freetds +brew install libtiff libjpeg webp little-cms2 openssl gettext git git-lfs mysql libxml2 libxmlsec1 pkg-config postgresql freetds openssl echo "2. 下载 IP 数据库" ip_db_path="${PROJECT_DIR}/apps/common/utils/geoip/GeoLite2-City.mmdb" From e1b3851be392eafaa2d19931bd7c6503c4ac43f7 Mon Sep 17 00:00:00 2001 From: halo Date: Sat, 16 Jul 2022 20:44:32 +0800 Subject: [PATCH 017/104] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E8=8A=82=E7=82=B9=E6=90=9C=E7=B4=A2=EF=BC=8C=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=85=A8=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/api/node.py b/apps/assets/api/node.py index 3d5d22178..2bb77b60c 100644 --- a/apps/assets/api/node.py +++ b/apps/assets/api/node.py @@ -43,7 +43,7 @@ __all__ = [ class NodeViewSet(SuggestionMixin, OrgBulkModelViewSet): model = Node filterset_fields = ('value', 'key', 'id') - search_fields = ('value',) + search_fields = ('full_value',) serializer_class = serializers.NodeSerializer rbac_perms = { 'match': 'assets.match_node', From de61e780e3db3240216d0740b4e24706a182c565 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 18 Jul 2022 10:33:21 +0800 Subject: [PATCH 018/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E6=8F=90=E7=A4=BA=E7=9A=84=E7=BF=BB=E8=AF=91=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.po | 2 +- apps/locale/zh/LC_MESSAGES/django.po | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 1ade4540a..54c5c70f0 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -4959,7 +4959,7 @@ msgstr "リンク期限切れ" #: terminal/models/sharing.py:68 msgid "User not allowed to join" -msgstr "IPは許可されていません" +msgstr "ユーザーはセッションに参加できません" #: terminal/models/sharing.py:85 terminal/serializers/sharing.py:59 msgid "Joiner" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 6f50d5c61..15cb33b57 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -4883,7 +4883,7 @@ msgstr "链接过期" #: terminal/models/sharing.py:68 msgid "User not allowed to join" -msgstr "来源 IP 不被允许登录" +msgstr "该用户无权加入会话" #: terminal/models/sharing.py:85 terminal/serializers/sharing.py:59 msgid "Joiner" From 2ca72a4bff6b9327f9d8092047a276c3e15a4949 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 18 Jul 2022 11:23:45 +0800 Subject: [PATCH 019/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=9C=AA?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E7=94=A8=E6=88=B7=EF=BC=8C=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E5=85=B1=E4=BA=AB=E4=BC=9A=E8=AF=9D=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/models/sharing.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/terminal/models/sharing.py b/apps/terminal/models/sharing.py index 6976b09cf..8675ced01 100644 --- a/apps/terminal/models/sharing.py +++ b/apps/terminal/models/sharing.py @@ -43,6 +43,8 @@ class SessionSharing(CommonModelMixin, OrgModelMixin): return 'Creator: {}'.format(self.creator) def users_display(self): + if not self.users: + return [] with tmp_to_root_org(): user_ids = self.users.split(',') users = User.objects.filter(id__in=user_ids) From 5055d140fd34a04b68aff41e581097d6af14f8c4 Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Mon, 18 Jul 2022 11:29:02 +0800 Subject: [PATCH 020/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dhost=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/connection_token.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index f0a7e0a63..60b91e4db 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -91,6 +91,11 @@ class ConnectionTokenMixin: "config": rdp_config } + def get_host(self, endpoint): + if not endpoint.host: + return self.request.get_host() + return endpoint.host + def get_rdp_file_info(self, token: ConnectionToken): rdp_options = { 'full address:s': '', @@ -140,7 +145,9 @@ class ConnectionTokenMixin: endpoint = self.get_smart_endpoint( protocol='rdp', asset=token.asset, application=token.application ) - rdp_options['full address:s'] = f'{endpoint.host}:{endpoint.rdp_port}' + # TODO 暂时获取一下host,后续优化 + host = self.get_host(endpoint) + rdp_options['full address:s'] = f'{host}:{endpoint.rdp_port}' # 设置用户名 rdp_options['username:s'] = '{}|{}'.format(token.user.username, str(token.id)) @@ -192,8 +199,10 @@ class ConnectionTokenMixin: endpoint = self.get_smart_endpoint( protocol='ssh', asset=token.asset, application=token.application ) + # TODO 暂时获取一下host,后续优化 + host = self.get_host(endpoint) data = { - 'ip': endpoint.host, + 'ip': host, 'port': str(endpoint.ssh_port), 'username': 'JMS-{}'.format(str(token.id)), 'password': token.secret From af5295d30eb15eec943d2fe2e6a18c66ea136145 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 18 Jul 2022 11:53:47 +0800 Subject: [PATCH 021/104] =?UTF-8?q?fix:=20django=20=E8=BF=98=E5=8E=9F=20(#?= =?UTF-8?q?8609)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 75e397656..afe9b7179 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -62,7 +62,7 @@ jsonfield2==4.0.0.post0 geoip2==4.5.0 ipip-ipdb==1.6.1 # Django environment -Django==3.2.14 +Django==3.2.13 django-bootstrap3==14.2.0 django-filter==2.4.0 django-formtools==2.2 From e09383ecf43e5ff68069ec3aca18f718253ce99c Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 18 Jul 2022 13:24:31 +0800 Subject: [PATCH 022/104] fix: django 3.1.14 (#8613) Co-authored-by: feng626 <1304903146@qq.com> --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index afe9b7179..1dac6922d 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -62,7 +62,7 @@ jsonfield2==4.0.0.post0 geoip2==4.5.0 ipip-ipdb==1.6.1 # Django environment -Django==3.2.13 +Django==3.1.14 django-bootstrap3==14.2.0 django-filter==2.4.0 django-formtools==2.2 From bb9d32dc189cc7c9b481568f68bd6607022ae93b Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 18 Jul 2022 13:44:20 +0800 Subject: [PATCH 023/104] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E6=89=80?= =?UTF-8?q?=E6=9C=89=E7=BB=84=E7=BB=87=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 74 ++++++++++--------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 74 ++++++++++--------- .../0013_alter_organization_options.py | 17 +++++ apps/orgs/models.py | 1 + apps/rbac/builtin.py | 5 +- apps/rbac/models/rolebinding.py | 11 ++- 8 files changed, 117 insertions(+), 73 deletions(-) create mode 100644 apps/orgs/migrations/0013_alter_organization_options.py diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 789260264..e6d644bf9 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4d5cc27fc996896f8cba5773c99de59ff854f7ef1ae8c470d5c74bb6b371e6ed -size 128472 +oid sha256:94dbd28454eaced93affd6baeb1f7c2cb1b2c28a7144ccdcef6963a2fad92616 +size 128666 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 54c5c70f0..e832dc06d 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-15 17:15+0800\n" +"POT-Creation-Date: 2022-07-18 14:01+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -88,8 +88,8 @@ msgstr "ログイン確認" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 -#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:214 -#: perms/models/base.py:84 rbac/builtin.py:117 rbac/models/rolebinding.py:41 +#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:215 +#: perms/models/base.py:84 rbac/builtin.py:120 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 #: terminal/models/sharing.py:33 terminal/notifications.py:91 @@ -363,7 +363,7 @@ msgstr "タイプ表示" #: assets/serializers/account.py:18 assets/serializers/cmd_filter.py:28 #: assets/serializers/cmd_filter.py:48 common/db/models.py:114 #: common/mixins/models.py:50 ops/models/adhoc.py:39 ops/models/command.py:30 -#: orgs/models.py:67 orgs/models.py:217 perms/models/base.py:92 +#: orgs/models.py:67 orgs/models.py:218 perms/models/base.py:92 #: users/models/group.py:18 users/models/user.py:922 #: xpack/plugins/cloud/models.py:125 msgid "Date created" @@ -373,7 +373,7 @@ msgstr "作成された日付" #: assets/models/gathered_user.py:20 assets/serializers/account.py:21 #: assets/serializers/cmd_filter.py:29 assets/serializers/cmd_filter.py:49 #: common/db/models.py:115 common/mixins/models.py:51 ops/models/adhoc.py:40 -#: orgs/models.py:218 +#: orgs/models.py:219 msgid "Date updated" msgstr "更新日" @@ -624,7 +624,7 @@ msgstr "ラベル" #: assets/models/cluster.py:28 assets/models/cmd_filter.py:52 #: assets/models/cmd_filter.py:99 assets/models/group.py:21 #: common/db/models.py:112 common/mixins/models.py:49 orgs/models.py:66 -#: orgs/models.py:219 perms/models/base.py:91 users/models/user.py:706 +#: orgs/models.py:220 perms/models/base.py:91 users/models/user.py:706 #: users/serializers/group.py:33 #: xpack/plugins/change_auth_plan/models/base.py:48 #: xpack/plugins/cloud/models.py:122 xpack/plugins/gathered_user/models.py:30 @@ -735,7 +735,7 @@ msgid "Trigger mode" msgstr "トリガーモード" #: assets/models/backup.py:119 audits/models.py:127 -#: terminal/models/sharing.py:106 +#: terminal/models/sharing.py:108 #: xpack/plugins/change_auth_plan/models/base.py:201 #: xpack/plugins/change_auth_plan/serializers/app.py:66 #: xpack/plugins/change_auth_plan/serializers/asset.py:180 @@ -1435,7 +1435,7 @@ msgid "Symlink" msgstr "Symlink" #: audits/models.py:38 audits/models.py:66 audits/models.py:89 -#: terminal/models/session.py:51 terminal/models/sharing.py:94 +#: terminal/models/session.py:51 terminal/models/sharing.py:96 msgid "Remote addr" msgstr "リモートaddr" @@ -1447,7 +1447,7 @@ msgstr "操作" msgid "Filename" msgstr "ファイル名" -#: audits/models.py:43 audits/models.py:117 terminal/models/sharing.py:102 +#: audits/models.py:43 audits/models.py:117 terminal/models/sharing.py:104 #: tickets/views/approve.py:115 #: xpack/plugins/change_auth_plan/serializers/app.py:87 #: xpack/plugins/change_auth_plan/serializers/asset.py:198 @@ -3025,7 +3025,7 @@ msgid "App organizations" msgstr "アプリ組織" #: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:80 -#: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 +#: orgs/models.py:212 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 msgid "Organization" @@ -3039,7 +3039,11 @@ msgstr "グローバル組織" msgid "Can view root org" msgstr "グローバル組織を表示できます" -#: orgs/models.py:216 rbac/models/role.py:46 rbac/models/rolebinding.py:44 +#: orgs/models.py:83 +msgid "Can view all joined org" +msgstr "参加しているすべての組織を表示できます" + +#: orgs/models.py:217 rbac/models/role.py:46 rbac/models/rolebinding.py:44 #: users/models/user.py:671 msgid "Role" msgstr "ロール" @@ -3260,27 +3264,27 @@ msgstr "{} 少なくとも1つのシステムロール" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:108 +#: rbac/builtin.py:111 msgid "SystemAdmin" msgstr "システム管理者" -#: rbac/builtin.py:111 +#: rbac/builtin.py:114 msgid "SystemAuditor" msgstr "システム監査人" -#: rbac/builtin.py:114 +#: rbac/builtin.py:117 msgid "SystemComponent" msgstr "システムコンポーネント" -#: rbac/builtin.py:120 +#: rbac/builtin.py:123 msgid "OrgAdmin" msgstr "組織管理者" -#: rbac/builtin.py:123 +#: rbac/builtin.py:126 msgid "OrgAuditor" msgstr "監査員を組織する" -#: rbac/builtin.py:126 +#: rbac/builtin.py:129 msgid "OrgUser" msgstr "組織ユーザー" @@ -3336,18 +3340,22 @@ msgstr "組織の役割" msgid "Role binding" msgstr "ロールバインディング" -#: rbac/models/rolebinding.py:159 +#: rbac/models/rolebinding.py:137 +msgid "All organizations" +msgstr "全ての組織" + +#: rbac/models/rolebinding.py:166 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" msgstr "" "ユーザーの最後のロールは削除できません。ユーザーを組織から削除できます。" -#: rbac/models/rolebinding.py:166 +#: rbac/models/rolebinding.py:173 msgid "Organization role binding" msgstr "組織の役割バインディング" -#: rbac/models/rolebinding.py:181 +#: rbac/models/rolebinding.py:188 msgid "System role binding" msgstr "システムロールバインディング" @@ -4775,7 +4783,7 @@ msgid "Output" msgstr "出力" #: terminal/backends/command/models.py:25 terminal/models/replay.py:9 -#: terminal/models/sharing.py:19 terminal/models/sharing.py:76 +#: terminal/models/sharing.py:19 terminal/models/sharing.py:78 #: terminal/templates/terminal/_msg_command_alert.html:10 #: tickets/models/ticket/command_confirm.py:20 msgid "Session" @@ -4897,7 +4905,7 @@ msgstr "セッションのリプレイをアップロードできます" msgid "Can download session replay" msgstr "セッション再生をダウンロードできます" -#: terminal/models/session.py:50 terminal/models/sharing.py:99 +#: terminal/models/session.py:50 terminal/models/sharing.py:101 msgid "Login from" msgstr "ログイン元" @@ -4933,7 +4941,7 @@ msgstr "セッションアクションのパーマを検証できます" msgid "Creator" msgstr "作成者" -#: terminal/models/sharing.py:26 terminal/models/sharing.py:78 +#: terminal/models/sharing.py:26 terminal/models/sharing.py:80 msgid "Verify code" msgstr "コードの確認" @@ -4941,7 +4949,7 @@ msgstr "コードの確認" msgid "Expired time (min)" msgstr "期限切れ時間 (分)" -#: terminal/models/sharing.py:37 terminal/models/sharing.py:81 +#: terminal/models/sharing.py:37 terminal/models/sharing.py:83 msgid "Session sharing" msgstr "セッション共有" @@ -4949,40 +4957,40 @@ msgstr "セッション共有" msgid "Can add super session sharing" msgstr "スーパーセッション共有を追加できます" -#: terminal/models/sharing.py:64 +#: terminal/models/sharing.py:66 msgid "Link not active" msgstr "リンクがアクティブでない" -#: terminal/models/sharing.py:66 +#: terminal/models/sharing.py:68 msgid "Link expired" msgstr "リンク期限切れ" -#: terminal/models/sharing.py:68 +#: terminal/models/sharing.py:70 msgid "User not allowed to join" msgstr "ユーザーはセッションに参加できません" -#: terminal/models/sharing.py:85 terminal/serializers/sharing.py:59 +#: terminal/models/sharing.py:87 terminal/serializers/sharing.py:59 msgid "Joiner" msgstr "ジョイナー" -#: terminal/models/sharing.py:88 +#: terminal/models/sharing.py:90 msgid "Date joined" msgstr "参加日" -#: terminal/models/sharing.py:91 +#: terminal/models/sharing.py:93 msgid "Date left" msgstr "日付が残っています" -#: terminal/models/sharing.py:109 tickets/const.py:26 +#: terminal/models/sharing.py:111 tickets/const.py:26 #: xpack/plugins/change_auth_plan/models/base.py:192 msgid "Finished" msgstr "終了" -#: terminal/models/sharing.py:114 +#: terminal/models/sharing.py:116 msgid "Session join record" msgstr "セッション参加記録" -#: terminal/models/sharing.py:130 +#: terminal/models/sharing.py:132 msgid "Invalid verification code" msgstr "検証コードが無効" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index acdae1731..3f244b4f6 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ee69ce22224f6cae615752c034e495c29d93ed9dbe86767f044d5c0f663b8cc -size 105904 +oid sha256:3803a3c5301b92b11e1478dc674d8a95525203ff9636e8ab99914b660005aa37 +size 106048 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 15cb33b57..42deeb5ba 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-15 17:15+0800\n" +"POT-Creation-Date: 2022-07-18 14:01+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -87,8 +87,8 @@ msgstr "登录复核" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 -#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:214 -#: perms/models/base.py:84 rbac/builtin.py:117 rbac/models/rolebinding.py:41 +#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:215 +#: perms/models/base.py:84 rbac/builtin.py:120 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 #: terminal/models/sharing.py:33 terminal/notifications.py:91 @@ -358,7 +358,7 @@ msgstr "类型名称" #: assets/serializers/account.py:18 assets/serializers/cmd_filter.py:28 #: assets/serializers/cmd_filter.py:48 common/db/models.py:114 #: common/mixins/models.py:50 ops/models/adhoc.py:39 ops/models/command.py:30 -#: orgs/models.py:67 orgs/models.py:217 perms/models/base.py:92 +#: orgs/models.py:67 orgs/models.py:218 perms/models/base.py:92 #: users/models/group.py:18 users/models/user.py:922 #: xpack/plugins/cloud/models.py:125 msgid "Date created" @@ -368,7 +368,7 @@ msgstr "创建日期" #: assets/models/gathered_user.py:20 assets/serializers/account.py:21 #: assets/serializers/cmd_filter.py:29 assets/serializers/cmd_filter.py:49 #: common/db/models.py:115 common/mixins/models.py:51 ops/models/adhoc.py:40 -#: orgs/models.py:218 +#: orgs/models.py:219 msgid "Date updated" msgstr "更新日期" @@ -619,7 +619,7 @@ msgstr "标签管理" #: assets/models/cluster.py:28 assets/models/cmd_filter.py:52 #: assets/models/cmd_filter.py:99 assets/models/group.py:21 #: common/db/models.py:112 common/mixins/models.py:49 orgs/models.py:66 -#: orgs/models.py:219 perms/models/base.py:91 users/models/user.py:706 +#: orgs/models.py:220 perms/models/base.py:91 users/models/user.py:706 #: users/serializers/group.py:33 #: xpack/plugins/change_auth_plan/models/base.py:48 #: xpack/plugins/cloud/models.py:122 xpack/plugins/gathered_user/models.py:30 @@ -730,7 +730,7 @@ msgid "Trigger mode" msgstr "触发模式" #: assets/models/backup.py:119 audits/models.py:127 -#: terminal/models/sharing.py:106 +#: terminal/models/sharing.py:108 #: xpack/plugins/change_auth_plan/models/base.py:201 #: xpack/plugins/change_auth_plan/serializers/app.py:66 #: xpack/plugins/change_auth_plan/serializers/asset.py:180 @@ -1423,7 +1423,7 @@ msgid "Symlink" msgstr "建立软链接" #: audits/models.py:38 audits/models.py:66 audits/models.py:89 -#: terminal/models/session.py:51 terminal/models/sharing.py:94 +#: terminal/models/session.py:51 terminal/models/sharing.py:96 msgid "Remote addr" msgstr "远端地址" @@ -1435,7 +1435,7 @@ msgstr "操作" msgid "Filename" msgstr "文件名" -#: audits/models.py:43 audits/models.py:117 terminal/models/sharing.py:102 +#: audits/models.py:43 audits/models.py:117 terminal/models/sharing.py:104 #: tickets/views/approve.py:115 #: xpack/plugins/change_auth_plan/serializers/app.py:87 #: xpack/plugins/change_auth_plan/serializers/asset.py:198 @@ -2985,7 +2985,7 @@ msgid "App organizations" msgstr "组织管理" #: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:80 -#: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 +#: orgs/models.py:212 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 msgid "Organization" @@ -2999,7 +2999,11 @@ msgstr "全局组织" msgid "Can view root org" msgstr "可以查看全局组织" -#: orgs/models.py:216 rbac/models/role.py:46 rbac/models/rolebinding.py:44 +#: orgs/models.py:83 +msgid "Can view all joined org" +msgstr "可以查看所有加入的组织" + +#: orgs/models.py:217 rbac/models/role.py:46 rbac/models/rolebinding.py:44 #: users/models/user.py:671 msgid "Role" msgstr "角色" @@ -3218,27 +3222,27 @@ msgstr "{} 至少有一个系统角色" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:108 +#: rbac/builtin.py:111 msgid "SystemAdmin" msgstr "系统管理员" -#: rbac/builtin.py:111 +#: rbac/builtin.py:114 msgid "SystemAuditor" msgstr "系统审计员" -#: rbac/builtin.py:114 +#: rbac/builtin.py:117 msgid "SystemComponent" msgstr "系统组件" -#: rbac/builtin.py:120 +#: rbac/builtin.py:123 msgid "OrgAdmin" msgstr "组织管理员" -#: rbac/builtin.py:123 +#: rbac/builtin.py:126 msgid "OrgAuditor" msgstr "组织审计员" -#: rbac/builtin.py:126 +#: rbac/builtin.py:129 msgid "OrgUser" msgstr "组织用户" @@ -3294,17 +3298,21 @@ msgstr "组织角色" msgid "Role binding" msgstr "角色绑定" -#: rbac/models/rolebinding.py:159 +#: rbac/models/rolebinding.py:137 +msgid "All organizations" +msgstr "所有组织" + +#: rbac/models/rolebinding.py:166 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" msgstr "用户最后一个角色,不能删除,你可以将用户从组织移除" -#: rbac/models/rolebinding.py:166 +#: rbac/models/rolebinding.py:173 msgid "Organization role binding" msgstr "组织角色绑定" -#: rbac/models/rolebinding.py:181 +#: rbac/models/rolebinding.py:188 msgid "System role binding" msgstr "系统角色绑定" @@ -4699,7 +4707,7 @@ msgid "Output" msgstr "输出" #: terminal/backends/command/models.py:25 terminal/models/replay.py:9 -#: terminal/models/sharing.py:19 terminal/models/sharing.py:76 +#: terminal/models/sharing.py:19 terminal/models/sharing.py:78 #: terminal/templates/terminal/_msg_command_alert.html:10 #: tickets/models/ticket/command_confirm.py:20 msgid "Session" @@ -4821,7 +4829,7 @@ msgstr "可以上传会话录像" msgid "Can download session replay" msgstr "可以下载会话录像" -#: terminal/models/session.py:50 terminal/models/sharing.py:99 +#: terminal/models/session.py:50 terminal/models/sharing.py:101 msgid "Login from" msgstr "登录来源" @@ -4857,7 +4865,7 @@ msgstr "可以验证会话动作权限" msgid "Creator" msgstr "创建者" -#: terminal/models/sharing.py:26 terminal/models/sharing.py:78 +#: terminal/models/sharing.py:26 terminal/models/sharing.py:80 msgid "Verify code" msgstr "验证码" @@ -4865,7 +4873,7 @@ msgstr "验证码" msgid "Expired time (min)" msgstr "过期时间 (分)" -#: terminal/models/sharing.py:37 terminal/models/sharing.py:81 +#: terminal/models/sharing.py:37 terminal/models/sharing.py:83 msgid "Session sharing" msgstr "会话分享" @@ -4873,40 +4881,40 @@ msgstr "会话分享" msgid "Can add super session sharing" msgstr "可以创建超级会话分享" -#: terminal/models/sharing.py:64 +#: terminal/models/sharing.py:66 msgid "Link not active" msgstr "链接失效" -#: terminal/models/sharing.py:66 +#: terminal/models/sharing.py:68 msgid "Link expired" msgstr "链接过期" -#: terminal/models/sharing.py:68 +#: terminal/models/sharing.py:70 msgid "User not allowed to join" msgstr "该用户无权加入会话" -#: terminal/models/sharing.py:85 terminal/serializers/sharing.py:59 +#: terminal/models/sharing.py:87 terminal/serializers/sharing.py:59 msgid "Joiner" msgstr "加入者" -#: terminal/models/sharing.py:88 +#: terminal/models/sharing.py:90 msgid "Date joined" msgstr "加入日期" -#: terminal/models/sharing.py:91 +#: terminal/models/sharing.py:93 msgid "Date left" msgstr "结束日期" -#: terminal/models/sharing.py:109 tickets/const.py:26 +#: terminal/models/sharing.py:111 tickets/const.py:26 #: xpack/plugins/change_auth_plan/models/base.py:192 msgid "Finished" msgstr "结束" -#: terminal/models/sharing.py:114 +#: terminal/models/sharing.py:116 msgid "Session join record" msgstr "会话加入记录" -#: terminal/models/sharing.py:130 +#: terminal/models/sharing.py:132 msgid "Invalid verification code" msgstr "验证码不正确" diff --git a/apps/orgs/migrations/0013_alter_organization_options.py b/apps/orgs/migrations/0013_alter_organization_options.py new file mode 100644 index 000000000..e868a87a3 --- /dev/null +++ b/apps/orgs/migrations/0013_alter_organization_options.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.12 on 2022-07-18 05:57 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('orgs', '0012_auto_20220118_1054'), + ] + + operations = [ + migrations.AlterModelOptions( + name='organization', + options={'permissions': (('view_rootorg', 'Can view root org'), ('view_alljoinedorg', 'Can view all joined org')), 'verbose_name': 'Organization'}, + ), + ] diff --git a/apps/orgs/models.py b/apps/orgs/models.py index def83f509..c4208d7d0 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -80,6 +80,7 @@ class Organization(OrgRoleMixin, models.Model): verbose_name = _("Organization") permissions = ( ('view_rootorg', _('Can view root org')), + ('view_alljoinedorg', _('Can view all joined org')), ) def __str__(self): diff --git a/apps/rbac/builtin.py b/apps/rbac/builtin.py index f5b030d2b..93b058504 100644 --- a/apps/rbac/builtin.py +++ b/apps/rbac/builtin.py @@ -5,6 +5,9 @@ from .const import Scope, system_exclude_permissions, org_exclude_permissions _view_root_perms = ( ('orgs', 'organization', 'view', 'rootorg'), ) +_view_all_joined_org_perms = ( + ('orgs', 'organization', 'view', 'alljoinedorg'), +) user_perms = ( ('rbac', 'menupermission', 'view', 'workbench'), @@ -24,7 +27,7 @@ system_user_perms = ( ('authentication', 'temptoken', 'add,change,view', 'temptoken'), ('authentication', 'accesskey', '*', '*'), ('tickets', 'ticket', 'view', 'ticket'), -) + user_perms + _view_root_perms +) + user_perms + _view_all_joined_org_perms _auditor_perms = ( ('rbac', 'menupermission', 'view', 'audit'), diff --git a/apps/rbac/models/rolebinding.py b/apps/rbac/models/rolebinding.py index 3caa83622..9b2256332 100644 --- a/apps/rbac/models/rolebinding.py +++ b/apps/rbac/models/rolebinding.py @@ -126,9 +126,16 @@ class RoleBinding(JMSModel): org_ids = [b.org.id for b in bindings if b.org] orgs = all_orgs.filter(id__in=org_ids) + workbench_perm = 'rbac.view_workbench' # 全局组织 - if orgs and user.has_perm('orgs.view_rootorg'): - orgs = [Organization.root(), *list(orgs)] + if orgs and perm != workbench_perm and user.has_perm('orgs.view_rootorg'): + root_org = Organization.root() + orgs = [root_org, *list(orgs)] + elif orgs and perm == workbench_perm and user.has_perm('orgs.view_alljoinedorg'): + # Todo: 先复用组织 + root_org = Organization.root() + root_org.name = _("All organizations") + orgs = [root_org, *list(orgs)] return orgs From 62d403bf216ec1611eba41307d050155f2f957b5 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 18 Jul 2022 19:24:17 +0800 Subject: [PATCH 024/104] fix: reverse console (#8615) Co-authored-by: feng626 <1304903146@qq.com> --- apps/common/utils/django.py | 20 +++++++++++++++----- apps/terminal/notifications.py | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/apps/common/utils/django.py b/apps/common/utils/django.py index 3e8066cef..1f3f83282 100644 --- a/apps/common/utils/django.py +++ b/apps/common/utils/django.py @@ -8,12 +8,14 @@ from django.utils import timezone from django.db import models from django.db.models.signals import post_save, pre_save - UUID_PATTERN = re.compile(r'[0-9a-zA-Z\-]{36}') -def reverse(view_name, urlconf=None, args=None, kwargs=None, - current_app=None, external=False, api_to_ui=False): +def reverse( + view_name, urlconf=None, args=None, kwargs=None, + current_app=None, external=False, api_to_ui=False, + is_console=False, is_audit=False, is_workbench=False +): url = dj_reverse(view_name, urlconf=urlconf, args=args, kwargs=kwargs, current_app=current_app) @@ -21,7 +23,15 @@ def reverse(view_name, urlconf=None, args=None, kwargs=None, site_url = settings.SITE_URL url = site_url.strip('/') + url if api_to_ui: - url = url.replace('api/v1', 'ui/#').rstrip('/') + replace_str = 'ui/#' + if is_console: + replace_str += '/console' + elif is_audit: + replace_str += '/audit' + elif is_workbench: + replace_str += '/workbench' + + url = url.replace('api/v1', replace_str).rstrip('/') return url @@ -38,7 +48,7 @@ def date_expired_default(): years = int(settings.DEFAULT_EXPIRED_YEARS) except TypeError: years = 70 - return timezone.now() + timezone.timedelta(days=365*years) + return timezone.now() + timezone.timedelta(days=365 * years) def union_queryset(*args, base_queryset=None): diff --git a/apps/terminal/notifications.py b/apps/terminal/notifications.py index 62bc50592..91509a901 100644 --- a/apps/terminal/notifications.py +++ b/apps/terminal/notifications.py @@ -130,7 +130,7 @@ class CommandExecutionAlert(CommandAlertMixin, SystemMessage): for asset in command['assets']: url = reverse( 'assets:asset-detail', kwargs={'pk': asset.id}, - api_to_ui=True, external=True + api_to_ui=True, external=True, is_console=True ) + '?oid={}'.format(asset.org_id) assets_with_url.append([asset, url]) From 0eab83f73b758024e3241251dac9081e5c4c6181 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 19 Jul 2022 10:49:15 +0800 Subject: [PATCH 025/104] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=20(#8616)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- .../serializers/attrs/application_category/remote_app.py | 2 +- apps/locale/ja/LC_MESSAGES/django.mo | 4 ++-- apps/locale/ja/LC_MESSAGES/django.po | 6 +++++- apps/locale/zh/LC_MESSAGES/django.mo | 4 ++-- apps/locale/zh/LC_MESSAGES/django.po | 6 +++++- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/apps/applications/serializers/attrs/application_category/remote_app.py b/apps/applications/serializers/attrs/application_category/remote_app.py index ad2610791..063af6daa 100644 --- a/apps/applications/serializers/attrs/application_category/remote_app.py +++ b/apps/applications/serializers/attrs/application_category/remote_app.py @@ -31,7 +31,7 @@ class ExistAssetPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField): class RemoteAppSerializer(serializers.Serializer): - asset_info = serializers.SerializerMethodField() + asset_info = serializers.SerializerMethodField(label=_('Asset Info')) asset = ExistAssetPrimaryKeyRelatedField( queryset=Asset.objects, required=True, label=_("Asset"), allow_null=True ) diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index e6d644bf9..7dbdfa16d 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:94dbd28454eaced93affd6baeb1f7c2cb1b2c28a7144ccdcef6963a2fad92616 -size 128666 +oid sha256:0f2fdd3a7bd34a26d068fc6ce521d0ea9983c477b13536ba3f51700a554d4ae3 +size 128706 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index e832dc06d..99652c84b 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-18 14:01+0800\n" +"POT-Creation-Date: 2022-07-19 10:45+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -412,6 +412,10 @@ msgstr "ホスト" msgid "Port" msgstr "ポート" +#: applications/serializers/attrs/application_category/remote_app.py:34 +msgid "Asset Info" +msgstr "資産情報" + #: applications/serializers/attrs/application_category/remote_app.py:39 #: applications/serializers/attrs/application_type/chrome.py:14 #: applications/serializers/attrs/application_type/mysql_workbench.py:14 diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 3f244b4f6..33d7105d9 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3803a3c5301b92b11e1478dc674d8a95525203ff9636e8ab99914b660005aa37 -size 106048 +oid sha256:9c2b13f7242beec8786179e03de895bd3e9d8d6392b74c2398409c1bfa33d9f8 +size 106088 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 42deeb5ba..9a62aa8da 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-18 14:01+0800\n" +"POT-Creation-Date: 2022-07-19 10:45+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -407,6 +407,10 @@ msgstr "主机" msgid "Port" msgstr "端口" +#: applications/serializers/attrs/application_category/remote_app.py:34 +msgid "Asset Info" +msgstr "资产信息" + #: applications/serializers/attrs/application_category/remote_app.py:39 #: applications/serializers/attrs/application_type/chrome.py:14 #: applications/serializers/attrs/application_type/mysql_workbench.py:14 From 585ddeb25ba790aa71c58984533f7bd57c2a879e Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 19 Jul 2022 11:15:56 +0800 Subject: [PATCH 026/104] =?UTF-8?q?fix:=20=E6=8E=88=E6=9D=83=E8=BF=87?= =?UTF-8?q?=E6=9C=9F=E5=A4=A9=E6=95=B0=E4=BF=AE=E6=94=B9=20(#8618)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/perms/tasks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/perms/tasks.py b/apps/perms/tasks.py index da96beb68..786b7b285 100644 --- a/apps/perms/tasks.py +++ b/apps/perms/tasks.py @@ -73,7 +73,7 @@ def check_asset_permission_will_expired(): for asset_perm in asset_perms: date_expired = dt_parser(asset_perm.date_expired) - remain_days = (end - date_expired).days + remain_days = (date_expired - start).days org = asset_perm.org # 资产授权按照组织分类 @@ -121,7 +121,7 @@ def check_app_permission_will_expired(): for app_perm in app_perms: date_expired = dt_parser(app_perm.date_expired) - remain_days = (end - date_expired).days + remain_days = (date_expired - start).days org = app_perm.org if org in org_perm_remain_day_mapper[remain_days]: From cc2b858769dc407dd121a97b92d07d6cec62fbfa Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 19 Jul 2022 15:57:02 +0800 Subject: [PATCH 027/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E4=BB=A4=E7=89=8C=E4=BF=A1=E6=81=AF=E7=9A=84remote=20?= =?UTF-8?q?app=E8=B5=84=E4=BA=A7=E4=BF=A1=E6=81=AF=20(#8619)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 修复连接令牌只获取自己的令牌信息;修复连接令牌系统用户角色权限问题(普通用户看不到); * fix: 修复获取令牌信息的remote app资产信息 * fix: 修复获取用户个人信息时使用连接令牌 * fix: 修复获取profile时的连接令牌问题 * fix: 修复连接令牌问题 * fix: 修复连接令牌问题 Co-authored-by: Jiangjie.Bai --- apps/authentication/api/connection_token.py | 4 +++- apps/authentication/models.py | 7 +++++++ .../serializers/connection_token.py | 2 +- apps/rbac/builtin.py | 2 +- apps/rbac/models/permission.py | 4 ++-- apps/users/api/profile.py | 20 ++++++++++++++++++- 6 files changed, 33 insertions(+), 6 deletions(-) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 60b91e4db..c0f85757d 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -231,7 +231,9 @@ class ConnectionTokenViewSet(ConnectionTokenMixin, RootOrgViewMixin, JMSModelVie 'get_rdp_file': 'authentication.add_connectiontoken', 'get_client_protocol_url': 'authentication.add_connectiontoken', } - queryset = ConnectionToken.objects.all() + + def get_queryset(self): + return ConnectionToken.objects.filter(user=self.request.user) def create_connection_token(self): data = self.request.query_params if self.request.method == 'GET' else self.request.data diff --git a/apps/authentication/models.py b/apps/authentication/models.py index d04a3fa4e..518db566c 100644 --- a/apps/authentication/models.py +++ b/apps/authentication/models.py @@ -228,6 +228,13 @@ class ConnectionToken(OrgModelMixin, models.JMSModel): return {} return self.application.get_rdp_remote_app_setting() + @lazyproperty + def asset_or_remote_app_asset(self): + if self.asset: + return self.asset + if self.application and self.application.category_remote_app: + return self.application.get_remote_app_asset() + @lazyproperty def cmd_filter_rules(self): from assets.models import CommandFilterRule diff --git a/apps/authentication/serializers/connection_token.py b/apps/authentication/serializers/connection_token.py index 0e811cbaa..5c3bef5a2 100644 --- a/apps/authentication/serializers/connection_token.py +++ b/apps/authentication/serializers/connection_token.py @@ -177,7 +177,7 @@ class ConnectionTokenCmdFilterRuleSerializer(serializers.ModelSerializer): class ConnectionTokenSecretSerializer(OrgResourceModelSerializerMixin): user = ConnectionTokenUserSerializer(read_only=True) - asset = ConnectionTokenAssetSerializer(read_only=True) + asset = ConnectionTokenAssetSerializer(read_only=True, source='asset_or_remote_app_asset') application = ConnectionTokenApplicationSerializer(read_only=True) remote_app = ConnectionTokenRemoteAppSerializer(read_only=True) system_user = ConnectionTokenSystemUserSerializer(read_only=True) diff --git a/apps/rbac/builtin.py b/apps/rbac/builtin.py index 93b058504..c56326601 100644 --- a/apps/rbac/builtin.py +++ b/apps/rbac/builtin.py @@ -23,7 +23,7 @@ user_perms = ( ) system_user_perms = ( - ('authentication', 'connectiontoken', 'add', 'connectiontoken'), + ('authentication', 'connectiontoken', 'add,view', 'connectiontoken'), ('authentication', 'temptoken', 'add,change,view', 'temptoken'), ('authentication', 'accesskey', '*', '*'), ('tickets', 'ticket', 'view', 'ticket'), diff --git a/apps/rbac/models/permission.py b/apps/rbac/models/permission.py index bc8fa6231..5b98b6045 100644 --- a/apps/rbac/models/permission.py +++ b/apps/rbac/models/permission.py @@ -60,11 +60,11 @@ class Permission(DjangoPermission): if actions == '*' and resource == '*': pass elif actions == '*' and resource != '*': - kwargs['codename__iregex'] = r'[a-z]+_{}'.format(resource) + kwargs['codename__iregex'] = r'[a-z]+_{}$'.format(resource) elif actions != '*' and resource == '*': kwargs['codename__iregex'] = r'({})_[a-z]+'.format(actions_regex) else: - kwargs['codename__iregex'] = r'({})_{}'.format(actions_regex, resource) + kwargs['codename__iregex'] = r'({})_{}$'.format(actions_regex, resource) q |= Q(**kwargs) return q diff --git a/apps/users/api/profile.py b/apps/users/api/profile.py index 3f5605144..b916c47a9 100644 --- a/apps/users/api/profile.py +++ b/apps/users/api/profile.py @@ -3,6 +3,10 @@ import uuid from rest_framework import generics from rest_framework.permissions import IsAuthenticated +from common.permissions import IsValidUserOrConnectionToken +from common.utils import get_object_or_none +from orgs.utils import tmp_to_root_org +from authentication.models import ConnectionToken from users.notifications import ( ResetPasswordMsg, ResetPasswordSuccessMsg, ResetSSHKeyMsg, @@ -44,12 +48,26 @@ class UserResetPKApi(UserQuerysetMixin, generics.UpdateAPIView): class UserProfileApi(generics.RetrieveUpdateAPIView): - permission_classes = (IsAuthenticated,) + permission_classes = (IsValidUserOrConnectionToken,) serializer_class = serializers.UserProfileSerializer def get_object(self): + if self.request.user.is_anonymous: + user = self.get_connection_token_user() + if user: + return user return self.request.user + def get_connection_token_user(self): + token_id = self.request.query_params.get('token') + if not token_id: + return + with tmp_to_root_org(): + token = get_object_or_none(ConnectionToken, id=token_id) + if not token: + return + return token.user + class UserPasswordApi(generics.RetrieveUpdateAPIView): permission_classes = (IsAuthenticated,) From 358460e7f0af98548953451fee7ba67ab979e09a Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Tue, 19 Jul 2022 16:22:49 +0800 Subject: [PATCH 028/104] =?UTF-8?q?fix:=20=E5=A6=82=E9=85=8D=E7=BD=AESECUR?= =?UTF-8?q?ITY=5FVIEW=5FAUTH=5FNEED=5FMFA=20=E8=B7=B3=E8=BF=87=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/permissions.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/common/permissions.py b/apps/common/permissions.py index c2d2cf4fa..869107a58 100644 --- a/apps/common/permissions.py +++ b/apps/common/permissions.py @@ -57,6 +57,9 @@ class UserConfirmation(permissions.BasePermission): 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') From fed0732c1ed842e05e8280dd94c024040121a6ea Mon Sep 17 00:00:00 2001 From: huangzhiwen Date: Tue, 19 Jul 2022 17:28:10 +0800 Subject: [PATCH 029/104] =?UTF-8?q?fix:=20=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E4=B8=8E=E7=94=A8=E6=88=B7=E8=B5=84=E4=BA=A7=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=8E=92=E5=BA=8F=E4=B8=8D=E7=BB=9F=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/asset/user_permission/user_permission_assets/mixin.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/perms/api/asset/user_permission/user_permission_assets/mixin.py b/apps/perms/api/asset/user_permission/user_permission_assets/mixin.py index 1b6b8e00f..ef0c8964a 100644 --- a/apps/perms/api/asset/user_permission/user_permission_assets/mixin.py +++ b/apps/perms/api/asset/user_permission/user_permission_assets/mixin.py @@ -33,7 +33,9 @@ class UserAllGrantedAssetsQuerysetMixin: only_fields = serializers.AssetGrantedSerializer.Meta.only_fields pagination_class = AllGrantedAssetPagination user: User - + ordering_fields = ("hostname", "ip", "port", "cpu_cores") + ordering = ('hostname', ) + def get_queryset(self): if getattr(self, 'swagger_fake_view', False): return Asset.objects.none() From 7b6eeb2e3df2088f7b87435905bff58bf3284aef Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Tue, 19 Jul 2022 17:34:55 +0800 Subject: [PATCH 030/104] =?UTF-8?q?fix:=20=E6=B8=85=E9=99=A4=20ftp=20?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/audits/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/audits/tasks.py b/apps/audits/tasks.py index 10fb67f44..5b58c5fd2 100644 --- a/apps/audits/tasks.py +++ b/apps/audits/tasks.py @@ -29,7 +29,7 @@ def clean_ftp_log_period(): now = timezone.now() days = get_log_keep_day('FTP_LOG_KEEP_DAYS') expired_day = now - datetime.timedelta(days=days) - FTPLog.objects.filter(datetime__lt=expired_day).delete() + FTPLog.objects.filter(date_start__lt=expired_day).delete() @register_as_period_task(interval=3600*24) From 29656b16302734a14e9678a9cf0e334db2d5cd99 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Tue, 19 Jul 2022 18:59:25 +0800 Subject: [PATCH 031/104] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=20rdp-file=20/=20client-url=20/=20smart-endpoint=20?= =?UTF-8?q?=E6=97=B6endpoint=20host=E5=90=8E=E5=8F=B0=E5=A4=84=E7=90=86?= =?UTF-8?q?=E4=B8=BA=E5=BD=93=E5=89=8D=E8=AF=B7=E6=B1=82=E7=9A=84host?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/connection_token.py | 13 ++----------- apps/terminal/models/endpoint.py | 5 +++-- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index c0f85757d..873129b20 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -91,11 +91,6 @@ class ConnectionTokenMixin: "config": rdp_config } - def get_host(self, endpoint): - if not endpoint.host: - return self.request.get_host() - return endpoint.host - def get_rdp_file_info(self, token: ConnectionToken): rdp_options = { 'full address:s': '', @@ -145,9 +140,7 @@ class ConnectionTokenMixin: endpoint = self.get_smart_endpoint( protocol='rdp', asset=token.asset, application=token.application ) - # TODO 暂时获取一下host,后续优化 - host = self.get_host(endpoint) - rdp_options['full address:s'] = f'{host}:{endpoint.rdp_port}' + rdp_options['full address:s'] = f'{endpoint.host}:{endpoint.rdp_port}' # 设置用户名 rdp_options['username:s'] = '{}|{}'.format(token.user.username, str(token.id)) @@ -199,10 +192,8 @@ class ConnectionTokenMixin: endpoint = self.get_smart_endpoint( protocol='ssh', asset=token.asset, application=token.application ) - # TODO 暂时获取一下host,后续优化 - host = self.get_host(endpoint) data = { - 'ip': host, + 'ip': endpoint.host, 'port': str(endpoint.ssh_port), 'username': 'JMS-{}'.format(str(token.id)), 'password': token.secret diff --git a/apps/terminal/models/endpoint.py b/apps/terminal/models/endpoint.py index 083b9c0a1..beefdeb69 100644 --- a/apps/terminal/models/endpoint.py +++ b/apps/terminal/models/endpoint.py @@ -63,8 +63,6 @@ class Endpoint(JMSModel): 'http_port': 0, } endpoint, created = cls.objects.get_or_create(id=cls.default_id, defaults=data) - if not endpoint.host and request: - endpoint.host = request.get_host().split(':')[0] return endpoint @classmethod @@ -122,4 +120,7 @@ class EndpointRule(JMSModel): endpoint = endpoint_rule.endpoint else: endpoint = Endpoint.get_or_create_default(request) + if not endpoint.host and request: + # 动态添加 current request host + endpoint.host = request.get_host().split(':')[0] return endpoint From ca5f6f3c6f9253787fc4894ab0a51cbb5ed1ff03 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 20 Jul 2022 13:01:43 +0800 Subject: [PATCH 032/104] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20windows=20?= =?UTF-8?q?ansible=20shell?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/inventory.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/ops/inventory.py b/apps/ops/inventory.py index b19ce8130..9ad69b9ac 100644 --- a/apps/ops/inventory.py +++ b/apps/ops/inventory.py @@ -15,8 +15,6 @@ logger = get_logger(__file__) class JMSBaseInventory(BaseInventory): - windows_ssh_default_shell = settings.WINDOWS_SSH_DEFAULT_SHELL - def convert_to_ansible(self, asset, run_as_admin=False): info = { 'id': asset.id, @@ -33,7 +31,7 @@ class JMSBaseInventory(BaseInventory): if asset.is_windows(): info["vars"].update({ "ansible_connection": "ssh", - "ansible_shell_type": self.windows_ssh_default_shell, + "ansible_shell_type": settings.WINDOWS_SSH_DEFAULT_SHELL, }) for label in asset.labels.all(): info["vars"].update({ From 772e5405275a523cb048b0a894fefff4c7075488 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 20 Jul 2022 13:13:40 +0800 Subject: [PATCH 033/104] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20connect=20?= =?UTF-8?q?token=20=E6=8D=A2=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/serializers/connection_token.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/authentication/serializers/connection_token.py b/apps/authentication/serializers/connection_token.py index 5c3bef5a2..8689b2ba4 100644 --- a/apps/authentication/serializers/connection_token.py +++ b/apps/authentication/serializers/connection_token.py @@ -27,9 +27,8 @@ class ConnectionTokenSerializer(OrgResourceModelSerializerMixin): model = ConnectionToken fields_mini = ['id', 'type'] fields_small = fields_mini + [ - 'secret', 'date_expired', - 'date_created', 'date_updated', 'created_by', 'updated_by', - 'org_id', 'org_name', + 'secret', 'date_expired', 'date_created', 'date_updated', + 'created_by', 'updated_by', 'org_id', 'org_name', ] fields_fk = [ 'user', 'system_user', 'asset', 'application', @@ -37,8 +36,8 @@ class ConnectionTokenSerializer(OrgResourceModelSerializerMixin): read_only_fields = [ # 普通 Token 不支持指定 user 'user', 'is_valid', 'expire_time', - 'type_display', 'user_display', 'system_user_display', 'asset_display', - 'application_display', + 'type_display', 'user_display', 'system_user_display', + 'asset_display', 'application_display', ] fields = fields_small + fields_fk + read_only_fields @@ -102,8 +101,8 @@ class SuperConnectionTokenSerializer(ConnectionTokenSerializer): class Meta(ConnectionTokenSerializer.Meta): read_only_fields = [ - 'validity', - 'user_display', 'system_user_display', 'asset_display', 'application_display', + 'validity', 'user_display', 'system_user_display', + 'asset_display', 'application_display', ] def get_user(self, attrs): From 2b2aa8f0726dcd7aec3a051ea096f9482c838052 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 20 Jul 2022 13:18:56 +0800 Subject: [PATCH 034/104] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20=E6=8D=A2?= =?UTF-8?q?=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/connection_token.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 873129b20..97abb58be 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -16,8 +16,8 @@ from orgs.mixins.api import RootOrgViewMixin from perms.models.base import Action from terminal.models import EndpointRule from ..serializers import ( - ConnectionTokenSerializer, ConnectionTokenSecretSerializer, SuperConnectionTokenSerializer, - ConnectionTokenDisplaySerializer, + ConnectionTokenSerializer, ConnectionTokenSecretSerializer, + SuperConnectionTokenSerializer, ConnectionTokenDisplaySerializer, ) from ..models import ConnectionToken @@ -204,8 +204,8 @@ class ConnectionTokenMixin: class ConnectionTokenViewSet(ConnectionTokenMixin, RootOrgViewMixin, JMSModelViewSet): filterset_fields = ( - 'type', - 'user_display', 'system_user_display', 'application_display', 'asset_display' + 'type', 'user_display', 'system_user_display', + 'application_display', 'asset_display' ) search_fields = filterset_fields serializer_classes = { From cb8690dd63e226a39ecb80283e7a899154b1d264 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 20 Jul 2022 13:23:43 +0800 Subject: [PATCH 035/104] =?UTF-8?q?fix:=20=E5=A4=84=E7=90=86=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E8=8E=B7=E5=8F=96connection=20token=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E4=B8=8D=E5=88=B0=E7=9A=84=E9=97=AE=E9=A2=98=20(#8629)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 处理组件获取connection token获取不到的问题 * fix: ViewSet 显示获取资源用户 * fix: ViewSet 显示获取资源用户 Co-authored-by: Jiangjie.Bai --- apps/authentication/api/connection_token.py | 24 ++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 97abb58be..ecd329af0 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -1,3 +1,4 @@ +import abc import os import json import base64 @@ -34,9 +35,12 @@ class ConnectionTokenMixin: if not is_valid: raise PermissionDenied(error) - @staticmethod - def get_request_resources(serializer): - user = serializer.validated_data.get('user') + @abc.abstractmethod + def get_request_resource_user(self, serializer): + raise NotImplementedError + + def get_request_resources(self, serializer): + user = self.get_request_resource_user(serializer) asset = serializer.validated_data.get('asset') application = serializer.validated_data.get('application') system_user = serializer.validated_data.get('system_user') @@ -226,6 +230,17 @@ class ConnectionTokenViewSet(ConnectionTokenMixin, RootOrgViewMixin, JMSModelVie def get_queryset(self): return ConnectionToken.objects.filter(user=self.request.user) + def get_request_resource_user(self, serializer): + return self.request.user + + def get_object(self): + if self.request.user.is_service_account: + # TODO: 组件获取 token 详情,将来放在 Super-connection-token API 中 + obj = get_object_or_404(ConnectionToken, pk=self.kwargs.get('pk')) + else: + obj = super(ConnectionTokenViewSet, self).get_object() + return obj + def create_connection_token(self): data = self.request.query_params if self.request.method == 'GET' else self.request.data serializer = self.get_serializer(data=data) @@ -293,6 +308,9 @@ class SuperConnectionTokenViewSet(ConnectionTokenViewSet): 'renewal': 'authentication.add_superconnectiontoken' } + def get_request_resource_user(self, serializer): + return serializer.validated_data.get('user') + @action(methods=['PATCH'], detail=False) def renewal(self, request, *args, **kwargs): from common.utils.timezone import as_current_tz From 626b6da9c44a76765cfec129ac8a1a2f05a652b7 Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Wed, 20 Jul 2022 13:20:37 +0800 Subject: [PATCH 036/104] =?UTF-8?q?fix=20cmd=E4=B8=BA=E7=A9=BA=E6=97=B6bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/models/cmd_filter.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/assets/models/cmd_filter.py b/apps/assets/models/cmd_filter.py index b17a4263d..c7fa33aae 100644 --- a/apps/assets/models/cmd_filter.py +++ b/apps/assets/models/cmd_filter.py @@ -125,6 +125,9 @@ class CommandFilterRule(OrgModelMixin): regex.append(cmd) continue + if not cmd: + continue + # 如果是单个字符 if cmd[-1].isalpha(): regex.append(r'\b{0}\b'.format(cmd)) From 88ae8ac67a6da79654a1adf3c3c61f5ef84d8932 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 20 Jul 2022 13:53:01 +0800 Subject: [PATCH 037/104] =?UTF-8?q?fix:=20=E4=BC=9A=E8=AF=9D=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E4=BF=AE=E6=94=B9=E7=BF=BB=E8=AF=91=E4=B8=BA=E7=BB=88?= =?UTF-8?q?=E7=AB=AFID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.po | 36 +++++++++++++++------------- apps/locale/zh/LC_MESSAGES/django.po | 36 +++++++++++++++------------- apps/terminal/serializers/session.py | 2 +- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 99652c84b..2d5151877 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-19 10:45+0800\n" +"POT-Creation-Date: 2022-07-20 13:51+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -29,7 +29,7 @@ msgstr "Acls" #: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24 #: orgs/models.py:65 perms/models/base.py:83 rbac/models/role.py:29 #: settings/models.py:29 settings/serializers/sms.py:6 -#: terminal/models/endpoint.py:10 terminal/models/endpoint.py:88 +#: terminal/models/endpoint.py:10 terminal/models/endpoint.py:86 #: terminal/models/storage.py:26 terminal/models/task.py:16 #: terminal/models/terminal.py:100 users/forms/profile.py:33 #: users/models/group.py:15 users/models/user.py:661 @@ -38,12 +38,12 @@ msgid "Name" msgstr "名前" #: acls/models/base.py:27 assets/models/cmd_filter.py:84 -#: assets/models/user.py:251 terminal/models/endpoint.py:91 +#: assets/models/user.py:251 terminal/models/endpoint.py:89 msgid "Priority" msgstr "優先順位" #: acls/models/base.py:28 assets/models/cmd_filter.py:84 -#: assets/models/user.py:251 terminal/models/endpoint.py:92 +#: assets/models/user.py:251 terminal/models/endpoint.py:90 msgid "1-100, the lower the value will be match first" msgstr "1-100、低い値は最初に一致します" @@ -61,7 +61,7 @@ msgstr "アクティブ" #: assets/models/domain.py:65 assets/models/group.py:23 #: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:68 #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 -#: terminal/models/endpoint.py:23 terminal/models/endpoint.py:98 +#: terminal/models/endpoint.py:23 terminal/models/endpoint.py:96 #: terminal/models/storage.py:29 terminal/models/terminal.py:114 #: tickets/models/comment.py:32 tickets/models/ticket/general.py:288 #: users/models/group.py:16 users/models/user.py:698 @@ -157,7 +157,7 @@ msgstr "コンマ区切り文字列の形式。* はすべて一致すること #: acls/serializers/login_asset_acl.py:51 assets/models/base.py:176 #: assets/models/gathered_user.py:15 audits/models.py:121 #: authentication/forms.py:25 authentication/forms.py:27 -#: authentication/models.py:253 +#: authentication/models.py:260 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 #: ops/models/adhoc.py:159 users/forms/profile.py:32 users/models/user.py:659 @@ -781,7 +781,7 @@ msgstr "失敗しました" msgid "Connectivity" msgstr "接続性" -#: assets/models/base.py:40 authentication/models.py:256 +#: assets/models/base.py:40 authentication/models.py:263 msgid "Date verified" msgstr "確認済みの日付" @@ -1629,7 +1629,7 @@ msgstr "本を飛ばす" msgid "DingTalk" msgstr "DingTalk" -#: audits/signal_handlers.py:56 authentication/models.py:260 +#: audits/signal_handlers.py:56 authentication/models.py:267 msgid "Temporary token" msgstr "仮パスワード" @@ -2137,13 +2137,13 @@ msgstr "期限切れ" msgid "SSO token" msgstr "SSO token" -#: authentication/models.py:72 authentication/models.py:254 +#: authentication/models.py:72 authentication/models.py:261 #: authentication/templates/authentication/_access_key_modal.html:31 #: settings/serializers/auth/radius.py:17 msgid "Secret" msgstr "ひみつ" -#: authentication/models.py:74 authentication/models.py:257 +#: authentication/models.py:74 authentication/models.py:264 #: perms/models/base.py:90 tickets/models/ticket/apply_application.py:26 #: tickets/models/ticket/apply_asset.py:24 users/models/user.py:703 msgid "Date expired" @@ -2201,11 +2201,11 @@ msgstr "" "ユーザーがアプリにアクセスする権限を持っていないか、権限の有効期限が切れてい" "ます" -#: authentication/models.py:255 +#: authentication/models.py:262 msgid "Verified" msgstr "確認済み" -#: authentication/models.py:276 +#: authentication/models.py:283 msgid "Super connection token" msgstr "スーパー接続トークン" @@ -4882,18 +4882,18 @@ msgstr "Oracle 11g ポート" msgid "Oracle 12c Port" msgstr "Oracle 12c ポート" -#: terminal/models/endpoint.py:28 terminal/models/endpoint.py:96 +#: terminal/models/endpoint.py:28 terminal/models/endpoint.py:94 #: terminal/serializers/endpoint.py:57 terminal/serializers/storage.py:38 #: terminal/serializers/storage.py:50 terminal/serializers/storage.py:80 #: terminal/serializers/storage.py:90 terminal/serializers/storage.py:98 msgid "Endpoint" msgstr "エンドポイント" -#: terminal/models/endpoint.py:89 +#: terminal/models/endpoint.py:87 msgid "IP group" msgstr "IP グループ" -#: terminal/models/endpoint.py:101 +#: terminal/models/endpoint.py:99 msgid "Endpoint rule" msgstr "エンドポイントルール" @@ -5050,7 +5050,7 @@ msgstr "クワーグ" msgid "type" msgstr "タイプ" -#: terminal/models/terminal.py:183 terminal/serializers/session.py:39 +#: terminal/models/terminal.py:183 msgid "Terminal" msgstr "ターミナル" @@ -5113,6 +5113,10 @@ msgstr "再生できます" msgid "Can join" msgstr "参加できます" +#: terminal/serializers/session.py:39 +msgid "Terminal ID" +msgstr "ターミナル ID" + #: terminal/serializers/session.py:41 msgid "Can terminate" msgstr "終了できます" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 9a62aa8da..808ca2b08 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-19 10:45+0800\n" +"POT-Creation-Date: 2022-07-20 13:51+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -28,7 +28,7 @@ msgstr "访问控制" #: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24 #: orgs/models.py:65 perms/models/base.py:83 rbac/models/role.py:29 #: settings/models.py:29 settings/serializers/sms.py:6 -#: terminal/models/endpoint.py:10 terminal/models/endpoint.py:88 +#: terminal/models/endpoint.py:10 terminal/models/endpoint.py:86 #: terminal/models/storage.py:26 terminal/models/task.py:16 #: terminal/models/terminal.py:100 users/forms/profile.py:33 #: users/models/group.py:15 users/models/user.py:661 @@ -37,12 +37,12 @@ msgid "Name" msgstr "名称" #: acls/models/base.py:27 assets/models/cmd_filter.py:84 -#: assets/models/user.py:251 terminal/models/endpoint.py:91 +#: assets/models/user.py:251 terminal/models/endpoint.py:89 msgid "Priority" msgstr "优先级" #: acls/models/base.py:28 assets/models/cmd_filter.py:84 -#: assets/models/user.py:251 terminal/models/endpoint.py:92 +#: assets/models/user.py:251 terminal/models/endpoint.py:90 msgid "1-100, the lower the value will be match first" msgstr "优先级可选范围为 1-100 (数值越小越优先)" @@ -60,7 +60,7 @@ msgstr "激活中" #: assets/models/domain.py:65 assets/models/group.py:23 #: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:68 #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 -#: terminal/models/endpoint.py:23 terminal/models/endpoint.py:98 +#: terminal/models/endpoint.py:23 terminal/models/endpoint.py:96 #: terminal/models/storage.py:29 terminal/models/terminal.py:114 #: tickets/models/comment.py:32 tickets/models/ticket/general.py:288 #: users/models/group.py:16 users/models/user.py:698 @@ -156,7 +156,7 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. " #: acls/serializers/login_asset_acl.py:51 assets/models/base.py:176 #: assets/models/gathered_user.py:15 audits/models.py:121 #: authentication/forms.py:25 authentication/forms.py:27 -#: authentication/models.py:253 +#: authentication/models.py:260 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 #: ops/models/adhoc.py:159 users/forms/profile.py:32 users/models/user.py:659 @@ -776,7 +776,7 @@ msgstr "失败" msgid "Connectivity" msgstr "可连接性" -#: assets/models/base.py:40 authentication/models.py:256 +#: assets/models/base.py:40 authentication/models.py:263 msgid "Date verified" msgstr "校验日期" @@ -1617,7 +1617,7 @@ msgstr "飞书" msgid "DingTalk" msgstr "钉钉" -#: audits/signal_handlers.py:56 authentication/models.py:260 +#: audits/signal_handlers.py:56 authentication/models.py:267 msgid "Temporary token" msgstr "临时密码" @@ -2116,13 +2116,13 @@ msgstr "过期时间" msgid "SSO token" msgstr "SSO token" -#: authentication/models.py:72 authentication/models.py:254 +#: authentication/models.py:72 authentication/models.py:261 #: authentication/templates/authentication/_access_key_modal.html:31 #: settings/serializers/auth/radius.py:17 msgid "Secret" msgstr "密钥" -#: authentication/models.py:74 authentication/models.py:257 +#: authentication/models.py:74 authentication/models.py:264 #: perms/models/base.py:90 tickets/models/ticket/apply_application.py:26 #: tickets/models/ticket/apply_asset.py:24 users/models/user.py:703 msgid "Date expired" @@ -2176,11 +2176,11 @@ msgstr "应用不存在" msgid "User has no permission to access application or permission expired" msgstr "用户没有权限访问应用或权限已过期" -#: authentication/models.py:255 +#: authentication/models.py:262 msgid "Verified" msgstr "已校验" -#: authentication/models.py:276 +#: authentication/models.py:283 msgid "Super connection token" msgstr "超级连接令牌" @@ -4806,18 +4806,18 @@ msgstr "Oracle 11g 端口" msgid "Oracle 12c Port" msgstr "Oracle 12c 端口" -#: terminal/models/endpoint.py:28 terminal/models/endpoint.py:96 +#: terminal/models/endpoint.py:28 terminal/models/endpoint.py:94 #: terminal/serializers/endpoint.py:57 terminal/serializers/storage.py:38 #: terminal/serializers/storage.py:50 terminal/serializers/storage.py:80 #: terminal/serializers/storage.py:90 terminal/serializers/storage.py:98 msgid "Endpoint" msgstr "端点" -#: terminal/models/endpoint.py:89 +#: terminal/models/endpoint.py:87 msgid "IP group" msgstr "IP 组" -#: terminal/models/endpoint.py:101 +#: terminal/models/endpoint.py:99 msgid "Endpoint rule" msgstr "端点规则" @@ -4974,7 +4974,7 @@ msgstr "其它参数" msgid "type" msgstr "类型" -#: terminal/models/terminal.py:183 terminal/serializers/session.py:39 +#: terminal/models/terminal.py:183 msgid "Terminal" msgstr "终端" @@ -5035,6 +5035,10 @@ msgstr "是否可重放" msgid "Can join" msgstr "是否可加入" +#: terminal/serializers/session.py:39 +msgid "Terminal ID" +msgstr "终端 ID" + #: terminal/serializers/session.py:41 msgid "Can terminate" msgstr "是否可中断" diff --git a/apps/terminal/serializers/session.py b/apps/terminal/serializers/session.py index 49d7f7270..e769d9c5c 100644 --- a/apps/terminal/serializers/session.py +++ b/apps/terminal/serializers/session.py @@ -36,7 +36,7 @@ class SessionSerializer(BulkOrgResourceModelSerializer): 'is_success': {'label': _('Is success')}, 'can_replay': {'label': _('Can replay')}, 'can_join': {'label': _('Can join')}, - 'terminal': {'label': _('Terminal')}, + 'terminal': {'label': _('Terminal ID')}, 'is_finished': {'label': _('Is finished')}, 'can_terminate': {'label': _('Can terminate')}, 'terminal_display': {'label': _('Terminal display')}, From e7dd731139334e4f18dd10f2298d3f9b3c21dc76 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 20 Jul 2022 15:44:00 +0800 Subject: [PATCH 038/104] =?UTF-8?q?fix:=20=E6=8E=88=E6=9D=83=E8=BF=87?= =?UTF-8?q?=E6=9C=9Furl=20404=20->=20/console/=20(#8634)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/perms/notifications.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/perms/notifications.py b/apps/perms/notifications.py index a6316eb8a..088fa107a 100644 --- a/apps/perms/notifications.py +++ b/apps/perms/notifications.py @@ -1,6 +1,3 @@ -from urllib.parse import urljoin - -from django.conf import settings from django.utils.translation import ugettext as _ from django.template.loader import render_to_string @@ -52,7 +49,7 @@ class AssetPermsWillExpireForOrgAdminMsg(UserMessage): url = js_reverse( 'perms:asset-permission-detail', kwargs={'pk': perm.id}, external=True, - api_to_ui=True + api_to_ui=True, is_console=True ) + f'?oid={perm.org_id}' items_with_url.append([perm.name, url]) return items_with_url @@ -123,9 +120,12 @@ class AppPermsWillExpireForOrgAdminMsg(UserMessage): def get_items_with_url(self): items_with_url = [] - perm_detail_url = urljoin(settings.SITE_URL, '/ui/#/perms/app-permissions/{}') for perm in self.perms: - url = perm_detail_url.format(perm.id) + f'?oid={perm.org_id}' + url = js_reverse( + 'perms:application-permission-detail', + kwargs={'pk': perm.id}, external=True, + api_to_ui=True, is_console=True + ) + f'?oid={perm.org_id}' items_with_url.append([perm.name, url]) return items_with_url From 60e455bea22a4754969e493837195f238a56c63e Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 20 Jul 2022 15:49:47 +0800 Subject: [PATCH 039/104] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9theme=5Finfo?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=80=BC=E4=B8=BA{}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/context_processor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/jumpserver/context_processor.py b/apps/jumpserver/context_processor.py index a02f38838..414144d39 100644 --- a/apps/jumpserver/context_processor.py +++ b/apps/jumpserver/context_processor.py @@ -11,7 +11,7 @@ default_interface = dict(( ('favicon', static('img/facio.ico')), ('login_title', _('JumpServer Open Source Bastion Host')), ('theme', 'classic_green'), - ('theme_info', None), + ('theme_info', {}), )) default_context = { From 12036f8c96b71d68c6e2d408bec3a412a9bdc6c2 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 20 Jul 2022 16:53:03 +0800 Subject: [PATCH 040/104] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20django=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/backends/command/es.py | 4 ++-- apps/terminal/backends/command/models.py | 15 --------------- apps/terminal/models/command.py | 17 +++++++++++++++-- requirements/requirements.txt | 2 +- requirements/rpm_pkg.sh | 3 ++- 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/apps/terminal/backends/command/es.py b/apps/terminal/backends/command/es.py index 1387f6656..20602769c 100644 --- a/apps/terminal/backends/command/es.py +++ b/apps/terminal/backends/command/es.py @@ -18,7 +18,7 @@ from common.utils.common import lazyproperty from common.utils import get_logger from common.utils.timezone import local_now_date_display, utc_now from common.exceptions import JMSException -from .models import AbstractSessionCommand +from terminal.models import Command logger = get_logger(__file__) @@ -181,7 +181,7 @@ class CommandStore(object): item['_source'].update({'id': item['_id']}) source_data.append(item['_source']) - return AbstractSessionCommand.from_multi_dict(source_data) + return Command.from_multi_dict(source_data) def count(self, **query): body = self.get_query_body(**query) diff --git a/apps/terminal/backends/command/models.py b/apps/terminal/backends/command/models.py index 0a795b905..d6eb7a458 100644 --- a/apps/terminal/backends/command/models.py +++ b/apps/terminal/backends/command/models.py @@ -47,21 +47,6 @@ class AbstractSessionCommand(OrgModelMixin): risk_mapper = dict(cls.RISK_LEVEL_CHOICES) return risk_mapper.get(risk_level) - @classmethod - def from_dict(cls, d): - self = cls() - for k, v in d.items(): - setattr(self, k, v) - return self - - @classmethod - def from_multi_dict(cls, l): - commands = [] - for d in l: - command = cls.from_dict(d) - commands.append(command) - return commands - def to_dict(self): d = {} for field in self._meta.fields: diff --git a/apps/terminal/models/command.py b/apps/terminal/models/command.py index 3e94740ff..44edf013c 100644 --- a/apps/terminal/models/command.py +++ b/apps/terminal/models/command.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -import time - from django.db import models from django.db.models.signals import post_save from django.utils.translation import ugettext_lazy as _ @@ -47,6 +45,21 @@ class Command(AbstractSessionCommand): cls.objects.bulk_create(commands) print(f'Create {len(commands)} commands of org ({org})') + @classmethod + def from_dict(cls, d): + self = cls() + for k, v in d.items(): + setattr(self, k, v) + return self + + @classmethod + def from_multi_dict(cls, l): + commands = [] + for d in l: + command = cls.from_dict(d) + commands.append(command) + return commands + class Meta: db_table = "terminal_command" ordering = ('-timestamp',) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 1dac6922d..75e397656 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -62,7 +62,7 @@ jsonfield2==4.0.0.post0 geoip2==4.5.0 ipip-ipdb==1.6.1 # Django environment -Django==3.1.14 +Django==3.2.14 django-bootstrap3==14.2.0 django-filter==2.4.0 django-formtools==2.2 diff --git a/requirements/rpm_pkg.sh b/requirements/rpm_pkg.sh index f48bd3ac8..b926690dc 100644 --- a/requirements/rpm_pkg.sh +++ b/requirements/rpm_pkg.sh @@ -1,4 +1,5 @@ #!/bin/bash yum -y install \ gcc-c++ sshpass mariadb-devel openldap-devel libxml2-devel \ - xmlsec1-devel xmlsec1-openssl-devel libtool-ltdl-devel + xmlsec1-devel xmlsec1-openssl-devel libtool-ltdl-devel \ + postgresql-devel From ca49029d8ff1cf14d7641bd23f8ee404eec79fe0 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 20 Jul 2022 17:12:39 +0800 Subject: [PATCH 041/104] =?UTF-8?q?fix:=20=E9=94=81=E5=AE=9A=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=20keystoneauth1=3D=3D3.4.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements/requirements.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 75e397656..3de0de2eb 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -117,6 +117,9 @@ tencentcloud-sdk-python==3.0.662 aliyun-python-sdk-core-v3==2.9.1 aliyun-python-sdk-ecs==4.10.1 huaweicloud-sdk-python==1.0.21 +# python-keystoneclient need keystoneauth1>=3.4.0 +# huaweicloud-sdk-python need keystoneauth1<=3.4.0 +keystoneauth1==3.4.0 boto3==1.24.12 botocore==1.27.12 s3transfer==0.6.0 From 046356728aa3f7d6ab08b2b815c5eb9097880f2f Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 21 Jul 2022 13:51:15 +0800 Subject: [PATCH 042/104] =?UTF-8?q?perf:=20sso=20token=20=E6=9C=80?= =?UTF-8?q?=E5=B0=8F60=E7=A7=92=20(#8642)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/settings/serializers/auth/sso.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/settings/serializers/auth/sso.py b/apps/settings/serializers/auth/sso.py index c04f38920..113391b45 100644 --- a/apps/settings/serializers/auth/sso.py +++ b/apps/settings/serializers/auth/sso.py @@ -1,4 +1,3 @@ - from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers @@ -14,5 +13,5 @@ class SSOSettingSerializer(serializers.Serializer): ) AUTH_SSO_AUTHKEY_TTL = serializers.IntegerField( required=False, label=_('SSO auth key TTL'), help_text=_("Unit: second"), - min_value=1, max_value=60*30 + min_value=60, max_value=60 * 30 ) From 36d0b8d085d0285525d4b74b59615e006d89a5de Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Thu, 21 Jul 2022 15:31:56 +0800 Subject: [PATCH 043/104] =?UTF-8?q?fix:=20=E7=BB=84=E4=BB=B6=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E7=BB=91=E5=AE=9A=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/orgs/models.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/orgs/models.py b/apps/orgs/models.py index c4208d7d0..4bcb14e33 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -16,9 +16,14 @@ class OrgRoleMixin: def add_member(self, user, role=None): from rbac.builtin import BuiltinRole from .utils import tmp_to_org - role_id = BuiltinRole.org_user.id + if role: role_id = role.id + elif user.is_service_account: + role_id = BuiltinRole.system_component.id + else: + role_id = BuiltinRole.org_user.id + with tmp_to_org(self): defaults = { 'user': user, 'role_id': role_id, From 9d17f27fb3988a91e9819d12c535654945fcccd8 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 21 Jul 2022 15:31:41 +0800 Subject: [PATCH 044/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E5=8F=AF=E8=83=BD=E8=A7=A3=E5=AF=86=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/utils/crypto.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/common/utils/crypto.py b/apps/common/utils/crypto.py index 331f8b0bb..0c818ec5b 100644 --- a/apps/common/utils/crypto.py +++ b/apps/common/utils/crypto.py @@ -259,7 +259,7 @@ def decrypt_password(value): aes = get_aes_crypto(aes_key, 'ECB') try: password = aes.decrypt(password_cipher) - except UnicodeDecodeError as e: + except Exception as e: logging.error("Decrypt password error: {}, {}".format(password_cipher, e)) return value return password From d07a230ba6f9ed0618ce3a1c90a1e8f58d000f93 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 22 Jul 2022 15:23:16 +0800 Subject: [PATCH 045/104] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=B7=A5=E5=8D=95=E6=8E=88=E6=9D=83=E6=97=B6=E9=97=B4?= =?UTF-8?q?=20(#8649)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/jumpserver/conf.py | 1 + apps/jumpserver/settings/custom.py | 1 + apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 70 +++++++++++++++------------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 70 +++++++++++++++------------- apps/settings/serializers/other.py | 5 ++ apps/settings/serializers/public.py | 1 + 8 files changed, 86 insertions(+), 70 deletions(-) diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 551076192..8ebc704d3 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -405,6 +405,7 @@ class Config(dict): 'CONNECTION_TOKEN_ENABLED': False, 'PERM_SINGLE_ASSET_TO_UNGROUP_NODE': False, + 'TICKET_AUTHORIZE_DEFAULT_TIME': 7, 'WINDOWS_SSH_DEFAULT_SHELL': 'cmd', 'PERIOD_TASK_ENABLED': True, diff --git a/apps/jumpserver/settings/custom.py b/apps/jumpserver/settings/custom.py index b6f6e9863..0bcdc77d9 100644 --- a/apps/jumpserver/settings/custom.py +++ b/apps/jumpserver/settings/custom.py @@ -85,6 +85,7 @@ TERMINAL_TELNET_REGEX = CONFIG.TERMINAL_TELNET_REGEX BACKEND_ASSET_USER_AUTH_VAULT = False PERM_SINGLE_ASSET_TO_UNGROUP_NODE = CONFIG.PERM_SINGLE_ASSET_TO_UNGROUP_NODE +TICKET_AUTHORIZE_DEFAULT_TIME = CONFIG.TICKET_AUTHORIZE_DEFAULT_TIME PERM_EXPIRED_CHECK_PERIODIC = CONFIG.PERM_EXPIRED_CHECK_PERIODIC WINDOWS_SSH_DEFAULT_SHELL = CONFIG.WINDOWS_SSH_DEFAULT_SHELL FLOWER_URL = CONFIG.FLOWER_URL diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 7dbdfa16d..fd09548da 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f2fdd3a7bd34a26d068fc6ce521d0ea9983c477b13536ba3f51700a554d4ae3 -size 128706 +oid sha256:92c63243fd3c83321311ffa44fbd91d619969ce18221b629de6e14db90b3a0e8 +size 128842 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 2d5151877..e7c47e63d 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-20 13:51+0800\n" +"POT-Creation-Date: 2022-07-22 14:49+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -27,7 +27,7 @@ msgstr "Acls" #: assets/models/base.py:175 assets/models/cluster.py:18 #: assets/models/cmd_filter.py:27 assets/models/domain.py:23 #: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24 -#: orgs/models.py:65 perms/models/base.py:83 rbac/models/role.py:29 +#: orgs/models.py:70 perms/models/base.py:83 rbac/models/role.py:29 #: settings/models.py:29 settings/serializers/sms.py:6 #: terminal/models/endpoint.py:10 terminal/models/endpoint.py:86 #: terminal/models/storage.py:26 terminal/models/task.py:16 @@ -59,7 +59,7 @@ msgstr "アクティブ" #: assets/models/cluster.py:29 assets/models/cmd_filter.py:48 #: assets/models/cmd_filter.py:96 assets/models/domain.py:24 #: assets/models/domain.py:65 assets/models/group.py:23 -#: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:68 +#: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:73 #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 #: terminal/models/endpoint.py:23 terminal/models/endpoint.py:96 #: terminal/models/storage.py:29 terminal/models/terminal.py:114 @@ -88,7 +88,7 @@ msgstr "ログイン確認" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 -#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:215 +#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:220 #: perms/models/base.py:84 rbac/builtin.py:120 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 @@ -363,7 +363,7 @@ msgstr "タイプ表示" #: assets/serializers/account.py:18 assets/serializers/cmd_filter.py:28 #: assets/serializers/cmd_filter.py:48 common/db/models.py:114 #: common/mixins/models.py:50 ops/models/adhoc.py:39 ops/models/command.py:30 -#: orgs/models.py:67 orgs/models.py:218 perms/models/base.py:92 +#: orgs/models.py:72 orgs/models.py:223 perms/models/base.py:92 #: users/models/group.py:18 users/models/user.py:922 #: xpack/plugins/cloud/models.py:125 msgid "Date created" @@ -373,7 +373,7 @@ msgstr "作成された日付" #: assets/models/gathered_user.py:20 assets/serializers/account.py:21 #: assets/serializers/cmd_filter.py:29 assets/serializers/cmd_filter.py:49 #: common/db/models.py:115 common/mixins/models.py:51 ops/models/adhoc.py:40 -#: orgs/models.py:219 +#: orgs/models.py:224 msgid "Date updated" msgstr "更新日" @@ -627,8 +627,8 @@ msgstr "ラベル" #: assets/models/asset.py:229 assets/models/base.py:183 #: assets/models/cluster.py:28 assets/models/cmd_filter.py:52 #: assets/models/cmd_filter.py:99 assets/models/group.py:21 -#: common/db/models.py:112 common/mixins/models.py:49 orgs/models.py:66 -#: orgs/models.py:220 perms/models/base.py:91 users/models/user.py:706 +#: common/db/models.py:112 common/mixins/models.py:49 orgs/models.py:71 +#: orgs/models.py:225 perms/models/base.py:91 users/models/user.py:706 #: users/serializers/group.py:33 #: xpack/plugins/change_auth_plan/models/base.py:48 #: xpack/plugins/cloud/models.py:122 xpack/plugins/gathered_user/models.py:30 @@ -907,11 +907,11 @@ msgstr "家を無視する" msgid "Command filter rule" msgstr "コマンドフィルタルール" -#: assets/models/cmd_filter.py:144 +#: assets/models/cmd_filter.py:147 msgid "The generated regular expression is incorrect: {}" msgstr "生成された正規表現が正しくありません: {}" -#: assets/models/cmd_filter.py:170 tickets/const.py:13 +#: assets/models/cmd_filter.py:173 tickets/const.py:13 msgid "Command confirm" msgstr "コマンドの確認" @@ -2226,7 +2226,7 @@ msgstr "有効性" msgid "Expired time" msgstr "期限切れ時間" -#: authentication/serializers/connection_token.py:74 +#: authentication/serializers/connection_token.py:73 msgid "Asset or application required" msgstr "アセットまたはアプリが必要" @@ -3028,26 +3028,26 @@ msgstr "組織のリソース ({}) は削除できません" msgid "App organizations" msgstr "アプリ組織" -#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:80 -#: orgs/models.py:212 rbac/const.py:7 rbac/models/rolebinding.py:48 +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:85 +#: orgs/models.py:217 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 msgid "Organization" msgstr "組織" -#: orgs/models.py:74 +#: orgs/models.py:79 msgid "GLOBAL" msgstr "グローバル組織" -#: orgs/models.py:82 +#: orgs/models.py:87 msgid "Can view root org" msgstr "グローバル組織を表示できます" -#: orgs/models.py:83 +#: orgs/models.py:88 msgid "Can view all joined org" msgstr "参加しているすべての組織を表示できます" -#: orgs/models.py:217 rbac/models/role.py:46 rbac/models/rolebinding.py:44 +#: orgs/models.py:222 rbac/models/role.py:46 rbac/models/rolebinding.py:44 #: users/models/user.py:671 msgid "Role" msgstr "ロール" @@ -3136,27 +3136,27 @@ msgstr "クリップボードコピーペースト" msgid "From ticket" msgstr "チケットから" -#: perms/notifications.py:18 +#: perms/notifications.py:15 msgid "You permed assets is about to expire" msgstr "パーマ資産の有効期限が近づいています" -#: perms/notifications.py:23 +#: perms/notifications.py:20 msgid "permed assets" msgstr "パーマ資産" -#: perms/notifications.py:62 +#: perms/notifications.py:59 msgid "Asset permissions is about to expire" msgstr "資産権限の有効期限が近づいています" -#: perms/notifications.py:67 +#: perms/notifications.py:64 msgid "asset permissions of organization {}" msgstr "組織 {} の資産権限" -#: perms/notifications.py:94 +#: perms/notifications.py:91 msgid "Your permed applications is about to expire" msgstr "パーマアプリケーションの有効期限が近づいています" -#: perms/notifications.py:98 +#: perms/notifications.py:95 msgid "permed applications" msgstr "Permedアプリケーション" @@ -3825,20 +3825,20 @@ msgstr "テンプレートコード" msgid "Test phone" msgstr "テスト電話" -#: settings/serializers/auth/sso.py:12 +#: settings/serializers/auth/sso.py:11 msgid "Enable SSO auth" msgstr "SSO Token認証の有効化" -#: settings/serializers/auth/sso.py:13 +#: settings/serializers/auth/sso.py:12 msgid "Other service can using SSO token login to JumpServer without password" msgstr "" "他のサービスはパスワードなしでJumpServerへのSSOトークンログインを使用できます" -#: settings/serializers/auth/sso.py:16 +#: settings/serializers/auth/sso.py:15 msgid "SSO auth key TTL" msgstr "Token有効期間" -#: settings/serializers/auth/sso.py:16 +#: settings/serializers/auth/sso.py:15 msgid "Unit: second" msgstr "単位: 秒" @@ -3904,7 +3904,7 @@ msgstr "ログインログは日数を保持します" #: settings/serializers/cleaning.py:10 settings/serializers/cleaning.py:14 #: settings/serializers/cleaning.py:18 settings/serializers/cleaning.py:22 -#: settings/serializers/cleaning.py:26 +#: settings/serializers/cleaning.py:26 settings/serializers/other.py:35 msgid "Unit: day" msgstr "単位: 日" @@ -4077,19 +4077,23 @@ msgstr "" "ノードが表示されないようにしますが、そのノードが許可されていないという質問に" "質問" -#: settings/serializers/other.py:34 +#: settings/serializers/other.py:35 +msgid "Ticket authorize default time" +msgstr "デフォルト製造オーダ承認時間" + +#: settings/serializers/other.py:39 msgid "Help Docs URL" msgstr "ドキュメントリンク" -#: settings/serializers/other.py:35 +#: settings/serializers/other.py:40 msgid "default: http://docs.jumpserver.org" msgstr "デフォルト: http://docs.jumpserver.org" -#: settings/serializers/other.py:39 +#: settings/serializers/other.py:44 msgid "Help Support URL" msgstr "サポートリンク" -#: settings/serializers/other.py:40 +#: settings/serializers/other.py:45 msgid "default: http://www.jumpserver.org/support/" msgstr "デフォルト: http://www.jumpserver.org/support/" @@ -4838,7 +4842,7 @@ msgstr "一括作成非サポート" msgid "Storage is invalid" msgstr "ストレージが無効です" -#: terminal/models/command.py:53 +#: terminal/models/command.py:66 msgid "Command record" msgstr "コマンドレコード" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 33d7105d9..7daf33248 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c2b13f7242beec8786179e03de895bd3e9d8d6392b74c2398409c1bfa33d9f8 -size 106088 +oid sha256:c4c49c98910aa6e85894d1ba57217932e4e960de325785003749f32000d62657 +size 106197 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 808ca2b08..7d4780a26 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-20 13:51+0800\n" +"POT-Creation-Date: 2022-07-22 14:49+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -26,7 +26,7 @@ msgstr "访问控制" #: assets/models/base.py:175 assets/models/cluster.py:18 #: assets/models/cmd_filter.py:27 assets/models/domain.py:23 #: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24 -#: orgs/models.py:65 perms/models/base.py:83 rbac/models/role.py:29 +#: orgs/models.py:70 perms/models/base.py:83 rbac/models/role.py:29 #: settings/models.py:29 settings/serializers/sms.py:6 #: terminal/models/endpoint.py:10 terminal/models/endpoint.py:86 #: terminal/models/storage.py:26 terminal/models/task.py:16 @@ -58,7 +58,7 @@ msgstr "激活中" #: assets/models/cluster.py:29 assets/models/cmd_filter.py:48 #: assets/models/cmd_filter.py:96 assets/models/domain.py:24 #: assets/models/domain.py:65 assets/models/group.py:23 -#: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:68 +#: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:73 #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 #: terminal/models/endpoint.py:23 terminal/models/endpoint.py:96 #: terminal/models/storage.py:29 terminal/models/terminal.py:114 @@ -87,7 +87,7 @@ msgstr "登录复核" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 -#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:215 +#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:220 #: perms/models/base.py:84 rbac/builtin.py:120 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 @@ -358,7 +358,7 @@ msgstr "类型名称" #: assets/serializers/account.py:18 assets/serializers/cmd_filter.py:28 #: assets/serializers/cmd_filter.py:48 common/db/models.py:114 #: common/mixins/models.py:50 ops/models/adhoc.py:39 ops/models/command.py:30 -#: orgs/models.py:67 orgs/models.py:218 perms/models/base.py:92 +#: orgs/models.py:72 orgs/models.py:223 perms/models/base.py:92 #: users/models/group.py:18 users/models/user.py:922 #: xpack/plugins/cloud/models.py:125 msgid "Date created" @@ -368,7 +368,7 @@ msgstr "创建日期" #: assets/models/gathered_user.py:20 assets/serializers/account.py:21 #: assets/serializers/cmd_filter.py:29 assets/serializers/cmd_filter.py:49 #: common/db/models.py:115 common/mixins/models.py:51 ops/models/adhoc.py:40 -#: orgs/models.py:219 +#: orgs/models.py:224 msgid "Date updated" msgstr "更新日期" @@ -622,8 +622,8 @@ msgstr "标签管理" #: assets/models/asset.py:229 assets/models/base.py:183 #: assets/models/cluster.py:28 assets/models/cmd_filter.py:52 #: assets/models/cmd_filter.py:99 assets/models/group.py:21 -#: common/db/models.py:112 common/mixins/models.py:49 orgs/models.py:66 -#: orgs/models.py:220 perms/models/base.py:91 users/models/user.py:706 +#: common/db/models.py:112 common/mixins/models.py:49 orgs/models.py:71 +#: orgs/models.py:225 perms/models/base.py:91 users/models/user.py:706 #: users/serializers/group.py:33 #: xpack/plugins/change_auth_plan/models/base.py:48 #: xpack/plugins/cloud/models.py:122 xpack/plugins/gathered_user/models.py:30 @@ -902,11 +902,11 @@ msgstr "忽略大小写" msgid "Command filter rule" msgstr "命令过滤规则" -#: assets/models/cmd_filter.py:144 +#: assets/models/cmd_filter.py:147 msgid "The generated regular expression is incorrect: {}" msgstr "生成的正则表达式有误" -#: assets/models/cmd_filter.py:170 tickets/const.py:13 +#: assets/models/cmd_filter.py:173 tickets/const.py:13 msgid "Command confirm" msgstr "命令复核" @@ -2201,7 +2201,7 @@ msgstr "有效" msgid "Expired time" msgstr "过期时间" -#: authentication/serializers/connection_token.py:74 +#: authentication/serializers/connection_token.py:73 msgid "Asset or application required" msgstr "资产或应用必填" @@ -2988,26 +2988,26 @@ msgstr "组织存在资源 ({}) 不能被删除" msgid "App organizations" msgstr "组织管理" -#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:80 -#: orgs/models.py:212 rbac/const.py:7 rbac/models/rolebinding.py:48 +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:85 +#: orgs/models.py:217 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 msgid "Organization" msgstr "组织" -#: orgs/models.py:74 +#: orgs/models.py:79 msgid "GLOBAL" msgstr "全局组织" -#: orgs/models.py:82 +#: orgs/models.py:87 msgid "Can view root org" msgstr "可以查看全局组织" -#: orgs/models.py:83 +#: orgs/models.py:88 msgid "Can view all joined org" msgstr "可以查看所有加入的组织" -#: orgs/models.py:217 rbac/models/role.py:46 rbac/models/rolebinding.py:44 +#: orgs/models.py:222 rbac/models/role.py:46 rbac/models/rolebinding.py:44 #: users/models/user.py:671 msgid "Role" msgstr "角色" @@ -3096,27 +3096,27 @@ msgstr "剪贴板复制粘贴" msgid "From ticket" msgstr "来自工单" -#: perms/notifications.py:18 +#: perms/notifications.py:15 msgid "You permed assets is about to expire" msgstr "你授权的资产即将到期" -#: perms/notifications.py:23 +#: perms/notifications.py:20 msgid "permed assets" msgstr "授权的资产" -#: perms/notifications.py:62 +#: perms/notifications.py:59 msgid "Asset permissions is about to expire" msgstr "资产授权规则将要过期" -#: perms/notifications.py:67 +#: perms/notifications.py:64 msgid "asset permissions of organization {}" msgstr "组织 ({}) 的资产授权" -#: perms/notifications.py:94 +#: perms/notifications.py:91 msgid "Your permed applications is about to expire" msgstr "你授权的应用即将过期" -#: perms/notifications.py:98 +#: perms/notifications.py:95 msgid "permed applications" msgstr "授权的应用" @@ -3782,19 +3782,19 @@ msgstr "模板" msgid "Test phone" msgstr "测试手机号" -#: settings/serializers/auth/sso.py:12 +#: settings/serializers/auth/sso.py:11 msgid "Enable SSO auth" msgstr "启用 SSO Token 认证" -#: settings/serializers/auth/sso.py:13 +#: settings/serializers/auth/sso.py:12 msgid "Other service can using SSO token login to JumpServer without password" msgstr "其它系统可以使用 SSO Token 对接 JumpServer, 免去登录的过程" -#: settings/serializers/auth/sso.py:16 +#: settings/serializers/auth/sso.py:15 msgid "SSO auth key TTL" msgstr "Token 有效期" -#: settings/serializers/auth/sso.py:16 +#: settings/serializers/auth/sso.py:15 msgid "Unit: second" msgstr "单位: 秒" @@ -3860,7 +3860,7 @@ msgstr "登录日志" #: settings/serializers/cleaning.py:10 settings/serializers/cleaning.py:14 #: settings/serializers/cleaning.py:18 settings/serializers/cleaning.py:22 -#: settings/serializers/cleaning.py:26 +#: settings/serializers/cleaning.py:26 settings/serializers/other.py:35 msgid "Unit: day" msgstr "单位: 天" @@ -4025,19 +4025,23 @@ msgstr "" "放置单独授权的资产到未分组节点, 避免能看到资产所在节点,但该节点未被授权的问" "题" -#: settings/serializers/other.py:34 +#: settings/serializers/other.py:35 +msgid "Ticket authorize default time" +msgstr "默认工单授权时间" + +#: settings/serializers/other.py:39 msgid "Help Docs URL" msgstr "文档链接" -#: settings/serializers/other.py:35 +#: settings/serializers/other.py:40 msgid "default: http://docs.jumpserver.org" msgstr "默认: http://dev.jumpserver.org:8080" -#: settings/serializers/other.py:39 +#: settings/serializers/other.py:44 msgid "Help Support URL" msgstr "支持链接" -#: settings/serializers/other.py:40 +#: settings/serializers/other.py:45 msgid "default: http://www.jumpserver.org/support/" msgstr "默认: http://www.jumpserver.org/support/" @@ -4762,7 +4766,7 @@ msgstr "不支持批量创建" msgid "Storage is invalid" msgstr "存储无效" -#: terminal/models/command.py:53 +#: terminal/models/command.py:66 msgid "Command record" msgstr "命令记录" diff --git a/apps/settings/serializers/other.py b/apps/settings/serializers/other.py index 7d701756c..775e26dd7 100644 --- a/apps/settings/serializers/other.py +++ b/apps/settings/serializers/other.py @@ -30,6 +30,11 @@ class OtherSettingSerializer(serializers.Serializer): help_text=_("Perm single to ungroup node") ) + TICKET_AUTHORIZE_DEFAULT_TIME = serializers.IntegerField( + min_value=7, max_value=9999, required=False, + label=_("Ticket authorize default time"), help_text=_("Unit: day") + ) + HELP_DOCUMENT_URL = serializers.URLField( required=False, allow_blank=True, allow_null=True, label=_("Help Docs URL"), help_text=_('default: http://docs.jumpserver.org') diff --git a/apps/settings/serializers/public.py b/apps/settings/serializers/public.py index 73b61a3bc..04e2b85af 100644 --- a/apps/settings/serializers/public.py +++ b/apps/settings/serializers/public.py @@ -14,6 +14,7 @@ class PublicSettingSerializer(serializers.Serializer): class PrivateSettingSerializer(PublicSettingSerializer): WINDOWS_SKIP_ALL_MANUAL_PASSWORD = serializers.BooleanField() OLD_PASSWORD_HISTORY_LIMIT_COUNT = serializers.IntegerField() + TICKET_AUTHORIZE_DEFAULT_TIME = serializers.IntegerField() SECURITY_MAX_IDLE_TIME = serializers.IntegerField() SECURITY_VIEW_AUTH_NEED_MFA = serializers.BooleanField() SECURITY_MFA_VERIFY_TTL = serializers.IntegerField() From dc322242949224d2e137f388b3fcbf7f058ae714 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 22 Jul 2022 16:24:57 +0800 Subject: [PATCH 046/104] =?UTF-8?q?feat:=20=E5=BA=94=E7=94=A8=E5=B7=A5?= =?UTF-8?q?=E5=8D=95=E6=94=AF=E6=8C=81=E9=80=89=E6=8B=A9=E5=8A=A8=E4=BD=9C?= =?UTF-8?q?=20(#8651)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/tickets/handlers/apply_application.py | 4 +++- ...018_applyapplicationticket_apply_actions.py | 18 ++++++++++++++++++ .../tickets/models/ticket/apply_application.py | 13 ++++++++++++- .../serializers/ticket/apply_application.py | 7 +++++-- apps/tickets/serializers/ticket/apply_asset.py | 5 +++-- 5 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 apps/tickets/migrations/0018_applyapplicationticket_apply_actions.py diff --git a/apps/tickets/handlers/apply_application.py b/apps/tickets/handlers/apply_application.py index 5b7712553..287c70c4a 100644 --- a/apps/tickets/handlers/apply_application.py +++ b/apps/tickets/handlers/apply_application.py @@ -1,6 +1,6 @@ from django.utils.translation import ugettext as _ -from orgs.utils import tmp_to_org, tmp_to_root_org +from orgs.utils import tmp_to_org from perms.models import ApplicationPermission from tickets.models import ApplyApplicationTicket from .base import BaseHandler @@ -26,6 +26,7 @@ class Handler(BaseHandler): apply_system_users = self.ticket.apply_system_users.all() apply_permission_name = self.ticket.apply_permission_name + apply_actions = self.ticket.apply_actions apply_category = self.ticket.apply_category apply_type = self.ticket.apply_type apply_date_start = self.ticket.apply_date_start @@ -50,6 +51,7 @@ class Handler(BaseHandler): 'name': apply_permission_name, 'from_ticket': True, 'category': apply_category, + 'actions': apply_actions, 'type': apply_type, 'comment': str(permission_comment), 'created_by': permission_created_by, diff --git a/apps/tickets/migrations/0018_applyapplicationticket_apply_actions.py b/apps/tickets/migrations/0018_applyapplicationticket_apply_actions.py new file mode 100644 index 000000000..74f5ed7a3 --- /dev/null +++ b/apps/tickets/migrations/0018_applyapplicationticket_apply_actions.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.14 on 2022-07-22 08:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tickets', '0017_auto_20220623_1027'), + ] + + operations = [ + migrations.AddField( + model_name='applyapplicationticket', + name='apply_actions', + field=models.IntegerField(choices=[(255, 'All'), (1, 'Connect'), (2, 'Upload file'), (4, 'Download file'), (6, 'Upload download'), (8, 'Clipboard copy'), (16, 'Clipboard paste'), (24, 'Clipboard copy paste')], default=255, verbose_name='Actions'), + ), + ] diff --git a/apps/tickets/models/ticket/apply_application.py b/apps/tickets/models/ticket/apply_application.py index 6bd721677..378047db2 100644 --- a/apps/tickets/models/ticket/apply_application.py +++ b/apps/tickets/models/ticket/apply_application.py @@ -1,8 +1,9 @@ from django.db import models from django.utils.translation import gettext_lazy as _ -from .general import Ticket +from perms.models import Action from applications.const import AppCategory, AppType +from .general import Ticket __all__ = ['ApplyApplicationTicket'] @@ -22,6 +23,9 @@ class ApplyApplicationTicket(Ticket): apply_system_users = models.ManyToManyField( 'assets.SystemUser', verbose_name=_('Apply system users'), ) + apply_actions = models.IntegerField( + choices=Action.DB_CHOICES, default=Action.ALL, verbose_name=_('Actions') + ) apply_date_start = models.DateTimeField(verbose_name=_('Date start'), null=True) apply_date_expired = models.DateTimeField(verbose_name=_('Date expired'), null=True) @@ -32,3 +36,10 @@ class ApplyApplicationTicket(Ticket): @property def apply_type_display(self): return AppType.get_label(self.apply_type) + + @property + def apply_actions_display(self): + return Action.value_to_choices_display(self.apply_actions) + + def get_apply_actions_display(self): + return ', '.join(self.apply_actions_display) diff --git a/apps/tickets/serializers/ticket/apply_application.py b/apps/tickets/serializers/ticket/apply_application.py index c713f21d6..12b3f230d 100644 --- a/apps/tickets/serializers/ticket/apply_application.py +++ b/apps/tickets/serializers/ticket/apply_application.py @@ -2,6 +2,7 @@ from django.utils.translation import ugettext as _ from rest_framework import serializers from perms.models import ApplicationPermission +from perms.serializers.base import ActionsField from orgs.utils import tmp_to_org from applications.models import Application from tickets.models import ApplyApplicationTicket @@ -12,6 +13,7 @@ __all__ = ['ApplyApplicationSerializer', 'ApplyApplicationDisplaySerializer', 'A class ApplyApplicationSerializer(BaseApplyAssetApplicationSerializer, TicketApplySerializer): + apply_actions = ActionsField(required=True, allow_empty=False) permission_model = ApplicationPermission class Meta: @@ -19,9 +21,10 @@ class ApplyApplicationSerializer(BaseApplyAssetApplicationSerializer, TicketAppl writeable_fields = [ 'id', 'title', 'type', 'apply_category', 'apply_type', 'apply_applications', 'apply_system_users', - 'apply_date_start', 'apply_date_expired', 'org_id' + 'apply_actions', 'apply_date_start', 'apply_date_expired', 'org_id' ] - fields = TicketApplySerializer.Meta.fields + writeable_fields + ['apply_permission_name'] + fields = TicketApplySerializer.Meta.fields + \ + writeable_fields + ['apply_permission_name', 'apply_actions_display'] read_only_fields = list(set(fields) - set(writeable_fields)) ticket_extra_kwargs = TicketApplySerializer.Meta.extra_kwargs extra_kwargs = { diff --git a/apps/tickets/serializers/ticket/apply_asset.py b/apps/tickets/serializers/ticket/apply_asset.py index b8a007e8d..93a4026c1 100644 --- a/apps/tickets/serializers/ticket/apply_asset.py +++ b/apps/tickets/serializers/ticket/apply_asset.py @@ -23,10 +23,11 @@ class ApplyAssetSerializer(BaseApplyAssetApplicationSerializer, TicketApplySeria model = ApplyAssetTicket writeable_fields = [ 'id', 'title', 'type', 'apply_nodes', 'apply_assets', - 'apply_system_users', 'apply_actions', 'apply_actions_display', + 'apply_system_users', 'apply_actions', 'apply_date_start', 'apply_date_expired', 'org_id' ] - fields = TicketApplySerializer.Meta.fields + writeable_fields + ['apply_permission_name'] + fields = TicketApplySerializer.Meta.fields + \ + writeable_fields + ['apply_permission_name', 'apply_actions_display'] read_only_fields = list(set(fields) - set(writeable_fields)) ticket_extra_kwargs = TicketApplySerializer.Meta.extra_kwargs extra_kwargs = { From c4146744e5f31b7f9942511254b752e4f3e365a5 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 25 Jul 2022 14:02:07 +0800 Subject: [PATCH 047/104] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E8=BF=87=E6=9C=9F=E6=8F=90=E9=86=92=20(#8654)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/locale/ja/LC_MESSAGES/django.mo | 4 ++-- apps/locale/ja/LC_MESSAGES/django.po | 26 ++++++++++++++++---------- apps/locale/zh/LC_MESSAGES/django.mo | 4 ++-- apps/locale/zh/LC_MESSAGES/django.po | 26 ++++++++++++++++---------- apps/perms/notifications.py | 14 +++++++------- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index fd09548da..a74e1daed 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:92c63243fd3c83321311ffa44fbd91d619969ce18221b629de6e14db90b3a0e8 -size 128842 +oid sha256:7ff3ae18c27279b8783eba9e85b270f9c3da63f812da315ba210877b33b960a8 +size 128908 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index e7c47e63d..7bc904143 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-22 14:49+0800\n" +"POT-Creation-Date: 2022-07-25 13:53+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -304,7 +304,7 @@ msgstr "アプリケーションアカウントの秘密を変更できます" #: applications/serializers/application.py:99 assets/models/label.py:21 #: perms/models/application_permission.py:21 #: perms/serializers/application/user_permission.py:33 -#: tickets/models/ticket/apply_application.py:14 +#: tickets/models/ticket/apply_application.py:15 #: xpack/plugins/change_auth_plan/models/app.py:25 msgid "Category" msgstr "カテゴリ" @@ -316,7 +316,7 @@ msgstr "カテゴリ" #: perms/serializers/application/user_permission.py:34 #: terminal/models/storage.py:58 terminal/models/storage.py:143 #: tickets/models/comment.py:26 tickets/models/flow.py:57 -#: tickets/models/ticket/apply_application.py:17 +#: tickets/models/ticket/apply_application.py:18 #: tickets/models/ticket/general.py:273 #: xpack/plugins/change_auth_plan/models/app.py:28 #: xpack/plugins/change_auth_plan/models/app.py:153 @@ -425,7 +425,7 @@ msgstr "アプリケーションパス" #: applications/serializers/attrs/application_category/remote_app.py:44 #: assets/serializers/system_user.py:167 -#: tickets/serializers/ticket/apply_application.py:35 +#: tickets/serializers/ticket/apply_application.py:38 #: tickets/serializers/ticket/common.py:59 #: xpack/plugins/change_auth_plan/serializers/asset.py:67 #: xpack/plugins/change_auth_plan/serializers/asset.py:70 @@ -711,7 +711,7 @@ msgstr "タイミングトリガー" #: assets/models/backup.py:105 audits/models.py:44 ops/models/command.py:31 #: perms/models/base.py:89 terminal/models/session.py:58 -#: tickets/models/ticket/apply_application.py:25 +#: tickets/models/ticket/apply_application.py:29 #: tickets/models/ticket/apply_asset.py:23 #: xpack/plugins/change_auth_plan/models/base.py:112 #: xpack/plugins/change_auth_plan/models/base.py:203 @@ -1141,6 +1141,7 @@ msgstr "CPU情報" #: perms/serializers/application/permission.py:42 #: perms/serializers/asset/permission.py:18 #: perms/serializers/asset/permission.py:46 +#: tickets/models/ticket/apply_application.py:27 #: tickets/models/ticket/apply_asset.py:21 msgid "Actions" msgstr "アクション" @@ -2144,7 +2145,7 @@ msgid "Secret" msgstr "ひみつ" #: authentication/models.py:74 authentication/models.py:264 -#: perms/models/base.py:90 tickets/models/ticket/apply_application.py:26 +#: perms/models/base.py:90 tickets/models/ticket/apply_application.py:30 #: tickets/models/ticket/apply_asset.py:24 users/models/user.py:703 msgid "Date expired" msgstr "期限切れの日付" @@ -3136,6 +3137,11 @@ msgstr "クリップボードコピーペースト" msgid "From ticket" msgstr "チケットから" +#: perms/notifications.py:12 perms/notifications.py:44 +#: perms/notifications.py:88 perms/notifications.py:119 +msgid "today" +msgstr "今" + #: perms/notifications.py:15 msgid "You permed assets is about to expire" msgstr "パーマ資産の有効期限が近づいています" @@ -5283,7 +5289,7 @@ msgstr "カスタムユーザー" msgid "Ticket already closed" msgstr "チケットはすでに閉じています" -#: tickets/handlers/apply_application.py:37 +#: tickets/handlers/apply_application.py:38 msgid "" "Created by the ticket, ticket title: {}, ticket applicant: {}, ticket " "processor: {}, ticket ID: {}" @@ -5369,16 +5375,16 @@ msgstr "チケットの流れ" msgid "Ticket session relation" msgstr "チケットセッションの関係" -#: tickets/models/ticket/apply_application.py:11 +#: tickets/models/ticket/apply_application.py:12 #: tickets/models/ticket/apply_asset.py:13 msgid "Permission name" msgstr "認可ルール名" -#: tickets/models/ticket/apply_application.py:20 +#: tickets/models/ticket/apply_application.py:21 msgid "Apply applications" msgstr "アプリケーションの適用" -#: tickets/models/ticket/apply_application.py:23 +#: tickets/models/ticket/apply_application.py:24 #: tickets/models/ticket/apply_asset.py:18 msgid "Apply system users" msgstr "システムユーザーの適用" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 7daf33248..fbc1449e5 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4c49c98910aa6e85894d1ba57217932e4e960de325785003749f32000d62657 -size 106197 +oid sha256:493d944976b6e1ad0daba8bae18bd0823aaab4a72b63916315601fd59e984a5a +size 106223 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 7d4780a26..025aa770b 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-22 14:49+0800\n" +"POT-Creation-Date: 2022-07-25 13:53+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -299,7 +299,7 @@ msgstr "可以查看应用账号密码" #: applications/serializers/application.py:99 assets/models/label.py:21 #: perms/models/application_permission.py:21 #: perms/serializers/application/user_permission.py:33 -#: tickets/models/ticket/apply_application.py:14 +#: tickets/models/ticket/apply_application.py:15 #: xpack/plugins/change_auth_plan/models/app.py:25 msgid "Category" msgstr "类别" @@ -311,7 +311,7 @@ msgstr "类别" #: perms/serializers/application/user_permission.py:34 #: terminal/models/storage.py:58 terminal/models/storage.py:143 #: tickets/models/comment.py:26 tickets/models/flow.py:57 -#: tickets/models/ticket/apply_application.py:17 +#: tickets/models/ticket/apply_application.py:18 #: tickets/models/ticket/general.py:273 #: xpack/plugins/change_auth_plan/models/app.py:28 #: xpack/plugins/change_auth_plan/models/app.py:153 @@ -420,7 +420,7 @@ msgstr "应用路径" #: applications/serializers/attrs/application_category/remote_app.py:44 #: assets/serializers/system_user.py:167 -#: tickets/serializers/ticket/apply_application.py:35 +#: tickets/serializers/ticket/apply_application.py:38 #: tickets/serializers/ticket/common.py:59 #: xpack/plugins/change_auth_plan/serializers/asset.py:67 #: xpack/plugins/change_auth_plan/serializers/asset.py:70 @@ -706,7 +706,7 @@ msgstr "定时触发" #: assets/models/backup.py:105 audits/models.py:44 ops/models/command.py:31 #: perms/models/base.py:89 terminal/models/session.py:58 -#: tickets/models/ticket/apply_application.py:25 +#: tickets/models/ticket/apply_application.py:29 #: tickets/models/ticket/apply_asset.py:23 #: xpack/plugins/change_auth_plan/models/base.py:112 #: xpack/plugins/change_auth_plan/models/base.py:203 @@ -1133,6 +1133,7 @@ msgstr "CPU信息" #: perms/serializers/application/permission.py:42 #: perms/serializers/asset/permission.py:18 #: perms/serializers/asset/permission.py:46 +#: tickets/models/ticket/apply_application.py:27 #: tickets/models/ticket/apply_asset.py:21 msgid "Actions" msgstr "动作" @@ -2123,7 +2124,7 @@ msgid "Secret" msgstr "密钥" #: authentication/models.py:74 authentication/models.py:264 -#: perms/models/base.py:90 tickets/models/ticket/apply_application.py:26 +#: perms/models/base.py:90 tickets/models/ticket/apply_application.py:30 #: tickets/models/ticket/apply_asset.py:24 users/models/user.py:703 msgid "Date expired" msgstr "失效日期" @@ -3096,6 +3097,11 @@ msgstr "剪贴板复制粘贴" msgid "From ticket" msgstr "来自工单" +#: perms/notifications.py:12 perms/notifications.py:44 +#: perms/notifications.py:88 perms/notifications.py:119 +msgid "today" +msgstr "今" + #: perms/notifications.py:15 msgid "You permed assets is about to expire" msgstr "你授权的资产即将到期" @@ -5205,7 +5211,7 @@ msgstr "自定义用户" msgid "Ticket already closed" msgstr "工单已经关闭" -#: tickets/handlers/apply_application.py:37 +#: tickets/handlers/apply_application.py:38 msgid "" "Created by the ticket, ticket title: {}, ticket applicant: {}, ticket " "processor: {}, ticket ID: {}" @@ -5289,16 +5295,16 @@ msgstr "工单流程" msgid "Ticket session relation" msgstr "工单会话" -#: tickets/models/ticket/apply_application.py:11 +#: tickets/models/ticket/apply_application.py:12 #: tickets/models/ticket/apply_asset.py:13 msgid "Permission name" msgstr "授权规则名称" -#: tickets/models/ticket/apply_application.py:20 +#: tickets/models/ticket/apply_application.py:21 msgid "Apply applications" msgstr "申请应用" -#: tickets/models/ticket/apply_application.py:23 +#: tickets/models/ticket/apply_application.py:24 #: tickets/models/ticket/apply_asset.py:18 msgid "Apply system users" msgstr "申请的系统用户" diff --git a/apps/perms/notifications.py b/apps/perms/notifications.py index 088fa107a..b40ccab7c 100644 --- a/apps/perms/notifications.py +++ b/apps/perms/notifications.py @@ -9,7 +9,7 @@ class PermedAssetsWillExpireUserMsg(UserMessage): def __init__(self, user, assets, day_count=0): super().__init__(user) self.assets = assets - self.day_count = day_count + self.day_count = _('today') if day_count == 0 else day_count def get_html_msg(self) -> dict: subject = _("You permed assets is about to expire") @@ -41,7 +41,7 @@ class AssetPermsWillExpireForOrgAdminMsg(UserMessage): super().__init__(user) self.perms = perms self.org = org - self.day_count = day_count + self.day_count = _('today') if day_count == 0 else day_count def get_items_with_url(self): items_with_url = [] @@ -59,7 +59,7 @@ class AssetPermsWillExpireForOrgAdminMsg(UserMessage): subject = _("Asset permissions is about to expire") context = { 'name': self.user.name, - 'count': self.day_count, + 'count': str(self.day_count), 'items_with_url': items_with_url, 'item_type': _('asset permissions of organization {}').format(self.org) } @@ -85,13 +85,13 @@ class PermedAppsWillExpireUserMsg(UserMessage): def __init__(self, user, apps, day_count=0): super().__init__(user) self.apps = apps - self.day_count = day_count + self.day_count = _('today') if day_count == 0 else day_count def get_html_msg(self) -> dict: subject = _("Your permed applications is about to expire") context = { 'name': self.user.name, - 'count': self.day_count, + 'count': str(self.day_count), 'item_type': _('permed applications'), 'items': [str(app) for app in self.apps] } @@ -116,7 +116,7 @@ class AppPermsWillExpireForOrgAdminMsg(UserMessage): super().__init__(user) self.perms = perms self.org = org - self.day_count = day_count + self.day_count = _('today') if day_count == 0 else day_count def get_items_with_url(self): items_with_url = [] @@ -134,7 +134,7 @@ class AppPermsWillExpireForOrgAdminMsg(UserMessage): subject = _('Application permissions is about to expire') context = { 'name': self.user.name, - 'count': self.day_count, + 'count': str(self.day_count), 'item_type': _('application permissions of organization {}').format(self.org), 'items_with_url': items } From 0f7b41d1776f2fc1dd9540f81f1879a0453685e5 Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Tue, 26 Jul 2022 15:01:47 +0800 Subject: [PATCH 048/104] fix: super ticket close bug --- apps/tickets/api/super_ticket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tickets/api/super_ticket.py b/apps/tickets/api/super_ticket.py index ea186bd1b..32c4a56c0 100644 --- a/apps/tickets/api/super_ticket.py +++ b/apps/tickets/api/super_ticket.py @@ -20,4 +20,4 @@ class SuperTicketStatusAPI(RetrieveDestroyAPIView): return Ticket.objects.all() def perform_destroy(self, instance): - instance.close(processor=instance.applicant) + instance.close() From e7229963bfc0c87167d50ce236acc24bf79b9647 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Mon, 18 Jul 2022 11:44:41 +0800 Subject: [PATCH 049/104] =?UTF-8?q?perf:=20=E6=9B=B4=E6=8D=A2oracle?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 3de0de2eb..75d5b6c5c 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -127,7 +127,7 @@ kubernetes==21.7.0 # DB requirements mysqlclient==2.1.0 PyMySQL==1.0.2 -cx-Oracle==8.2.1 +oracledb==1.0.1 psycopg2-binary==2.9.1 pymssql==2.1.5 django-mysql==3.9.0 From ea7133dea01e19c4c04bcbe8de713e6f49780077 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 28 Jul 2022 13:47:32 +0800 Subject: [PATCH 050/104] fix: translate (#8664) Co-authored-by: feng626 <1304903146@qq.com> --- apps/locale/ja/LC_MESSAGES/django.po | 2 +- apps/locale/zh/LC_MESSAGES/django.mo | 2 +- apps/locale/zh/LC_MESSAGES/django.po | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 7bc904143..7668705cc 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-25 13:53+0800\n" +"POT-Creation-Date: 2022-07-28 13:43+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index fbc1449e5..841d1186d 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:493d944976b6e1ad0daba8bae18bd0823aaab4a72b63916315601fd59e984a5a +oid sha256:4c10c6bd05e79bc462db9863136e538978e5ca2644c6fd228050603135559d83 size 106223 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 025aa770b..dab498f08 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-25 13:53+0800\n" +"POT-Creation-Date: 2022-07-28 13:43+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -4271,7 +4271,7 @@ msgstr "会话分享" #: settings/serializers/security.py:180 msgid "Enabled, Allows user active session to be shared with other users" -msgstr "开启后允许用户分享已连接的资产会话给它人,协同工作" +msgstr "开启后允许用户分享已连接的资产会话给他人,协同工作" #: settings/serializers/security.py:183 msgid "Remote Login Protection" From ee1aff243c431d7b1eb94df270e2b93b57bfefb3 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 29 Jul 2022 10:02:23 +0800 Subject: [PATCH 051/104] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Eping=E3=80=81?= =?UTF-8?q?telnet=E7=B3=BB=E7=BB=9F=E5=B7=A5=E5=85=B7=20(#8666)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 新增ping、telnet系统工具 * perf: 消息返回 Co-authored-by: halo --- apps/jumpserver/routing.py | 4 +- apps/settings/urls/ws_urls.py | 9 ++ apps/settings/utils/__init__.py | 2 + apps/settings/utils/ping.py | 154 ++++++++++++++++++++++++++++++++ apps/settings/utils/telnet.py | 25 ++++++ apps/settings/ws.py | 77 ++++++++++++++++ 6 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 apps/settings/urls/ws_urls.py create mode 100644 apps/settings/utils/ping.py create mode 100644 apps/settings/utils/telnet.py create mode 100644 apps/settings/ws.py diff --git a/apps/jumpserver/routing.py b/apps/jumpserver/routing.py index 1d1de2230..773baee99 100644 --- a/apps/jumpserver/routing.py +++ b/apps/jumpserver/routing.py @@ -4,10 +4,10 @@ from django.core.asgi import get_asgi_application from ops.urls.ws_urls import urlpatterns as ops_urlpatterns from notifications.urls.ws_urls import urlpatterns as notifications_urlpatterns +from settings.urls.ws_urls import urlpatterns as setting_urlpatterns urlpatterns = [] -urlpatterns += ops_urlpatterns \ - + notifications_urlpatterns +urlpatterns += ops_urlpatterns + notifications_urlpatterns + setting_urlpatterns application = ProtocolTypeRouter({ 'websocket': AuthMiddlewareStack( diff --git a/apps/settings/urls/ws_urls.py b/apps/settings/urls/ws_urls.py new file mode 100644 index 000000000..b1555c957 --- /dev/null +++ b/apps/settings/urls/ws_urls.py @@ -0,0 +1,9 @@ +from django.urls import path + +from .. import ws + +app_name = 'common' + +urlpatterns = [ + path('ws/setting/tools/', ws.ToolsWebsocket.as_asgi(), name='setting-tools-ws'), +] diff --git a/apps/settings/utils/__init__.py b/apps/settings/utils/__init__.py index e17c4e43c..0927bde18 100644 --- a/apps/settings/utils/__init__.py +++ b/apps/settings/utils/__init__.py @@ -3,3 +3,5 @@ from .ldap import * from .common import * +from .ping import * +from .telnet import * diff --git a/apps/settings/utils/ping.py b/apps/settings/utils/ping.py new file mode 100644 index 000000000..409edc83a --- /dev/null +++ b/apps/settings/utils/ping.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +# + +import os +import select +import socket +import struct +import time + +# From /usr/include/linux/icmp.h; your milage may vary. +ICMP_ECHO_REQUEST = 8 # Seems to be the same on Solaris. + + +def checksum(source_string): + """ + I'm not too confident that this is right but testing seems + to suggest that it gives the same answers as in_cksum in ping.c + """ + sum = 0 + count_to = int((len(source_string) / 2) * 2) + for count in range(0, count_to, 2): + this = source_string[count + 1] * 256 + source_string[count] + sum = sum + this + sum = sum & 0xffffffff # Necessary? + + if count_to < len(source_string): + sum = sum + ord(source_string[len(source_string) - 1]) + sum = sum & 0xffffffff # Necessary? + + sum = (sum >> 16) + (sum & 0xffff) + sum = sum + (sum >> 16) + answer = ~sum + answer = answer & 0xffff + + # Swap bytes. Bugger me if I know why. + answer = answer >> 8 | (answer << 8 & 0xff00) + + return answer + + +def receive_one_ping(my_socket, id, timeout): + """ + Receive the ping from the socket. + """ + time_left = timeout + while True: + started_select = time.time() + what_ready = select.select([my_socket], [], [], time_left) + how_long_in_select = time.time() - started_select + if not what_ready[0]: # Timeout + return + + time_received = time.time() + received_packet, addr = my_socket.recvfrom(1024) + icmpHeader = received_packet[20:28] + type, code, checksum, packet_id, sequence = struct.unpack("bbHHh", icmpHeader) + if packet_id == id: + bytes = struct.calcsize("d") + time_sent = struct.unpack("d", received_packet[28: 28 + bytes])[0] + return time_received - time_sent + + time_left = time_left - how_long_in_select + if time_left <= 0: + return + + +def send_one_ping(my_socket, dest_addr, id, psize): + """ + Send one ping to the given >dest_addr<. + """ + dest_addr = socket.gethostbyname(dest_addr) + + # Remove header size from packet size + # psize = psize - 8 + # laixintao edit: + # Do not need to remove header here. From BSD ping man: + # The default is 56, which translates into 64 ICMP data + # bytes when combined with the 8 bytes of ICMP header data. + + # Header is type (8), code (8), checksum (16), id (16), sequence (16) + my_checksum = 0 + + # Make a dummy heder with a 0 checksum. + header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, my_checksum, id, 1) + bytes = struct.calcsize("d") + data = (psize - bytes) * b"Q" + data = struct.pack("d", time.time()) + data + + # Calculate the checksum on the data and the dummy header. + my_checksum = checksum(header + data) + + # Now that we have the right checksum, we put that in. It's just easier + # to make up a new header than to stuff it into the dummy. + header = struct.pack( + "bbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), id, 1 + ) + packet = header + data + my_socket.sendto(packet, (dest_addr, 1)) # Don't know about the 1 + + +def ping(dest_addr, timeout, psize, flag=0): + """ + Returns either the delay (in seconds) or none on timeout. + """ + icmp = socket.getprotobyname("icmp") + try: + if os.getuid() != 0: + my_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, icmp) + else: + my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp) + except socket.error as e: + if e.errno == 1: + # Operation not permitted + msg = str(e) + raise socket.error(msg) + raise # raise the original error + + process_pre = os.getpid() & 0xFF00 + flag = flag & 0x00FF + my_id = process_pre | flag + + send_one_ping(my_socket, dest_addr, my_id, psize) + delay = receive_one_ping(my_socket, my_id, timeout) + + my_socket.close() + return delay + + +def verbose_ping(dest_addr, timeout=2, count=5, psize=64): + """ + Send `count' ping with `psize' size to `dest_addr' with + the given `timeout' and display the result. + """ + for i in range(count): + print("ping %s with ..." % dest_addr, end="") + try: + delay = ping(dest_addr, timeout, psize) + except socket.gaierror as e: + print("failed. (socket error: '%s')" % str(e)) + break + + if delay is None: + print("failed. (timeout within %ssec.)" % timeout) + else: + delay = delay * 1000 + print("get ping in %0.4fms" % delay) + print() + + +if __name__ == "__main__": + verbose_ping("google.com") + verbose_ping("192.168.4.1") + verbose_ping("www.baidu.com") + verbose_ping("sssssss") diff --git a/apps/settings/utils/telnet.py b/apps/settings/utils/telnet.py new file mode 100644 index 000000000..9785b43ae --- /dev/null +++ b/apps/settings/utils/telnet.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# +import socket +import telnetlib + +PROMPT_REGEX = r'[\<|\[](.*)[\>|\]]' + + +def telnet(dest_addr, port_number=23, timeout=10): + try: + connection = telnetlib.Telnet(dest_addr, port_number, timeout) + except (ConnectionRefusedError, socket.timeout, socket.gaierror) as e: + return False, str(e) + expected_regexes = [bytes(PROMPT_REGEX, encoding='ascii')] + index, prompt_regex, output = connection.expect(expected_regexes, timeout=3) + return True, output.decode('ascii') + + +if __name__ == "__main__": + print(telnet(dest_addr='1.1.1.1', port_number=2222)) + print(telnet(dest_addr='baidu.com', port_number=80)) + print(telnet(dest_addr='baidu.com', port_number=8080)) + print(telnet(dest_addr='192.168.4.1', port_number=2222)) + print(telnet(dest_addr='192.168.4.1', port_number=2223)) + print(telnet(dest_addr='ssssss', port_number=-1)) diff --git a/apps/settings/ws.py b/apps/settings/ws.py new file mode 100644 index 000000000..3455abe2b --- /dev/null +++ b/apps/settings/ws.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# + +import json + +from channels.generic.websocket import JsonWebsocketConsumer + +from common.db.utils import close_old_connections +from common.utils import get_logger +from .utils import ping, telnet + +logger = get_logger(__name__) + + +class ToolsWebsocket(JsonWebsocketConsumer): + + def connect(self): + user = self.scope["user"] + if user.is_authenticated: + self.accept() + else: + self.close() + + def imitate_ping(self, dest_addr, timeout=3, count=5, psize=64): + """ + Send `count' ping with `psize' size to `dest_addr' with + the given `timeout' and display the result. + """ + logger.info('receive request ping {}'.format(dest_addr)) + self.send_json({'msg': 'Trying {0}...\r\n'.format(dest_addr)}) + for i in range(count): + msg = 'ping {0} with ...{1}\r\n' + try: + delay = ping(dest_addr, timeout, psize) + except Exception as e: + msg = msg.format(dest_addr, 'failed. (socket error: {})'.format(str(e))) + logger.error(msg) + self.send_json({'msg': msg}) + break + if delay is None: + msg = msg.format(dest_addr, 'failed. (timeout within {}sec.)'.format(timeout)) + else: + delay = delay * 1000 + msg = msg.format(dest_addr, 'get ping in %0.4fms' % delay) + self.send_json({'msg': msg}) + + def imitate_telnet(self, dest_addr, port_num=23, timeout=10): + logger.info('receive request telnet {}'.format(dest_addr)) + self.send_json({'msg': 'Trying {0} {1}...\r\n'.format(dest_addr, port_num)}) + msg = 'Telnet: {}' + try: + is_connective, resp = telnet(dest_addr, port_num, timeout) + if is_connective: + msg = msg.format('Connected to {0} {1}\r\n{2}'.format(dest_addr, port_num, resp)) + else: + msg = msg.format('Connect to {0} {1} {2}\r\nTelnet: Unable to connect to remote host' + .format(dest_addr, port_num, resp)) + except Exception as e: + logger.error(msg) + msg = msg.format(str(e)) + finally: + self.send_json({'msg': msg}) + + def receive(self, text_data=None, bytes_data=None, **kwargs): + data = json.loads(text_data) + tool_type = data.get('tool_type', 'Ping') + dest_addr = data.get('dest_addr') + if tool_type == 'Ping': + self.imitate_ping(dest_addr) + else: + port_num = data.get('port_num') + self.imitate_telnet(dest_addr, port_num) + self.close() + + def disconnect(self, code): + self.close() + close_old_connections() From 429e83897397acff7d64c00f12cda281c20fdfcc Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 29 Jul 2022 11:37:16 +0800 Subject: [PATCH 052/104] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=99=BB=E5=BD=95ACL=E6=A0=B9=E6=8D=AE=E8=A7=84?= =?UTF-8?q?=E5=88=99=E4=BC=98=E5=85=88=E7=BA=A7=E8=BF=9B=E8=A1=8C=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=20(#8672)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf: 优化用户登录ACL根据规则优先级进行匹配 * perf: 修改冲突 Co-authored-by: Jiangjie.Bai Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com> --- apps/acls/models/login_acl.py | 61 +++++------------ apps/authentication/errors/failed.py | 11 +--- apps/authentication/mixins.py | 97 +++++++++++++++------------- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 26 ++++---- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 26 ++++---- 7 files changed, 98 insertions(+), 131 deletions(-) diff --git a/apps/acls/models/login_acl.py b/apps/acls/models/login_acl.py index 1887ecd33..6fcff0231 100644 --- a/apps/acls/models/login_acl.py +++ b/apps/acls/models/login_acl.py @@ -44,58 +44,29 @@ class LoginACL(BaseACL): def __str__(self): return self.name - @property - def action_reject(self): - return self.action == self.ActionChoices.reject - - @property - def action_allow(self): - return self.action == self.ActionChoices.allow + def is_action(self, action): + return self.action == action @classmethod def filter_acl(cls, user): return user.login_acls.all().valid().distinct() @staticmethod - def allow_user_confirm_if_need(user, ip): - acl = LoginACL.filter_acl(user).filter( - action=LoginACL.ActionChoices.confirm - ).first() - acl = acl if acl and acl.reviewers.exists() else None - if not acl: - return False, acl - ip_group = acl.rules.get('ip_group') - time_periods = acl.rules.get('time_period') - is_contain_ip = contains_ip(ip, ip_group) - is_contain_time_period = contains_time_period(time_periods) - return is_contain_ip and is_contain_time_period, acl + def match(user, ip): + acls = LoginACL.filter_acl(user) + if not acls: + return - @staticmethod - def allow_user_to_login(user, ip): - acl = LoginACL.filter_acl(user).exclude( - action=LoginACL.ActionChoices.confirm - ).first() - if not acl: - return True, '' - ip_group = acl.rules.get('ip_group') - time_periods = acl.rules.get('time_period') - is_contain_ip = contains_ip(ip, ip_group) - is_contain_time_period = contains_time_period(time_periods) - - reject_type = '' - if is_contain_ip and is_contain_time_period: - # 满足条件 - allow = acl.action_allow - if not allow: - reject_type = 'ip' if is_contain_ip else 'time' - else: - # 不满足条件 - # 如果acl本身允许,那就拒绝;如果本身拒绝,那就允许 - allow = not acl.action_allow - if not allow: - reject_type = 'ip' if not is_contain_ip else 'time' - - return allow, reject_type + for acl in acls: + if acl.is_action(LoginACL.ActionChoices.confirm) and not acl.reviewers.exists(): + continue + ip_group = acl.rules.get('ip_group') + time_periods = acl.rules.get('time_period') + is_contain_ip = contains_ip(ip, ip_group) + is_contain_time_period = contains_time_period(time_periods) + if is_contain_ip and is_contain_time_period: + # 满足条件,则返回 + return acl def create_confirm_ticket(self, request): from tickets import const diff --git a/apps/authentication/errors/failed.py b/apps/authentication/errors/failed.py index 118fd6d6e..cd3274094 100644 --- a/apps/authentication/errors/failed.py +++ b/apps/authentication/errors/failed.py @@ -138,18 +138,11 @@ class ACLError(AuthFailedNeedLogMixin, AuthFailedError): } -class LoginIPNotAllowed(ACLError): +class LoginACLNotAllowed(ACLError): def __init__(self, username, request, **kwargs): self.username = username self.request = request - super().__init__(_("IP is not allowed"), **kwargs) - - -class TimePeriodNotAllowed(ACLError): - def __init__(self, username, request, **kwargs): - self.username = username - self.request = request - super().__init__(_("Time Period is not allowed"), **kwargs) + super().__init__(_("ACL is not allowed"), **kwargs) class MFACodeRequiredError(AuthFailedError): diff --git a/apps/authentication/mixins.py b/apps/authentication/mixins.py index 403f7186d..af51f2f2d 100644 --- a/apps/authentication/mixins.py +++ b/apps/authentication/mixins.py @@ -328,13 +328,56 @@ class AuthACLMixin: def _check_login_acl(self, user, ip): # ACL 限制用户登录 - is_allowed, limit_type = LoginACL.allow_user_to_login(user, ip) - if is_allowed: + acl = LoginACL.match(user, ip) + if not acl: return - if limit_type == 'ip': - raise errors.LoginIPNotAllowed(username=user.username, request=self.request) - elif limit_type == 'time': - raise errors.TimePeriodNotAllowed(username=user.username, request=self.request) + + acl: LoginACL + if acl.is_action(acl.ActionChoices.allow): + return + + if acl.is_action(acl.ActionChoices.reject): + raise errors.LoginACLNotAllowed(username=user.username, request=self.request) + + if acl.is_action(acl.ActionChoices.confirm): + self.request.session['auth_confirm_required'] = '1' + self.request.session['auth_acl_id'] = str(acl.id) + return + + def check_user_login_confirm_if_need(self, user): + if not self.request.session.get("auth_confirm_required"): + return + acl_id = self.request.session.get('auth_acl_id') + logger.debug('Login confirm acl id: {}'.format(acl_id)) + if not acl_id: + return + acl = LoginACL.filter_acl(user).filter(id=acl_id).first() + if not acl: + return + if not acl.is_action(acl.ActionChoices.confirm): + return + self.get_ticket_or_create(acl) + self.check_user_login_confirm() + + def get_ticket_or_create(self, acl): + ticket = self.get_ticket() + if not ticket or ticket.is_state(ticket.State.closed): + ticket = acl.create_confirm_ticket(self.request) + self.request.session['auth_ticket_id'] = str(ticket.id) + return ticket + + def check_user_login_confirm(self): + ticket = self.get_ticket() + if not ticket: + raise errors.LoginConfirmOtherError('', "Not found") + elif ticket.is_state(ticket.State.approved): + self.request.session["auth_confirm_required"] = '' + return + elif ticket.is_status(ticket.Status.open): + raise errors.LoginConfirmWaitError(ticket.id) + else: + # rejected, closed + raise errors.LoginConfirmOtherError(ticket.id, ticket.get_state_display()) def get_ticket(self): from tickets.models import ApplyLoginTicket @@ -346,44 +389,6 @@ class AuthACLMixin: ticket = ApplyLoginTicket.all().filter(id=ticket_id).first() return ticket - def get_ticket_or_create(self, confirm_setting): - ticket = self.get_ticket() - if not ticket or ticket.is_status(ticket.Status.closed): - ticket = confirm_setting.create_confirm_ticket(self.request) - self.request.session['auth_ticket_id'] = str(ticket.id) - return ticket - - def check_user_login_confirm(self): - ticket = self.get_ticket() - if not ticket: - raise errors.LoginConfirmOtherError('', "Not found") - - if ticket.is_status(ticket.Status.open): - raise errors.LoginConfirmWaitError(ticket.id) - elif ticket.is_state(ticket.State.approved): - self.request.session["auth_confirm"] = "1" - return - elif ticket.is_state(ticket.State.rejected): - raise errors.LoginConfirmOtherError( - ticket.id, ticket.get_state_display() - ) - elif ticket.is_state(ticket.State.closed): - raise errors.LoginConfirmOtherError( - ticket.id, ticket.get_state_display() - ) - else: - raise errors.LoginConfirmOtherError( - ticket.id, ticket.get_status_display() - ) - - def check_user_login_confirm_if_need(self, user): - ip = self.get_request_ip() - is_allowed, confirm_setting = LoginACL.allow_user_confirm_if_need(user, ip) - if self.request.session.get('auth_confirm') or not is_allowed: - return - self.get_ticket_or_create(confirm_setting) - self.check_user_login_confirm() - class AuthMixin(CommonMixin, AuthPreCheckMixin, AuthACLMixin, MFAMixin, AuthPostCheckMixin): request = None @@ -482,7 +487,9 @@ class AuthMixin(CommonMixin, AuthPreCheckMixin, AuthACLMixin, MFAMixin, AuthPost return self.check_user_auth(valid_data) def clear_auth_mark(self): - keys = ['auth_password', 'user_id', 'auth_confirm', 'auth_ticket_id'] + keys = [ + 'auth_password', 'user_id', 'auth_confirm_required', 'auth_ticket_id', 'auth_acl_id' + ] for k in keys: self.request.session.pop(k, '') diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index a74e1daed..b3b599833 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ff3ae18c27279b8783eba9e85b270f9c3da63f812da315ba210877b33b960a8 -size 128908 +oid sha256:322701b975fe90b4b187c4a99ddd1837291150502c82accf0a4c6e32dddf91be +size 128721 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 7668705cc..3b3f1d7d6 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-28 13:43+0800\n" +"POT-Creation-Date: 2022-07-29 10:56+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -80,7 +80,7 @@ msgstr "拒否" msgid "Allow" msgstr "許可" -#: acls/models/login_acl.py:20 acls/models/login_acl.py:104 +#: acls/models/login_acl.py:20 acls/models/login_acl.py:75 #: acls/models/login_asset_acl.py:17 tickets/const.py:9 msgid "Login confirm" msgstr "ログイン確認" @@ -1915,7 +1915,7 @@ msgstr "このアカウントは期限切れです" msgid "Auth backend not match" msgstr "Authバックエンドが一致しない" -#: authentication/errors/const.py:28 +#: authentication/errors/const.py:28 authentication/errors/failed.py:145 msgid "ACL is not allowed" msgstr "ACLは許可されません" @@ -1983,23 +1983,15 @@ msgstr "受け入れのためのログイン確認チケットを待つ" msgid "Login confirm ticket was {}" msgstr "ログイン確認チケットは {} でした" -#: authentication/errors/failed.py:145 -msgid "IP is not allowed" -msgstr "IPは許可されていません" - -#: authentication/errors/failed.py:152 -msgid "Time Period is not allowed" -msgstr "期間は許可されていません" - -#: authentication/errors/failed.py:157 +#: authentication/errors/failed.py:150 msgid "Please enter MFA code" msgstr "MFAコードを入力してください" -#: authentication/errors/failed.py:162 +#: authentication/errors/failed.py:155 msgid "Please enter SMS code" msgstr "SMSコードを入力してください" -#: authentication/errors/failed.py:167 users/exceptions.py:15 +#: authentication/errors/failed.py:160 users/exceptions.py:15 msgid "Phone not set" msgstr "電話が設定されていない" @@ -6863,5 +6855,11 @@ msgstr "究極のエディション" msgid "Community edition" msgstr "コミュニティ版" +#~ msgid "IP is not allowed" +#~ msgstr "IPは許可されていません" + +#~ msgid "Time Period is not allowed" +#~ msgstr "期間は許可されていません" + #~ msgid "User cannot self-update fields: {}" #~ msgstr "ユーザーは自分のフィールドを更新できません: {}" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 841d1186d..26e44a3d7 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c10c6bd05e79bc462db9863136e538978e5ca2644c6fd228050603135559d83 -size 106223 +oid sha256:9ed12e275e241284573d49c752cf01bafddb912dfe38ae2888a62e62cdb30ebd +size 106084 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index dab498f08..99fba8067 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-28 13:43+0800\n" +"POT-Creation-Date: 2022-07-29 10:56+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -79,7 +79,7 @@ msgstr "拒绝" msgid "Allow" msgstr "允许" -#: acls/models/login_acl.py:20 acls/models/login_acl.py:104 +#: acls/models/login_acl.py:20 acls/models/login_acl.py:75 #: acls/models/login_asset_acl.py:17 tickets/const.py:9 msgid "Login confirm" msgstr "登录复核" @@ -1901,7 +1901,7 @@ msgstr "此账号已过期" msgid "Auth backend not match" msgstr "没有匹配到认证后端" -#: authentication/errors/const.py:28 +#: authentication/errors/const.py:28 authentication/errors/failed.py:145 msgid "ACL is not allowed" msgstr "ACL 不被允许" @@ -1963,23 +1963,15 @@ msgstr "等待登录复核处理" msgid "Login confirm ticket was {}" msgstr "登录复核: {}" -#: authentication/errors/failed.py:145 -msgid "IP is not allowed" -msgstr "来源 IP 不被允许登录" - -#: authentication/errors/failed.py:152 -msgid "Time Period is not allowed" -msgstr "该 时间段 不被允许登录" - -#: authentication/errors/failed.py:157 +#: authentication/errors/failed.py:150 msgid "Please enter MFA code" msgstr "请输入 MFA 验证码" -#: authentication/errors/failed.py:162 +#: authentication/errors/failed.py:155 msgid "Please enter SMS code" msgstr "请输入短信验证码" -#: authentication/errors/failed.py:167 users/exceptions.py:15 +#: authentication/errors/failed.py:160 users/exceptions.py:15 msgid "Phone not set" msgstr "手机号没有设置" @@ -6766,5 +6758,11 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" +#~ msgid "IP is not allowed" +#~ msgstr "来源 IP 不被允许登录" + +#~ msgid "Time Period is not allowed" +#~ msgstr "该 时间段 不被允许登录" + #~ msgid "User cannot self-update fields: {}" #~ msgstr "用户不能更新自己的字段: {}" From e8b4ee5c40a55daf03f4633547153d5a55d8575f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=B9=BF?= Date: Thu, 28 Jul 2022 15:36:09 +0800 Subject: [PATCH 053/104] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 70dac07d1..f46836725 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ -JumpServer 是全球首款开源的堡垒机,使用 GPLv3 开源协议,是符合 4A 规范的运维安全审计系统。 +JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。 JumpServer 使用 Python 开发,配备了业界领先的 Web Terminal 方案,交互界面美观、用户体验好。 From 9319c4748c001226aebaaf24272d17feec428102 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Tue, 2 Aug 2022 14:28:58 +0800 Subject: [PATCH 054/104] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=99=BB=E5=BD=95=20ACL=20=E7=BF=BB=E8=AF=91=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/errors/failed.py | 4 ++-- apps/authentication/mixins.py | 2 +- apps/locale/ja/LC_MESSAGES/django.po | 13 +++++++------ apps/locale/zh/LC_MESSAGES/django.po | 13 +++++++------ 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/apps/authentication/errors/failed.py b/apps/authentication/errors/failed.py index cd3274094..93efebf78 100644 --- a/apps/authentication/errors/failed.py +++ b/apps/authentication/errors/failed.py @@ -138,11 +138,11 @@ class ACLError(AuthFailedNeedLogMixin, AuthFailedError): } -class LoginACLNotAllowed(ACLError): +class LoginACLIPAndTimePeriodNotAllowed(ACLError): def __init__(self, username, request, **kwargs): self.username = username self.request = request - super().__init__(_("ACL is not allowed"), **kwargs) + super().__init__(_("Current IP and Time period is not allowed"), **kwargs) class MFACodeRequiredError(AuthFailedError): diff --git a/apps/authentication/mixins.py b/apps/authentication/mixins.py index af51f2f2d..739048d75 100644 --- a/apps/authentication/mixins.py +++ b/apps/authentication/mixins.py @@ -337,7 +337,7 @@ class AuthACLMixin: return if acl.is_action(acl.ActionChoices.reject): - raise errors.LoginACLNotAllowed(username=user.username, request=self.request) + raise errors.LoginACLIPAndTimePeriodNotAllowed(user.username, request=self.request) if acl.is_action(acl.ActionChoices.confirm): self.request.session['auth_confirm_required'] = '1' diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 3b3f1d7d6..0dfe25a4a 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-29 10:56+0800\n" +"POT-Creation-Date: 2022-08-02 11:39+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1915,9 +1915,9 @@ msgstr "このアカウントは期限切れです" msgid "Auth backend not match" msgstr "Authバックエンドが一致しない" -#: authentication/errors/const.py:28 authentication/errors/failed.py:145 +#: authentication/errors/const.py:28 msgid "ACL is not allowed" -msgstr "ACLは許可されません" +msgstr "ログイン アクセス制御は許可されません" #: authentication/errors/const.py:29 msgid "Only local users are allowed" @@ -1983,6 +1983,10 @@ msgstr "受け入れのためのログイン確認チケットを待つ" msgid "Login confirm ticket was {}" msgstr "ログイン確認チケットは {} でした" +#: authentication/errors/failed.py:145 +msgid "Current IP and Time period is not allowed" +msgstr "現在の IP と期間はログインを許可されていません" + #: authentication/errors/failed.py:150 msgid "Please enter MFA code" msgstr "MFAコードを入力してください" @@ -6858,8 +6862,5 @@ msgstr "コミュニティ版" #~ msgid "IP is not allowed" #~ msgstr "IPは許可されていません" -#~ msgid "Time Period is not allowed" -#~ msgstr "期間は許可されていません" - #~ msgid "User cannot self-update fields: {}" #~ msgstr "ユーザーは自分のフィールドを更新できません: {}" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 99fba8067..c8320846f 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-29 10:56+0800\n" +"POT-Creation-Date: 2022-08-02 11:39+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -1901,9 +1901,9 @@ msgstr "此账号已过期" msgid "Auth backend not match" msgstr "没有匹配到认证后端" -#: authentication/errors/const.py:28 authentication/errors/failed.py:145 +#: authentication/errors/const.py:28 msgid "ACL is not allowed" -msgstr "ACL 不被允许" +msgstr "登录访问控制不被允许" #: authentication/errors/const.py:29 msgid "Only local users are allowed" @@ -1963,6 +1963,10 @@ msgstr "等待登录复核处理" msgid "Login confirm ticket was {}" msgstr "登录复核: {}" +#: authentication/errors/failed.py:145 +msgid "Current IP and Time period is not allowed" +msgstr "当前 IP 和时间段不被允许登录" + #: authentication/errors/failed.py:150 msgid "Please enter MFA code" msgstr "请输入 MFA 验证码" @@ -6761,8 +6765,5 @@ msgstr "社区版" #~ msgid "IP is not allowed" #~ msgstr "来源 IP 不被允许登录" -#~ msgid "Time Period is not allowed" -#~ msgstr "该 时间段 不被允许登录" - #~ msgid "User cannot self-update fields: {}" #~ msgstr "用户不能更新自己的字段: {}" From 9ff345747bbb0f7a2317e8743a2e76a240f1c2c8 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Tue, 2 Aug 2022 14:47:53 +0800 Subject: [PATCH 055/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=B9=B3=E5=8F=B0=E4=B8=8D=E8=83=BD=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset.py | 4 ++-- apps/assets/serializers/asset.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/assets/api/asset.py b/apps/assets/api/asset.py index 3f4b7a209..f8c2ab179 100644 --- a/apps/assets/api/asset.py +++ b/apps/assets/api/asset.py @@ -6,7 +6,7 @@ from django.shortcuts import get_object_or_404 from django.db.models import Q from common.utils import get_logger, get_object_or_none -from common.mixins.api import SuggestionMixin +from common.mixins.api import SuggestionMixin, RenderToJsonMixin from users.models import User, UserGroup from users.serializers import UserSerializer, UserGroupSerializer from users.filters import UserFilter @@ -88,7 +88,7 @@ class AssetPlatformRetrieveApi(RetrieveAPIView): return asset.platform -class AssetPlatformViewSet(ModelViewSet): +class AssetPlatformViewSet(ModelViewSet, RenderToJsonMixin): queryset = Platform.objects.all() serializer_class = serializers.PlatformSerializer filterset_fields = ['name', 'base'] diff --git a/apps/assets/serializers/asset.py b/apps/assets/serializers/asset.py index 427d0e470..5211cfef6 100644 --- a/apps/assets/serializers/asset.py +++ b/apps/assets/serializers/asset.py @@ -189,6 +189,9 @@ class PlatformSerializer(serializers.ModelSerializer): 'id', 'name', 'base', 'charset', 'internal', 'meta', 'comment' ] + extra_kwargs = { + 'internal': {'read_only': True}, + } class AssetSimpleSerializer(serializers.ModelSerializer): From 40f8b99242faf1a3a0eefc76c8bdd66624217c41 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Tue, 2 Aug 2022 16:39:21 +0800 Subject: [PATCH 056/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E8=B5=84=E4=BA=A7=E8=B4=A6=E5=8F=B7=E4=B8=8D=E6=88=90?= =?UTF-8?q?=E5=8A=9F=E7=9A=84=E9=97=AE=E9=A2=98(=E6=9C=AB=E5=B0=BE:)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/utils/crypto.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/common/utils/crypto.py b/apps/common/utils/crypto.py index 0c818ec5b..3922a5462 100644 --- a/apps/common/utils/crypto.py +++ b/apps/common/utils/crypto.py @@ -255,6 +255,8 @@ def decrypt_password(value): if len(cipher) != 2: return value key_cipher, password_cipher = cipher + if not all([key_cipher, password_cipher]): + return value aes_key = rsa_decrypt_by_session_pkey(key_cipher) aes = get_aes_crypto(aes_key, 'ECB') try: From 3e7f83d44e5f3a4313dafd15ed72c47b221aea80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Chuailei000=E2=80=9D?= <2280131253@qq.com> Date: Tue, 2 Aug 2022 16:31:46 +0800 Subject: [PATCH 057/104] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E5=BF=98?= =?UTF-8?q?=E8=AE=B0=E5=AF=86=E7=A0=81=E9=A1=B5=E5=B8=83=E5=B1=80=E9=94=99?= =?UTF-8?q?=E4=BD=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/users/templates/users/forgot_password.html | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/users/templates/users/forgot_password.html b/apps/users/templates/users/forgot_password.html index 8289726f3..16c784250 100644 --- a/apps/users/templates/users/forgot_password.html +++ b/apps/users/templates/users/forgot_password.html @@ -6,6 +6,7 @@ +
+

+

+ {% if error %} + {{ error }} + {% else %} + {{ message|safe }} + {% endif %} +
+

+ + +
+{% endblock %} + +{% block custom_foot_js %} + +{% endblock %} + diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index 803315f9c..9ab01b6a1 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -205,6 +205,7 @@ AUTHENTICATION_BACKENDS = [ AUTH_BACKEND_AUTH_TOKEN, AUTH_BACKEND_SSO, AUTH_BACKEND_TEMP_TOKEN ] +AUTHENTICATION_BACKENDS_THIRD_PARTY = [AUTH_BACKEND_OIDC_CODE, AUTH_BACKEND_CAS, AUTH_BACKEND_SAML2] ONLY_ALLOW_EXIST_USER_AUTH = CONFIG.ONLY_ALLOW_EXIST_USER_AUTH ONLY_ALLOW_AUTH_FROM_SOURCE = CONFIG.ONLY_ALLOW_AUTH_FROM_SOURCE diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index 547aa9c1b..a65266a1f 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -109,6 +109,7 @@ MIDDLEWARE = [ 'authentication.backends.oidc.middleware.OIDCRefreshIDTokenMiddleware', 'authentication.backends.cas.middleware.CASMiddleware', 'authentication.middleware.MFAMiddleware', + 'authentication.middleware.ThirdPartyLoginMiddleware', 'authentication.middleware.SessionCookieMiddleware', 'simple_history.middleware.HistoryRequestMiddleware', ] From 6a30e0739d37cc9a48103181508a919f0b770005 Mon Sep 17 00:00:00 2001 From: huangzhiwen Date: Tue, 9 Aug 2022 11:31:04 +0800 Subject: [PATCH 067/104] =?UTF-8?q?feat:=20OAuth2.0=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E5=8A=A0=E4=B8=8A=E7=94=A8=E6=88=B7=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E8=A7=84=E5=88=99=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/settings/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index 9ab01b6a1..0270913b0 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -205,7 +205,7 @@ AUTHENTICATION_BACKENDS = [ AUTH_BACKEND_AUTH_TOKEN, AUTH_BACKEND_SSO, AUTH_BACKEND_TEMP_TOKEN ] -AUTHENTICATION_BACKENDS_THIRD_PARTY = [AUTH_BACKEND_OIDC_CODE, AUTH_BACKEND_CAS, AUTH_BACKEND_SAML2] +AUTHENTICATION_BACKENDS_THIRD_PARTY = [AUTH_BACKEND_OIDC_CODE, AUTH_BACKEND_CAS, AUTH_BACKEND_SAML2, AUTH_BACKEND_OAUTH2] ONLY_ALLOW_EXIST_USER_AUTH = CONFIG.ONLY_ALLOW_EXIST_USER_AUTH ONLY_ALLOW_AUTH_FROM_SOURCE = CONFIG.ONLY_ALLOW_AUTH_FROM_SOURCE From 708a87c903384865adf966d37b02306474eada1b Mon Sep 17 00:00:00 2001 From: jiangweidong <80373698+F2C-Jiang@users.noreply.github.com> Date: Tue, 9 Aug 2022 16:09:20 +0800 Subject: [PATCH 068/104] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81CMPPv2.0?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE=E7=9F=AD=E4=BF=A1=E7=BD=91=E5=85=B3=20(#8591?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 支持CMPPv2.0协议短信网关 * 修改翻译 Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com> --- apps/common/sdk/sms/base.py | 4 + apps/common/sdk/sms/cmpp2.py | 322 ++++++++++++++++++++++++++ apps/common/sdk/sms/endpoint.py | 3 +- apps/jumpserver/conf.py | 9 + apps/locale/ja/LC_MESSAGES/django.po | 153 +++++++----- apps/locale/zh/LC_MESSAGES/django.po | 152 +++++++----- apps/settings/api/__init__.py | 2 - apps/settings/api/alibaba_sms.py | 58 ----- apps/settings/api/settings.py | 1 + apps/settings/api/sms.py | 118 +++++++++- apps/settings/api/tencent_sms.py | 63 ----- apps/settings/serializers/auth/sms.py | 33 ++- apps/settings/serializers/settings.py | 3 +- apps/settings/urls/api_urls.py | 3 +- 14 files changed, 686 insertions(+), 238 deletions(-) create mode 100644 apps/common/sdk/sms/cmpp2.py delete mode 100644 apps/settings/api/alibaba_sms.py delete mode 100644 apps/settings/api/tencent_sms.py diff --git a/apps/common/sdk/sms/base.py b/apps/common/sdk/sms/base.py index 4d02370b1..77dcc669a 100644 --- a/apps/common/sdk/sms/base.py +++ b/apps/common/sdk/sms/base.py @@ -17,4 +17,8 @@ class BaseSMSClient: def send_sms(self, phone_numbers: list, sign_name: str, template_code: str, template_param: dict, **kwargs): raise NotImplementedError + @staticmethod + def need_pre_check(): + return True + diff --git a/apps/common/sdk/sms/cmpp2.py b/apps/common/sdk/sms/cmpp2.py new file mode 100644 index 000000000..8a6a4fe32 --- /dev/null +++ b/apps/common/sdk/sms/cmpp2.py @@ -0,0 +1,322 @@ +import hashlib +import socket +import struct +import time + +from django.conf import settings + +from common.utils import get_logger +from common.exceptions import JMSException +from .base import BaseSMSClient + + +logger = get_logger(__file__) + + +CMPP_CONNECT = 0x00000001 # 请求连接 +CMPP_CONNECT_RESP = 0x80000001 # 请求连接应答 +CMPP_TERMINATE = 0x00000002 # 终止连接 +CMPP_TERMINATE_RESP = 0x80000002 # 终止连接应答 +CMPP_SUBMIT = 0x00000004 # 提交短信 +CMPP_SUBMIT_RESP = 0x80000004 # 提交短信应答 +CMPP_DELIVER = 0x00000005 # 短信下发 +CMPP_DELIVER_RESP = 0x80000005 # 下发短信应答 + + +class CMPPBaseRequestInstance(object): + def __init__(self): + self.command_id = '' + self.body = b'' + self.length = 0 + + def get_header(self, sequence_id): + length = struct.pack('!L', 12 + self.length) + command_id = struct.pack('!L', self.command_id) + sequence_id = struct.pack('!L', sequence_id) + return length + command_id + sequence_id + + def get_message(self, sequence_id): + return self.get_header(sequence_id) + self.body + + +class CMPPConnectRequestInstance(CMPPBaseRequestInstance): + def __init__(self, sp_id, sp_secret): + if len(sp_id) != 6: + raise ValueError("sp_id and sp_secret are both 6 bits") + + super().__init__() + + source_addr = sp_id.encode('utf-8') + sp_secret = sp_secret.encode('utf-8') + version = struct.pack('!B', 0x02) + timestamp = struct.pack('!L', int(self.get_now())) + authenticator_source = source_addr + 9 * b'\x00' + sp_secret + self.get_now().encode('utf-8') + auth_source_md5 = hashlib.md5(authenticator_source).digest() + self.body = source_addr + auth_source_md5 + version + timestamp + self.length = len(self.body) + self.command_id = CMPP_CONNECT + + @staticmethod + def get_now(): + return time.strftime('%m%d%H%M%S', time.localtime(time.time())) + + +class CMPPSubmitRequestInstance(CMPPBaseRequestInstance): + def __init__(self, msg_src, dest_terminal_id, msg_content, src_id, + service_id='', dest_usr_tl=1): + if len(msg_content) >= 70: + raise JMSException('The message length should be within 70 characters') + if len(dest_terminal_id) > 100: + raise JMSException('The number of users receiving information should be less than 100') + + super().__init__() + + msg_id = 8 * b'\x00' + pk_total = struct.pack('!B', 1) + pk_number = struct.pack('!B', 1) + registered_delivery = struct.pack('!B', 0) + msg_level = struct.pack('!B', 0) + service_id = ((10 - len(service_id)) * '\x00' + service_id).encode('utf-8') + fee_user_type = struct.pack('!B', 2) + fee_terminal_id = ('0' * 21).encode('utf-8') + tp_pid = struct.pack('!B', 0) + tp_udhi = struct.pack('!B', 0) + msg_fmt = struct.pack('!B', 8) + fee_type = '01'.encode('utf-8') + fee_code = '000000'.encode('utf-8') + valid_time = ('\x00' * 17).encode('utf-8') + at_time = ('\x00' * 17).encode('utf-8') + src_id = ((21 - len(src_id)) * '\x00' + src_id).encode('utf-8') + reserve = b'\x00' * 8 + _msg_length = struct.pack('!B', len(msg_content) * 2) + _msg_src = msg_src.encode('utf-8') + _dest_usr_tl = struct.pack('!B', dest_usr_tl) + _msg_content = msg_content.encode('utf-16-be') + _dest_terminal_id = b''.join([ + (i + (21 - len(i)) * '\x00').encode('utf-8') for i in dest_terminal_id + ]) + self.length = 126 + 21 * dest_usr_tl + len(_msg_content) + self.command_id = CMPP_SUBMIT + self.body = msg_id + pk_total + pk_number + registered_delivery \ + + msg_level + service_id + fee_user_type + fee_terminal_id \ + + tp_pid + tp_udhi + msg_fmt + _msg_src + fee_type + fee_code \ + + valid_time + at_time + src_id + _dest_usr_tl + _dest_terminal_id \ + + _msg_length + _msg_content + reserve + + +class CMPPTerminateRequestInstance(CMPPBaseRequestInstance): + def __init__(self): + super().__init__() + self.body = b'' + self.command_id = CMPP_TERMINATE + + +class CMPPDeliverRespRequestInstance(CMPPBaseRequestInstance): + def __init__(self, msg_id, result=0): + super().__init__() + msg_id = struct.pack('!Q', msg_id) + result = struct.pack('!B', result) + self.length = len(self.body) + self.body = msg_id + result + + +class CMPPResponseInstance(object): + def __init__(self): + self.command_id = None + self.length = None + self.response_handler_map = { + CMPP_CONNECT_RESP: self.connect_response_parse, + CMPP_SUBMIT_RESP: self.submit_response_parse, + CMPP_DELIVER: self.deliver_request_parse, + } + + @staticmethod + def connect_response_parse(body): + status, = struct.unpack('!B', body[0:1]) + authenticator_ISMG = body[1:17] + version, = struct.unpack('!B', body[17:18]) + return { + 'Status': status, + 'AuthenticatorISMG': authenticator_ISMG, + 'Version': version + } + + @staticmethod + def submit_response_parse(body): + msg_id = body[:8] + result = struct.unpack('!B', body[8:9]) + return { + 'Msg_Id': msg_id, 'Result': result[0] + } + + @staticmethod + def deliver_request_parse(body): + msg_id, = struct.unpack('!Q', body[0:8]) + dest_id = body[8:29] + service_id = body[29:39] + tp_pid = struct.unpack('!B', body[39:40]) + tp_udhi = struct.unpack('!B', body[40:41]) + msg_fmt = struct.unpack('!B', body[41:42]) + src_terminal_id = body[42:63] + registered_delivery = struct.unpack('!B', body[63:64]) + msg_length = struct.unpack('!B', body[64:65]) + msg_content = body[65:msg_length[0]+65] + return { + 'Msg_Id': msg_id, 'Dest_Id': dest_id, 'Service_Id': service_id, + 'TP_pid': tp_pid, 'TP_udhi': tp_udhi, 'Msg_Fmt': msg_fmt, + 'Src_terminal_Id': src_terminal_id, 'Registered_Delivery': registered_delivery, + 'Msg_Length': msg_length, 'Msg_content': msg_content + } + + def parse_header(self, data): + self.command_id, = struct.unpack('!L', data[4:8]) + sequence_id, = struct.unpack('!L', data[8:12]) + return { + 'length': self.length, + 'command_id': hex(self.command_id), + 'sequence_id': sequence_id + } + + def parse_body(self, body): + response_body_func = self.response_handler_map.get(self.command_id) + if response_body_func is None: + raise JMSException('Unable to parse the returned result: %s' % body) + return response_body_func(body) + + def parse(self, data): + self.length, = struct.unpack('!L', data[0:4]) + header = self.parse_header(data) + body = self.parse_body(data[12:self.length]) + return header, body + + +class CMPPClient(object): + def __init__(self, host, port, sp_id, sp_secret, src_id, service_id): + self.ip = host + self.port = port + self.sp_id = sp_id + self.sp_secret = sp_secret + self.src_id = src_id + self.service_id = service_id + self._sequence_id = 0 + self._is_connect = False + self._times = 3 + self.__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self._connect() + + @property + def sequence_id(self): + s = self._sequence_id + self._sequence_id += 1 + return s + + def _connect(self): + self.__socket.settimeout(5) + for i in range(self._times): + try: + self.__socket.connect((self.ip, self.port)) + except socket.timeout: + time.sleep(1) + else: + self._is_connect = True + break + + def send(self, instance): + if isinstance(instance, CMPPBaseRequestInstance): + message = instance.get_message(sequence_id=self.sequence_id) + else: + message = instance + self.__socket.send(message) + + def recv(self): + raw_length = self.__socket.recv(4) + length, = struct.unpack('!L', raw_length) + header, body = CMPPResponseInstance().parse( + raw_length + self.__socket.recv(length - 4) + ) + return header, body + + def close(self): + if self._is_connect: + terminate_request = CMPPTerminateRequestInstance() + self.send(terminate_request) + self.__socket.close() + + def _cmpp_connect(self): + connect_request = CMPPConnectRequestInstance(self.sp_id, self.sp_secret) + self.send(connect_request) + header, body = self.recv() + if body['Status'] != 0: + raise JMSException('CMPPv2.0 authentication failed: %s' % body) + + def _cmpp_send_sms(self, dest, sign_name, template_code, template_param): + """ + 优先发送template_param中message的信息 + 若该内容不存在,则根据template_code构建验证码发送 + """ + message = template_param.get('message') + if message is None: + code = template_param.get('code') + message = template_code.replace('{code}', code) + msg = '【%s】 %s' % (sign_name, message) + submit_request = CMPPSubmitRequestInstance( + msg_src=self.sp_id, src_id=self.src_id, msg_content=msg, + dest_usr_tl=len(dest), dest_terminal_id=dest, + service_id=self.service_id + ) + self.send(submit_request) + header, body = self.recv() + command_id = header.get('command_id') + if command_id == CMPP_DELIVER: + deliver_request = CMPPDeliverRespRequestInstance( + msg_id=body['Msg_Id'], result=body['Result'] + ) + self.send(deliver_request) + + def send_sms(self, dest, sign_name, template_code, template_param): + try: + self._cmpp_connect() + self._cmpp_send_sms(dest, sign_name, template_code, template_param) + except Exception as e: + logger.error('CMPPv2.0 Error: %s', e) + self.close() + raise JMSException(e) + + +class CMPP2SMS(BaseSMSClient): + SIGN_AND_TMPL_SETTING_FIELD_PREFIX = 'CMPP2' + + @classmethod + def new_from_settings(cls): + return cls( + host=settings.CMPP2_HOST, port=settings.CMPP2_PORT, + sp_id=settings.CMPP2_SP_ID, sp_secret=settings.CMPP2_SP_SECRET, + service_id=settings.CMPP2_SERVICE_ID, src_id=getattr(settings, 'CMPP2_SRC_ID', ''), + ) + + def __init__(self, host: str, port: int, sp_id: str, sp_secret: str, service_id: str, src_id=''): + try: + self.client = CMPPClient( + host=host, port=port, sp_id=sp_id, sp_secret=sp_secret, src_id=src_id, service_id=service_id + ) + except socket.timeout: + self.client = None + logger.warning('CMPPv2.0 connect remote time out.') + + @staticmethod + def need_pre_check(): + return False + + def send_sms(self, phone_numbers: list, sign_name: str, template_code: str, template_param: dict, **kwargs): + try: + logger.info(f'CMPPv2.0 sms send: ' + f'phone_numbers={phone_numbers} ' + f'sign_name={sign_name} ' + f'template_code={template_code} ' + f'template_param={template_param}') + self.client.send_sms(phone_numbers, sign_name, template_code, template_param) + except Exception as e: + raise JMSException(e) + + +client = CMPP2SMS diff --git a/apps/common/sdk/sms/endpoint.py b/apps/common/sdk/sms/endpoint.py index 610bf2d99..3bcaa8559 100644 --- a/apps/common/sdk/sms/endpoint.py +++ b/apps/common/sdk/sms/endpoint.py @@ -15,6 +15,7 @@ logger = get_logger(__name__) class BACKENDS(TextChoices): ALIBABA = 'alibaba', _('Alibaba cloud') TENCENT = 'tencent', _('Tencent cloud') + CMPP2 = 'cmpp2', _('CMPP v2.0') class SMS: @@ -43,7 +44,7 @@ class SMS: sign_name = getattr(settings, f'{self.client.SIGN_AND_TMPL_SETTING_FIELD_PREFIX}_VERIFY_SIGN_NAME') template_code = getattr(settings, f'{self.client.SIGN_AND_TMPL_SETTING_FIELD_PREFIX}_VERIFY_TEMPLATE_CODE') - if not (sign_name and template_code): + if self.client.need_pre_check() and not (sign_name and template_code): raise JMSException( code='verify_code_sign_tmpl_invalid', detail=_('SMS verification code signature or template invalid') diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 78e73ba6c..7b26b4ee2 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -376,6 +376,15 @@ class Config(dict): 'TENCENT_VERIFY_SIGN_NAME': '', 'TENCENT_VERIFY_TEMPLATE_CODE': '', + 'CMPP2_HOST': '', + 'CMPP2_PORT': 7890, + 'CMPP2_SP_ID': '', + 'CMPP2_SP_SECRET': '', + 'CMPP2_SRC_ID': '', + 'CMPP2_SERVICE_ID': '', + 'CMPP2_VERIFY_SIGN_NAME': '', + 'CMPP2_VERIFY_TEMPLATE_CODE': '{code}', + # Email 'EMAIL_CUSTOM_USER_CREATED_SUBJECT': _('Create account successfully'), 'EMAIL_CUSTOM_USER_CREATED_HONORIFIC': _('Hello'), diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index a1ae87cba..fb5b39b2f 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -88,8 +88,8 @@ msgstr "ログイン確認" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 -#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:220 -#: perms/models/base.py:84 rbac/builtin.py:120 rbac/models/rolebinding.py:41 +#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:214 +#: perms/models/base.py:84 rbac/builtin.py:117 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 #: terminal/models/sharing.py:33 terminal/notifications.py:91 @@ -393,8 +393,8 @@ msgstr "クラスター" #: applications/serializers/attrs/application_category/db.py:11 #: ops/models/adhoc.py:157 settings/serializers/auth/radius.py:14 -#: terminal/models/endpoint.py:11 -#: xpack/plugins/cloud/serializers/account_attrs.py:72 +#: settings/serializers/auth/sms.py:52 terminal/models/endpoint.py:11 +#: xpack/plugins/cloud/serializers/account_attrs.py:70 msgid "Host" msgstr "ホスト" @@ -407,8 +407,8 @@ msgstr "ホスト" #: applications/serializers/attrs/application_type/redis.py:10 #: applications/serializers/attrs/application_type/sqlserver.py:10 #: assets/models/asset.py:214 assets/models/domain.py:62 -#: settings/serializers/auth/radius.py:15 -#: xpack/plugins/cloud/serializers/account_attrs.py:73 +#: settings/serializers/auth/radius.py:15 settings/serializers/auth/sms.py:53 +#: xpack/plugins/cloud/serializers/account_attrs.py:71 msgid "Port" msgstr "ポート" @@ -591,7 +591,7 @@ msgstr "ホスト名生" #: assets/models/asset.py:215 assets/serializers/account.py:16 #: assets/serializers/asset.py:65 perms/serializers/asset/user_permission.py:41 -#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:43 +#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:42 msgid "Protocols" msgstr "プロトコル" @@ -990,7 +990,7 @@ msgid "Parent key" msgstr "親キー" #: assets/models/node.py:559 assets/serializers/system_user.py:267 -#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:70 +#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:69 msgid "Node" msgstr "ノード" @@ -2318,7 +2318,7 @@ msgstr "コードエラー" #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:323 ops/tasks.py:145 ops/tasks.py:148 +#: jumpserver/conf.py:316 ops/tasks.py:145 ops/tasks.py:148 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -2723,11 +2723,15 @@ msgstr "アリ雲" msgid "Tencent cloud" msgstr "テンセント雲" -#: common/sdk/sms/endpoint.py:28 +#: common/sdk/sms/endpoint.py:18 +msgid "CMPP v2.0" +msgstr "CMPP v2.0" + +#: common/sdk/sms/endpoint.py:29 msgid "SMS provider not support: {}" msgstr "SMSプロバイダーはサポートしていません: {}" -#: common/sdk/sms/endpoint.py:49 +#: common/sdk/sms/endpoint.py:50 msgid "SMS verification code signature or template invalid" msgstr "SMS検証コードの署名またはテンプレートが無効" @@ -2763,11 +2767,11 @@ msgstr "特殊文字を含むべきではない" msgid "The mobile phone number format is incorrect" msgstr "携帯電話番号の形式が正しくありません" -#: jumpserver/conf.py:322 +#: jumpserver/conf.py:315 msgid "Create account successfully" msgstr "アカウントを正常に作成" -#: jumpserver/conf.py:324 +#: jumpserver/conf.py:317 msgid "Your account has been created successfully" msgstr "アカウントが正常に作成されました" @@ -3026,8 +3030,8 @@ msgstr "組織のリソース ({}) は削除できません" msgid "App organizations" msgstr "アプリ組織" -#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:85 -#: orgs/models.py:217 rbac/const.py:7 rbac/models/rolebinding.py:48 +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:80 +#: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 msgid "Organization" @@ -3271,27 +3275,27 @@ msgstr "{} 少なくとも1つのシステムロール" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:111 +#: rbac/builtin.py:108 msgid "SystemAdmin" msgstr "システム管理者" -#: rbac/builtin.py:114 +#: rbac/builtin.py:111 msgid "SystemAuditor" msgstr "システム監査人" -#: rbac/builtin.py:117 +#: rbac/builtin.py:114 msgid "SystemComponent" msgstr "システムコンポーネント" -#: rbac/builtin.py:123 +#: rbac/builtin.py:120 msgid "OrgAdmin" msgstr "組織管理者" -#: rbac/builtin.py:126 +#: rbac/builtin.py:123 msgid "OrgAuditor" msgstr "監査員を組織する" -#: rbac/builtin.py:129 +#: rbac/builtin.py:126 msgid "OrgUser" msgstr "組織ユーザー" @@ -3463,13 +3467,8 @@ msgstr "権限ツリーの表示" msgid "Execute batch command" msgstr "バッチ実行コマンド" -#: settings/api/alibaba_sms.py:31 settings/api/tencent_sms.py:35 -msgid "test_phone is required" -msgstr "携帯番号をテストこのフィールドは必須です" - -#: settings/api/alibaba_sms.py:52 settings/api/dingtalk.py:31 -#: settings/api/feishu.py:36 settings/api/tencent_sms.py:57 -#: settings/api/wecom.py:37 +#: settings/api/dingtalk.py:31 settings/api/feishu.py:36 +#: settings/api/sms.py:131 settings/api/wecom.py:37 msgid "Test success" msgstr "テストの成功" @@ -3497,6 +3496,14 @@ msgstr "Ldapユーザーを取得するにはNone" msgid "Imported {} users successfully (Organization: {})" msgstr "{} 人のユーザーを正常にインポートしました (組織: {})" +#: settings/api/sms.py:113 +msgid "Invalid SMS platform" +msgstr "無効なショートメッセージプラットフォーム" + +#: settings/api/sms.py:119 +msgid "test_phone is required" +msgstr "携帯番号をテストこのフィールドは必須です" + #: settings/apps.py:7 msgid "Settings" msgstr "設定" @@ -3821,29 +3828,69 @@ msgstr "SP プライベートキー" msgid "SP cert" msgstr "SP 証明書" -#: settings/serializers/auth/sms.py:11 +#: settings/serializers/auth/sms.py:14 msgid "Enable SMS" msgstr "SMSの有効化" -#: settings/serializers/auth/sms.py:13 -msgid "SMS provider" -msgstr "SMSプロバイダ" +#: settings/serializers/auth/sms.py:16 +msgid "SMS provider / Protocol" +msgstr "SMSプロバイダ / プロトコル" -#: settings/serializers/auth/sms.py:18 settings/serializers/auth/sms.py:36 -#: settings/serializers/auth/sms.py:44 settings/serializers/email.py:65 +#: settings/serializers/auth/sms.py:21 settings/serializers/auth/sms.py:39 +#: settings/serializers/auth/sms.py:47 settings/serializers/auth/sms.py:58 +#: settings/serializers/email.py:65 msgid "Signature" msgstr "署名" -#: settings/serializers/auth/sms.py:19 settings/serializers/auth/sms.py:37 -#: settings/serializers/auth/sms.py:45 +#: settings/serializers/auth/sms.py:22 settings/serializers/auth/sms.py:40 +#: settings/serializers/auth/sms.py:48 msgid "Template code" msgstr "テンプレートコード" -#: settings/serializers/auth/sms.py:23 +#: settings/serializers/auth/sms.py:26 msgid "Test phone" msgstr "テスト電話" -#: settings/serializers/auth/sso.py:11 +#: settings/serializers/auth/sms.py:54 +msgid "Gateway account(SP id)" +msgstr "ゲートウェイアカウント(SP id)" + +#: settings/serializers/auth/sms.py:55 +msgid "Gateway password(SP secret)" +msgstr "ゲートウェイパスワード(SP secret)" + +#: settings/serializers/auth/sms.py:56 +msgid "Original number(Src id)" +msgstr "元の番号(Src id)" + +#: settings/serializers/auth/sms.py:57 +msgid "Business type(Service id)" +msgstr "ビジネス・タイプ(Service id)" + +#: settings/serializers/auth/sms.py:60 +msgid "Template" +msgstr "テンプレート" + +#: settings/serializers/auth/sms.py:61 +msgid "" +"Template need contain {code} and Signature + template length does not exceed " +"67 words. For example, your verification code is {code}, which is valid for " +"5 minutes. Please do not disclose it to others." +msgstr "" +"テンプレートには{code}を含める必要があり、署名+テンプレートの長さは67ワード未" +"満です。たとえば、認証コードは{code}で、有効期間は5分です。他の人には言わない" +"でください。" + +#: settings/serializers/auth/sms.py:70 +#, python-brace-format +msgid "The template needs to contain {code}" +msgstr "テンプレートには{code}を含める必要があります" + +#: settings/serializers/auth/sms.py:73 +msgid "Signature + Template must not exceed 65 words" +msgstr "署名+テンプレートの長さは65文字以内" + +#: settings/serializers/auth/sso.py:12 msgid "Enable SSO auth" msgstr "SSO Token認証の有効化" @@ -6460,11 +6507,11 @@ msgstr "クラウドアカウント" msgid "Test cloud account" msgstr "クラウドアカウントのテスト" -#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:67 +#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:66 msgid "Account" msgstr "アカウント" -#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:38 +#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:37 msgid "Regions" msgstr "リージョン" @@ -6472,19 +6519,19 @@ msgstr "リージョン" msgid "Hostname strategy" msgstr "ホスト名戦略" -#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:68 +#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:67 msgid "Unix admin user" msgstr "Unix adminユーザー" -#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:69 +#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:68 msgid "Windows admin user" msgstr "Windows管理者" -#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:46 +#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:45 msgid "IP network segment group" msgstr "IPネットワークセグメントグループ" -#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:72 +#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:71 msgid "Always update" msgstr "常に更新" @@ -6790,11 +6837,9 @@ msgstr "テストポート" #: xpack/plugins/cloud/serializers/task.py:29 msgid "" -"Only instances matching the IP range will be synced.
If the instance " -"contains multiple IP addresses, the first IP address that matches will be " -"used as the IP for the created asset.
The default value of * means sync " -"all instances and randomly match IP addresses.
Format for comma-" -"delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" +"The IP address that is first matched to will be used as the IP of the " +"created asset.
The default * indicates a random match.
Format for " +"comma-delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" msgstr "" "IP範囲に一致するインスタンスのみが同期されます。
インスタンスに複数のIPア" "ドレスが含まれている場合、一致する最初のIPアドレスが作成されたアセットのIPと" @@ -6802,24 +6847,24 @@ msgstr "" "ドレスをランダムに一致させることを意味します。
形式はコンマ区切りの文字列" "です。例:192.168.1.0/24,10.1.1.1-10.1.1.20" -#: xpack/plugins/cloud/serializers/task.py:36 +#: xpack/plugins/cloud/serializers/task.py:35 msgid "History count" msgstr "実行回数" -#: xpack/plugins/cloud/serializers/task.py:37 +#: xpack/plugins/cloud/serializers/task.py:36 msgid "Instance count" msgstr "インスタンス数" -#: xpack/plugins/cloud/serializers/task.py:66 +#: xpack/plugins/cloud/serializers/task.py:65 msgid "Linux admin user" msgstr "Linux管理者" -#: xpack/plugins/cloud/serializers/task.py:71 +#: xpack/plugins/cloud/serializers/task.py:70 #: xpack/plugins/gathered_user/serializers.py:20 msgid "Periodic display" msgstr "定期的な表示" -#: xpack/plugins/cloud/utils.py:69 +#: xpack/plugins/cloud/utils.py:68 msgid "Account unavailable" msgstr "利用できないアカウント" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index cce71cba7..34da7efb9 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -87,8 +87,8 @@ msgstr "登录复核" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 -#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:220 -#: perms/models/base.py:84 rbac/builtin.py:120 rbac/models/rolebinding.py:41 +#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:214 +#: perms/models/base.py:84 rbac/builtin.py:117 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 #: terminal/models/sharing.py:33 terminal/notifications.py:91 @@ -388,8 +388,8 @@ msgstr "集群" #: applications/serializers/attrs/application_category/db.py:11 #: ops/models/adhoc.py:157 settings/serializers/auth/radius.py:14 -#: terminal/models/endpoint.py:11 -#: xpack/plugins/cloud/serializers/account_attrs.py:72 +#: settings/serializers/auth/sms.py:52 terminal/models/endpoint.py:11 +#: xpack/plugins/cloud/serializers/account_attrs.py:70 msgid "Host" msgstr "主机" @@ -402,8 +402,8 @@ msgstr "主机" #: applications/serializers/attrs/application_type/redis.py:10 #: applications/serializers/attrs/application_type/sqlserver.py:10 #: assets/models/asset.py:214 assets/models/domain.py:62 -#: settings/serializers/auth/radius.py:15 -#: xpack/plugins/cloud/serializers/account_attrs.py:73 +#: settings/serializers/auth/radius.py:15 settings/serializers/auth/sms.py:53 +#: xpack/plugins/cloud/serializers/account_attrs.py:71 msgid "Port" msgstr "端口" @@ -586,7 +586,7 @@ msgstr "主机名原始" #: assets/models/asset.py:215 assets/serializers/account.py:16 #: assets/serializers/asset.py:65 perms/serializers/asset/user_permission.py:41 -#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:43 +#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:42 msgid "Protocols" msgstr "协议组" @@ -985,7 +985,7 @@ msgid "Parent key" msgstr "ssh私钥" #: assets/models/node.py:559 assets/serializers/system_user.py:267 -#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:70 +#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:69 msgid "Node" msgstr "节点" @@ -2293,7 +2293,7 @@ msgstr "代码错误" #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:323 ops/tasks.py:145 ops/tasks.py:148 +#: jumpserver/conf.py:316 ops/tasks.py:145 ops/tasks.py:148 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -2689,11 +2689,15 @@ msgstr "阿里云" msgid "Tencent cloud" msgstr "腾讯云" -#: common/sdk/sms/endpoint.py:28 +#: common/sdk/sms/endpoint.py:18 +msgid "CMPP v2.0" +msgstr "CMPP v2.0" + +#: common/sdk/sms/endpoint.py:29 msgid "SMS provider not support: {}" msgstr "短信服务商不支持:{}" -#: common/sdk/sms/endpoint.py:49 +#: common/sdk/sms/endpoint.py:50 msgid "SMS verification code signature or template invalid" msgstr "短信验证码签名或模版无效" @@ -2729,11 +2733,11 @@ msgstr "不能包含特殊字符" msgid "The mobile phone number format is incorrect" msgstr "手机号格式不正确" -#: jumpserver/conf.py:322 +#: jumpserver/conf.py:315 msgid "Create account successfully" msgstr "创建账号成功" -#: jumpserver/conf.py:324 +#: jumpserver/conf.py:317 msgid "Your account has been created successfully" msgstr "你的账号已创建成功" @@ -2986,8 +2990,8 @@ msgstr "组织存在资源 ({}) 不能被删除" msgid "App organizations" msgstr "组织管理" -#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:85 -#: orgs/models.py:217 rbac/const.py:7 rbac/models/rolebinding.py:48 +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:80 +#: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 msgid "Organization" @@ -3229,27 +3233,27 @@ msgstr "{} 至少有一个系统角色" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:111 +#: rbac/builtin.py:108 msgid "SystemAdmin" msgstr "系统管理员" -#: rbac/builtin.py:114 +#: rbac/builtin.py:111 msgid "SystemAuditor" msgstr "系统审计员" -#: rbac/builtin.py:117 +#: rbac/builtin.py:114 msgid "SystemComponent" msgstr "系统组件" -#: rbac/builtin.py:123 +#: rbac/builtin.py:120 msgid "OrgAdmin" msgstr "组织管理员" -#: rbac/builtin.py:126 +#: rbac/builtin.py:123 msgid "OrgAuditor" msgstr "组织审计员" -#: rbac/builtin.py:129 +#: rbac/builtin.py:126 msgid "OrgUser" msgstr "组织用户" @@ -3420,13 +3424,8 @@ msgstr "查看授权树" msgid "Execute batch command" msgstr "执行批量命令" -#: settings/api/alibaba_sms.py:31 settings/api/tencent_sms.py:35 -msgid "test_phone is required" -msgstr "测试手机号 该字段是必填项。" - -#: settings/api/alibaba_sms.py:52 settings/api/dingtalk.py:31 -#: settings/api/feishu.py:36 settings/api/tencent_sms.py:57 -#: settings/api/wecom.py:37 +#: settings/api/dingtalk.py:31 settings/api/feishu.py:36 +#: settings/api/sms.py:131 settings/api/wecom.py:37 msgid "Test success" msgstr "测试成功" @@ -3454,6 +3453,14 @@ msgstr "获取 LDAP 用户为 None" msgid "Imported {} users successfully (Organization: {})" msgstr "成功导入 {} 个用户 ( 组织: {} )" +#: settings/api/sms.py:113 +msgid "Invalid SMS platform" +msgstr "无效的短信平台" + +#: settings/api/sms.py:119 +msgid "test_phone is required" +msgstr "测试手机号 该字段是必填项。" + #: settings/apps.py:7 msgid "Settings" msgstr "系统设置" @@ -3778,29 +3785,68 @@ msgstr "SP 密钥" msgid "SP cert" msgstr "SP 证书" -#: settings/serializers/auth/sms.py:11 +#: settings/serializers/auth/sms.py:14 msgid "Enable SMS" msgstr "启用 SMS" -#: settings/serializers/auth/sms.py:13 -msgid "SMS provider" -msgstr "短信服务商" +#: settings/serializers/auth/sms.py:16 +msgid "SMS provider / Protocol" +msgstr "短信服务商 / 协议" -#: settings/serializers/auth/sms.py:18 settings/serializers/auth/sms.py:36 -#: settings/serializers/auth/sms.py:44 settings/serializers/email.py:65 +#: settings/serializers/auth/sms.py:21 settings/serializers/auth/sms.py:39 +#: settings/serializers/auth/sms.py:47 settings/serializers/auth/sms.py:58 +#: settings/serializers/email.py:65 msgid "Signature" msgstr "签名" -#: settings/serializers/auth/sms.py:19 settings/serializers/auth/sms.py:37 -#: settings/serializers/auth/sms.py:45 +#: settings/serializers/auth/sms.py:22 settings/serializers/auth/sms.py:40 +#: settings/serializers/auth/sms.py:48 msgid "Template code" msgstr "模板" -#: settings/serializers/auth/sms.py:23 +#: settings/serializers/auth/sms.py:26 msgid "Test phone" msgstr "测试手机号" -#: settings/serializers/auth/sso.py:11 +#: settings/serializers/auth/sms.py:54 +msgid "Gateway account(SP id)" +msgstr "网关账号(SP id)" + +#: settings/serializers/auth/sms.py:55 +msgid "Gateway password(SP secret)" +msgstr "网关密码(SP secret)" + +#: settings/serializers/auth/sms.py:56 +msgid "Original number(Src id)" +msgstr "原始号码(Src id)" + +#: settings/serializers/auth/sms.py:57 +msgid "Business type(Service id)" +msgstr "业务类型(Service id)" + +#: settings/serializers/auth/sms.py:60 +msgid "Template" +msgstr "模板" + +#: settings/serializers/auth/sms.py:61 +msgid "" +"Template need contain {code} and Signature + template length does not exceed " +"67 words. For example, your verification code is {code}, which is valid for " +"5 minutes. Please do not disclose it to others." +msgstr "" +"模板需要包含 {code},并且模板+签名长度不能超过67个字。例如, 您的验证码是 " +"{code}, 有效期为5分钟。请不要泄露给其他人。" + +#: settings/serializers/auth/sms.py:70 +#, python-brace-format +msgid "The template needs to contain {code}" +msgstr "模板需要包含 {code}" + +#: settings/serializers/auth/sms.py:73 +msgid "Signature + Template must not exceed 65 words" +msgstr "模板+签名不能超过65个字" + +#: settings/serializers/auth/sso.py:12 msgid "Enable SSO auth" msgstr "启用 SSO Token 认证" @@ -6365,11 +6411,11 @@ msgstr "云账号" msgid "Test cloud account" msgstr "测试云账号" -#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:67 +#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:66 msgid "Account" msgstr "账号" -#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:38 +#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:37 msgid "Regions" msgstr "地域" @@ -6377,19 +6423,19 @@ msgstr "地域" msgid "Hostname strategy" msgstr "主机名策略" -#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:68 +#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:67 msgid "Unix admin user" msgstr "Unix 管理员" -#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:69 +#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:68 msgid "Windows admin user" msgstr "Windows 管理员" -#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:46 +#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:45 msgid "IP network segment group" msgstr "IP网段组" -#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:72 +#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:71 msgid "Always update" msgstr "总是更新" @@ -6694,34 +6740,32 @@ msgstr "测试端口" #: xpack/plugins/cloud/serializers/task.py:29 msgid "" -"Only instances matching the IP range will be synced.
If the instance " -"contains multiple IP addresses, the first IP address that matches will be " -"used as the IP for the created asset.
The default value of * means sync " -"all instances and randomly match IP addresses.
Format for comma-" -"delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" +"The IP address that is first matched to will be used as the IP of the " +"created asset.
The default * indicates a random match.
Format for " +"comma-delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" msgstr "" "只有匹配到 IP 段的实例会被同步。
如果实例包含多个 IP 地址,那么第一个匹配" "到的 IP 地址将被用作创建的资产的 IP。
默认值 * 表示同步所有实例和随机匹配 " "IP 地址。
格式为以逗号分隔的字符串,例如:192.168.1.0/24,10.1.1.1-10.1.1.20" -#: xpack/plugins/cloud/serializers/task.py:36 +#: xpack/plugins/cloud/serializers/task.py:35 msgid "History count" msgstr "执行次数" -#: xpack/plugins/cloud/serializers/task.py:37 +#: xpack/plugins/cloud/serializers/task.py:36 msgid "Instance count" msgstr "实例个数" -#: xpack/plugins/cloud/serializers/task.py:66 +#: xpack/plugins/cloud/serializers/task.py:65 msgid "Linux admin user" msgstr "Linux 管理员" -#: xpack/plugins/cloud/serializers/task.py:71 +#: xpack/plugins/cloud/serializers/task.py:70 #: xpack/plugins/gathered_user/serializers.py:20 msgid "Periodic display" msgstr "定时执行" -#: xpack/plugins/cloud/utils.py:69 +#: xpack/plugins/cloud/utils.py:68 msgid "Account unavailable" msgstr "账号无效" diff --git a/apps/settings/api/__init__.py b/apps/settings/api/__init__.py index 65438dda1..176a6c2c6 100644 --- a/apps/settings/api/__init__.py +++ b/apps/settings/api/__init__.py @@ -5,6 +5,4 @@ from .dingtalk import * from .feishu import * from .public import * from .email import * -from .alibaba_sms import * -from .tencent_sms import * from .sms import * diff --git a/apps/settings/api/alibaba_sms.py b/apps/settings/api/alibaba_sms.py deleted file mode 100644 index 8240ba0e0..000000000 --- a/apps/settings/api/alibaba_sms.py +++ /dev/null @@ -1,58 +0,0 @@ -from rest_framework.views import Response -from rest_framework.generics import GenericAPIView -from rest_framework.exceptions import APIException -from rest_framework import status -from django.utils.translation import gettext_lazy as _ - -from common.sdk.sms.alibaba import AlibabaSMS -from settings.models import Setting -from common.exceptions import JMSException - -from .. import serializers - - -class AlibabaSMSTestingAPI(GenericAPIView): - serializer_class = serializers.AlibabaSMSSettingSerializer - rbac_perms = { - 'POST': 'settings.change_sms' - } - - def post(self, request): - serializer = self.serializer_class(data=request.data) - serializer.is_valid(raise_exception=True) - - alibaba_access_key_id = serializer.validated_data['ALIBABA_ACCESS_KEY_ID'] - alibaba_access_key_secret = serializer.validated_data.get('ALIBABA_ACCESS_KEY_SECRET') - alibaba_verify_sign_name = serializer.validated_data['ALIBABA_VERIFY_SIGN_NAME'] - alibaba_verify_template_code = serializer.validated_data['ALIBABA_VERIFY_TEMPLATE_CODE'] - test_phone = serializer.validated_data.get('SMS_TEST_PHONE') - - if not test_phone: - raise JMSException(code='test_phone_required', detail=_('test_phone is required')) - - if not alibaba_access_key_secret: - secret = Setting.objects.filter(name='ALIBABA_ACCESS_KEY_SECRET').first() - if secret: - alibaba_access_key_secret = secret.cleaned_value - - alibaba_access_key_secret = alibaba_access_key_secret or '' - - try: - client = AlibabaSMS( - access_key_id=alibaba_access_key_id, - access_key_secret=alibaba_access_key_secret - ) - - client.send_sms( - phone_numbers=[test_phone], - sign_name=alibaba_verify_sign_name, - template_code=alibaba_verify_template_code, - template_param={'code': 'test'} - ) - return Response(status=status.HTTP_200_OK, data={'msg': _('Test success')}) - except APIException as e: - try: - error = e.detail['errmsg'] - except: - error = e.detail - return Response(status=status.HTTP_400_BAD_REQUEST, data={'error': error}) diff --git a/apps/settings/api/settings.py b/apps/settings/api/settings.py index 4cce5e718..0f487c280 100644 --- a/apps/settings/api/settings.py +++ b/apps/settings/api/settings.py @@ -40,6 +40,7 @@ class SettingsApi(generics.RetrieveUpdateAPIView): 'sms': serializers.SMSSettingSerializer, 'alibaba': serializers.AlibabaSMSSettingSerializer, 'tencent': serializers.TencentSMSSettingSerializer, + 'cmpp2': serializers.CMPP2SMSSettingSerializer, } rbac_category_permissions = { diff --git a/apps/settings/api/sms.py b/apps/settings/api/sms.py index bb30fa3aa..a886a3d8f 100644 --- a/apps/settings/api/sms.py +++ b/apps/settings/api/sms.py @@ -1,8 +1,19 @@ -from rest_framework.generics import ListAPIView +import importlib + +from collections import OrderedDict + +from rest_framework.generics import ListAPIView, GenericAPIView from rest_framework.response import Response +from rest_framework.exceptions import APIException +from rest_framework import status +from django.utils.translation import gettext_lazy as _ from common.sdk.sms import BACKENDS +from common.exceptions import JMSException from settings.serializers.sms import SMSBackendSerializer +from settings.models import Setting + +from .. import serializers class SMSBackendAPI(ListAPIView): @@ -21,3 +32,108 @@ class SMSBackendAPI(ListAPIView): ] return Response(data) + + +class SMSTestingAPI(GenericAPIView): + backends_serializer = { + 'alibaba': serializers.AlibabaSMSSettingSerializer, + 'tencent': serializers.TencentSMSSettingSerializer, + 'cmpp2': serializers.CMPP2SMSSettingSerializer + } + rbac_perms = { + 'POST': 'settings.change_sms' + } + + @staticmethod + def get_or_from_setting(key, value=''): + if not value: + secret = Setting.objects.filter(name=key).first() + if secret: + value = secret.cleaned_value + + return value or '' + + def get_alibaba_params(self, data): + init_params = { + 'access_key_id': data['ALIBABA_ACCESS_KEY_ID'], + 'access_key_secret': self.get_or_from_setting( + 'ALIBABA_ACCESS_KEY_SECRET', data.get('ALIBABA_ACCESS_KEY_SECRET') + ) + } + send_sms_params = { + 'sign_name': data['ALIBABA_VERIFY_SIGN_NAME'], + 'template_code': data['ALIBABA_VERIFY_TEMPLATE_CODE'], + 'template_param': {'code': '666666'} + } + return init_params, send_sms_params + + def get_tencent_params(self, data): + init_params = { + 'secret_id': data['TENCENT_SECRET_ID'], + 'secret_key': self.get_or_from_setting( + 'TENCENT_SECRET_KEY', data.get('TENCENT_SECRET_KEY') + ), + 'sdkappid': data['TENCENT_SDKAPPID'] + } + send_sms_params = { + 'sign_name': data['TENCENT_VERIFY_SIGN_NAME'], + 'template_code': data['TENCENT_VERIFY_TEMPLATE_CODE'], + 'template_param': OrderedDict(code='666666') + } + return init_params, send_sms_params + + def get_cmpp2_params(self, data): + init_params = { + 'host': data['CMPP2_HOST'], 'port': data['CMPP2_PORT'], + 'sp_id': data['CMPP2_SP_ID'], 'src_id': data['CMPP2_SRC_ID'], + 'sp_secret': self.get_or_from_setting( + 'CMPP2_SP_SECRET', data.get('CMPP2_SP_SECRET') + ), + 'service_id': data['CMPP2_SERVICE_ID'], + } + send_sms_params = { + 'sign_name': data['CMPP2_VERIFY_SIGN_NAME'], + 'template_code': data['CMPP2_VERIFY_TEMPLATE_CODE'], + 'template_param': OrderedDict(code='666666') + } + return init_params, send_sms_params + + def get_params_by_backend(self, backend, data): + """ + 返回两部分参数 + 1、实例化参数 + 2、发送测试短信参数 + """ + get_params_func = getattr(self, 'get_%s_params' % backend) + return get_params_func(data) + + def post(self, request, backend): + serializer_class = self.backends_serializer.get(backend) + if serializer_class is None: + raise JMSException(_('Invalid SMS platform')) + serializer = serializer_class(data=request.data) + serializer.is_valid(raise_exception=True) + + test_phone = serializer.validated_data.get('SMS_TEST_PHONE') + if not test_phone: + raise JMSException(code='test_phone_required', detail=_('test_phone is required')) + + init_params, send_sms_params = self.get_params_by_backend(backend, serializer.validated_data) + + m = importlib.import_module(f'common.sdk.sms.{backend}', __package__) + try: + client = m.client(**init_params) + client.send_sms( + phone_numbers=[test_phone], + **send_sms_params + ) + status_code = status.HTTP_200_OK + data = {'msg': _('Test success')} + except APIException as e: + try: + error = e.detail['errmsg'] + except: + error = e.detail + status_code = status.HTTP_400_BAD_REQUEST + data = {'error': error} + return Response(status=status_code, data=data) diff --git a/apps/settings/api/tencent_sms.py b/apps/settings/api/tencent_sms.py deleted file mode 100644 index 83a87a474..000000000 --- a/apps/settings/api/tencent_sms.py +++ /dev/null @@ -1,63 +0,0 @@ -from collections import OrderedDict - -from rest_framework.views import Response -from rest_framework.generics import GenericAPIView -from rest_framework.exceptions import APIException -from rest_framework import status -from django.utils.translation import gettext_lazy as _ - -from common.sdk.sms.tencent import TencentSMS -from settings.models import Setting -from common.exceptions import JMSException - -from .. import serializers - - -class TencentSMSTestingAPI(GenericAPIView): - serializer_class = serializers.TencentSMSSettingSerializer - rbac_perms = { - 'POST': 'settings.change_sms' - } - - def post(self, request): - serializer = self.serializer_class(data=request.data) - serializer.is_valid(raise_exception=True) - - tencent_secret_id = serializer.validated_data['TENCENT_SECRET_ID'] - tencent_secret_key = serializer.validated_data.get('TENCENT_SECRET_KEY') - tencent_verify_sign_name = serializer.validated_data['TENCENT_VERIFY_SIGN_NAME'] - tencent_verify_template_code = serializer.validated_data['TENCENT_VERIFY_TEMPLATE_CODE'] - tencent_sdkappid = serializer.validated_data.get('TENCENT_SDKAPPID') - - test_phone = serializer.validated_data.get('SMS_TEST_PHONE') - - if not test_phone: - raise JMSException(code='test_phone_required', detail=_('test_phone is required')) - - if not tencent_secret_key: - secret = Setting.objects.filter(name='TENCENT_SECRET_KEY').first() - if secret: - tencent_secret_key = secret.cleaned_value - - tencent_secret_key = tencent_secret_key or '' - - try: - client = TencentSMS( - secret_id=tencent_secret_id, - secret_key=tencent_secret_key, - sdkappid=tencent_sdkappid - ) - - client.send_sms( - phone_numbers=[test_phone], - sign_name=tencent_verify_sign_name, - template_code=tencent_verify_template_code, - template_param=OrderedDict(code='666666') - ) - return Response(status=status.HTTP_200_OK, data={'msg': _('Test success')}) - except APIException as e: - try: - error = e.detail['errmsg'] - except: - error = e.detail - return Response(status=status.HTTP_400_BAD_REQUEST, data={'error': error}) diff --git a/apps/settings/serializers/auth/sms.py b/apps/settings/serializers/auth/sms.py index cd3bef74c..8875f6437 100644 --- a/apps/settings/serializers/auth/sms.py +++ b/apps/settings/serializers/auth/sms.py @@ -4,13 +4,16 @@ from rest_framework import serializers from common.drf.fields import EncryptedField from common.sdk.sms import BACKENDS -__all__ = ['SMSSettingSerializer', 'AlibabaSMSSettingSerializer', 'TencentSMSSettingSerializer'] +__all__ = [ + 'SMSSettingSerializer', 'AlibabaSMSSettingSerializer', 'TencentSMSSettingSerializer', + 'CMPP2SMSSettingSerializer' +] class SMSSettingSerializer(serializers.Serializer): SMS_ENABLED = serializers.BooleanField(default=False, label=_('Enable SMS')) SMS_BACKEND = serializers.ChoiceField( - choices=BACKENDS.choices, default=BACKENDS.ALIBABA, label=_('SMS provider') + choices=BACKENDS.choices, default=BACKENDS.ALIBABA, label=_('SMS provider / Protocol') ) @@ -43,3 +46,29 @@ class TencentSMSSettingSerializer(BaseSMSSettingSerializer): TENCENT_SDKAPPID = serializers.CharField(max_length=256, required=True, label='SDK app id') TENCENT_VERIFY_SIGN_NAME = serializers.CharField(max_length=256, required=True, label=_('Signature')) TENCENT_VERIFY_TEMPLATE_CODE = serializers.CharField(max_length=256, required=True, label=_('Template code')) + + +class CMPP2SMSSettingSerializer(BaseSMSSettingSerializer): + CMPP2_HOST = serializers.CharField(max_length=256, required=True, label=_('Host')) + CMPP2_PORT = serializers.IntegerField(default=7890, label=_('Port')) + CMPP2_SP_ID = serializers.CharField(max_length=128, required=True, label=_('Gateway account(SP id)')) + CMPP2_SP_SECRET = EncryptedField(max_length=256, required=False, label=_('Gateway password(SP secret)')) + CMPP2_SRC_ID = serializers.CharField(max_length=256, required=False, label=_('Original number(Src id)')) + CMPP2_SERVICE_ID = serializers.CharField(max_length=256, required=True, label=_('Business type(Service id)')) + CMPP2_VERIFY_SIGN_NAME = serializers.CharField(max_length=256, required=True, label=_('Signature')) + CMPP2_VERIFY_TEMPLATE_CODE = serializers.CharField( + max_length=69, required=True, label=_('Template'), + help_text=_('Template need contain {code} and Signature + template length does not exceed 67 words. ' + 'For example, your verification code is {code}, which is valid for 5 minutes. ' + 'Please do not disclose it to others.') + ) + + def validate(self, attrs): + sign_name = attrs.get('CMPP2_VERIFY_SIGN_NAME', '') + template_code = attrs.get('CMPP2_VERIFY_TEMPLATE_CODE', '') + if template_code.find('{code}') == -1: + raise serializers.ValidationError(_('The template needs to contain {code}')) + if len(sign_name + template_code) > 65: + # 保证验证码内容在一条短信中(长度小于70字), 签名两边的括号和空格占3个字,再减去2个即可(验证码占用4个但占位符6个 + raise serializers.ValidationError(_('Signature + Template must not exceed 65 words')) + return attrs diff --git a/apps/settings/serializers/settings.py b/apps/settings/serializers/settings.py index 7baa19196..3152a5ef5 100644 --- a/apps/settings/serializers/settings.py +++ b/apps/settings/serializers/settings.py @@ -7,7 +7,7 @@ from .auth import ( LDAPSettingSerializer, OIDCSettingSerializer, KeycloakSettingSerializer, CASSettingSerializer, RadiusSettingSerializer, FeiShuSettingSerializer, WeComSettingSerializer, DingTalkSettingSerializer, AlibabaSMSSettingSerializer, - TencentSMSSettingSerializer, + TencentSMSSettingSerializer, CMPP2SMSSettingSerializer ) from .terminal import TerminalSettingSerializer from .security import SecuritySettingSerializer @@ -37,6 +37,7 @@ class SettingsSerializer( CleaningSerializer, AlibabaSMSSettingSerializer, TencentSMSSettingSerializer, + CMPP2SMSSettingSerializer, ): # encrypt_fields 现在使用 write_only 来判断了 pass diff --git a/apps/settings/urls/api_urls.py b/apps/settings/urls/api_urls.py index 728baf0ae..ba04f2a4b 100644 --- a/apps/settings/urls/api_urls.py +++ b/apps/settings/urls/api_urls.py @@ -16,8 +16,7 @@ urlpatterns = [ path('wecom/testing/', api.WeComTestingAPI.as_view(), name='wecom-testing'), path('dingtalk/testing/', api.DingTalkTestingAPI.as_view(), name='dingtalk-testing'), path('feishu/testing/', api.FeiShuTestingAPI.as_view(), name='feishu-testing'), - path('alibaba/testing/', api.AlibabaSMSTestingAPI.as_view(), name='alibaba-sms-testing'), - path('tencent/testing/', api.TencentSMSTestingAPI.as_view(), name='tencent-sms-testing'), + path('sms//testing/', api.SMSTestingAPI.as_view(), name='sms-testing'), path('sms/backend/', api.SMSBackendAPI.as_view(), name='sms-backend'), path('setting/', api.SettingsApi.as_view(), name='settings-setting'), From 30fe5214c781b1e2b59704af251ed1e8bd0de318 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 10 Aug 2022 11:03:51 +0800 Subject: [PATCH 069/104] =?UTF-8?q?fix:=20=E5=A2=9E=E5=8A=A0=E4=B8=8A?= =?UTF-8?q?=E4=BA=86=E7=AC=AC=E4=B8=89=E6=96=B9=E7=94=A8=E6=88=B7=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E5=A4=B1=E8=B4=A5=E7=9A=84=E5=8E=9F=E5=9B=A0=20(#8714?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: OAuth2.0登录方式加上用户登录规则校验 * fix: 修复第三方用户登录规则(复核)问题 * fix: 增加上了第三方用户登录失败的原因 * fix: 修改变量名称 Co-authored-by: huangzhiwen --- apps/authentication/api/login_confirm.py | 2 ++ apps/authentication/middleware.py | 9 ++++++++- apps/authentication/signal_handlers.py | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/authentication/api/login_confirm.py b/apps/authentication/api/login_confirm.py index 22594b88e..71613348c 100644 --- a/apps/authentication/api/login_confirm.py +++ b/apps/authentication/api/login_confirm.py @@ -17,8 +17,10 @@ class TicketStatusApi(mixins.AuthMixin, APIView): def get(self, request, *args, **kwargs): try: self.check_user_login_confirm() + self.request.session['auth_third_party_done'] = 1 return Response({"msg": "ok"}) except errors.NeedMoreInfoError as e: + self.send_auth_signal(success=False, reason=e.as_data().get('msg')) return Response(e.as_data(), status=200) def delete(self, request, *args, **kwargs): diff --git a/apps/authentication/middleware.py b/apps/authentication/middleware.py index 9411b09a6..9a55bdfa2 100644 --- a/apps/authentication/middleware.py +++ b/apps/authentication/middleware.py @@ -10,6 +10,7 @@ from django.contrib.auth import logout as auth_logout from apps.authentication import mixins from common.utils import gen_key_pair from common.utils import get_request_ip +from .signals import post_auth_failed class MFAMiddleware: @@ -62,8 +63,13 @@ class ThirdPartyLoginMiddleware(mixins.AuthMixin): return response ip = get_request_ip(request) try: + self.request = request self._check_login_acl(request.user, ip) except Exception as e: + post_auth_failed.send( + sender=self.__class__, username=request.user.username, + request=self.request, reason=e.msg + ) auth_logout(request) context = { 'title': _('Authentication failed'), @@ -72,7 +78,8 @@ class ThirdPartyLoginMiddleware(mixins.AuthMixin): 'redirect_url': reverse('authentication:login'), 'auto_redirect': True, } - response = render(request, 'authentication/auth_fail_flash_message_standalone.html', context) + response = render( + request, 'authentication/auth_fail_flash_message_standalone.html', context) else: guard_url = reverse('authentication:login-guard') args = request.META.get('QUERY_STRING', '') diff --git a/apps/authentication/signal_handlers.py b/apps/authentication/signal_handlers.py index 68d8c0531..e7be3465c 100644 --- a/apps/authentication/signal_handlers.py +++ b/apps/authentication/signal_handlers.py @@ -29,7 +29,7 @@ def on_user_auth_login_success(sender, user, request, **kwargs): and user.mfa_enabled \ and not request.session.get('auth_mfa'): request.session['auth_mfa_required'] = 1 - if request.session.get('auth_backend') in AUTHENTICATION_BACKENDS_THIRD_PARTY: + if not request.session.get("auth_third_party_done") and request.session.get('auth_backend') in AUTHENTICATION_BACKENDS_THIRD_PARTY: request.session['auth_third_party_required'] = 1 # 单点登录,超过了自动退出 if settings.USER_LOGIN_SINGLE_MACHINE_ENABLED: From abcd12f6452c994822fef8ed162a417a341f1655 Mon Sep 17 00:00:00 2001 From: jiangweidong <80373698+F2C-Jiang@users.noreply.github.com> Date: Wed, 10 Aug 2022 17:32:28 +0800 Subject: [PATCH 070/104] =?UTF-8?q?perf:=20=E8=A1=A5=E5=85=85cmpp2?= =?UTF-8?q?=E7=BF=BB=E8=AF=91=E5=8F=8A=E9=83=A8=E5=88=86=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=20(#8717)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 修改CMPPv2.0翻译内容 * perf: 捕捉连接网关出错问题 * perf: 测试短信验证失败提示错误信息 * perf: 修改翻译 --- apps/common/sdk/sms/cmpp2.py | 15 +++- apps/locale/ja/LC_MESSAGES/django.po | 114 +++++++++++++++----------- apps/locale/zh/LC_MESSAGES/django.po | 114 +++++++++++++++----------- apps/settings/api/sms.py | 3 + apps/settings/serializers/auth/sms.py | 4 +- 5 files changed, 144 insertions(+), 106 deletions(-) diff --git a/apps/common/sdk/sms/cmpp2.py b/apps/common/sdk/sms/cmpp2.py index 8a6a4fe32..4d81ee1a0 100644 --- a/apps/common/sdk/sms/cmpp2.py +++ b/apps/common/sdk/sms/cmpp2.py @@ -4,6 +4,7 @@ import struct import time from django.conf import settings +from django.utils.translation import ugettext_lazy as _ from common.utils import get_logger from common.exceptions import JMSException @@ -42,7 +43,7 @@ class CMPPBaseRequestInstance(object): class CMPPConnectRequestInstance(CMPPBaseRequestInstance): def __init__(self, sp_id, sp_secret): if len(sp_id) != 6: - raise ValueError("sp_id and sp_secret are both 6 bits") + raise ValueError(_("sp_id is 6 bits")) super().__init__() @@ -212,14 +213,19 @@ class CMPPClient(object): def _connect(self): self.__socket.settimeout(5) + error_msg = _('Failed to connect to the CMPP gateway server, err: {}') for i in range(self._times): try: self.__socket.connect((self.ip, self.port)) - except socket.timeout: + except Exception as err: + error_msg = error_msg.format(str(err)) + logger.warning(error_msg) time.sleep(1) else: self._is_connect = True break + else: + raise JMSException(error_msg) def send(self, instance): if isinstance(instance, CMPPBaseRequestInstance): @@ -299,9 +305,10 @@ class CMPP2SMS(BaseSMSClient): self.client = CMPPClient( host=host, port=port, sp_id=sp_id, sp_secret=sp_secret, src_id=src_id, service_id=service_id ) - except socket.timeout: + except Exception as err: self.client = None - logger.warning('CMPPv2.0 connect remote time out.') + logger.warning(err) + raise JMSException(err) @staticmethod def need_pre_check(): diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index fb5b39b2f..29d6b9ec0 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-08-05 14:42+0800\n" +"POT-Creation-Date: 2022-08-10 14:50+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -88,8 +88,8 @@ msgstr "ログイン確認" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 -#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:214 -#: perms/models/base.py:84 rbac/builtin.py:117 rbac/models/rolebinding.py:41 +#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:220 +#: perms/models/base.py:84 rbac/builtin.py:120 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 #: terminal/models/sharing.py:33 terminal/notifications.py:91 @@ -394,7 +394,7 @@ msgstr "クラスター" #: applications/serializers/attrs/application_category/db.py:11 #: ops/models/adhoc.py:157 settings/serializers/auth/radius.py:14 #: settings/serializers/auth/sms.py:52 terminal/models/endpoint.py:11 -#: xpack/plugins/cloud/serializers/account_attrs.py:70 +#: xpack/plugins/cloud/serializers/account_attrs.py:72 msgid "Host" msgstr "ホスト" @@ -408,7 +408,7 @@ msgstr "ホスト" #: applications/serializers/attrs/application_type/sqlserver.py:10 #: assets/models/asset.py:214 assets/models/domain.py:62 #: settings/serializers/auth/radius.py:15 settings/serializers/auth/sms.py:53 -#: xpack/plugins/cloud/serializers/account_attrs.py:71 +#: xpack/plugins/cloud/serializers/account_attrs.py:73 msgid "Port" msgstr "ポート" @@ -591,7 +591,7 @@ msgstr "ホスト名生" #: assets/models/asset.py:215 assets/serializers/account.py:16 #: assets/serializers/asset.py:65 perms/serializers/asset/user_permission.py:41 -#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:42 +#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:43 msgid "Protocols" msgstr "プロトコル" @@ -929,7 +929,8 @@ msgstr "テストゲートウェイ" msgid "Unable to connect to port {port} on {ip}" msgstr "{ip} でポート {port} に接続できません" -#: assets/models/domain.py:134 xpack/plugins/cloud/providers/fc.py:48 +#: assets/models/domain.py:134 authentication/middleware.py:75 +#: xpack/plugins/cloud/providers/fc.py:48 msgid "Authentication failed" msgstr "認証に失敗しました" @@ -990,7 +991,7 @@ msgid "Parent key" msgstr "親キー" #: assets/models/node.py:559 assets/serializers/system_user.py:267 -#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:69 +#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:70 msgid "Node" msgstr "ノード" @@ -1988,19 +1989,19 @@ msgstr "受け入れのためのログイン確認チケットを待つ" msgid "Login confirm ticket was {}" msgstr "ログイン確認チケットは {} でした" -#: authentication/errors/failed.py:145 +#: authentication/errors/failed.py:146 msgid "Current IP and Time period is not allowed" msgstr "現在の IP と期間はログインを許可されていません" -#: authentication/errors/failed.py:150 +#: authentication/errors/failed.py:151 msgid "Please enter MFA code" msgstr "MFAコードを入力してください" -#: authentication/errors/failed.py:155 +#: authentication/errors/failed.py:156 msgid "Please enter SMS code" msgstr "SMSコードを入力してください" -#: authentication/errors/failed.py:160 users/exceptions.py:15 +#: authentication/errors/failed.py:161 users/exceptions.py:15 msgid "Phone not set" msgstr "電話が設定されていない" @@ -2115,6 +2116,10 @@ msgstr "電話番号を設定して有効にする" msgid "Clear phone number to disable" msgstr "無効にする電話番号をクリアする" +#: authentication/middleware.py:76 settings/utils/ldap.py:652 +msgid "Authentication failed (before login check failed): {}" +msgstr "認証に失敗しました (ログインチェックが失敗する前): {}" + #: authentication/mixins.py:256 msgid "The MFA type ({}) is not enabled" msgstr "MFAタイプ ({}) が有効になっていない" @@ -2304,6 +2309,7 @@ msgid "Need MFA for view auth" msgstr "ビューオートのためにMFAが必要" #: authentication/templates/authentication/_mfa_confirm_modal.html:20 +#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:37 #: templates/_modal.html:23 templates/flash_message_standalone.html:37 #: users/templates/users/user_password_verify.html:20 msgid "Confirm" @@ -2318,7 +2324,7 @@ msgstr "コードエラー" #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:316 ops/tasks.py:145 ops/tasks.py:148 +#: jumpserver/conf.py:390 ops/tasks.py:145 ops/tasks.py:148 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -2409,6 +2415,11 @@ msgstr "" "公開鍵の更新が開始されなかった場合、アカウントにセキュリティ上の問題がある可" "能性があります" +#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:28 +#: templates/flash_message_standalone.html:28 tickets/const.py:20 +msgid "Cancel" +msgstr "キャンセル" + #: authentication/templates/authentication/login.html:221 msgid "Welcome back, please enter username and password to login" msgstr "" @@ -2715,6 +2726,14 @@ msgstr "企業微信エラー、システム管理者に連絡してください msgid "Signature does not match" msgstr "署名が一致しない" +#: common/sdk/sms/cmpp2.py:46 +msgid "sp_id is 6 bits" +msgstr "SP idは6ビット" + +#: common/sdk/sms/cmpp2.py:216 +msgid "Failed to connect to the CMPP gateway server, err: {}" +msgstr "接続ゲートウェイサーバエラー, 非: {}" + #: common/sdk/sms/endpoint.py:16 msgid "Alibaba cloud" msgstr "アリ雲" @@ -2767,11 +2786,11 @@ msgstr "特殊文字を含むべきではない" msgid "The mobile phone number format is incorrect" msgstr "携帯電話番号の形式が正しくありません" -#: jumpserver/conf.py:315 +#: jumpserver/conf.py:389 msgid "Create account successfully" msgstr "アカウントを正常に作成" -#: jumpserver/conf.py:317 +#: jumpserver/conf.py:391 msgid "Your account has been created successfully" msgstr "アカウントが正常に作成されました" @@ -3030,8 +3049,8 @@ msgstr "組織のリソース ({}) は削除できません" msgid "App organizations" msgstr "アプリ組織" -#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:80 -#: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:85 +#: orgs/models.py:217 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 msgid "Organization" @@ -3275,27 +3294,27 @@ msgstr "{} 少なくとも1つのシステムロール" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:108 +#: rbac/builtin.py:111 msgid "SystemAdmin" msgstr "システム管理者" -#: rbac/builtin.py:111 +#: rbac/builtin.py:114 msgid "SystemAuditor" msgstr "システム監査人" -#: rbac/builtin.py:114 +#: rbac/builtin.py:117 msgid "SystemComponent" msgstr "システムコンポーネント" -#: rbac/builtin.py:120 +#: rbac/builtin.py:123 msgid "OrgAdmin" msgstr "組織管理者" -#: rbac/builtin.py:123 +#: rbac/builtin.py:126 msgid "OrgAuditor" msgstr "監査員を組織する" -#: rbac/builtin.py:126 +#: rbac/builtin.py:129 msgid "OrgUser" msgstr "組織ユーザー" @@ -3852,12 +3871,12 @@ msgid "Test phone" msgstr "テスト電話" #: settings/serializers/auth/sms.py:54 -msgid "Gateway account(SP id)" -msgstr "ゲートウェイアカウント(SP id)" +msgid "Enterprise code(SP id)" +msgstr "企業コード(SP id)" #: settings/serializers/auth/sms.py:55 -msgid "Gateway password(SP secret)" -msgstr "ゲートウェイパスワード(SP secret)" +msgid "Shared secret(Shared secret)" +msgstr "パスワードを共有する(Shared secret)" #: settings/serializers/auth/sms.py:56 msgid "Original number(Src id)" @@ -3872,6 +3891,7 @@ msgid "Template" msgstr "テンプレート" #: settings/serializers/auth/sms.py:61 +#, python-brace-format msgid "" "Template need contain {code} and Signature + template length does not exceed " "67 words. For example, your verification code is {code}, which is valid for " @@ -3890,7 +3910,7 @@ msgstr "テンプレートには{code}を含める必要があります" msgid "Signature + Template must not exceed 65 words" msgstr "署名+テンプレートの長さは65文字以内" -#: settings/serializers/auth/sso.py:12 +#: settings/serializers/auth/sso.py:11 msgid "Enable SSO auth" msgstr "SSO Token認証の有効化" @@ -4547,10 +4567,6 @@ msgstr "成功: {} 人のユーザーに一致" msgid "Authentication failed (configuration incorrect): {}" msgstr "認証に失敗しました (設定が正しくありません): {}" -#: settings/utils/ldap.py:652 -msgid "Authentication failed (before login check failed): {}" -msgstr "認証に失敗しました (ログインチェックが失敗する前): {}" - #: settings/utils/ldap.py:654 msgid "Authentication failed (username or password incorrect): {}" msgstr "認証に失敗しました (ユーザー名またはパスワードが正しくありません): {}" @@ -4721,10 +4737,6 @@ msgstr "確認コードが送信されました" msgid "Home page" msgstr "ホームページ" -#: templates/flash_message_standalone.html:28 tickets/const.py:20 -msgid "Cancel" -msgstr "キャンセル" - #: templates/resource_download.html:18 templates/resource_download.html:31 msgid "Client" msgstr "クライアント" @@ -6507,11 +6519,11 @@ msgstr "クラウドアカウント" msgid "Test cloud account" msgstr "クラウドアカウントのテスト" -#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:66 +#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:67 msgid "Account" msgstr "アカウント" -#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:37 +#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:38 msgid "Regions" msgstr "リージョン" @@ -6519,19 +6531,19 @@ msgstr "リージョン" msgid "Hostname strategy" msgstr "ホスト名戦略" -#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:67 +#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:68 msgid "Unix admin user" msgstr "Unix adminユーザー" -#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:68 +#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:69 msgid "Windows admin user" msgstr "Windows管理者" -#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:45 +#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:46 msgid "IP network segment group" msgstr "IPネットワークセグメントグループ" -#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:71 +#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:72 msgid "Always update" msgstr "常に更新" @@ -6837,9 +6849,11 @@ msgstr "テストポート" #: xpack/plugins/cloud/serializers/task.py:29 msgid "" -"The IP address that is first matched to will be used as the IP of the " -"created asset.
The default * indicates a random match.
Format for " -"comma-delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" +"Only instances matching the IP range will be synced.
If the instance " +"contains multiple IP addresses, the first IP address that matches will be " +"used as the IP for the created asset.
The default value of * means sync " +"all instances and randomly match IP addresses.
Format for comma-" +"delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" msgstr "" "IP範囲に一致するインスタンスのみが同期されます。
インスタンスに複数のIPア" "ドレスが含まれている場合、一致する最初のIPアドレスが作成されたアセットのIPと" @@ -6847,24 +6861,24 @@ msgstr "" "ドレスをランダムに一致させることを意味します。
形式はコンマ区切りの文字列" "です。例:192.168.1.0/24,10.1.1.1-10.1.1.20" -#: xpack/plugins/cloud/serializers/task.py:35 +#: xpack/plugins/cloud/serializers/task.py:36 msgid "History count" msgstr "実行回数" -#: xpack/plugins/cloud/serializers/task.py:36 +#: xpack/plugins/cloud/serializers/task.py:37 msgid "Instance count" msgstr "インスタンス数" -#: xpack/plugins/cloud/serializers/task.py:65 +#: xpack/plugins/cloud/serializers/task.py:66 msgid "Linux admin user" msgstr "Linux管理者" -#: xpack/plugins/cloud/serializers/task.py:70 +#: xpack/plugins/cloud/serializers/task.py:71 #: xpack/plugins/gathered_user/serializers.py:20 msgid "Periodic display" msgstr "定期的な表示" -#: xpack/plugins/cloud/utils.py:68 +#: xpack/plugins/cloud/utils.py:69 msgid "Account unavailable" msgstr "利用できないアカウント" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 34da7efb9..42bacedf9 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-08-05 14:42+0800\n" +"POT-Creation-Date: 2022-08-10 14:50+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -87,8 +87,8 @@ msgstr "登录复核" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 -#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:214 -#: perms/models/base.py:84 rbac/builtin.py:117 rbac/models/rolebinding.py:41 +#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:220 +#: perms/models/base.py:84 rbac/builtin.py:120 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 #: terminal/models/sharing.py:33 terminal/notifications.py:91 @@ -389,7 +389,7 @@ msgstr "集群" #: applications/serializers/attrs/application_category/db.py:11 #: ops/models/adhoc.py:157 settings/serializers/auth/radius.py:14 #: settings/serializers/auth/sms.py:52 terminal/models/endpoint.py:11 -#: xpack/plugins/cloud/serializers/account_attrs.py:70 +#: xpack/plugins/cloud/serializers/account_attrs.py:72 msgid "Host" msgstr "主机" @@ -403,7 +403,7 @@ msgstr "主机" #: applications/serializers/attrs/application_type/sqlserver.py:10 #: assets/models/asset.py:214 assets/models/domain.py:62 #: settings/serializers/auth/radius.py:15 settings/serializers/auth/sms.py:53 -#: xpack/plugins/cloud/serializers/account_attrs.py:71 +#: xpack/plugins/cloud/serializers/account_attrs.py:73 msgid "Port" msgstr "端口" @@ -586,7 +586,7 @@ msgstr "主机名原始" #: assets/models/asset.py:215 assets/serializers/account.py:16 #: assets/serializers/asset.py:65 perms/serializers/asset/user_permission.py:41 -#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:42 +#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:43 msgid "Protocols" msgstr "协议组" @@ -924,7 +924,8 @@ msgstr "测试网关" msgid "Unable to connect to port {port} on {ip}" msgstr "无法连接到 {ip} 上的端口 {port}" -#: assets/models/domain.py:134 xpack/plugins/cloud/providers/fc.py:48 +#: assets/models/domain.py:134 authentication/middleware.py:75 +#: xpack/plugins/cloud/providers/fc.py:48 msgid "Authentication failed" msgstr "认证失败" @@ -985,7 +986,7 @@ msgid "Parent key" msgstr "ssh私钥" #: assets/models/node.py:559 assets/serializers/system_user.py:267 -#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:69 +#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:70 msgid "Node" msgstr "节点" @@ -1968,19 +1969,19 @@ msgstr "等待登录复核处理" msgid "Login confirm ticket was {}" msgstr "登录复核: {}" -#: authentication/errors/failed.py:145 +#: authentication/errors/failed.py:146 msgid "Current IP and Time period is not allowed" msgstr "当前 IP 和时间段不被允许登录" -#: authentication/errors/failed.py:150 +#: authentication/errors/failed.py:151 msgid "Please enter MFA code" msgstr "请输入 MFA 验证码" -#: authentication/errors/failed.py:155 +#: authentication/errors/failed.py:156 msgid "Please enter SMS code" msgstr "请输入短信验证码" -#: authentication/errors/failed.py:160 users/exceptions.py:15 +#: authentication/errors/failed.py:161 users/exceptions.py:15 msgid "Phone not set" msgstr "手机号没有设置" @@ -2094,6 +2095,10 @@ msgstr "设置手机号码启用" msgid "Clear phone number to disable" msgstr "清空手机号码禁用" +#: authentication/middleware.py:76 settings/utils/ldap.py:652 +msgid "Authentication failed (before login check failed): {}" +msgstr "认证失败(登录前检查失败): {}" + #: authentication/mixins.py:256 msgid "The MFA type ({}) is not enabled" msgstr "该 MFA ({}) 方式没有启用" @@ -2279,6 +2284,7 @@ msgid "Need MFA for view auth" msgstr "需要 MFA 认证来查看账号信息" #: authentication/templates/authentication/_mfa_confirm_modal.html:20 +#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:37 #: templates/_modal.html:23 templates/flash_message_standalone.html:37 #: users/templates/users/user_password_verify.html:20 msgid "Confirm" @@ -2293,7 +2299,7 @@ msgstr "代码错误" #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:316 ops/tasks.py:145 ops/tasks.py:148 +#: jumpserver/conf.py:390 ops/tasks.py:145 ops/tasks.py:148 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -2376,6 +2382,11 @@ msgid "" "security issues" msgstr "如果这次公钥更新不是由你发起的,那么你的账号可能存在安全问题" +#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:28 +#: templates/flash_message_standalone.html:28 tickets/const.py:20 +msgid "Cancel" +msgstr "取消" + #: authentication/templates/authentication/login.html:221 msgid "Welcome back, please enter username and password to login" msgstr "欢迎回来,请输入用户名和密码登录" @@ -2681,6 +2692,14 @@ msgstr "企业微信错误,请联系系统管理员" msgid "Signature does not match" msgstr "签名不匹配" +#: common/sdk/sms/cmpp2.py:46 +msgid "sp_id is 6 bits" +msgstr "SP_id 为6位" + +#: common/sdk/sms/cmpp2.py:216 +msgid "Failed to connect to the CMPP gateway server, err: {}" +msgstr "连接网关服务器错误,错误:{}" + #: common/sdk/sms/endpoint.py:16 msgid "Alibaba cloud" msgstr "阿里云" @@ -2733,11 +2752,11 @@ msgstr "不能包含特殊字符" msgid "The mobile phone number format is incorrect" msgstr "手机号格式不正确" -#: jumpserver/conf.py:315 +#: jumpserver/conf.py:389 msgid "Create account successfully" msgstr "创建账号成功" -#: jumpserver/conf.py:317 +#: jumpserver/conf.py:391 msgid "Your account has been created successfully" msgstr "你的账号已创建成功" @@ -2990,8 +3009,8 @@ msgstr "组织存在资源 ({}) 不能被删除" msgid "App organizations" msgstr "组织管理" -#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:80 -#: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:85 +#: orgs/models.py:217 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 msgid "Organization" @@ -3233,27 +3252,27 @@ msgstr "{} 至少有一个系统角色" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:108 +#: rbac/builtin.py:111 msgid "SystemAdmin" msgstr "系统管理员" -#: rbac/builtin.py:111 +#: rbac/builtin.py:114 msgid "SystemAuditor" msgstr "系统审计员" -#: rbac/builtin.py:114 +#: rbac/builtin.py:117 msgid "SystemComponent" msgstr "系统组件" -#: rbac/builtin.py:120 +#: rbac/builtin.py:123 msgid "OrgAdmin" msgstr "组织管理员" -#: rbac/builtin.py:123 +#: rbac/builtin.py:126 msgid "OrgAuditor" msgstr "组织审计员" -#: rbac/builtin.py:126 +#: rbac/builtin.py:129 msgid "OrgUser" msgstr "组织用户" @@ -3809,12 +3828,12 @@ msgid "Test phone" msgstr "测试手机号" #: settings/serializers/auth/sms.py:54 -msgid "Gateway account(SP id)" -msgstr "网关账号(SP id)" +msgid "Enterprise code(SP id)" +msgstr "企业代码(SP id)" #: settings/serializers/auth/sms.py:55 -msgid "Gateway password(SP secret)" -msgstr "网关密码(SP secret)" +msgid "Shared secret(Shared secret)" +msgstr "共享密码(Shared secret)" #: settings/serializers/auth/sms.py:56 msgid "Original number(Src id)" @@ -3829,6 +3848,7 @@ msgid "Template" msgstr "模板" #: settings/serializers/auth/sms.py:61 +#, python-brace-format msgid "" "Template need contain {code} and Signature + template length does not exceed " "67 words. For example, your verification code is {code}, which is valid for " @@ -3846,7 +3866,7 @@ msgstr "模板需要包含 {code}" msgid "Signature + Template must not exceed 65 words" msgstr "模板+签名不能超过65个字" -#: settings/serializers/auth/sso.py:12 +#: settings/serializers/auth/sso.py:11 msgid "Enable SSO auth" msgstr "启用 SSO Token 认证" @@ -4480,10 +4500,6 @@ msgstr "成功匹配 {} 个用户" msgid "Authentication failed (configuration incorrect): {}" msgstr "认证失败(配置错误): {}" -#: settings/utils/ldap.py:652 -msgid "Authentication failed (before login check failed): {}" -msgstr "认证失败(登录前检查失败): {}" - #: settings/utils/ldap.py:654 msgid "Authentication failed (username or password incorrect): {}" msgstr "认证失败 (用户名或密码不正确): {}" @@ -4649,10 +4665,6 @@ msgstr "验证码已发送" msgid "Home page" msgstr "首页" -#: templates/flash_message_standalone.html:28 tickets/const.py:20 -msgid "Cancel" -msgstr "取消" - #: templates/resource_download.html:18 templates/resource_download.html:31 msgid "Client" msgstr "客户端" @@ -6411,11 +6423,11 @@ msgstr "云账号" msgid "Test cloud account" msgstr "测试云账号" -#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:66 +#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:67 msgid "Account" msgstr "账号" -#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:37 +#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:38 msgid "Regions" msgstr "地域" @@ -6423,19 +6435,19 @@ msgstr "地域" msgid "Hostname strategy" msgstr "主机名策略" -#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:67 +#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:68 msgid "Unix admin user" msgstr "Unix 管理员" -#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:68 +#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:69 msgid "Windows admin user" msgstr "Windows 管理员" -#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:45 +#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:46 msgid "IP network segment group" msgstr "IP网段组" -#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:71 +#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:72 msgid "Always update" msgstr "总是更新" @@ -6740,32 +6752,34 @@ msgstr "测试端口" #: xpack/plugins/cloud/serializers/task.py:29 msgid "" -"The IP address that is first matched to will be used as the IP of the " -"created asset.
The default * indicates a random match.
Format for " -"comma-delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" +"Only instances matching the IP range will be synced.
If the instance " +"contains multiple IP addresses, the first IP address that matches will be " +"used as the IP for the created asset.
The default value of * means sync " +"all instances and randomly match IP addresses.
Format for comma-" +"delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" msgstr "" "只有匹配到 IP 段的实例会被同步。
如果实例包含多个 IP 地址,那么第一个匹配" "到的 IP 地址将被用作创建的资产的 IP。
默认值 * 表示同步所有实例和随机匹配 " "IP 地址。
格式为以逗号分隔的字符串,例如:192.168.1.0/24,10.1.1.1-10.1.1.20" -#: xpack/plugins/cloud/serializers/task.py:35 +#: xpack/plugins/cloud/serializers/task.py:36 msgid "History count" msgstr "执行次数" -#: xpack/plugins/cloud/serializers/task.py:36 +#: xpack/plugins/cloud/serializers/task.py:37 msgid "Instance count" msgstr "实例个数" -#: xpack/plugins/cloud/serializers/task.py:65 +#: xpack/plugins/cloud/serializers/task.py:66 msgid "Linux admin user" msgstr "Linux 管理员" -#: xpack/plugins/cloud/serializers/task.py:70 +#: xpack/plugins/cloud/serializers/task.py:71 #: xpack/plugins/gathered_user/serializers.py:20 msgid "Periodic display" msgstr "定时执行" -#: xpack/plugins/cloud/utils.py:68 +#: xpack/plugins/cloud/utils.py:69 msgid "Account unavailable" msgstr "账号无效" diff --git a/apps/settings/api/sms.py b/apps/settings/api/sms.py index a886a3d8f..668b5ec56 100644 --- a/apps/settings/api/sms.py +++ b/apps/settings/api/sms.py @@ -136,4 +136,7 @@ class SMSTestingAPI(GenericAPIView): error = e.detail status_code = status.HTTP_400_BAD_REQUEST data = {'error': error} + except Exception as e: + status_code = status.HTTP_400_BAD_REQUEST + data = {'error': str(e)} return Response(status=status_code, data=data) diff --git a/apps/settings/serializers/auth/sms.py b/apps/settings/serializers/auth/sms.py index 8875f6437..d3f96b33f 100644 --- a/apps/settings/serializers/auth/sms.py +++ b/apps/settings/serializers/auth/sms.py @@ -51,8 +51,8 @@ class TencentSMSSettingSerializer(BaseSMSSettingSerializer): class CMPP2SMSSettingSerializer(BaseSMSSettingSerializer): CMPP2_HOST = serializers.CharField(max_length=256, required=True, label=_('Host')) CMPP2_PORT = serializers.IntegerField(default=7890, label=_('Port')) - CMPP2_SP_ID = serializers.CharField(max_length=128, required=True, label=_('Gateway account(SP id)')) - CMPP2_SP_SECRET = EncryptedField(max_length=256, required=False, label=_('Gateway password(SP secret)')) + CMPP2_SP_ID = serializers.CharField(max_length=128, required=True, label=_('Enterprise code(SP id)')) + CMPP2_SP_SECRET = EncryptedField(max_length=256, required=False, label=_('Shared secret(Shared secret)')) CMPP2_SRC_ID = serializers.CharField(max_length=256, required=False, label=_('Original number(Src id)')) CMPP2_SERVICE_ID = serializers.CharField(max_length=256, required=True, label=_('Business type(Service id)')) CMPP2_VERIFY_SIGN_NAME = serializers.CharField(max_length=256, required=True, label=_('Signature')) From acf8b5798b9bd96356a4165b056e0a2e3a18d17e Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 10 Aug 2022 18:17:59 +0800 Subject: [PATCH 071/104] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96rdp=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=90=8D=E7=9A=84=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/connection_token.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index ecd329af0..2b4ce7e2b 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -22,7 +22,6 @@ from ..serializers import ( ) from ..models import ConnectionToken - __all__ = ['ConnectionTokenViewSet', 'SuperConnectionTokenViewSet'] @@ -174,9 +173,8 @@ class ConnectionTokenMixin: rdp_options['remoteapplicationname:s'] = name else: name = '*' - - filename = "{}-{}-jumpserver".format(token.user.username, name) - filename = urllib.parse.quote(filename) + prefix_name = f'{token.user.username}-{name}' + filename = self.get_connect_filename(prefix_name) content = '' for k, v in rdp_options.items(): @@ -184,6 +182,15 @@ class ConnectionTokenMixin: return filename, content + @staticmethod + def get_connect_filename(prefix_name): + prefix_name = prefix_name.replace('/', '_') + prefix_name = prefix_name.replace('\\', '_') + prefix_name = prefix_name.replace('.', '_') + filename = f'{prefix_name}-jumpserver' + filename = urllib.parse.quote(filename) + return filename + def get_ssh_token(self, token: ConnectionToken): if token.asset: name = token.asset.hostname @@ -191,7 +198,8 @@ class ConnectionTokenMixin: name = token.application.name else: name = '*' - filename = f'{token.user.username}-{name}-jumpserver' + prefix_name = f'{token.user.username}-{name}' + filename = self.get_connect_filename(prefix_name) endpoint = self.get_smart_endpoint( protocol='ssh', asset=token.asset, application=token.application @@ -326,4 +334,3 @@ class SuperConnectionTokenViewSet(ConnectionTokenViewSet): 'msg': f'Token is renewed, date expired: {date_expired}' } return Response(data=data, status=status.HTTP_200_OK) - From 795d6e01dc821ea7524ab685332767b464309f1b Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 10 Aug 2022 19:00:22 +0800 Subject: [PATCH 072/104] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E6=B5=8B?= =?UTF-8?q?=E8=AF=95IP=E5=9C=B0=E5=9D=80=E5=B7=A5=E5=85=B7=E7=9A=84?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E8=B6=85=E5=B8=82=E6=97=B6=E9=97=B4=E4=B8=BA?= =?UTF-8?q?=200.5s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/utils/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/common/utils/common.py b/apps/common/utils/common.py index 0a177735d..44920a339 100644 --- a/apps/common/utils/common.py +++ b/apps/common/utils/common.py @@ -369,7 +369,7 @@ def group_by_count(it, count): return [it[i:i+count] for i in range(0, len(it), count)] -def test_ip_connectivity(host, port, timeout=3): +def test_ip_connectivity(host, port, timeout=0.5): """ timeout: seconds """ @@ -388,4 +388,4 @@ def static_or_direct(logo_path): if logo_path.startswith('img/'): return static(logo_path) else: - return logo_path \ No newline at end of file + return logo_path From 6af20d298dd2b2cdba303b95b406626df5741ccc Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 10 Aug 2022 19:04:32 +0800 Subject: [PATCH 073/104] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.po | 9 +++++++-- apps/locale/zh/LC_MESSAGES/django.po | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 29d6b9ec0..655e05db0 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-08-10 14:50+0800\n" +"POT-Creation-Date: 2022-08-10 19:03+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -529,7 +529,7 @@ msgstr "内部" #: assets/models/asset.py:162 assets/models/asset.py:216 #: assets/serializers/account.py:15 assets/serializers/asset.py:63 #: perms/serializers/asset/user_permission.py:43 -#: xpack/plugins/cloud/serializers/account_attrs.py:159 +#: xpack/plugins/cloud/serializers/account_attrs.py:162 msgid "Platform" msgstr "プラットフォーム" @@ -3924,6 +3924,7 @@ msgid "SSO auth key TTL" msgstr "Token有効期間" #: settings/serializers/auth/sso.py:15 +#: xpack/plugins/cloud/serializers/account_attrs.py:159 msgid "Unit: second" msgstr "単位: 秒" @@ -6847,6 +6848,10 @@ msgstr "IP セグメント" msgid "Test port" msgstr "テストポート" +#: xpack/plugins/cloud/serializers/account_attrs.py:159 +msgid "Test timeout" +msgstr "テストタイムアウト" + #: xpack/plugins/cloud/serializers/task.py:29 msgid "" "Only instances matching the IP range will be synced.
If the instance " diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 42bacedf9..d36c5f037 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-08-10 14:50+0800\n" +"POT-Creation-Date: 2022-08-10 19:03+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -524,7 +524,7 @@ msgstr "内部的" #: assets/models/asset.py:162 assets/models/asset.py:216 #: assets/serializers/account.py:15 assets/serializers/asset.py:63 #: perms/serializers/asset/user_permission.py:43 -#: xpack/plugins/cloud/serializers/account_attrs.py:159 +#: xpack/plugins/cloud/serializers/account_attrs.py:162 msgid "Platform" msgstr "系统平台" @@ -3879,6 +3879,7 @@ msgid "SSO auth key TTL" msgstr "Token 有效期" #: settings/serializers/auth/sso.py:15 +#: xpack/plugins/cloud/serializers/account_attrs.py:159 msgid "Unit: second" msgstr "单位: 秒" @@ -6750,6 +6751,10 @@ msgstr "IP 网段" msgid "Test port" msgstr "测试端口" +#: xpack/plugins/cloud/serializers/account_attrs.py:159 +msgid "Test timeout" +msgstr "测试超时时间" + #: xpack/plugins/cloud/serializers/task.py:29 msgid "" "Only instances matching the IP range will be synced.
If the instance " From a14ebc5f0f568af4dbbb2e136d601f1e5d0e0158 Mon Sep 17 00:00:00 2001 From: huangzhiwen Date: Wed, 10 Aug 2022 19:30:54 +0800 Subject: [PATCH 074/104] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E7=AC=AC?= =?UTF-8?q?=E4=B8=89=E6=96=B9=E7=99=BB=E5=BD=95=E6=97=A0=E9=99=90=E9=87=8D?= =?UTF-8?q?=E5=AE=9A=E5=90=91=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/middleware.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/authentication/middleware.py b/apps/authentication/middleware.py index 9a55bdfa2..5b6d7c06f 100644 --- a/apps/authentication/middleware.py +++ b/apps/authentication/middleware.py @@ -78,9 +78,10 @@ class ThirdPartyLoginMiddleware(mixins.AuthMixin): 'redirect_url': reverse('authentication:login'), 'auto_redirect': True, } - response = render( - request, 'authentication/auth_fail_flash_message_standalone.html', context) + response = render(request, 'authentication/auth_fail_flash_message_standalone.html', context) else: + if not self.request.session['auth_confirm_required']: + return response guard_url = reverse('authentication:login-guard') args = request.META.get('QUERY_STRING', '') if args: From 28c8ec1fab98018b4835767a190b2fd708e7cc2e Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Tue, 9 Aug 2022 21:57:22 +0800 Subject: [PATCH 075/104] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0app=20?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=AF=B9=E5=BA=94actions=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/application/application_permission.py | 18 +++++++++++++++--- apps/perms/urls/application_permission.py | 2 ++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/apps/perms/api/application/application_permission.py b/apps/perms/api/application/application_permission.py index 798455053..bd8fb3452 100644 --- a/apps/perms/api/application/application_permission.py +++ b/apps/perms/api/application/application_permission.py @@ -1,8 +1,12 @@ # -*- coding: utf-8 -*- # -from applications.models import Application -from perms.models import ApplicationPermission +from rest_framework.response import Response +from rest_framework.generics import RetrieveAPIView + from perms import serializers +from perms.models import ApplicationPermission +from applications.models import Application +from common.permissions import IsValidUser from ..base import BasePermissionViewSet @@ -23,7 +27,7 @@ class ApplicationPermissionViewSet(BasePermissionViewSet): 'application_id', 'application', 'app', 'app_name' ] ordering_fields = ('name',) - ordering = ('name', ) + ordering = ('name',) def get_queryset(self): queryset = super().get_queryset().prefetch_related( @@ -53,3 +57,11 @@ class ApplicationPermissionViewSet(BasePermissionViewSet): queryset = self.filter_application(queryset) return queryset + +class ApplicationPermissionActionsApi(RetrieveAPIView): + permission_classes = (IsValidUser,) + + def retrieve(self, request, *args, **kwargs): + category = request.GET.get('category') + actions = ApplicationPermission.get_include_actions_choices(category=category) + return Response(data=actions) diff --git a/apps/perms/urls/application_permission.py b/apps/perms/urls/application_permission.py index 4ed9e6d37..50772a8d5 100644 --- a/apps/perms/urls/application_permission.py +++ b/apps/perms/urls/application_permission.py @@ -37,6 +37,8 @@ permission_urlpatterns = [ # 验证用户是否有某个应用的权限 path('user/validate/', api.ValidateUserApplicationPermissionApi.as_view(), name='validate-user-application-permission'), + + path('applications/actions/', api.ApplicationPermissionActionsApi.as_view(), name='application-actions'), ] application_permission_urlpatterns = [ From cfa5de13ab33252d1bc5f0b40defbc7b39bc83eb Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Thu, 11 Aug 2022 11:07:17 +0800 Subject: [PATCH 076/104] =?UTF-8?q?feat:=20=E8=8A=82=E7=82=B9=E6=A0=91?= =?UTF-8?q?=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/mixin.py | 2 +- apps/assets/api/node.py | 11 ++++++++++- apps/assets/models/node.py | 11 +++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/apps/assets/api/mixin.py b/apps/assets/api/mixin.py index 7f485bf29..43220a1a5 100644 --- a/apps/assets/api/mixin.py +++ b/apps/assets/api/mixin.py @@ -24,7 +24,7 @@ class SerializeToTreeNodeMixin: 'title': _name(node), 'pId': node.parent_key, 'isParent': True, - 'open': node.is_org_root(), + 'open': True, 'meta': { 'data': { "id": node.id, diff --git a/apps/assets/api/node.py b/apps/assets/api/node.py index 2bb77b60c..0ef3aecc6 100644 --- a/apps/assets/api/node.py +++ b/apps/assets/api/node.py @@ -101,6 +101,8 @@ class NodeListAsTreeApi(generics.ListAPIView): class NodeChildrenApi(generics.ListCreateAPIView): serializer_class = serializers.NodeSerializer + search_fields = ('value',) + instance = None is_initial = False @@ -179,8 +181,15 @@ class NodeChildrenAsTreeApi(SerializeToTreeNodeMixin, NodeChildrenApi): """ model = Node + def filter_queryset(self, queryset): + if not self.request.GET.get('search'): + return queryset + queryset = super().filter_queryset(queryset) + queryset = self.model.get_ancestor_queryset(queryset) + return queryset + def list(self, request, *args, **kwargs): - nodes = self.get_queryset().order_by('value') + nodes = self.filter_queryset(self.get_queryset()).order_by('value') nodes = self.serialize_nodes(nodes, with_asset_amount=True) assets = self.get_assets() data = [*nodes, *assets] diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index dcebab3eb..0e98bce14 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -25,7 +25,6 @@ from orgs.mixins.models import OrgModelMixin, OrgManager from orgs.utils import get_current_org, tmp_to_org, tmp_to_root_org from orgs.models import Organization - __all__ = ['Node', 'FamilyMixin', 'compute_parent_key', 'NodeQuerySet'] logger = get_logger(__name__) @@ -98,6 +97,14 @@ class FamilyMixin: q |= Q(key=self.key) return Node.objects.filter(q) + @classmethod + def get_ancestor_queryset(cls, queryset, with_self=True): + parent_keys = set() + for i in queryset: + parent_keys.update(set(i.get_ancestor_keys(with_self=with_self))) + queryset = queryset.model.objects.filter(key__in=list(parent_keys)).distinct() + return queryset + @property def children(self): return self.get_children(with_self=False) @@ -396,7 +403,7 @@ class NodeAllAssetsMappingMixin: mapping[ancestor_key].update(asset_ids) t3 = time.time() - logger.info('t1-t2(DB Query): {} s, t3-t2(Generate mapping): {} s'.format(t2-t1, t3-t2)) + logger.info('t1-t2(DB Query): {} s, t3-t2(Generate mapping): {} s'.format(t2 - t1, t3 - t2)) return mapping From 16634907b437cc4d53240b9331223f95f54d1c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com> Date: Wed, 10 Aug 2022 19:07:54 +0800 Subject: [PATCH 077/104] =?UTF-8?q?perf:=20ldap=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AF=E8=AF=81=E4=B9=A6=E8=AE=A4=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/settings/auth.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index 0270913b0..de43b03be 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -24,9 +24,15 @@ AUTH_LDAP_GLOBAL_OPTIONS = { ldap.OPT_X_TLS_REQUIRE_CERT: ldap.OPT_X_TLS_NEVER, ldap.OPT_REFERRALS: CONFIG.AUTH_LDAP_OPTIONS_OPT_REFERRALS } -LDAP_CERT_FILE = os.path.join(PROJECT_DIR, "data", "certs", "ldap_ca.pem") +LDAP_CACERT_FILE = os.path.join(PROJECT_DIR, "data", "certs", "ldap_ca.pem") +if os.path.isfile(LDAP_CACERT_FILE): + AUTH_LDAP_GLOBAL_OPTIONS[ldap.OPT_X_TLS_CACERTFILE] = LDAP_CACERT_FILE +LDAP_CERT_FILE = os.path.join(PROJECT_DIR, "data", "certs", "ldap_cert.pem") if os.path.isfile(LDAP_CERT_FILE): - AUTH_LDAP_GLOBAL_OPTIONS[ldap.OPT_X_TLS_CACERTFILE] = LDAP_CERT_FILE + AUTH_LDAP_GLOBAL_OPTIONS[ldap.OPT_X_TLS_CERTFILE] = LDAP_CERT_FILE +LDAP_KEY_FILE = os.path.join(PROJECT_DIR, "data", "certs", "ldap_cert.key") +if os.path.isfile(LDAP_KEY_FILE): + AUTH_LDAP_GLOBAL_OPTIONS[ldap.OPT_X_TLS_KEYFILE] = LDAP_KEY_FILE # AUTH_LDAP_GROUP_SEARCH_OU = CONFIG.AUTH_LDAP_GROUP_SEARCH_OU # AUTH_LDAP_GROUP_SEARCH_FILTER = CONFIG.AUTH_LDAP_GROUP_SEARCH_FILTER # AUTH_LDAP_GROUP_SEARCH = LDAPSearch( From 2e944c68984fdcb1ad23eeb86102d1a808660606 Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Thu, 11 Aug 2022 14:52:36 +0800 Subject: [PATCH 078/104] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E7=89=88=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/templates/resource_download.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/templates/resource_download.html b/apps/templates/resource_download.html index 4b60e1e09..9938d60a4 100644 --- a/apps/templates/resource_download.html +++ b/apps/templates/resource_download.html @@ -15,7 +15,7 @@ p {
-

JumpServer {% trans 'Client' %} v1.1.6

+

JumpServer {% trans 'Client' %} v1.1.7

{% trans 'JumpServer Client, currently used to launch the client, now only support launch RDP SSH client, The Telnet client will next' %}

From 1ed388459b0229d38ae5e6349e28f82a3d21a39d Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 12 Aug 2022 14:29:13 +0800 Subject: [PATCH 079/104] =?UTF-8?q?fix:=20=E5=B7=A5=E5=8D=95=E6=B5=81=20?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E7=BB=84=E7=BB=87=E4=B8=8D=E8=83=BD=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20(#8735)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/tickets/serializers/flow.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/tickets/serializers/flow.py b/apps/tickets/serializers/flow.py index 42c7bed15..e8c066100 100644 --- a/apps/tickets/serializers/flow.py +++ b/apps/tickets/serializers/flow.py @@ -3,6 +3,7 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers from orgs.models import Organization +from orgs.utils import get_current_org_id from orgs.mixins.serializers import OrgResourceModelSerializerMixin from tickets.models import TicketFlow, ApprovalRule from tickets.const import TicketApprovalStrategy @@ -96,7 +97,9 @@ class TicketFlowSerializer(OrgResourceModelSerializerMixin): @atomic def update(self, instance, validated_data): - if instance.org_id == Organization.ROOT_ID: + current_org_id = get_current_org_id() + root_org_id = Organization.ROOT_ID + if instance.org_id == root_org_id and current_org_id != root_org_id: instance = self.create(validated_data) else: instance = self.create_or_update('update', validated_data, instance) From 18af5e8c4a2ddceef89ff315a159729f00be551e Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 12 Aug 2022 18:01:04 +0800 Subject: [PATCH 080/104] =?UTF-8?q?fix:=20=E3=80=90=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E3=80=91=E7=99=BB=E5=BD=95=E5=A4=8D=E6=A0=B8?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E8=A2=AB=E6=8B=92=E7=BB=9D=EF=BC=8C=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E6=97=A5=E5=BF=97=E6=97=A0=E7=99=BB=E5=BD=95=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E8=AE=B0=E5=BD=95=E3=80=91=20(#8739)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 【登录】第三方用户登录复核,拒绝状态,未真正拦截 * fix: 【登录日志】登录复核用户被拒绝,登录日志无登录日志记录】 * fix: 【登录日志】用户设置登录复核,登录。此时不处理工单,管理员全局组织下查看登录日志,日志无限新增,且无记录用户名】 Co-authored-by: huangzhiwen --- apps/authentication/api/login_confirm.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/authentication/api/login_confirm.py b/apps/authentication/api/login_confirm.py index 71613348c..5bddda4e3 100644 --- a/apps/authentication/api/login_confirm.py +++ b/apps/authentication/api/login_confirm.py @@ -6,6 +6,8 @@ from rest_framework.permissions import AllowAny from common.utils import get_logger from .. import errors, mixins +from django.contrib.auth import logout as auth_logout + __all__ = ['TicketStatusApi'] logger = get_logger(__name__) @@ -19,8 +21,11 @@ class TicketStatusApi(mixins.AuthMixin, APIView): self.check_user_login_confirm() self.request.session['auth_third_party_done'] = 1 return Response({"msg": "ok"}) + except errors.LoginConfirmOtherError as e: + self.send_auth_signal(success=False, user=request.user, username=request.user.name, reason=e.as_data().get('msg')) + auth_logout(request) + return Response(e.as_data(), status=200) except errors.NeedMoreInfoError as e: - self.send_auth_signal(success=False, reason=e.as_data().get('msg')) return Response(e.as_data(), status=200) def delete(self, request, *args, **kwargs): From 0eaaa7b4f6da18a70afa7711c01542157f569e95 Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Fri, 12 Aug 2022 18:36:17 +0800 Subject: [PATCH 081/104] =?UTF-8?q?fix:=20=E7=94=A8=E6=88=B7=E5=BC=82?= =?UTF-8?q?=E5=9C=B0=E7=99=BB=E9=99=86bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/utils.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/authentication/utils.py b/apps/authentication/utils.py index 836cb55bf..a7f18648b 100644 --- a/apps/authentication/utils.py +++ b/apps/authentication/utils.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- # +import ipaddress from urllib.parse import urljoin from django.conf import settings +from django.utils.translation import ugettext_lazy as _ from common.utils import validate_ip, get_ip_city, get_request_ip from common.utils import get_logger @@ -23,8 +25,9 @@ def check_different_city_login_if_need(user, request): else: city = get_ip_city(ip) or DEFAULT_CITY - city_white = ['LAN', ] - if city not in city_white: + city_white = [_('LAN'), 'LAN'] + is_private = ipaddress.ip_address(ip).is_private + if not is_private: last_user_login = UserLoginLog.objects.exclude(city__in=city_white) \ .filter(username=user.username, status=True).first() From ddf4b61c9fc8785dff4a55f496086f69f9af6648 Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Mon, 15 Aug 2022 16:02:39 +0800 Subject: [PATCH 082/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E7=BB=84=E7=BB=87=E6=89=B9=E9=87=8F=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E8=B5=84=E4=BA=A7500?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/orgs/mixins/models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/orgs/mixins/models.py b/apps/orgs/mixins/models.py index 3406271b6..83e4aeac2 100644 --- a/apps/orgs/mixins/models.py +++ b/apps/orgs/mixins/models.py @@ -40,12 +40,11 @@ class OrgManager(models.Manager): set_current_org(org) return self - def bulk_create(self, objs, batch_size=None, ignore_conflicts=False): org = get_current_org() for obj in objs: if org.is_root(): - if not self.org_id: + if not obj.org_id: raise ValidationError('Please save in a organization') else: obj.org_id = org.id From 9a4b32cb3cd49d9e5fe8f6aeef9db0f55f603dcc Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Mon, 15 Aug 2022 16:02:40 +0800 Subject: [PATCH 083/104] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20metadata?= =?UTF-8?q?=20=E7=B1=BB=E5=9E=8B=E6=B7=BB=E5=8A=A0=20float?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/drf/metadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/common/drf/metadata.py b/apps/common/drf/metadata.py index 569854722..5abdf1d35 100644 --- a/apps/common/drf/metadata.py +++ b/apps/common/drf/metadata.py @@ -67,7 +67,7 @@ class SimpleMetadataWithFilters(SimpleMetadata): default = getattr(field, 'default', None) if default is not None and default != empty: - if isinstance(default, (str, int, bool, datetime.datetime, list)): + if isinstance(default, (str, int, bool, float, datetime.datetime, list)): field_info['default'] = default for attr in self.attrs: From 5559f112db9de452ddbedd87756fe2e890113ca1 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 15 Aug 2022 16:21:27 +0800 Subject: [PATCH 084/104] =?UTF-8?q?fix:=20=E7=94=A8=E6=88=B7=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E5=A4=8D=E5=90=88500=20(#8743)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/authentication/api/login_confirm.py | 5 ++++- apps/authentication/errors/redirect.py | 8 +++++++- apps/authentication/mixins.py | 5 ++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/authentication/api/login_confirm.py b/apps/authentication/api/login_confirm.py index 5bddda4e3..866964677 100644 --- a/apps/authentication/api/login_confirm.py +++ b/apps/authentication/api/login_confirm.py @@ -22,7 +22,10 @@ class TicketStatusApi(mixins.AuthMixin, APIView): self.request.session['auth_third_party_done'] = 1 return Response({"msg": "ok"}) except errors.LoginConfirmOtherError as e: - self.send_auth_signal(success=False, user=request.user, username=request.user.name, reason=e.as_data().get('msg')) + reason = e.msg + username = e.username + self.send_auth_signal(success=False, username=username, reason=reason) + # 若为三方登录,此时应退出登录 auth_logout(request) return Response(e.as_data(), status=200) except errors.NeedMoreInfoError as e: diff --git a/apps/authentication/errors/redirect.py b/apps/authentication/errors/redirect.py index bf334133d..466ec708d 100644 --- a/apps/authentication/errors/redirect.py +++ b/apps/authentication/errors/redirect.py @@ -69,10 +69,16 @@ class LoginConfirmWaitError(LoginConfirmBaseError): class LoginConfirmOtherError(LoginConfirmBaseError): error = 'login_confirm_error' - def __init__(self, ticket_id, status): + def __init__(self, ticket_id, status, username): + self.username = username msg = const.login_confirm_error_msg.format(status) super().__init__(ticket_id=ticket_id, msg=msg) + def as_data(self): + ret = super().as_data() + ret['data']['username'] = self.username + return ret + class PasswordTooSimple(NeedRedirectError): default_code = 'passwd_too_simple' diff --git a/apps/authentication/mixins.py b/apps/authentication/mixins.py index 739048d75..7341b4bd1 100644 --- a/apps/authentication/mixins.py +++ b/apps/authentication/mixins.py @@ -377,7 +377,10 @@ class AuthACLMixin: raise errors.LoginConfirmWaitError(ticket.id) else: # rejected, closed - raise errors.LoginConfirmOtherError(ticket.id, ticket.get_state_display()) + ticket_id = ticket.id + status = ticket.get_state_display() + username = ticket.applicant.username + raise errors.LoginConfirmOtherError(ticket_id, status, username) def get_ticket(self): from tickets.models import ApplyLoginTicket From 88d9078c43f118766d508c487ca3ae408b4f09b5 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Mon, 15 Aug 2022 16:52:45 +0800 Subject: [PATCH 085/104] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=20OAuth2.0=20?= =?UTF-8?q?=E8=AE=A4=E8=AF=81=E7=9A=84=E5=AD=97=E6=AE=B5=E7=9A=84=E5=BF=85?= =?UTF-8?q?=E5=A1=AB=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/settings/serializers/auth/oauth2.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/settings/serializers/auth/oauth2.py b/apps/settings/serializers/auth/oauth2.py index 2c620d331..279f3c34f 100644 --- a/apps/settings/serializers/auth/oauth2.py +++ b/apps/settings/serializers/auth/oauth2.py @@ -17,39 +17,39 @@ class SettingImageField(serializers.ImageField): class OAuth2SettingSerializer(serializers.Serializer): AUTH_OAUTH2 = serializers.BooleanField( - default=False, required=False, label=_('Enable OAuth2 Auth') + default=False, label=_('Enable OAuth2 Auth') ) AUTH_OAUTH2_LOGO_PATH = SettingImageField( allow_null=True, required=False, label=_('Logo') ) AUTH_OAUTH2_PROVIDER = serializers.CharField( - required=False, max_length=16, label=_('Service provider') + required=True, max_length=16, label=_('Service provider') ) AUTH_OAUTH2_CLIENT_ID = serializers.CharField( - required=False, max_length=1024, label=_('Client Id') + required=True, max_length=1024, label=_('Client Id') ) AUTH_OAUTH2_CLIENT_SECRET = EncryptedField( required=False, max_length=1024, label=_('Client Secret') ) AUTH_OAUTH2_SCOPE = serializers.CharField( - required=False, max_length=1024, label=_('Scope'), allow_blank=True + required=True, max_length=1024, label=_('Scope'), allow_blank=True ) AUTH_OAUTH2_PROVIDER_AUTHORIZATION_ENDPOINT = serializers.CharField( - required=False, max_length=1024, label=_('Provider auth endpoint') + required=True, max_length=1024, label=_('Provider auth endpoint') ) AUTH_OAUTH2_ACCESS_TOKEN_ENDPOINT = serializers.CharField( - required=False, max_length=1024, label=_('Provider token endpoint') + required=True, max_length=1024, label=_('Provider token endpoint') ) AUTH_OAUTH2_ACCESS_TOKEN_METHOD = serializers.ChoiceField( default='GET', label=_('Client authentication method'), choices=(('GET', 'GET'), ('POST', 'POST')) ) AUTH_OAUTH2_PROVIDER_USERINFO_ENDPOINT = serializers.CharField( - required=False, max_length=1024, label=_('Provider userinfo endpoint') + required=True, max_length=1024, label=_('Provider userinfo endpoint') ) AUTH_OAUTH2_USER_ATTR_MAP = serializers.DictField( - required=False, label=_('User attr map') + required=True, label=_('User attr map') ) AUTH_OAUTH2_ALWAYS_UPDATE_USER = serializers.BooleanField( - required=False, label=_('Always update user') + default=True, label=_('Always update user') ) From 78133b0c60448e410f24c5f4a78c30b47fa8509c Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 15 Aug 2022 17:39:54 +0800 Subject: [PATCH 086/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=90=8E?= =?UTF-8?q?=E5=8F=B0=E6=89=8B=E6=9C=BA=E5=8F=B7=E6=A0=A1=E9=AA=8C=20(#8747?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/settings/serializers/auth/sms.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/settings/serializers/auth/sms.py b/apps/settings/serializers/auth/sms.py index d3f96b33f..1278dea06 100644 --- a/apps/settings/serializers/auth/sms.py +++ b/apps/settings/serializers/auth/sms.py @@ -2,6 +2,7 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers from common.drf.fields import EncryptedField +from common.validators import PhoneValidator from common.sdk.sms import BACKENDS __all__ = [ @@ -23,7 +24,10 @@ class SignTmplPairSerializer(serializers.Serializer): class BaseSMSSettingSerializer(serializers.Serializer): - SMS_TEST_PHONE = serializers.CharField(max_length=256, required=False, allow_blank=True, label=_('Test phone')) + SMS_TEST_PHONE = serializers.CharField( + max_length=256, required=False, validators=[PhoneValidator(), ], + allow_blank=True, label=_('Test phone') + ) def to_representation(self, instance): data = super().to_representation(instance) From 2f8a07e665973058cdb4a1d5b1a42220eac26021 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 16 Aug 2022 13:56:19 +0800 Subject: [PATCH 087/104] =?UTF-8?q?perf:=20=E6=89=B9=E9=87=8F=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E6=96=B0=E5=A2=9E=E8=BF=87=E6=BB=A4=E9=80=89=E9=A1=B9?= =?UTF-8?q?=20(#8749)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/audits/api.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/audits/api.py b/apps/audits/api.py index fb1efe989..ca0e4d86a 100644 --- a/apps/audits/api.py +++ b/apps/audits/api.py @@ -126,9 +126,12 @@ class CommandExecutionViewSet(ListModelMixin, OrgGenericViewSet): class CommandExecutionHostRelationViewSet(OrgRelationMixin, OrgBulkModelViewSet): serializer_class = CommandExecutionHostsRelationSerializer m2m_field = CommandExecution.hosts.field - filterset_fields = [ - 'id', 'asset', 'commandexecution' - ] + filterset_fields = { + 'id': ['exact'], + 'asset': ['exact'], + 'asset__hostname': ['icontains'], + 'commandexecution': ['exact'], + } search_fields = ('asset__hostname', ) http_method_names = ['options', 'get'] rbac_perms = { From 4cad5affecc147d9028691d9cf81c4d22e0a0adb Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 16 Aug 2022 17:15:21 +0800 Subject: [PATCH 088/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=B7=A5?= =?UTF-8?q?=E5=8D=95=E7=81=AB=E7=8B=90=E6=B5=8F=E8=A7=88=E5=99=A8=E4=B8=8A?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=B1=95=E7=A4=BA=20(#8753)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/tickets/notifications.py | 2 +- apps/tickets/templates/tickets/ticket_approve_diff.html | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/tickets/notifications.py b/apps/tickets/notifications.py index 3fa0e5a82..26997b0dc 100644 --- a/apps/tickets/notifications.py +++ b/apps/tickets/notifications.py @@ -87,7 +87,7 @@ class BaseTicketMessage(UserMessage): @property def spec_items(self): fields = self.ticket._meta.local_fields + self.ticket._meta.local_many_to_many - excludes = ['ticket_ptr'] + excludes = ['ticket_ptr', 'flow'] item_names = [field.name for field in fields if field.name not in excludes] return self._get_fields_items(item_names) diff --git a/apps/tickets/templates/tickets/ticket_approve_diff.html b/apps/tickets/templates/tickets/ticket_approve_diff.html index 9fe6b80e0..8426b34ed 100644 --- a/apps/tickets/templates/tickets/ticket_approve_diff.html +++ b/apps/tickets/templates/tickets/ticket_approve_diff.html @@ -2,6 +2,7 @@

{{ approve_info }}

+{% if content %}
@@ -20,5 +21,6 @@
+{% endif %} From 68841d1f15e7877b50877d8394d8cfb7ec7b51da Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 16 Aug 2022 17:24:58 +0800 Subject: [PATCH 089/104] =?UTF-8?q?fix:=20=E9=85=8D=E7=BD=AE=E4=BB=85?= =?UTF-8?q?=E5=B7=B2=E5=AD=98=E5=9C=A8=E7=94=A8=E6=88=B7=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E5=90=8E=20cas=E7=94=A8=E6=88=B7=E9=A6=96=E6=AC=A1=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E6=8A=A5403=20(#8752)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/authentication/backends/cas/urls.py | 3 ++- apps/authentication/backends/cas/views.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 apps/authentication/backends/cas/views.py diff --git a/apps/authentication/backends/cas/urls.py b/apps/authentication/backends/cas/urls.py index 39a838b6a..376ce2332 100644 --- a/apps/authentication/backends/cas/urls.py +++ b/apps/authentication/backends/cas/urls.py @@ -3,9 +3,10 @@ from django.urls import path import django_cas_ng.views +from .views import CASLoginView urlpatterns = [ - path('login/', django_cas_ng.views.LoginView.as_view(), name='cas-login'), + path('login/', CASLoginView.as_view(), name='cas-login'), path('logout/', django_cas_ng.views.LogoutView.as_view(), name='cas-logout'), path('callback/', django_cas_ng.views.CallbackView.as_view(), name='cas-proxy-callback'), ] diff --git a/apps/authentication/backends/cas/views.py b/apps/authentication/backends/cas/views.py new file mode 100644 index 000000000..f74e46e9c --- /dev/null +++ b/apps/authentication/backends/cas/views.py @@ -0,0 +1,15 @@ +from django_cas_ng.views import LoginView +from django.core.exceptions import PermissionDenied +from django.http import HttpResponseRedirect + +__all__ = ['LoginView'] + + +class CASLoginView(LoginView): + def get(self, request): + try: + return super().get(request) + except PermissionDenied: + return HttpResponseRedirect('/') + + From d405bae2058cc9641c2c55d2c03473b2316a8b49 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 16 Aug 2022 17:46:17 +0800 Subject: [PATCH 090/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=AE=A4?= =?UTF-8?q?=E8=AF=81=E5=A4=B1=E8=B4=A5=E5=90=8E=E9=94=99=E8=AF=AF=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E6=80=BB=E6=98=AF=20IP=20block=20=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(#8755)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jiangjie.Bai --- apps/authentication/errors/failed.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/authentication/errors/failed.py b/apps/authentication/errors/failed.py index ec43d1b73..c85695fe5 100644 --- a/apps/authentication/errors/failed.py +++ b/apps/authentication/errors/failed.py @@ -56,7 +56,8 @@ class BlockGlobalIpLoginError(AuthFailedError): error = 'block_global_ip_login' def __init__(self, username, ip, **kwargs): - self.msg = const.block_ip_login_msg.format(settings.SECURITY_LOGIN_IP_LIMIT_TIME) + if not self.msg: + self.msg = const.block_ip_login_msg.format(settings.SECURITY_LOGIN_IP_LIMIT_TIME) LoginIpBlockUtil(ip).set_block_if_need() super().__init__(username=username, ip=ip, **kwargs) @@ -66,22 +67,21 @@ class CredentialError( BlockGlobalIpLoginError, AuthFailedError ): def __init__(self, error, username, ip, request): - super().__init__(error=error, username=username, ip=ip, request=request) util = LoginBlockUtil(username, ip) times_remainder = util.get_remainder_times() block_time = settings.SECURITY_LOGIN_LIMIT_TIME - if times_remainder < 1: self.msg = const.block_user_login_msg.format(settings.SECURITY_LOGIN_LIMIT_TIME) - return - - default_msg = const.invalid_login_msg.format( - times_try=times_remainder, block_time=block_time - ) - if error == const.reason_password_failed: - self.msg = default_msg else: - self.msg = const.reason_choices.get(error, default_msg) + default_msg = const.invalid_login_msg.format( + times_try=times_remainder, block_time=block_time + ) + if error == const.reason_password_failed: + self.msg = default_msg + else: + self.msg = const.reason_choices.get(error, default_msg) + # 先处理 msg 在 super,记录日志时原因才准确 + super().__init__(error=error, username=username, ip=ip, request=request) class MFAFailedError(AuthFailedNeedLogMixin, AuthFailedError): From 7d0a19635adca26e2429c4b8dceab0f133d4c946 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 17 Aug 2022 14:45:02 +0800 Subject: [PATCH 091/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E7=AC=A6=E5=90=88=E6=8B=92=E7=BB=9D=E6=97=B6=20?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E6=97=A5=E5=BF=97=E7=B1=BB=E5=9E=8B=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E9=97=AE=E9=A2=98=20(#8758)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- .../templates/authentication/login_wait_confirm.html | 5 ++++- apps/static/js/jumpserver.js | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/authentication/templates/authentication/login_wait_confirm.html b/apps/authentication/templates/authentication/login_wait_confirm.html index bd94c1986..a74c8db26 100644 --- a/apps/authentication/templates/authentication/login_wait_confirm.html +++ b/apps/authentication/templates/authentication/login_wait_confirm.html @@ -98,7 +98,10 @@ function doRequestAuth() { }, error: function (text, data) { }, - flash_message: false + beforeSend: function(request) { + request.setRequestHeader("X-JMS-LOGIN-TYPE", "W"); + }, + flash_message: false, // 是否显示flash消息 }) } function initClipboard() { diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index 3edf445b0..e3537cb84 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -270,11 +270,13 @@ function requestApi(props) { if (typeof(dataBody) === "object") { dataBody = JSON.stringify(dataBody) } + var beforeSend = props.beforeSend || function (request) {} $.ajax({ url: props.url, type: props.method || "PATCH", data: dataBody, + beforeSend: beforeSend, contentType: props.content_type || "application/json; charset=utf-8", dataType: props.data_type || "json" }).done(function (data, textStatue, jqXHR) { From 867ad94a302b15ed1f035ce07c97b43b2de96c68 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 17 Aug 2022 15:20:42 +0800 Subject: [PATCH 092/104] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E8=AE=A4?= =?UTF-8?q?=E8=AF=81=E9=87=8D=E5=AE=9A=E5=90=91=E5=9C=B0=E5=9D=80=20scheme?= =?UTF-8?q?=20=E5=8F=96=E5=80=BC=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/utils.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/authentication/utils.py b/apps/authentication/utils.py index a7f18648b..a0db9061c 100644 --- a/apps/authentication/utils.py +++ b/apps/authentication/utils.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # import ipaddress -from urllib.parse import urljoin +from urllib.parse import urljoin, urlparse from django.conf import settings from django.utils.translation import ugettext_lazy as _ @@ -39,7 +39,11 @@ def build_absolute_uri(request, path=None): """ Build absolute redirect """ if path is None: path = '/' - redirect_uri = request.build_absolute_uri(path) + site_url = urlparse(settings.SITE_URL) + scheme = site_url.scheme or request.scheme + host = request.get_host() + url = f'{scheme}://{host}' + redirect_uri = urljoin(url, path) return redirect_uri @@ -50,6 +54,5 @@ def build_absolute_uri_for_oidc(request, path=None): if settings.BASE_SITE_URL: # OIDC 专用配置项 redirect_uri = urljoin(settings.BASE_SITE_URL, path) - else: - redirect_uri = request.build_absolute_uri(path) - return redirect_uri + return redirect_uri + return build_absolute_uri(request, path=path) From 3ab634d88ebc098d764bbb4bce5451f940f0aa29 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 17 Aug 2022 16:40:56 +0800 Subject: [PATCH 093/104] =?UTF-8?q?fix:=20=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 83 ++++++++++++++-------------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 83 ++++++++++++++-------------- 4 files changed, 88 insertions(+), 86 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 66532110b..4378759fd 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62879a50d21ad41c43bf748f6045bf30a933d5d08021d97dc1c68e23f6bf8e65 -size 130015 +oid sha256:d7d4ace7d7ec976b0321bde41789f994f02e3ab6f034828cbfb7e675a313611f +size 131531 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 655e05db0..a5cb194ad 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-08-10 19:03+0800\n" +"POT-Creation-Date: 2022-08-17 16:28+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -352,7 +352,7 @@ msgstr "カテゴリ表示" #: assets/serializers/cmd_filter.py:34 assets/serializers/system_user.py:34 #: audits/serializers.py:29 authentication/serializers/connection_token.py:22 #: perms/serializers/application/permission.py:19 -#: tickets/serializers/flow.py:48 tickets/serializers/ticket/ticket.py:17 +#: tickets/serializers/flow.py:49 tickets/serializers/ticket/ticket.py:17 msgid "Type display" msgstr "タイプ表示" @@ -393,7 +393,7 @@ msgstr "クラスター" #: applications/serializers/attrs/application_category/db.py:11 #: ops/models/adhoc.py:157 settings/serializers/auth/radius.py:14 -#: settings/serializers/auth/sms.py:52 terminal/models/endpoint.py:11 +#: settings/serializers/auth/sms.py:56 terminal/models/endpoint.py:11 #: xpack/plugins/cloud/serializers/account_attrs.py:72 msgid "Host" msgstr "ホスト" @@ -407,7 +407,7 @@ msgstr "ホスト" #: applications/serializers/attrs/application_type/redis.py:10 #: applications/serializers/attrs/application_type/sqlserver.py:10 #: assets/models/asset.py:214 assets/models/domain.py:62 -#: settings/serializers/auth/radius.py:15 settings/serializers/auth/sms.py:53 +#: settings/serializers/auth/radius.py:15 settings/serializers/auth/sms.py:57 #: xpack/plugins/cloud/serializers/account_attrs.py:73 msgid "Port" msgstr "ポート" @@ -962,7 +962,7 @@ msgstr "資産グループ" msgid "Default asset group" msgstr "デフォルトアセットグループ" -#: assets/models/label.py:19 assets/models/node.py:546 settings/models.py:34 +#: assets/models/label.py:19 assets/models/node.py:553 settings/models.py:34 msgid "Value" msgstr "値" @@ -970,32 +970,32 @@ msgstr "値" msgid "Label" msgstr "ラベル" -#: assets/models/node.py:151 +#: assets/models/node.py:158 msgid "New node" msgstr "新しいノード" -#: assets/models/node.py:474 +#: assets/models/node.py:481 msgid "empty" msgstr "空" -#: assets/models/node.py:545 perms/models/asset_permission.py:101 +#: assets/models/node.py:552 perms/models/asset_permission.py:101 msgid "Key" msgstr "キー" -#: assets/models/node.py:547 assets/serializers/node.py:20 +#: assets/models/node.py:554 assets/serializers/node.py:20 msgid "Full value" msgstr "フルバリュー" -#: assets/models/node.py:550 perms/models/asset_permission.py:102 +#: assets/models/node.py:557 perms/models/asset_permission.py:102 msgid "Parent key" msgstr "親キー" -#: assets/models/node.py:559 assets/serializers/system_user.py:267 +#: assets/models/node.py:566 assets/serializers/system_user.py:267 #: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:70 msgid "Node" msgstr "ノード" -#: assets/models/node.py:562 +#: assets/models/node.py:569 msgid "Can match node" msgstr "ノードを一致させることができます" @@ -2031,15 +2031,15 @@ msgstr "本を飛ばすは拘束されていません" msgid "Your password is invalid" msgstr "パスワードが無効です" -#: authentication/errors/redirect.py:79 authentication/mixins.py:306 +#: authentication/errors/redirect.py:85 authentication/mixins.py:306 msgid "Your password is too simple, please change it for security" msgstr "パスワードがシンプルすぎるので、セキュリティのために変更してください" -#: authentication/errors/redirect.py:87 authentication/mixins.py:313 +#: authentication/errors/redirect.py:93 authentication/mixins.py:313 msgid "You should to change your password before login" msgstr "ログインする前にパスワードを変更する必要があります" -#: authentication/errors/redirect.py:95 authentication/mixins.py:320 +#: authentication/errors/redirect.py:101 authentication/mixins.py:320 msgid "Your password has expired, please reset before logging in" msgstr "" "パスワードの有効期限が切れました。ログインする前にリセットしてください。" @@ -2468,10 +2468,15 @@ msgstr "リンクのコピー" msgid "Return" msgstr "返品" -#: authentication/templates/authentication/login_wait_confirm.html:113 +#: authentication/templates/authentication/login_wait_confirm.html:116 msgid "Copy success" msgstr "コピー成功" +#: authentication/utils.py:28 common/utils/ip/geoip/utils.py:24 +#: xpack/plugins/cloud/const.py:24 +msgid "LAN" +msgstr "ローカルエリアネットワーク" + #: authentication/views/dingtalk.py:41 msgid "DingTalk Error, Please contact your system administrator" msgstr "DingTalkエラー、システム管理者に連絡してください" @@ -2766,10 +2771,6 @@ msgstr "確認コードが正しくありません" msgid "Please wait {} seconds before sending" msgstr "{} 秒待ってから送信してください" -#: common/utils/ip/geoip/utils.py:24 xpack/plugins/cloud/const.py:24 -msgid "LAN" -msgstr "ローカルエリアネットワーク" - #: common/utils/ip/geoip/utils.py:26 common/utils/ip/utils.py:78 msgid "Invalid ip" msgstr "無効なIP" @@ -3049,7 +3050,7 @@ msgstr "組織のリソース ({}) は削除できません" msgid "App organizations" msgstr "アプリ組織" -#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:85 +#: orgs/mixins/models.py:56 orgs/mixins/serializers.py:25 orgs/models.py:85 #: orgs/models.py:217 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 @@ -3847,50 +3848,50 @@ msgstr "SP プライベートキー" msgid "SP cert" msgstr "SP 証明書" -#: settings/serializers/auth/sms.py:14 +#: settings/serializers/auth/sms.py:15 msgid "Enable SMS" msgstr "SMSの有効化" -#: settings/serializers/auth/sms.py:16 +#: settings/serializers/auth/sms.py:17 msgid "SMS provider / Protocol" msgstr "SMSプロバイダ / プロトコル" -#: settings/serializers/auth/sms.py:21 settings/serializers/auth/sms.py:39 -#: settings/serializers/auth/sms.py:47 settings/serializers/auth/sms.py:58 +#: settings/serializers/auth/sms.py:22 settings/serializers/auth/sms.py:43 +#: settings/serializers/auth/sms.py:51 settings/serializers/auth/sms.py:62 #: settings/serializers/email.py:65 msgid "Signature" msgstr "署名" -#: settings/serializers/auth/sms.py:22 settings/serializers/auth/sms.py:40 -#: settings/serializers/auth/sms.py:48 +#: settings/serializers/auth/sms.py:23 settings/serializers/auth/sms.py:44 +#: settings/serializers/auth/sms.py:52 msgid "Template code" msgstr "テンプレートコード" -#: settings/serializers/auth/sms.py:26 +#: settings/serializers/auth/sms.py:29 msgid "Test phone" msgstr "テスト電話" -#: settings/serializers/auth/sms.py:54 +#: settings/serializers/auth/sms.py:58 msgid "Enterprise code(SP id)" msgstr "企業コード(SP id)" -#: settings/serializers/auth/sms.py:55 +#: settings/serializers/auth/sms.py:59 msgid "Shared secret(Shared secret)" msgstr "パスワードを共有する(Shared secret)" -#: settings/serializers/auth/sms.py:56 +#: settings/serializers/auth/sms.py:60 msgid "Original number(Src id)" msgstr "元の番号(Src id)" -#: settings/serializers/auth/sms.py:57 +#: settings/serializers/auth/sms.py:61 msgid "Business type(Service id)" msgstr "ビジネス・タイプ(Service id)" -#: settings/serializers/auth/sms.py:60 +#: settings/serializers/auth/sms.py:64 msgid "Template" msgstr "テンプレート" -#: settings/serializers/auth/sms.py:61 +#: settings/serializers/auth/sms.py:65 #, python-brace-format msgid "" "Template need contain {code} and Signature + template length does not exceed " @@ -3901,12 +3902,12 @@ msgstr "" "満です。たとえば、認証コードは{code}で、有効期間は5分です。他の人には言わない" "でください。" -#: settings/serializers/auth/sms.py:70 +#: settings/serializers/auth/sms.py:74 #, python-brace-format msgid "The template needs to contain {code}" msgstr "テンプレートには{code}を含める必要があります" -#: settings/serializers/auth/sms.py:73 +#: settings/serializers/auth/sms.py:77 msgid "Signature + Template must not exceed 65 words" msgstr "署名+テンプレートの長さは65文字以内" @@ -5427,11 +5428,11 @@ msgstr "ボディ" msgid "Approve level" msgstr "レベルを承認する" -#: tickets/models/flow.py:25 tickets/serializers/flow.py:14 +#: tickets/models/flow.py:25 tickets/serializers/flow.py:15 msgid "Approve strategy" msgstr "戦略を承認する" -#: tickets/models/flow.py:30 tickets/serializers/flow.py:15 +#: tickets/models/flow.py:30 tickets/serializers/flow.py:16 msgid "Assignees" msgstr "アシニーズ" @@ -5574,15 +5575,15 @@ msgstr "チケットが処理されました。プロセッサー- {}" msgid "Ticket has processed - {} ({})" msgstr "チケットが処理済み- {} ({})" -#: tickets/serializers/flow.py:16 +#: tickets/serializers/flow.py:17 msgid "Assignees display" msgstr "受付者名" -#: tickets/serializers/flow.py:42 +#: tickets/serializers/flow.py:43 msgid "Please select the Assignees" msgstr "受付をお選びください" -#: tickets/serializers/flow.py:68 +#: tickets/serializers/flow.py:69 msgid "The current organization type already exists" msgstr "現在の組織タイプは既に存在します。" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 034a33cb1..1b7f36e83 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:adb46a0b7afdddc1b8a399e0fc0a0926012308ddce0ff487b68cb6c209d74039 -size 107133 +oid sha256:114dc04325f5a778a7cd0fb1b4d5aa71dfb60ada57b1b4f3ae43d89c1c818e0f +size 108398 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index d36c5f037..0eed25b45 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-08-10 19:03+0800\n" +"POT-Creation-Date: 2022-08-17 16:28+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -347,7 +347,7 @@ msgstr "类别名称" #: assets/serializers/cmd_filter.py:34 assets/serializers/system_user.py:34 #: audits/serializers.py:29 authentication/serializers/connection_token.py:22 #: perms/serializers/application/permission.py:19 -#: tickets/serializers/flow.py:48 tickets/serializers/ticket/ticket.py:17 +#: tickets/serializers/flow.py:49 tickets/serializers/ticket/ticket.py:17 msgid "Type display" msgstr "类型名称" @@ -388,7 +388,7 @@ msgstr "集群" #: applications/serializers/attrs/application_category/db.py:11 #: ops/models/adhoc.py:157 settings/serializers/auth/radius.py:14 -#: settings/serializers/auth/sms.py:52 terminal/models/endpoint.py:11 +#: settings/serializers/auth/sms.py:56 terminal/models/endpoint.py:11 #: xpack/plugins/cloud/serializers/account_attrs.py:72 msgid "Host" msgstr "主机" @@ -402,7 +402,7 @@ msgstr "主机" #: applications/serializers/attrs/application_type/redis.py:10 #: applications/serializers/attrs/application_type/sqlserver.py:10 #: assets/models/asset.py:214 assets/models/domain.py:62 -#: settings/serializers/auth/radius.py:15 settings/serializers/auth/sms.py:53 +#: settings/serializers/auth/radius.py:15 settings/serializers/auth/sms.py:57 #: xpack/plugins/cloud/serializers/account_attrs.py:73 msgid "Port" msgstr "端口" @@ -957,7 +957,7 @@ msgstr "资产组" msgid "Default asset group" msgstr "默认资产组" -#: assets/models/label.py:19 assets/models/node.py:546 settings/models.py:34 +#: assets/models/label.py:19 assets/models/node.py:553 settings/models.py:34 msgid "Value" msgstr "值" @@ -965,32 +965,32 @@ msgstr "值" msgid "Label" msgstr "标签" -#: assets/models/node.py:151 +#: assets/models/node.py:158 msgid "New node" msgstr "新节点" -#: assets/models/node.py:474 +#: assets/models/node.py:481 msgid "empty" msgstr "空" -#: assets/models/node.py:545 perms/models/asset_permission.py:101 +#: assets/models/node.py:552 perms/models/asset_permission.py:101 msgid "Key" msgstr "键" -#: assets/models/node.py:547 assets/serializers/node.py:20 +#: assets/models/node.py:554 assets/serializers/node.py:20 msgid "Full value" msgstr "全称" -#: assets/models/node.py:550 perms/models/asset_permission.py:102 +#: assets/models/node.py:557 perms/models/asset_permission.py:102 msgid "Parent key" msgstr "ssh私钥" -#: assets/models/node.py:559 assets/serializers/system_user.py:267 +#: assets/models/node.py:566 assets/serializers/system_user.py:267 #: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:70 msgid "Node" msgstr "节点" -#: assets/models/node.py:562 +#: assets/models/node.py:569 msgid "Can match node" msgstr "可以匹配节点" @@ -2011,15 +2011,15 @@ msgstr "没有绑定飞书" msgid "Your password is invalid" msgstr "您的密码无效" -#: authentication/errors/redirect.py:79 authentication/mixins.py:306 +#: authentication/errors/redirect.py:85 authentication/mixins.py:306 msgid "Your password is too simple, please change it for security" msgstr "你的密码过于简单,为了安全,请修改" -#: authentication/errors/redirect.py:87 authentication/mixins.py:313 +#: authentication/errors/redirect.py:93 authentication/mixins.py:313 msgid "You should to change your password before login" msgstr "登录完成前,请先修改密码" -#: authentication/errors/redirect.py:95 authentication/mixins.py:320 +#: authentication/errors/redirect.py:101 authentication/mixins.py:320 msgid "Your password has expired, please reset before logging in" msgstr "您的密码已过期,先修改再登录" @@ -2434,10 +2434,15 @@ msgstr "复制链接" msgid "Return" msgstr "返回" -#: authentication/templates/authentication/login_wait_confirm.html:113 +#: authentication/templates/authentication/login_wait_confirm.html:116 msgid "Copy success" msgstr "复制成功" +#: authentication/utils.py:28 common/utils/ip/geoip/utils.py:24 +#: xpack/plugins/cloud/const.py:24 +msgid "LAN" +msgstr "局域网" + #: authentication/views/dingtalk.py:41 msgid "DingTalk Error, Please contact your system administrator" msgstr "钉钉错误,请联系系统管理员" @@ -2732,10 +2737,6 @@ msgstr "验证码错误" msgid "Please wait {} seconds before sending" msgstr "请在 {} 秒后发送" -#: common/utils/ip/geoip/utils.py:24 xpack/plugins/cloud/const.py:24 -msgid "LAN" -msgstr "局域网" - #: common/utils/ip/geoip/utils.py:26 common/utils/ip/utils.py:78 msgid "Invalid ip" msgstr "无效IP" @@ -3009,7 +3010,7 @@ msgstr "组织存在资源 ({}) 不能被删除" msgid "App organizations" msgstr "组织管理" -#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:85 +#: orgs/mixins/models.py:56 orgs/mixins/serializers.py:25 orgs/models.py:85 #: orgs/models.py:217 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 @@ -3804,50 +3805,50 @@ msgstr "SP 密钥" msgid "SP cert" msgstr "SP 证书" -#: settings/serializers/auth/sms.py:14 +#: settings/serializers/auth/sms.py:15 msgid "Enable SMS" msgstr "启用 SMS" -#: settings/serializers/auth/sms.py:16 +#: settings/serializers/auth/sms.py:17 msgid "SMS provider / Protocol" msgstr "短信服务商 / 协议" -#: settings/serializers/auth/sms.py:21 settings/serializers/auth/sms.py:39 -#: settings/serializers/auth/sms.py:47 settings/serializers/auth/sms.py:58 +#: settings/serializers/auth/sms.py:22 settings/serializers/auth/sms.py:43 +#: settings/serializers/auth/sms.py:51 settings/serializers/auth/sms.py:62 #: settings/serializers/email.py:65 msgid "Signature" msgstr "签名" -#: settings/serializers/auth/sms.py:22 settings/serializers/auth/sms.py:40 -#: settings/serializers/auth/sms.py:48 +#: settings/serializers/auth/sms.py:23 settings/serializers/auth/sms.py:44 +#: settings/serializers/auth/sms.py:52 msgid "Template code" msgstr "模板" -#: settings/serializers/auth/sms.py:26 +#: settings/serializers/auth/sms.py:29 msgid "Test phone" msgstr "测试手机号" -#: settings/serializers/auth/sms.py:54 +#: settings/serializers/auth/sms.py:58 msgid "Enterprise code(SP id)" msgstr "企业代码(SP id)" -#: settings/serializers/auth/sms.py:55 +#: settings/serializers/auth/sms.py:59 msgid "Shared secret(Shared secret)" msgstr "共享密码(Shared secret)" -#: settings/serializers/auth/sms.py:56 +#: settings/serializers/auth/sms.py:60 msgid "Original number(Src id)" msgstr "原始号码(Src id)" -#: settings/serializers/auth/sms.py:57 +#: settings/serializers/auth/sms.py:61 msgid "Business type(Service id)" msgstr "业务类型(Service id)" -#: settings/serializers/auth/sms.py:60 +#: settings/serializers/auth/sms.py:64 msgid "Template" msgstr "模板" -#: settings/serializers/auth/sms.py:61 +#: settings/serializers/auth/sms.py:65 #, python-brace-format msgid "" "Template need contain {code} and Signature + template length does not exceed " @@ -3857,12 +3858,12 @@ msgstr "" "模板需要包含 {code},并且模板+签名长度不能超过67个字。例如, 您的验证码是 " "{code}, 有效期为5分钟。请不要泄露给其他人。" -#: settings/serializers/auth/sms.py:70 +#: settings/serializers/auth/sms.py:74 #, python-brace-format msgid "The template needs to contain {code}" msgstr "模板需要包含 {code}" -#: settings/serializers/auth/sms.py:73 +#: settings/serializers/auth/sms.py:77 msgid "Signature + Template must not exceed 65 words" msgstr "模板+签名不能超过65个字" @@ -5346,11 +5347,11 @@ msgstr "内容" msgid "Approve level" msgstr "审批级别" -#: tickets/models/flow.py:25 tickets/serializers/flow.py:14 +#: tickets/models/flow.py:25 tickets/serializers/flow.py:15 msgid "Approve strategy" msgstr "审批策略" -#: tickets/models/flow.py:30 tickets/serializers/flow.py:15 +#: tickets/models/flow.py:30 tickets/serializers/flow.py:16 msgid "Assignees" msgstr "受理人" @@ -5493,15 +5494,15 @@ msgstr "你的工单已被处理, 处理人 - {}" msgid "Ticket has processed - {} ({})" msgstr "你的工单已被处理, 处理人 - {} ({})" -#: tickets/serializers/flow.py:16 +#: tickets/serializers/flow.py:17 msgid "Assignees display" msgstr "受理人名称" -#: tickets/serializers/flow.py:42 +#: tickets/serializers/flow.py:43 msgid "Please select the Assignees" msgstr "请选择受理人" -#: tickets/serializers/flow.py:68 +#: tickets/serializers/flow.py:69 msgid "The current organization type already exists" msgstr "当前组织已存在该类型" From ccd6b01020c3f706bb3eca1f4151fa1e107f1510 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 17 Aug 2022 18:33:23 +0800 Subject: [PATCH 094/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=BC=80?= =?UTF-8?q?=E5=90=AF=E4=BB=85=E5=85=81=E8=AE=B8=E5=B7=B2=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=99=BB=E5=BD=95=E5=B9=B6=E4=B8=94=E6=98=AF?= =?UTF-8?q?=E7=AC=AC=E4=B8=89=E6=96=B9=E7=94=A8=E6=88=B7=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E6=97=B6=E6=8A=A5=E9=94=99instance=E6=B2=A1=E6=9C=89id?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/orgs/signal_handlers/common.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/orgs/signal_handlers/common.py b/apps/orgs/signal_handlers/common.py index 48576a828..876613ba1 100644 --- a/apps/orgs/signal_handlers/common.py +++ b/apps/orgs/signal_handlers/common.py @@ -147,6 +147,9 @@ def _clear_users_from_org(org, users): @receiver(post_save, sender=User) @on_transaction_commit def on_user_created_set_default_org(sender, instance, created, **kwargs): + if not instance.id: + # 用户已被手动删除,instance.orgs 时会使用 id 进行查找报错,所以判断不存在id时不做处理 + return if not created: return if instance.orgs.count() > 0: From b347acd5ecdd6fe513a44f2e3c5d318465b715c8 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 17 Aug 2022 18:50:47 +0800 Subject: [PATCH 095/104] =?UTF-8?q?perf:=20=E6=9B=BF=E6=8D=A2=20mirrors=20?= =?UTF-8?q?(#8765)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf: 替换 mirrors * perf: 使用中科大 mirrors Co-authored-by: 吴小白 <296015668@qq.com> --- Dockerfile | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index de4022338..c0fc19fa2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,24 +29,22 @@ ARG TOOLS=" \ redis-tools \ telnet \ vim \ - unzip \ + unzip \ wget" -RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list \ - && sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list \ - && apt update && sleep 1 && apt update \ - && apt -y install ${BUILD_DEPENDENCIES} \ - && apt -y install ${DEPENDENCIES} \ - && apt -y install ${TOOLS} \ +RUN sed -i 's@http://.*.debian.org@http://mirrors.ustc.edu.cn@g' /etc/apt/sources.list \ + && apt-get update \ + && apt-get -y install --no-install-recommends ${BUILD_DEPENDENCIES} \ + && apt-get -y install --no-install-recommends ${DEPENDENCIES} \ + && apt-get -y install --no-install-recommends ${TOOLS} \ && localedef -c -f UTF-8 -i zh_CN zh_CN.UTF-8 \ && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && mkdir -p /root/.ssh/ \ && echo "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null" > /root/.ssh/config \ && sed -i "s@# alias l@alias l@g" ~/.bashrc \ && echo "set mouse-=a" > ~/.vimrc \ - && rm -rf /var/lib/apt/lists/* \ - && mv /bin/sh /bin/sh.bak \ - && ln -s /bin/bash /bin/sh + && echo "no" | dpkg-reconfigure dash \ + && rm -rf /var/lib/apt/lists/* ARG TARGETARCH ARG ORACLE_LIB_MAJOR=19 From 3e69e6840b28cf039519e7a136bf935607df2110 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 18 Aug 2022 10:30:20 +0800 Subject: [PATCH 096/104] =?UTF-8?q?fix:=20oauth2=E4=B8=8D=E5=B1=9E?= =?UTF-8?q?=E4=BA=8E=E5=AF=86=E7=A0=81=E8=AE=A4=E8=AF=81=20(#8771)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/users/models/user.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 9fd6ea0b9..78d5eb540 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -800,7 +800,8 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): def is_password_authenticate(self): cas = self.Source.cas saml2 = self.Source.saml2 - return self.source not in [cas, saml2] + oauth2 = self.Source.oauth2 + return self.source not in [cas, saml2, oauth2] def set_unprovide_attr_if_need(self): if not self.name: From 382112ee3354f701166273704539b8d0964be3af Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 18 Aug 2022 11:48:58 +0800 Subject: [PATCH 097/104] =?UTF-8?q?perf:=20=E6=89=B9=E9=87=8F=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E6=90=9C=E7=B4=A2=E4=BC=98=E5=8C=96=20(#8772)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/audits/api.py | 8 ++------ apps/audits/filters.py | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/apps/audits/api.py b/apps/audits/api.py index ca0e4d86a..ff1bb0309 100644 --- a/apps/audits/api.py +++ b/apps/audits/api.py @@ -12,6 +12,7 @@ from common.api import CommonGenericViewSet from orgs.mixins.api import OrgGenericViewSet, OrgBulkModelViewSet, OrgRelationMixin from orgs.utils import current_org from ops.models import CommandExecution +from . import filters from .models import FTPLog, UserLoginLog, OperateLog, PasswordChangeLog from .serializers import FTPLogSerializer, UserLoginLogSerializer, CommandExecutionSerializer from .serializers import OperateLogSerializer, PasswordChangeLogSerializer, CommandExecutionHostsRelationSerializer @@ -126,12 +127,7 @@ class CommandExecutionViewSet(ListModelMixin, OrgGenericViewSet): class CommandExecutionHostRelationViewSet(OrgRelationMixin, OrgBulkModelViewSet): serializer_class = CommandExecutionHostsRelationSerializer m2m_field = CommandExecution.hosts.field - filterset_fields = { - 'id': ['exact'], - 'asset': ['exact'], - 'asset__hostname': ['icontains'], - 'commandexecution': ['exact'], - } + filterset_class = filters.CommandExecutionFilter search_fields = ('asset__hostname', ) http_method_names = ['options', 'get'] rbac_perms = { diff --git a/apps/audits/filters.py b/apps/audits/filters.py index 470c2c4b5..b8bf466ec 100644 --- a/apps/audits/filters.py +++ b/apps/audits/filters.py @@ -1,10 +1,14 @@ +from django.db.models import F, Value +from django.db.models.functions import Concat +from django_filters.rest_framework import CharFilter from rest_framework import filters from rest_framework.compat import coreapi, coreschema from orgs.utils import current_org +from ops.models import CommandExecution +from common.drf.filters import BaseFilterSet - -__all__ = ['CurrentOrgMembersFilter'] +__all__ = ['CurrentOrgMembersFilter', 'CommandExecutionFilter'] class CurrentOrgMembersFilter(filters.BaseFilterBackend): @@ -30,3 +34,22 @@ class CurrentOrgMembersFilter(filters.BaseFilterBackend): else: queryset = queryset.filter(user__in=self._get_user_list()) return queryset + + +class CommandExecutionFilter(BaseFilterSet): + hostname_ip = CharFilter(method='filter_hostname_ip') + + class Meta: + model = CommandExecution.hosts.through + fields = ( + 'id', 'asset', 'commandexecution', 'hostname_ip' + ) + + def filter_hostname_ip(self, queryset, name, value): + queryset = queryset.annotate( + hostname_ip=Concat( + F('asset__hostname'), Value('('), + F('asset__ip'), Value(')') + ) + ).filter(hostname_ip__icontains=value) + return queryset From bb4da12366c4f8bc09a703dd8a57d7cd53a79d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com> Date: Wed, 17 Aug 2022 19:13:29 +0800 Subject: [PATCH 098/104] =?UTF-8?q?perf:=20=E6=9B=B4=E6=96=B0=20pypi=20?= =?UTF-8?q?=E9=95=9C=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index c0fc19fa2..e2ec06457 100644 --- a/Dockerfile +++ b/Dockerfile @@ -63,9 +63,9 @@ RUN mkdir -p /opt/oracle/ \ WORKDIR /tmp/build COPY ./requirements ./requirements -ARG PIP_MIRROR=https://mirrors.aliyun.com/pypi/simple/ +ARG PIP_MIRROR=https://pypi.douban.com/simple ENV PIP_MIRROR=$PIP_MIRROR -ARG PIP_JMS_MIRROR=https://mirrors.aliyun.com/pypi/simple/ +ARG PIP_JMS_MIRROR=https://pypi.douban.com/simple ENV PIP_JMS_MIRROR=$PIP_JMS_MIRROR # 因为以 jms 或者 jumpserver 开头的 mirror 上可能没有 RUN pip install --upgrade pip==20.2.4 setuptools==49.6.0 wheel==0.34.2 -i ${PIP_MIRROR} \ From 24a1738e731b604dc79b1eb281a1ac934869121b Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Fri, 19 Aug 2022 10:34:16 +0800 Subject: [PATCH 099/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E7=AB=AF=E6=B8=B2=E6=9F=93=E8=AF=B7=E6=B1=82=E7=BC=BA?= =?UTF-8?q?=E5=B0=91csrf=20token=20=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/authentication/login_wait_confirm.html | 3 --- apps/static/js/jumpserver.js | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/authentication/templates/authentication/login_wait_confirm.html b/apps/authentication/templates/authentication/login_wait_confirm.html index a74c8db26..6107b3bc8 100644 --- a/apps/authentication/templates/authentication/login_wait_confirm.html +++ b/apps/authentication/templates/authentication/login_wait_confirm.html @@ -98,9 +98,6 @@ function doRequestAuth() { }, error: function (text, data) { }, - beforeSend: function(request) { - request.setRequestHeader("X-JMS-LOGIN-TYPE", "W"); - }, flash_message: false, // 是否显示flash消息 }) } diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index e3537cb84..974652bb1 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -132,6 +132,7 @@ function setAjaxCSRFToken() { $.ajaxSetup({ beforeSend: function (xhr, settings) { + xhr.setRequestHeader("X-JMS-LOGIN-TYPE", "W"); if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } @@ -270,13 +271,11 @@ function requestApi(props) { if (typeof(dataBody) === "object") { dataBody = JSON.stringify(dataBody) } - var beforeSend = props.beforeSend || function (request) {} $.ajax({ url: props.url, type: props.method || "PATCH", data: dataBody, - beforeSend: beforeSend, contentType: props.content_type || "application/json; charset=utf-8", dataType: props.data_type || "json" }).done(function (data, textStatue, jqXHR) { From 8ae98887ee072ec567394db0fbf64087a70e8ba4 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Fri, 19 Aug 2022 14:19:47 +0800 Subject: [PATCH 100/104] =?UTF-8?q?Revert=20"fix:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E7=AB=AF=E6=B8=B2=E6=9F=93=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E7=BC=BA=E5=B0=91csrf=20token=20=E9=97=AE=E9=A2=98"=20(#8780)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 24a1738e731b604dc79b1eb281a1ac934869121b. --- .../templates/authentication/login_wait_confirm.html | 3 +++ apps/static/js/jumpserver.js | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/authentication/templates/authentication/login_wait_confirm.html b/apps/authentication/templates/authentication/login_wait_confirm.html index 6107b3bc8..a74c8db26 100644 --- a/apps/authentication/templates/authentication/login_wait_confirm.html +++ b/apps/authentication/templates/authentication/login_wait_confirm.html @@ -98,6 +98,9 @@ function doRequestAuth() { }, error: function (text, data) { }, + beforeSend: function(request) { + request.setRequestHeader("X-JMS-LOGIN-TYPE", "W"); + }, flash_message: false, // 是否显示flash消息 }) } diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index 974652bb1..e3537cb84 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -132,7 +132,6 @@ function setAjaxCSRFToken() { $.ajaxSetup({ beforeSend: function (xhr, settings) { - xhr.setRequestHeader("X-JMS-LOGIN-TYPE", "W"); if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } @@ -271,11 +270,13 @@ function requestApi(props) { if (typeof(dataBody) === "object") { dataBody = JSON.stringify(dataBody) } + var beforeSend = props.beforeSend || function (request) {} $.ajax({ url: props.url, type: props.method || "PATCH", data: dataBody, + beforeSend: beforeSend, contentType: props.content_type || "application/json; charset=utf-8", dataType: props.data_type || "json" }).done(function (data, textStatue, jqXHR) { From 1432fe16095ca4b604e72189b6f6184869733ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com> Date: Fri, 19 Aug 2022 13:59:48 +0800 Subject: [PATCH 101/104] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=20openssh-cli?= =?UTF-8?q?ent=20=E4=BE=9D=E8=B5=96=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements/deb_pkg.sh | 2 +- requirements/rpm_pkg.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements/deb_pkg.sh b/requirements/deb_pkg.sh index 3643d25d0..18d0b8f06 100644 --- a/requirements/deb_pkg.sh +++ b/requirements/deb_pkg.sh @@ -1,5 +1,5 @@ #!/bin/bash apt install \ g++ make iputils-ping default-libmysqlclient-dev libpq-dev \ - libffi-dev libldap2-dev libsasl2-dev sshpass pkg-config libxml2-dev \ + libffi-dev libldap2-dev libsasl2-dev openssh-client sshpass pkg-config libxml2-dev \ libxmlsec1-dev libxmlsec1-openssl libaio-dev freetds-dev diff --git a/requirements/rpm_pkg.sh b/requirements/rpm_pkg.sh index b926690dc..53df8bf0d 100644 --- a/requirements/rpm_pkg.sh +++ b/requirements/rpm_pkg.sh @@ -1,5 +1,5 @@ #!/bin/bash yum -y install \ - gcc-c++ sshpass mariadb-devel openldap-devel libxml2-devel \ + gcc-c++ sshpass mariadb-devel openldap-devel openssh-clients libxml2-devel \ xmlsec1-devel xmlsec1-openssl-devel libtool-ltdl-devel \ postgresql-devel From 37b150bc04d350db0725f19220574bc82570cbdf Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Fri, 19 Aug 2022 14:38:59 +0800 Subject: [PATCH 102/104] =?UTF-8?q?fix:=20=E8=A1=A8=E5=8D=95=E6=8F=90?= =?UTF-8?q?=E4=BA=A4csrftoken=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/authentication/login_wait_confirm.html | 6 +++--- apps/static/js/jumpserver.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/authentication/templates/authentication/login_wait_confirm.html b/apps/authentication/templates/authentication/login_wait_confirm.html index a74c8db26..157ee1d1a 100644 --- a/apps/authentication/templates/authentication/login_wait_confirm.html +++ b/apps/authentication/templates/authentication/login_wait_confirm.html @@ -79,6 +79,9 @@ function doRequestAuth() { requestApi({ url: url, method: "GET", + headers: { + "X-JMS-LOGIN-TYPE": "W" + }, success: function (data) { if (!data.error && data.msg === 'ok') { window.onbeforeunload = function(){}; @@ -98,9 +101,6 @@ function doRequestAuth() { }, error: function (text, data) { }, - beforeSend: function(request) { - request.setRequestHeader("X-JMS-LOGIN-TYPE", "W"); - }, flash_message: false, // 是否显示flash消息 }) } diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index e3537cb84..c95c06c2c 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -270,13 +270,13 @@ function requestApi(props) { if (typeof(dataBody) === "object") { dataBody = JSON.stringify(dataBody) } - var beforeSend = props.beforeSend || function (request) {} + var headers = props.headers || {} $.ajax({ url: props.url, type: props.method || "PATCH", + headers: headers, data: dataBody, - beforeSend: beforeSend, contentType: props.content_type || "application/json; charset=utf-8", dataType: props.data_type || "json" }).done(function (data, textStatue, jqXHR) { From 5f1b7ff8f950b6c11c023273bb3c52f29727a6a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com> Date: Sat, 20 Aug 2022 19:15:51 +0800 Subject: [PATCH 103/104] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index e2ec06457..7e6eac422 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,7 @@ ARG DEPENDENCIES=" \ libxmlsec1-dev \ libxmlsec1-openssl \ libaio-dev \ + openssh-client \ sshpass" ARG TOOLS=" \ From 60cb1f8136ac13dffa908e6a39a327557cccc402 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 22 Aug 2022 14:13:26 +0800 Subject: [PATCH 104/104] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=20gcm=20key=20padding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/utils/crypto.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/common/utils/crypto.py b/apps/common/utils/crypto.py index 5943ad9e3..0a75ee4e3 100644 --- a/apps/common/utils/crypto.py +++ b/apps/common/utils/crypto.py @@ -4,6 +4,7 @@ import re from Cryptodome.Cipher import AES, PKCS1_v1_5 from Cryptodome.Random import get_random_bytes from Cryptodome.PublicKey import RSA +from Cryptodome.Util.Padding import pad from Cryptodome import Random from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT @@ -107,7 +108,15 @@ class AESCryptoGCM: """ def __init__(self, key): - self.key = padding_key(key) + self.key = self.process_key(key) + + @staticmethod + def process_key(key): + if not isinstance(key, bytes): + key = bytes(key, encoding='utf-8') + if len(key) >= 32: + return key[:32] + return pad(key, 32) def encrypt(self, text): """