merge: with dev

pull/10583/head
ibuler 2023-05-30 09:47:59 +08:00
commit 7a39552bb2
21 changed files with 163 additions and 79 deletions

View File

@ -1,6 +1,6 @@
# Generated by Django 3.2.17 on 2023-04-25 09:04 # 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 import common.db.fields
@ -14,7 +14,7 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='commandfilteracl', model_name='commandfilteracl',
name='new_accounts', 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( migrations.AddField(
model_name='commandfilteracl', model_name='commandfilteracl',
@ -29,7 +29,7 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='loginassetacl', model_name='loginassetacl',
name='new_accounts', 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( migrations.AddField(
model_name='loginassetacl', model_name='loginassetacl',

View File

@ -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'),
),
]

View File

@ -4,6 +4,8 @@ from django.utils.translation import gettext_lazy as _
from common.db.fields import JSONManyToManyField from common.db.fields import JSONManyToManyField
from common.db.models import JMSBaseModel 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 from orgs.mixins.models import OrgModelMixin
__all__ = [ __all__ = [
@ -52,11 +54,35 @@ class BaseACL(JMSBaseModel):
def is_action(self, action): def is_action(self, action):
return self.action == 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): class UserAssetAccountBaseACL(BaseACL, OrgModelMixin):
users = JSONManyToManyField('users.User', default=dict, verbose_name=_('Users')) users = JSONManyToManyField('users.User', default=dict, verbose_name=_('Users'))
assets = JSONManyToManyField('assets.Asset', default=dict, verbose_name=_('Assets')) 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): class Meta(BaseACL.Meta):
unique_together = ('name', 'org_id') unique_together = ('name', 'org_id')
@ -85,4 +111,4 @@ class UserAssetAccountBaseACL(BaseACL, OrgModelMixin):
kwargs['org_id'] = org_id kwargs['org_id'] = org_id
if kwargs: if kwargs:
queryset = queryset.filter(**kwargs) queryset = queryset.filter(**kwargs)
return queryset.distinct() return queryset.valid().distinct().order_by('priority', 'date_created')

View File

@ -2,15 +2,14 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.utils import get_request_ip, get_ip_city 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 common.utils.timezone import local_now_display
from .base import BaseACL from .base import BaseACL
class LoginACL(BaseACL): class LoginACL(BaseACL):
user = models.ForeignKey( 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 # 规则, ip_group, time_period
rules = models.JSONField(default=dict, verbose_name=_('Rule')) rules = models.JSONField(default=dict, verbose_name=_('Rule'))
@ -29,23 +28,9 @@ class LoginACL(BaseACL):
def filter_acl(cls, user): def filter_acl(cls, user):
return user.login_acls.all().valid().distinct() return user.login_acls.all().valid().distinct()
@staticmethod @classmethod
def match(user, ip): def get_user_acls(cls, user):
acl_qs = LoginACL.filter_acl(user) return cls.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
def create_confirm_ticket(self, request): def create_confirm_ticket(self, request):
from tickets import const from tickets import const

View File

@ -1,9 +1,13 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from .base import UserAssetAccountBaseACL from .base import UserAssetAccountBaseACL
class LoginAssetACL(UserAssetAccountBaseACL): class LoginAssetACL(UserAssetAccountBaseACL):
# 规则, ip_group, time_period
rules = models.JSONField(default=dict, verbose_name=_('Rule'))
class Meta(UserAssetAccountBaseACL.Meta): class Meta(UserAssetAccountBaseACL.Meta):
verbose_name = _('Login asset acl') verbose_name = _('Login asset acl')
abstract = False abstract = False

View File

@ -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 .base import BaseUserAssetAccountACLSerializerMixin as BaseSerializer
from .rules import RuleSerializer
from ..models import LoginAssetACL from ..models import LoginAssetACL
__all__ = ["LoginAssetACLSerializer"] __all__ = ["LoginAssetACLSerializer"]
class LoginAssetACLSerializer(BaseSerializer, BulkOrgResourceModelSerializer): class LoginAssetACLSerializer(BaseSerializer, BulkOrgResourceModelSerializer):
rules = MethodSerializer(label=_('Rule'))
class Meta(BaseSerializer.Meta): class Meta(BaseSerializer.Meta):
model = LoginAssetACL model = LoginAssetACL
fields = BaseSerializer.Meta.fields + ['rules']
def get_rules_serializer(self):
return RuleSerializer()

View File

@ -7,6 +7,6 @@ type:
- windows - windows
i18n: i18n:
Gather facts windows: Gather facts windows:
zh: 从 Windows 获取信息 zh: 从 Windows 获取硬件信息
en: Gather facts windows en: Gather facts windows
ja: Windowsから事実を取得する ja: Windowsから事実を取得する

View File

@ -1,12 +1,12 @@
# Generated by Django 2.1.7 on 2019-02-28 09:15 # 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 uuid
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('audits', '0004_operatelog_passwordchangelog_userloginlog'), ('audits', '0004_operatelog_passwordchangelog_userloginlog'),
('users', '0019_auto_20190304_1459'), ('users', '0019_auto_20190304_1459'),
@ -22,7 +22,7 @@ class Migration(migrations.Migration):
('type', ('type',
models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')], models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')],
max_length=2, verbose_name='Login type')), 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, ('city', models.CharField(blank=True, max_length=254, null=True,
verbose_name='Login city')), verbose_name='Login city')),
('user_agent', ('user_agent',

View File

@ -158,7 +158,7 @@ class UserLoginLog(models.Model):
type = models.CharField( type = models.CharField(
choices=LoginTypeChoices.choices, max_length=2, verbose_name=_("Login type") 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( city = models.CharField(
max_length=254, blank=True, null=True, verbose_name=_("Login city") max_length=254, blank=True, null=True, verbose_name=_("Login city")
) )

View File

@ -16,7 +16,7 @@ from rest_framework.response import Response
from common.api import JMSModelViewSet from common.api import JMSModelViewSet
from common.exceptions import JMSException 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.django import get_request_os
from common.utils.http import is_true, is_false from common.utils.http import is_true, is_false
from orgs.mixins.api import RootOrgViewMixin from orgs.mixins.api import RootOrgViewMixin
@ -311,7 +311,9 @@ class ConnectionTokenViewSet(ExtraActionApiMixin, RootOrgViewMixin, JMSModelView
def _validate_acl(self, user, asset, account): def _validate_acl(self, user, asset, account):
from acls.models import LoginAssetACL 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: if not acl:
return return
if acl.is_action(acl.ActionChoices.accept): if acl.is_action(acl.ActionChoices.accept):

View File

@ -340,15 +340,14 @@ class AuthACLMixin:
def _check_login_acl(self, user, ip): def _check_login_acl(self, user, ip):
# ACL 限制用户登录 # ACL 限制用户登录
acl = LoginACL.match(user, ip) acl = LoginACL.get_match_rule_acls(user, ip)
if not acl: if not acl:
return return
acl: LoginACL if acl.is_action(LoginACL.ActionChoices.accept):
if acl.is_action(acl.ActionChoices.accept):
return return
if acl.is_action(acl.ActionChoices.reject): if acl.is_action(LoginACL.ActionChoices.reject):
raise errors.LoginACLIPAndTimePeriodNotAllowed(user.username, request=self.request) raise errors.LoginACLIPAndTimePeriodNotAllowed(user.username, request=self.request)
if acl.is_action(acl.ActionChoices.review): if acl.is_action(acl.ActionChoices.review):

View File

@ -1,14 +1,16 @@
from common.utils.timezone import local_now 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"}] time_periods: [{"id": 1, "value": "00:00~07:30、10:00~13:00"}, {"id": 2, "value": "00:00~00:00"}]
""" """
if not time_periods: 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 = next(filter(lambda x: str(x['id']) == local_now().strftime("%w"), time_periods))
today_time_period = today_time_period['value'] today_time_period = today_time_period['value']
if not today_time_period: if not today_time_period:

View File

@ -221,7 +221,7 @@ msgstr "ソース ID"
#: accounts/models/account.py:61 #: accounts/models/account.py:61
#: accounts/serializers/automations/change_secret.py:113 #: 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 #: 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 #: 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 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39
@ -820,6 +820,12 @@ msgstr "アクティブ"
msgid "Users" msgid "Users"
msgstr "ユーザー" 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 #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60
#: ops/serializers/job.py:55 terminal/const.py:68 #: ops/serializers/job.py:55 terminal/const.py:68
#: terminal/models/session/session.py:43 terminal/serializers/command.py:18 #: terminal/models/session/session.py:43 terminal/serializers/command.py:18
@ -876,10 +882,16 @@ msgid "Login confirm"
msgstr "ログイン確認" msgstr "ログイン確認"
#: acls/models/login_asset_acl.py:8 #: 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" msgid "Login asset acl"
msgstr "ログイン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" msgid "Login asset confirm"
msgstr "ログイン資産の確認" msgstr "ログイン資産の確認"
@ -917,6 +929,11 @@ msgstr "いずれのレビューアも組織 '{}' に属していません"
msgid "Command group amount" msgid "Command group amount"
msgstr "コマンドグループ数" 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 #: acls/serializers/rules/rules.py:20
#: xpack/plugins/cloud/serializers/task.py:22 #: xpack/plugins/cloud/serializers/task.py:22
msgid "IP address invalid: `{}`" msgid "IP address invalid: `{}`"
@ -1331,11 +1348,6 @@ msgstr "パスワードセレクター"
msgid "Submit selector" msgid "Submit selector"
msgstr "ボタンセレクターを確認する" 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 #: assets/models/automations/base.py:22 ops/models/job.py:187
#: settings/serializers/auth/sms.py:100 #: settings/serializers/auth/sms.py:100
msgid "Parameters" msgid "Parameters"
@ -2004,10 +2016,6 @@ msgstr "パスワード変更ログ"
msgid "Login type" msgid "Login type"
msgstr "ログインタイプ" msgstr "ログインタイプ"
#: audits/models.py:161 tickets/models/ticket/login_confirm.py:10
msgid "Login ip"
msgstr "ログインIP"
#: audits/models.py:163 #: audits/models.py:163
#: authentication/templates/authentication/_msg_different_city.html:11 #: authentication/templates/authentication/_msg_different_city.html:11
#: tickets/models/ticket/login_confirm.py:11 #: tickets/models/ticket/login_confirm.py:11
@ -5754,7 +5762,7 @@ msgid "Redis port"
msgstr "Redis ポート" msgstr "Redis ポート"
#: terminal/models/component/endpoint.py:29 #: 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:38 terminal/serializers/storage.py:50
#: terminal/serializers/storage.py:80 terminal/serializers/storage.py:90 #: terminal/serializers/storage.py:80 terminal/serializers/storage.py:90
#: terminal/serializers/storage.py:98 #: terminal/serializers/storage.py:98
@ -6055,11 +6063,21 @@ msgstr ""
#: terminal/serializers/endpoint.py:64 #: terminal/serializers/endpoint.py:64
msgid "" 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" "If asset IP addresses under different endpoints conflict, use asset labels"
msgstr "" msgstr ""
"異なるエンドポイントの下に競合するアセットIPがある場合は、アセットタグを使用" "異なるエンドポイントの下に競合するアセットIPがある場合は、アセットタグを使用"
"して実装します" "して実装します"
#: terminal/serializers/endpoint.py:64
msgid "Asset IP"
msgstr "資産 IP"
#: terminal/serializers/session.py:24 terminal/serializers/session.py:46 #: terminal/serializers/session.py:24 terminal/serializers/session.py:46
msgid "Can replay" msgid "Can replay"
msgstr "再生できます" msgstr "再生できます"

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:4819183bc06cc0e33c741be855881d093e2936f99dadadde38bfdb8ef1cae4dd oid sha256:f4cf57efef290fb80f5159a628b8cde7861cb2bd3fcc247fcf7255fbd2757fb9
size 115922 size 115892

View File

@ -220,7 +220,7 @@ msgstr "来源 ID"
#: accounts/models/account.py:61 #: accounts/models/account.py:61
#: accounts/serializers/automations/change_secret.py:113 #: 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 #: 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 #: 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 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39
@ -816,6 +816,12 @@ msgstr "激活中"
msgid "Users" msgid "Users"
msgstr "用户管理" 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 #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60
#: ops/serializers/job.py:55 terminal/const.py:68 #: ops/serializers/job.py:55 terminal/const.py:68
#: terminal/models/session/session.py:43 terminal/serializers/command.py:18 #: terminal/models/session/session.py:43 terminal/serializers/command.py:18
@ -872,10 +878,16 @@ msgid "Login confirm"
msgstr "登录复核" msgstr "登录复核"
#: acls/models/login_asset_acl.py:8 #: 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" msgid "Login asset acl"
msgstr "登录资产访问控制" 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" msgid "Login asset confirm"
msgstr "登录资产复核" msgstr "登录资产复核"
@ -912,6 +924,11 @@ msgstr "所有复核人都不属于组织 `{}`"
msgid "Command group amount" msgid "Command group amount"
msgstr "命令组数量" 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 #: acls/serializers/rules/rules.py:20
#: xpack/plugins/cloud/serializers/task.py:22 #: xpack/plugins/cloud/serializers/task.py:22
msgid "IP address invalid: `{}`" msgid "IP address invalid: `{}`"
@ -929,7 +946,7 @@ msgstr ""
#: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_oauth_bind.html:12
#: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_password_success.html:8
#: authentication/templates/authentication/_msg_rest_public_key_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" msgid "IP"
msgstr "IP" msgstr "IP"
@ -1324,11 +1341,6 @@ msgstr "密码选择器"
msgid "Submit selector" msgid "Submit selector"
msgstr "确认按钮选择器" 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 #: assets/models/automations/base.py:22 ops/models/job.py:187
#: settings/serializers/auth/sms.py:100 #: settings/serializers/auth/sms.py:100
msgid "Parameters" msgid "Parameters"
@ -1993,10 +2005,6 @@ msgstr "改密日志"
msgid "Login type" msgid "Login type"
msgstr "登录方式" msgstr "登录方式"
#: audits/models.py:161 tickets/models/ticket/login_confirm.py:10
msgid "Login ip"
msgstr "登录IP"
#: audits/models.py:163 #: audits/models.py:163
#: authentication/templates/authentication/_msg_different_city.html:11 #: authentication/templates/authentication/_msg_different_city.html:11
#: tickets/models/ticket/login_confirm.py:11 #: tickets/models/ticket/login_confirm.py:11
@ -5673,7 +5681,7 @@ msgid "Redis port"
msgstr "Redis 端口" msgstr "Redis 端口"
#: terminal/models/component/endpoint.py:29 #: 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:38 terminal/serializers/storage.py:50
#: terminal/serializers/storage.py:80 terminal/serializers/storage.py:90 #: terminal/serializers/storage.py:80 terminal/serializers/storage.py:90
#: terminal/serializers/storage.py:98 #: terminal/serializers/storage.py:98
@ -5971,9 +5979,19 @@ msgstr ""
#: terminal/serializers/endpoint.py:64 #: terminal/serializers/endpoint.py:64
msgid "" 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" "If asset IP addresses under different endpoints conflict, use asset labels"
msgstr "如果不同端点下的资产 IP 有冲突,使用资产标签实现" msgstr "如果不同端点下的资产 IP 有冲突,使用资产标签实现"
#: terminal/serializers/endpoint.py:64
msgid "Asset IP"
msgstr "资产 IP"
#: terminal/serializers/session.py:24 terminal/serializers/session.py:46 #: terminal/serializers/session.py:24 terminal/serializers/session.py:46
msgid "Can replay" msgid "Can replay"
msgstr "是否可重放" msgstr "是否可重放"

View File

@ -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 rest_framework import serializers
from acls.serializers.rules import ip_group_child_validator, ip_group_help_text 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, max_length=128, default=db_port_manager.oracle_port_range, read_only=True,
label=_('Oracle port range'), label=_('Oracle port range'),
help_text=_( 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): class EndpointRuleSerializer(BulkModelSerializer):
_ip_group_help_text = '{} <br> {}'.format( _ip_group_help_text = '{}, {} <br>{}'.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, ip_group_help_text,
_('If asset IP addresses under different endpoints conflict, use asset labels')
) )
ip_group = serializers.ListField( 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]) child=serializers.CharField(max_length=1024, validators=[ip_group_child_validator])
) )
endpoint = ObjectRelatedField( endpoint = ObjectRelatedField(
@ -80,4 +82,5 @@ class EndpointRuleSerializer(BulkModelSerializer):
'comment', 'date_created', 'date_updated', 'created_by' 'comment', 'date_created', 'date_updated', 'created_by'
] ]
extra_kwargs = { extra_kwargs = {
'priority': {'default': 50}
} }

View File

@ -1,8 +1,8 @@
# Generated by Django 3.1.14 on 2022-06-09 09:58 # Generated by Django 3.1.14 on 2022-06-09 09:58
import django.db.models.deletion
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -21,7 +21,7 @@ class Migration(migrations.Migration):
('ticket_ptr', ('ticket_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='tickets.ticket')), 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_city', models.CharField(max_length=64, null=True, verbose_name='Login city')),
('apply_login_datetime', models.DateTimeField(null=True, verbose_name='Login datetime')), ('apply_login_datetime', models.DateTimeField(null=True, verbose_name='Login datetime')),
], ],

View File

@ -12,7 +12,7 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='applyassetticket', model_name='applyassetticket',
name='apply_actions', name='apply_actions',
field=models.IntegerField(default=31, verbose_name='Actions'), field=models.IntegerField(default=1, verbose_name='Actions'),
), ),
migrations.AlterField( migrations.AlterField(
model_name='approvalrule', model_name='approvalrule',

View File

@ -15,7 +15,7 @@ class ApplyAssetTicket(Ticket):
# 申请信息 # 申请信息
apply_assets = models.ManyToManyField('assets.Asset', verbose_name=_('Asset')) apply_assets = models.ManyToManyField('assets.Asset', verbose_name=_('Asset'))
apply_accounts = models.JSONField(default=list, verbose_name=_('Apply accounts')) 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_start = models.DateTimeField(verbose_name=_('Date start'), null=True)
apply_date_expired = models.DateTimeField(verbose_name=_('Date expired'), null=True) apply_date_expired = models.DateTimeField(verbose_name=_('Date expired'), null=True)

View File

@ -7,6 +7,6 @@ __all__ = ['ApplyLoginTicket']
class ApplyLoginTicket(Ticket): 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_city = models.CharField(max_length=64, verbose_name=_('Login city'), null=True)
apply_login_datetime = models.DateTimeField(verbose_name=_('Login datetime'), null=True) apply_login_datetime = models.DateTimeField(verbose_name=_('Login datetime'), null=True)

View File

@ -97,7 +97,7 @@ class Migration(migrations.Migration):
('username', models.CharField(max_length=20, verbose_name='Username')), ('username', models.CharField(max_length=20, verbose_name='Username')),
('type', ('type',
models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')], max_length=2, verbose_name='Login 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')), ('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')), ('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')), ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date login')),