From e61227d69421b881a5ae1b8040e06668fb0c3a8b Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 29 May 2023 19:45:55 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E7=99=BB=E5=BD=95=E8=B5=84=E4=BA=A7?= =?UTF-8?q?=E7=9A=84=20ACL=20=E6=94=AF=E6=8C=81=20ip=20=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=20(#10581)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ibuler --- .../migrations/0011_auto_20230425_1704.py | 6 +- .../migrations/0014_loginassetacl_rules.py | 18 +++ apps/acls/models/base.py | 30 ++++- apps/acls/models/login_acl.py | 25 +---- apps/acls/models/login_asset_acl.py | 4 + apps/acls/serializers/login_asset_acl.py | 11 +- .../gather_facts/host/windows/manifest.yml | 2 +- .../migrations/0005_auto_20190228_1715.py | 8 +- apps/audits/models.py | 2 +- apps/authentication/api/connection_token.py | 6 +- apps/authentication/mixins.py | 7 +- apps/common/utils/time_period.py | 8 +- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 101 +++++++++++------ apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 103 +++++++++++------- apps/terminal/serializers/endpoint.py | 13 ++- .../migrations/0016_auto_20220609_1758.py | 4 +- ...23_alter_applyassetticket_apply_actions.py | 2 +- apps/tickets/models/ticket/apply_asset.py | 2 +- apps/tickets/models/ticket/login_confirm.py | 2 +- apps/users/migrations/0001_initial.py | 2 +- 22 files changed, 235 insertions(+), 129 deletions(-) create mode 100644 apps/acls/migrations/0014_loginassetacl_rules.py diff --git a/apps/acls/migrations/0011_auto_20230425_1704.py b/apps/acls/migrations/0011_auto_20230425_1704.py index 2a8682129..f5d7dee6c 100644 --- a/apps/acls/migrations/0011_auto_20230425_1704.py +++ b/apps/acls/migrations/0011_auto_20230425_1704.py @@ -1,6 +1,6 @@ # Generated by Django 3.2.17 on 2023-04-25 09:04 -from django.db import migrations +from django.db import migrations, models import common.db.fields @@ -14,7 +14,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='commandfilteracl', name='new_accounts', - field=common.db.fields.JSONManyToManyField(default=dict, to='assets.Account', verbose_name='Accounts'), + field=models.JSONField(default=list, verbose_name='Accounts'), ), migrations.AddField( model_name='commandfilteracl', @@ -29,7 +29,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='loginassetacl', name='new_accounts', - field=common.db.fields.JSONManyToManyField(default=dict, to='assets.Account', verbose_name='Accounts'), + field=models.JSONField(default=list, verbose_name='Accounts') ), migrations.AddField( model_name='loginassetacl', diff --git a/apps/acls/migrations/0014_loginassetacl_rules.py b/apps/acls/migrations/0014_loginassetacl_rules.py new file mode 100644 index 000000000..d7574ffd0 --- /dev/null +++ b/apps/acls/migrations/0014_loginassetacl_rules.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.17 on 2023-05-26 09:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('acls', '0013_auto_20230426_1759'), + ] + + operations = [ + migrations.AddField( + model_name='loginassetacl', + name='rules', + field=models.JSONField(default=dict, verbose_name='Rule'), + ), + ] diff --git a/apps/acls/models/base.py b/apps/acls/models/base.py index 4b05f887c..12c66167c 100644 --- a/apps/acls/models/base.py +++ b/apps/acls/models/base.py @@ -4,6 +4,8 @@ from django.utils.translation import gettext_lazy as _ from common.db.fields import JSONManyToManyField from common.db.models import JMSBaseModel +from common.utils import contains_ip +from common.utils.time_period import contains_time_period from orgs.mixins.models import OrgModelMixin __all__ = [ @@ -52,11 +54,35 @@ class BaseACL(JMSBaseModel): def is_action(self, action): return self.action == action + @classmethod + def get_user_acls(cls, user): + return cls.objects.none() + + @classmethod + def get_match_rule_acls(cls, user, ip, acl_qs=None): + if acl_qs is None: + acl_qs = cls.get_user_acls(user) + if not acl_qs: + return + + for acl in acl_qs: + if acl.is_action(ActionChoices.review) 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) if ip_group else True + is_contain_time_period = contains_time_period(time_periods) if time_periods else True + + if is_contain_ip and is_contain_time_period: + # 满足条件,则返回 + return acl + return None + class UserAssetAccountBaseACL(BaseACL, OrgModelMixin): users = JSONManyToManyField('users.User', default=dict, verbose_name=_('Users')) assets = JSONManyToManyField('assets.Asset', default=dict, verbose_name=_('Assets')) - accounts = models.JSONField(default=list, verbose_name=_("Account")) + accounts = models.JSONField(default=list, verbose_name=_("Accounts")) class Meta(BaseACL.Meta): unique_together = ('name', 'org_id') @@ -85,4 +111,4 @@ class UserAssetAccountBaseACL(BaseACL, OrgModelMixin): kwargs['org_id'] = org_id if kwargs: queryset = queryset.filter(**kwargs) - return queryset.distinct() + return queryset.valid().distinct().order_by('priority', 'date_created') diff --git a/apps/acls/models/login_acl.py b/apps/acls/models/login_acl.py index 1178993c8..143196d78 100644 --- a/apps/acls/models/login_acl.py +++ b/apps/acls/models/login_acl.py @@ -2,15 +2,14 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from common.utils import get_request_ip, get_ip_city -from common.utils.ip import contains_ip -from common.utils.time_period import contains_time_period from common.utils.timezone import local_now_display from .base import BaseACL class LoginACL(BaseACL): user = models.ForeignKey( - 'users.User', on_delete=models.CASCADE, related_name='login_acls', verbose_name=_('User') + 'users.User', on_delete=models.CASCADE, + related_name='login_acls', verbose_name=_('User') ) # 规则, ip_group, time_period rules = models.JSONField(default=dict, verbose_name=_('Rule')) @@ -29,23 +28,9 @@ class LoginACL(BaseACL): def filter_acl(cls, user): return user.login_acls.all().valid().distinct() - @staticmethod - def match(user, ip): - acl_qs = LoginACL.filter_acl(user) - if not acl_qs: - return - - for acl in acl_qs: - if acl.is_action(LoginACL.ActionChoices.review) 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 + @classmethod + def get_user_acls(cls, user): + return cls.filter_acl(user) def create_confirm_ticket(self, request): from tickets import const diff --git a/apps/acls/models/login_asset_acl.py b/apps/acls/models/login_asset_acl.py index fc5da088b..5d2293a18 100644 --- a/apps/acls/models/login_asset_acl.py +++ b/apps/acls/models/login_asset_acl.py @@ -1,9 +1,13 @@ +from django.db import models from django.utils.translation import ugettext_lazy as _ from .base import UserAssetAccountBaseACL class LoginAssetACL(UserAssetAccountBaseACL): + # 规则, ip_group, time_period + rules = models.JSONField(default=dict, verbose_name=_('Rule')) + class Meta(UserAssetAccountBaseACL.Meta): verbose_name = _('Login asset acl') abstract = False diff --git a/apps/acls/serializers/login_asset_acl.py b/apps/acls/serializers/login_asset_acl.py index de160d124..7480100f8 100644 --- a/apps/acls/serializers/login_asset_acl.py +++ b/apps/acls/serializers/login_asset_acl.py @@ -1,11 +1,20 @@ -from orgs.mixins.serializers import BulkOrgResourceModelSerializer +from django.utils.translation import gettext_lazy as _ +from common.serializers import MethodSerializer +from orgs.mixins.serializers import BulkOrgResourceModelSerializer from .base import BaseUserAssetAccountACLSerializerMixin as BaseSerializer +from .rules import RuleSerializer from ..models import LoginAssetACL __all__ = ["LoginAssetACLSerializer"] class LoginAssetACLSerializer(BaseSerializer, BulkOrgResourceModelSerializer): + rules = MethodSerializer(label=_('Rule')) + class Meta(BaseSerializer.Meta): model = LoginAssetACL + fields = BaseSerializer.Meta.fields + ['rules'] + + def get_rules_serializer(self): + return RuleSerializer() diff --git a/apps/assets/automations/gather_facts/host/windows/manifest.yml b/apps/assets/automations/gather_facts/host/windows/manifest.yml index af7c50f68..bf2b4e0fd 100644 --- a/apps/assets/automations/gather_facts/host/windows/manifest.yml +++ b/apps/assets/automations/gather_facts/host/windows/manifest.yml @@ -7,6 +7,6 @@ type: - windows i18n: Gather facts windows: - zh: 从 Windows 获取信息 + zh: 从 Windows 获取硬件信息 en: Gather facts windows ja: Windowsから事実を取得する diff --git a/apps/audits/migrations/0005_auto_20190228_1715.py b/apps/audits/migrations/0005_auto_20190228_1715.py index 40636ed8c..aac747e9b 100644 --- a/apps/audits/migrations/0005_auto_20190228_1715.py +++ b/apps/audits/migrations/0005_auto_20190228_1715.py @@ -1,12 +1,12 @@ # Generated by Django 2.1.7 on 2019-02-28 09:15 -from django.db import migrations, models, connection -import django.utils.timezone import uuid +import django.utils.timezone +from django.db import migrations, models + class Migration(migrations.Migration): - dependencies = [ ('audits', '0004_operatelog_passwordchangelog_userloginlog'), ('users', '0019_auto_20190304_1459'), @@ -22,7 +22,7 @@ class Migration(migrations.Migration): ('type', models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')], max_length=2, verbose_name='Login type')), - ('ip', models.GenericIPAddressField(verbose_name='Login ip')), + ('ip', models.GenericIPAddressField(verbose_name='Login IP')), ('city', models.CharField(blank=True, max_length=254, null=True, verbose_name='Login city')), ('user_agent', diff --git a/apps/audits/models.py b/apps/audits/models.py index c20e6cb4b..099bde56e 100644 --- a/apps/audits/models.py +++ b/apps/audits/models.py @@ -158,7 +158,7 @@ class UserLoginLog(models.Model): type = models.CharField( choices=LoginTypeChoices.choices, max_length=2, verbose_name=_("Login type") ) - ip = models.GenericIPAddressField(verbose_name=_("Login ip")) + ip = models.GenericIPAddressField(verbose_name=_("Login IP")) city = models.CharField( max_length=254, blank=True, null=True, verbose_name=_("Login city") ) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 7c1bbb3f8..23344c9fb 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -16,7 +16,7 @@ from rest_framework.response import Response from common.api import JMSModelViewSet from common.exceptions import JMSException -from common.utils import random_string, get_logger +from common.utils import random_string, get_logger, get_request_ip from common.utils.django import get_request_os from common.utils.http import is_true, is_false from orgs.mixins.api import RootOrgViewMixin @@ -311,7 +311,9 @@ class ConnectionTokenViewSet(ExtraActionApiMixin, RootOrgViewMixin, JMSModelView def _validate_acl(self, user, asset, account): from acls.models import LoginAssetACL - acl = LoginAssetACL.filter_queryset(user, asset, account).valid().first() + acls = LoginAssetACL.filter_queryset(user, asset, account) + ip = get_request_ip(self.request) + acl = LoginAssetACL.get_match_rule_acls(user, ip, acls) if not acl: return if acl.is_action(acl.ActionChoices.accept): diff --git a/apps/authentication/mixins.py b/apps/authentication/mixins.py index 9fce76e57..c1fb2720d 100644 --- a/apps/authentication/mixins.py +++ b/apps/authentication/mixins.py @@ -340,15 +340,14 @@ class AuthACLMixin: def _check_login_acl(self, user, ip): # ACL 限制用户登录 - acl = LoginACL.match(user, ip) + acl = LoginACL.get_match_rule_acls(user, ip) if not acl: return - acl: LoginACL - if acl.is_action(acl.ActionChoices.accept): + if acl.is_action(LoginACL.ActionChoices.accept): return - if acl.is_action(acl.ActionChoices.reject): + if acl.is_action(LoginACL.ActionChoices.reject): raise errors.LoginACLIPAndTimePeriodNotAllowed(user.username, request=self.request) if acl.is_action(acl.ActionChoices.review): diff --git a/apps/common/utils/time_period.py b/apps/common/utils/time_period.py index cf4f0f0b9..0b25b4e34 100644 --- a/apps/common/utils/time_period.py +++ b/apps/common/utils/time_period.py @@ -1,14 +1,16 @@ from common.utils.timezone import local_now -def contains_time_period(time_periods): +def contains_time_period(time_periods, ctime=None): """ time_periods: [{"id": 1, "value": "00:00~07:30、10:00~13:00"}, {"id": 2, "value": "00:00~00:00"}] """ if not time_periods: - return False + return None - current_time = local_now().strftime('%H:%M') + if ctime is None: + ctime = local_now() + current_time = ctime.strftime('%H:%M') today_time_period = next(filter(lambda x: str(x['id']) == local_now().strftime("%w"), time_periods)) today_time_period = today_time_period['value'] if not today_time_period: diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 2d93e8efc..5988ab745 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:fc0862f2a9091f2e06602d6db26cfc9cc7a6b067012ec56b41ebc1e26d5072e9 -size 142045 +oid sha256:8e5c8032359c81278ddea64227bd4492fb49ea6b48587e6a0f406824238d6d46 +size 141638 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 6164e3b1c..be447ea8a 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: 2023-05-26 17:11+0800\n" +"POT-Creation-Date: 2023-05-26 16:18+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -221,7 +221,7 @@ msgstr "ソース ID" #: accounts/models/account.py:61 #: accounts/serializers/automations/change_secret.py:113 -#: accounts/serializers/automations/change_secret.py:133 acls/models/base.py:59 +#: accounts/serializers/automations/change_secret.py:133 #: acls/serializers/base.py:77 assets/serializers/asset/common.py:125 #: assets/serializers/gateway.py:28 audits/models.py:49 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 @@ -820,6 +820,12 @@ msgstr "アクティブ" msgid "Users" msgstr "ユーザー" +#: acls/models/base.py:59 assets/models/automations/base.py:17 +#: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:305 +#: rbac/tree.py:35 +msgid "Accounts" +msgstr "アカウント" + #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 #: ops/serializers/job.py:55 terminal/const.py:68 #: terminal/models/session/session.py:43 terminal/serializers/command.py:18 @@ -833,7 +839,7 @@ msgid "Regex" msgstr "正規情報" #: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79 -#: settings/serializers/basic.py:10 xpack/plugins/license/models.py:30 +#: settings/serializers/basic.py:10 xpack/plugins/license/models.py:29 msgid "Content" msgstr "コンテンツ" @@ -876,10 +882,16 @@ msgid "Login confirm" msgstr "ログイン確認" #: acls/models/login_asset_acl.py:8 +#, fuzzy +#| msgid "User ID" +msgid "User IP" +msgstr "ユーザーID" + +#: acls/models/login_asset_acl.py:11 msgid "Login asset acl" msgstr "ログインasset acl" -#: acls/models/login_asset_acl.py:18 tickets/const.py:12 +#: acls/models/login_asset_acl.py:21 tickets/const.py:12 msgid "Login asset confirm" msgstr "ログイン資産の確認" @@ -917,6 +929,11 @@ msgstr "いずれのレビューアも組織 '{}' に属していません" msgid "Command group amount" msgstr "コマンドグループ数" +#: acls/serializers/login_asset_acl.py:12 audits/models.py:161 +#: tickets/models/ticket/login_confirm.py:10 +msgid "Login IP" +msgstr "ログインIP" + #: acls/serializers/rules/rules.py:20 #: xpack/plugins/cloud/serializers/task.py:22 msgid "IP address invalid: `{}`" @@ -1251,7 +1268,7 @@ msgstr "アドレス" #: assets/models/asset/common.py:151 assets/models/platform.py:112 #: authentication/serializers/connect_token_secret.py:115 #: perms/serializers/user_permission.py:24 -#: xpack/plugins/cloud/serializers/account_attrs.py:196 +#: xpack/plugins/cloud/serializers/account_attrs.py:187 msgid "Platform" msgstr "プラットフォーム" @@ -1331,11 +1348,6 @@ msgstr "パスワードセレクター" msgid "Submit selector" msgstr "ボタンセレクターを確認する" -#: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:305 rbac/tree.py:35 -msgid "Accounts" -msgstr "アカウント" - #: assets/models/automations/base.py:22 ops/models/job.py:187 #: settings/serializers/auth/sms.py:100 msgid "Parameters" @@ -2004,10 +2016,6 @@ msgstr "パスワード変更ログ" msgid "Login type" msgstr "ログインタイプ" -#: audits/models.py:161 tickets/models/ticket/login_confirm.py:10 -msgid "Login ip" -msgstr "ログインIP" - #: audits/models.py:163 #: authentication/templates/authentication/_msg_different_city.html:11 #: tickets/models/ticket/login_confirm.py:11 @@ -4606,7 +4614,7 @@ msgid "SSO auth key TTL" msgstr "Token有効期間" #: settings/serializers/auth/sso.py:17 -#: xpack/plugins/cloud/serializers/account_attrs.py:193 +#: xpack/plugins/cloud/serializers/account_attrs.py:184 msgid "Unit: second" msgstr "単位: 秒" @@ -5750,7 +5758,7 @@ msgid "Redis port" msgstr "Redis ポート" #: terminal/models/component/endpoint.py:29 -#: terminal/models/component/endpoint.py:98 terminal/serializers/endpoint.py:71 +#: terminal/models/component/endpoint.py:98 terminal/serializers/endpoint.py:68 #: 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 @@ -6051,11 +6059,21 @@ msgstr "" #: terminal/serializers/endpoint.py:64 msgid "" +"The assets within this IP range, the following endpoint will be used for the " +"connection" +msgstr "このIP範囲内のアセットは、以下のエンドポイントを使用して接続されます" + +#: terminal/serializers/endpoint.py:60 +msgid "" "If asset IP addresses under different endpoints conflict, use asset labels" msgstr "" "異なるエンドポイントの下に競合するアセットIPがある場合は、アセットタグを使用" "して実装します" +#: terminal/serializers/endpoint.py:64 +msgid "Asset IP" +msgstr "資産 IP" + #: terminal/serializers/session.py:24 terminal/serializers/session.py:46 msgid "Can replay" msgstr "再生できます" @@ -7248,7 +7266,7 @@ msgstr "クラウドアカウント" msgid "Test cloud account" msgstr "クラウドアカウントのテスト" -#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:36 +#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:37 msgid "Regions" msgstr "リージョン" @@ -7256,15 +7274,15 @@ msgstr "リージョン" msgid "Hostname strategy" msgstr "ホスト名戦略" -#: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:39 +#: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:40 msgid "IP network segment group" msgstr "IPネットワークセグメントグループ" -#: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:44 +#: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:45 msgid "Sync IP type" msgstr "同期IPタイプ" -#: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:61 +#: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:62 msgid "Always update" msgstr "常に更新" @@ -7549,11 +7567,15 @@ msgstr "ファイルはJSON形式です。" msgid "IP address invalid `{}`, {}" msgstr "IPアドレスが無効: '{}', {}" -#: xpack/plugins/cloud/serializers/account_attrs.py:172 -msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255" +#: xpack/plugins/cloud/serializers/account_attrs.py:162 +#, fuzzy +#| msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255" +msgid "" +"Format for comma-delimited string,Such as: 192.168.1.0/24, " +"10.0.0.0-10.0.0.255" msgstr "例:192.168.1.0/24,10.0.0.0-10.0.0.255" -#: xpack/plugins/cloud/serializers/account_attrs.py:175 +#: xpack/plugins/cloud/serializers/account_attrs.py:166 msgid "" "The port is used to detect the validity of the IP address. When the " "synchronization task is executed, only the valid IP address will be " @@ -7563,29 +7585,36 @@ msgstr "" "実行されると、有効な IP アドレスのみが同期されます。
ポートが0の場合、す" "べてのIPアドレスが有効です。" -#: xpack/plugins/cloud/serializers/account_attrs.py:183 +#: xpack/plugins/cloud/serializers/account_attrs.py:174 msgid "Hostname prefix" msgstr "ホスト名プレフィックス" -#: xpack/plugins/cloud/serializers/account_attrs.py:186 +#: xpack/plugins/cloud/serializers/account_attrs.py:177 msgid "IP segment" msgstr "IP セグメント" -#: xpack/plugins/cloud/serializers/account_attrs.py:190 +#: xpack/plugins/cloud/serializers/account_attrs.py:181 msgid "Test port" msgstr "テストポート" -#: xpack/plugins/cloud/serializers/account_attrs.py:193 +#: xpack/plugins/cloud/serializers/account_attrs.py:184 msgid "Test timeout" msgstr "テストタイムアウト" #: xpack/plugins/cloud/serializers/task.py:28 +#, fuzzy +#| 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.
Such as: " +#| "192.168.1.0/24, 10.1.1.1-10.1.1.20" 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.
Such as: 192.168.1.0/24, " -"10.1.1.1-10.1.1.20" +"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と" @@ -7593,11 +7622,11 @@ msgstr "" "ドレスをランダムに一致させることを意味します。
例:" "192.168.1.0/24,10.1.1.1-10.1.1.20" -#: xpack/plugins/cloud/serializers/task.py:34 +#: xpack/plugins/cloud/serializers/task.py:35 msgid "History count" msgstr "実行回数" -#: xpack/plugins/cloud/serializers/task.py:35 +#: xpack/plugins/cloud/serializers/task.py:36 msgid "Instance count" msgstr "インスタンス数" @@ -7657,23 +7686,23 @@ msgstr "ライセンスのインポートに成功" msgid "License is invalid" msgstr "ライセンスが無効です" -#: xpack/plugins/license/meta.py:11 xpack/plugins/license/models.py:138 +#: xpack/plugins/license/meta.py:11 xpack/plugins/license/models.py:135 msgid "License" msgstr "ライセンス" -#: xpack/plugins/license/models.py:80 +#: xpack/plugins/license/models.py:79 msgid "Standard edition" msgstr "標準版" -#: xpack/plugins/license/models.py:82 +#: xpack/plugins/license/models.py:81 msgid "Enterprise edition" msgstr "エンタープライズ版" -#: xpack/plugins/license/models.py:84 +#: xpack/plugins/license/models.py:83 msgid "Ultimate edition" msgstr "究極のエディション" -#: xpack/plugins/license/models.py:86 +#: xpack/plugins/license/models.py:85 msgid "Community edition" msgstr "コミュニティ版" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index b986dcb5b..256aed8c9 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:1fabd2ec950291422c14b66af097bd73cce52bbc4b7913c1b9ea732eee855901 -size 116210 +oid sha256:f4cf57efef290fb80f5159a628b8cde7861cb2bd3fcc247fcf7255fbd2757fb9 +size 115892 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index d7aaf420f..9949ec5aa 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: 2023-05-26 17:11+0800\n" +"POT-Creation-Date: 2023-05-26 16:18+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -220,7 +220,7 @@ msgstr "来源 ID" #: accounts/models/account.py:61 #: accounts/serializers/automations/change_secret.py:113 -#: accounts/serializers/automations/change_secret.py:133 acls/models/base.py:59 +#: accounts/serializers/automations/change_secret.py:133 #: acls/serializers/base.py:77 assets/serializers/asset/common.py:125 #: assets/serializers/gateway.py:28 audits/models.py:49 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 @@ -816,6 +816,12 @@ msgstr "激活中" msgid "Users" msgstr "用户管理" +#: acls/models/base.py:59 assets/models/automations/base.py:17 +#: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:305 +#: rbac/tree.py:35 +msgid "Accounts" +msgstr "账号管理" + #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 #: ops/serializers/job.py:55 terminal/const.py:68 #: terminal/models/session/session.py:43 terminal/serializers/command.py:18 @@ -829,7 +835,7 @@ msgid "Regex" msgstr "正则表达式" #: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79 -#: settings/serializers/basic.py:10 xpack/plugins/license/models.py:30 +#: settings/serializers/basic.py:10 xpack/plugins/license/models.py:29 msgid "Content" msgstr "内容" @@ -872,10 +878,16 @@ msgid "Login confirm" msgstr "登录复核" #: acls/models/login_asset_acl.py:8 +#, fuzzy +#| msgid "User ID" +msgid "User IP" +msgstr "用户 ID" + +#: acls/models/login_asset_acl.py:11 msgid "Login asset acl" msgstr "登录资产访问控制" -#: acls/models/login_asset_acl.py:18 tickets/const.py:12 +#: acls/models/login_asset_acl.py:21 tickets/const.py:12 msgid "Login asset confirm" msgstr "登录资产复核" @@ -912,6 +924,11 @@ msgstr "所有复核人都不属于组织 `{}`" msgid "Command group amount" msgstr "命令组数量" +#: acls/serializers/login_asset_acl.py:12 audits/models.py:161 +#: tickets/models/ticket/login_confirm.py:10 +msgid "Login IP" +msgstr "登录 IP" + #: acls/serializers/rules/rules.py:20 #: xpack/plugins/cloud/serializers/task.py:22 msgid "IP address invalid: `{}`" @@ -929,7 +946,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:10 terminal/serializers/endpoint.py:67 +#: settings/serializers/terminal.py:10 msgid "IP" msgstr "IP" @@ -1244,7 +1261,7 @@ msgstr "地址" #: assets/models/asset/common.py:151 assets/models/platform.py:112 #: authentication/serializers/connect_token_secret.py:115 #: perms/serializers/user_permission.py:24 -#: xpack/plugins/cloud/serializers/account_attrs.py:196 +#: xpack/plugins/cloud/serializers/account_attrs.py:187 msgid "Platform" msgstr "系统平台" @@ -1324,11 +1341,6 @@ msgstr "密码选择器" msgid "Submit selector" msgstr "确认按钮选择器" -#: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:305 rbac/tree.py:35 -msgid "Accounts" -msgstr "账号管理" - #: assets/models/automations/base.py:22 ops/models/job.py:187 #: settings/serializers/auth/sms.py:100 msgid "Parameters" @@ -1993,10 +2005,6 @@ msgstr "改密日志" msgid "Login type" msgstr "登录方式" -#: audits/models.py:161 tickets/models/ticket/login_confirm.py:10 -msgid "Login ip" -msgstr "登录IP" - #: audits/models.py:163 #: authentication/templates/authentication/_msg_different_city.html:11 #: tickets/models/ticket/login_confirm.py:11 @@ -4562,7 +4570,7 @@ msgid "SSO auth key TTL" msgstr "令牌有效期" #: settings/serializers/auth/sso.py:17 -#: xpack/plugins/cloud/serializers/account_attrs.py:193 +#: xpack/plugins/cloud/serializers/account_attrs.py:184 msgid "Unit: second" msgstr "单位: 秒" @@ -5669,7 +5677,7 @@ msgid "Redis port" msgstr "Redis 端口" #: terminal/models/component/endpoint.py:29 -#: terminal/models/component/endpoint.py:98 terminal/serializers/endpoint.py:71 +#: terminal/models/component/endpoint.py:98 terminal/serializers/endpoint.py:68 #: 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 @@ -5967,9 +5975,19 @@ msgstr "" #: terminal/serializers/endpoint.py:64 msgid "" +"The assets within this IP range, the following endpoint will be used for the " +"connection" +msgstr "该 IP 范围内的资产,将使用下面的端点进行连接" + +#: terminal/serializers/endpoint.py:60 +msgid "" "If asset IP addresses under different endpoints conflict, use asset labels" msgstr "如果不同端点下的资产 IP 有冲突,使用资产标签实现" +#: terminal/serializers/endpoint.py:64 +msgid "Asset IP" +msgstr "资产 IP" + #: terminal/serializers/session.py:24 terminal/serializers/session.py:46 msgid "Can replay" msgstr "是否可重放" @@ -7143,7 +7161,7 @@ msgstr "云账号" msgid "Test cloud account" msgstr "测试云账号" -#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:36 +#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:37 msgid "Regions" msgstr "地域" @@ -7151,15 +7169,15 @@ msgstr "地域" msgid "Hostname strategy" msgstr "主机名策略" -#: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:39 +#: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:40 msgid "IP network segment group" msgstr "IP网段组" -#: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:44 +#: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:45 msgid "Sync IP type" msgstr "同步IP类型" -#: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:61 +#: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:62 msgid "Always update" msgstr "总是更新" @@ -7444,11 +7462,15 @@ msgstr "JSON 格式的文件" msgid "IP address invalid `{}`, {}" msgstr "IP 地址无效: `{}`, {}" -#: xpack/plugins/cloud/serializers/account_attrs.py:172 -msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255" +#: xpack/plugins/cloud/serializers/account_attrs.py:162 +#, fuzzy +#| msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255" +msgid "" +"Format for comma-delimited string,Such as: 192.168.1.0/24, " +"10.0.0.0-10.0.0.255" msgstr "如:192.168.1.0/24,10.0.0.0-10.0.0.255" -#: xpack/plugins/cloud/serializers/account_attrs.py:175 +#: xpack/plugins/cloud/serializers/account_attrs.py:166 msgid "" "The port is used to detect the validity of the IP address. When the " "synchronization task is executed, only the valid IP address will be " @@ -7457,39 +7479,46 @@ msgstr "" "端口用来检测 IP 地址的有效性,在同步任务执行时,只会同步有效的 IP 地址。
" "如果端口为 0,则表示所有 IP 地址均有效。" -#: xpack/plugins/cloud/serializers/account_attrs.py:183 +#: xpack/plugins/cloud/serializers/account_attrs.py:174 msgid "Hostname prefix" msgstr "主机名前缀" -#: xpack/plugins/cloud/serializers/account_attrs.py:186 +#: xpack/plugins/cloud/serializers/account_attrs.py:177 msgid "IP segment" msgstr "IP 网段" -#: xpack/plugins/cloud/serializers/account_attrs.py:190 +#: xpack/plugins/cloud/serializers/account_attrs.py:181 msgid "Test port" msgstr "测试端口" -#: xpack/plugins/cloud/serializers/account_attrs.py:193 +#: xpack/plugins/cloud/serializers/account_attrs.py:184 msgid "Test timeout" msgstr "测试超时时间" #: xpack/plugins/cloud/serializers/task.py:28 +#, fuzzy +#| 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.
Such as: " +#| "192.168.1.0/24, 10.1.1.1-10.1.1.20" 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.
Such as: 192.168.1.0/24, " -"10.1.1.1-10.1.1.20" +"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:34 +#: xpack/plugins/cloud/serializers/task.py:35 msgid "History count" msgstr "执行次数" -#: xpack/plugins/cloud/serializers/task.py:35 +#: xpack/plugins/cloud/serializers/task.py:36 msgid "Instance count" msgstr "实例个数" @@ -7549,23 +7578,23 @@ msgstr "许可证导入成功" msgid "License is invalid" msgstr "无效的许可证" -#: xpack/plugins/license/meta.py:11 xpack/plugins/license/models.py:138 +#: xpack/plugins/license/meta.py:11 xpack/plugins/license/models.py:135 msgid "License" msgstr "许可证" -#: xpack/plugins/license/models.py:80 +#: xpack/plugins/license/models.py:79 msgid "Standard edition" msgstr "标准版" -#: xpack/plugins/license/models.py:82 +#: xpack/plugins/license/models.py:81 msgid "Enterprise edition" msgstr "企业版" -#: xpack/plugins/license/models.py:84 +#: xpack/plugins/license/models.py:83 msgid "Ultimate edition" msgstr "旗舰版" -#: xpack/plugins/license/models.py:86 +#: xpack/plugins/license/models.py:85 msgid "Community edition" msgstr "社区版" diff --git a/apps/terminal/serializers/endpoint.py b/apps/terminal/serializers/endpoint.py index 5058b292f..d7534adeb 100644 --- a/apps/terminal/serializers/endpoint.py +++ b/apps/terminal/serializers/endpoint.py @@ -1,4 +1,4 @@ -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from rest_framework import serializers from acls.serializers.rules import ip_group_child_validator, ip_group_help_text @@ -17,7 +17,8 @@ class EndpointSerializer(BulkModelSerializer): max_length=128, default=db_port_manager.oracle_port_range, read_only=True, label=_('Oracle port range'), help_text=_( - 'Oracle proxy server listen port is dynamic, Each additional Oracle database instance adds a port listener' + 'Oracle proxy server listen port is dynamic, Each additional Oracle ' + 'database instance adds a port listener' ) ) @@ -59,12 +60,13 @@ class EndpointSerializer(BulkModelSerializer): class EndpointRuleSerializer(BulkModelSerializer): - _ip_group_help_text = '{}
{}'.format( + _ip_group_help_text = '{}, {}
{}'.format( + _('The assets within this IP range, the following endpoint will be used for the connection'), + _('If asset IP addresses under different endpoints conflict, use asset labels'), ip_group_help_text, - _('If asset IP addresses under different endpoints conflict, use asset labels') ) ip_group = serializers.ListField( - default=['*'], label=_('IP'), help_text=_ip_group_help_text, + default=['*'], label=_('Asset IP'), help_text=_ip_group_help_text, child=serializers.CharField(max_length=1024, validators=[ip_group_child_validator]) ) endpoint = ObjectRelatedField( @@ -80,4 +82,5 @@ class EndpointRuleSerializer(BulkModelSerializer): 'comment', 'date_created', 'date_updated', 'created_by' ] extra_kwargs = { + 'priority': {'default': 50} } diff --git a/apps/tickets/migrations/0016_auto_20220609_1758.py b/apps/tickets/migrations/0016_auto_20220609_1758.py index e5e6f61ce..20f9674f7 100644 --- a/apps/tickets/migrations/0016_auto_20220609_1758.py +++ b/apps/tickets/migrations/0016_auto_20220609_1758.py @@ -1,8 +1,8 @@ # Generated by Django 3.1.14 on 2022-06-09 09:58 +import django.db.models.deletion from django.conf import settings from django.db import migrations, models -import django.db.models.deletion class Migration(migrations.Migration): @@ -21,7 +21,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_login_ip', models.GenericIPAddressField(null=True, verbose_name='Login ip')), + ('apply_login_ip', models.GenericIPAddressField(null=True, verbose_name='Login IP')), ('apply_login_city', models.CharField(max_length=64, null=True, verbose_name='Login city')), ('apply_login_datetime', models.DateTimeField(null=True, verbose_name='Login datetime')), ], diff --git a/apps/tickets/migrations/0023_alter_applyassetticket_apply_actions.py b/apps/tickets/migrations/0023_alter_applyassetticket_apply_actions.py index f401fe298..b4121ce51 100644 --- a/apps/tickets/migrations/0023_alter_applyassetticket_apply_actions.py +++ b/apps/tickets/migrations/0023_alter_applyassetticket_apply_actions.py @@ -12,7 +12,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='applyassetticket', name='apply_actions', - field=models.IntegerField(default=31, verbose_name='Actions'), + field=models.IntegerField(default=1, verbose_name='Actions'), ), migrations.AlterField( model_name='approvalrule', diff --git a/apps/tickets/models/ticket/apply_asset.py b/apps/tickets/models/ticket/apply_asset.py index ef29c607f..39784201b 100644 --- a/apps/tickets/models/ticket/apply_asset.py +++ b/apps/tickets/models/ticket/apply_asset.py @@ -15,7 +15,7 @@ class ApplyAssetTicket(Ticket): # 申请信息 apply_assets = models.ManyToManyField('assets.Asset', verbose_name=_('Asset')) apply_accounts = models.JSONField(default=list, verbose_name=_('Apply accounts')) - apply_actions = models.IntegerField(verbose_name=_('Actions'), default=ActionChoices.all()) + apply_actions = models.IntegerField(verbose_name=_('Actions'), default=ActionChoices.connect) apply_date_start = models.DateTimeField(verbose_name=_('Date start'), null=True) apply_date_expired = models.DateTimeField(verbose_name=_('Date expired'), null=True) diff --git a/apps/tickets/models/ticket/login_confirm.py b/apps/tickets/models/ticket/login_confirm.py index ee9d9fa80..024761ac7 100644 --- a/apps/tickets/models/ticket/login_confirm.py +++ b/apps/tickets/models/ticket/login_confirm.py @@ -7,6 +7,6 @@ __all__ = ['ApplyLoginTicket'] class ApplyLoginTicket(Ticket): - apply_login_ip = models.GenericIPAddressField(verbose_name=_('Login ip'), null=True) + apply_login_ip = models.GenericIPAddressField(verbose_name=_('Login IP'), null=True) apply_login_city = models.CharField(max_length=64, verbose_name=_('Login city'), null=True) apply_login_datetime = models.DateTimeField(verbose_name=_('Login datetime'), null=True) diff --git a/apps/users/migrations/0001_initial.py b/apps/users/migrations/0001_initial.py index d5c584181..5c0f28a38 100644 --- a/apps/users/migrations/0001_initial.py +++ b/apps/users/migrations/0001_initial.py @@ -97,7 +97,7 @@ class Migration(migrations.Migration): ('username', models.CharField(max_length=20, verbose_name='Username')), ('type', models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')], max_length=2, verbose_name='Login type')), - ('ip', models.GenericIPAddressField(verbose_name='Login ip')), + ('ip', models.GenericIPAddressField(verbose_name='Login IP')), ('city', models.CharField(blank=True, max_length=254, null=True, verbose_name='Login city')), ('user_agent', models.CharField(blank=True, max_length=254, null=True, verbose_name='User agent')), ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date login')),