diff --git a/apps/applications/serializers/application.py b/apps/applications/serializers/application.py index 35a07e262..ac8f38f2a 100644 --- a/apps/applications/serializers/application.py +++ b/apps/applications/serializers/application.py @@ -16,7 +16,7 @@ from .. import const __all__ = [ 'AppSerializer', 'MiniAppSerializer', 'AppSerializerMixin', - 'AppAccountSerializer', 'AppAccountSecretSerializer' + 'AppAccountSerializer', 'AppAccountSecretSerializer', 'AppAccountBackUpSerializer' ] @@ -32,21 +32,23 @@ class AppSerializerMixin(serializers.Serializer): return instance def get_attrs_serializer(self): - default_serializer = serializers.Serializer(read_only=True) instance = self.app - if instance: - _type = instance.type - _category = instance.category - else: - _type = self.context['request'].query_params.get('type') - _category = self.context['request'].query_params.get('category') - if _type: - if isinstance(self, AppAccountSecretSerializer): - serializer_class = type_secret_serializer_classes_mapping.get(_type) + tp = getattr(self, 'tp', None) + default_serializer = serializers.Serializer(read_only=True) + if not tp: + if instance: + tp = instance.type + category = instance.category else: - serializer_class = type_serializer_classes_mapping.get(_type) - elif _category: - serializer_class = category_serializer_classes_mapping.get(_category) + tp = self.context['request'].query_params.get('type') + category = self.context['request'].query_params.get('category') + if tp: + if isinstance(self, AppAccountBackUpSerializer): + serializer_class = type_secret_serializer_classes_mapping.get(tp) + else: + serializer_class = type_serializer_classes_mapping.get(tp) + elif category: + serializer_class = category_serializer_classes_mapping.get(category) else: serializer_class = default_serializer @@ -154,11 +156,6 @@ class AppAccountSerializer(AppSerializerMixin, AuthSerializerMixin, BulkOrgResou class AppAccountSecretSerializer(SecretReadableMixin, AppAccountSerializer): class Meta(AppAccountSerializer.Meta): - fields_backup = [ - 'id', 'app_display', 'attrs', 'username', 'password', 'private_key', - 'public_key', 'date_created', 'date_updated', 'version' - ] - extra_kwargs = { 'password': {'write_only': False}, 'private_key': {'write_only': False}, @@ -166,3 +163,22 @@ class AppAccountSecretSerializer(SecretReadableMixin, AppAccountSerializer): 'app_display': {'label': _('Application display')}, 'systemuser_display': {'label': _('System User')} } + + +class AppAccountBackUpSerializer(AppAccountSecretSerializer): + class Meta(AppAccountSecretSerializer.Meta): + fields = [ + 'id', 'app_display', 'attrs', 'username', 'password', 'private_key', + 'public_key', 'date_created', 'date_updated', 'version' + ] + + def __init__(self, *args, **kwargs): + self.tp = kwargs.pop('tp', None) + super().__init__(*args, **kwargs) + + @classmethod + def setup_eager_loading(cls, queryset): + return queryset + + def to_representation(self, instance): + return super(AppAccountSerializer, self).to_representation(instance) diff --git a/apps/applications/serializers/attrs/application_category/db.py b/apps/applications/serializers/attrs/application_category/db.py index 4bb862604..183397e8e 100644 --- a/apps/applications/serializers/attrs/application_category/db.py +++ b/apps/applications/serializers/attrs/application_category/db.py @@ -17,3 +17,10 @@ class DBSerializer(serializers.Serializer): ca_cert = serializers.CharField( required=False, allow_null=True, label=_('CA certificate') ) + client_cert = serializers.CharField( + required=False, allow_null=True, label=_('Client certificate file') + ) + cert_key = serializers.CharField( + required=False, allow_null=True, label=_('Certificate key file') + ) + allow_invalid_cert = serializers.BooleanField(default=False, label=_('Allow invalid cert')) diff --git a/apps/assets/serializers/account.py b/apps/assets/serializers/account.py index e4e320f33..9b06944c3 100644 --- a/apps/assets/serializers/account.py +++ b/apps/assets/serializers/account.py @@ -76,10 +76,6 @@ class AccountSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer): class AccountSecretSerializer(SecretReadableMixin, AccountSerializer): class Meta(AccountSerializer.Meta): - fields_backup = [ - 'hostname', 'ip', 'platform', 'protocols', 'username', 'password', - 'private_key', 'public_key', 'date_created', 'date_updated', 'version' - ] extra_kwargs = { 'password': {'write_only': False}, 'private_key': {'write_only': False}, @@ -88,6 +84,22 @@ class AccountSecretSerializer(SecretReadableMixin, AccountSerializer): } +class AccountBackUpSerializer(AccountSecretSerializer): + class Meta(AccountSecretSerializer.Meta): + fields = [ + 'id', 'hostname', 'ip', 'username', 'password', + 'private_key', 'public_key', 'date_created', + 'date_updated', 'version' + ] + + @classmethod + def setup_eager_loading(cls, queryset): + return queryset + + def to_representation(self, instance): + return super(AccountSerializer, self).to_representation(instance) + + class AccountTaskSerializer(serializers.Serializer): ACTION_CHOICES = ( ('test', 'test'), diff --git a/apps/assets/task_handlers/backup/handlers.py b/apps/assets/task_handlers/backup/handlers.py index 311d8e395..43e6a80db 100644 --- a/apps/assets/task_handlers/backup/handlers.py +++ b/apps/assets/task_handlers/backup/handlers.py @@ -4,15 +4,16 @@ from openpyxl import Workbook from collections import defaultdict, OrderedDict from django.conf import settings +from django.db.models import F from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers -from assets.models import AuthBook -from assets.serializers import AccountSecretSerializer +from assets.models import AuthBook, SystemUser, Asset +from assets.serializers import AccountBackUpSerializer from assets.notifications import AccountBackupExecutionTaskMsg -from applications.models import Account +from applications.models import Account, Application from applications.const import AppType -from applications.serializers import AppAccountSecretSerializer +from applications.serializers import AppAccountBackUpSerializer from users.models import User from common.utils import get_logger from common.utils.timezone import local_now_display @@ -38,7 +39,7 @@ class BaseAccountHandler: @classmethod def get_header_fields(cls, serializer: serializers.Serializer): try: - backup_fields = getattr(serializer, 'Meta').fields_backup + backup_fields = getattr(serializer, 'Meta').fields except AttributeError: backup_fields = serializer.fields.keys() header_fields = {} @@ -51,17 +52,41 @@ class BaseAccountHandler: header_fields[field] = str(v.label) return header_fields + @staticmethod + def load_auth(tp, value, system_user): + if value: + return value + if system_user: + return getattr(system_user, tp, '') + return '' + @classmethod - def create_row(cls, account, serializer_cls, header_fields=None): - serializer = serializer_cls(account) - if not header_fields: - header_fields = cls.get_header_fields(serializer) - data = cls.unpack_data(serializer.data) + def replace_auth(cls, account, system_user_dict): + system_user = system_user_dict.get(account.systemuser_id) + account.username = cls.load_auth('username', account.username, system_user) + account.password = cls.load_auth('password', account.password, system_user) + account.private_key = cls.load_auth('private_key', account.private_key, system_user) + account.public_key = cls.load_auth('public_key', account.public_key, system_user) + return account + + @classmethod + def create_row(cls, data, header_fields): + data = cls.unpack_data(data) row_dict = {} for field, header_name in header_fields.items(): - row_dict[header_name] = str(data[field]) + row_dict[header_name] = str(data.get(field, field)) return row_dict + @classmethod + def add_rows(cls, data, header_fields, sheet): + data_map = defaultdict(list) + for i in data: + row = cls.create_row(i, header_fields) + if sheet not in data_map: + data_map[sheet].append(list(row.keys())) + data_map[sheet].append(list(row.values())) + return data_map + class AssetAccountHandler(BaseAccountHandler): @staticmethod @@ -72,22 +97,27 @@ class AssetAccountHandler(BaseAccountHandler): return filename @classmethod - def create_data_map(cls): - data_map = defaultdict(list) + def replace_account_info(cls, account, asset_dict, system_user_dict): + asset = asset_dict.get(account.asset_id) + account.ip = asset.ip if asset else '' + account.hostname = asset.hostname if asset else '' + account = cls.replace_auth(account, system_user_dict) + return account + + @classmethod + def create_data_map(cls, system_user_dict): sheet_name = AuthBook._meta.verbose_name + assets = Asset.objects.only('id', 'hostname', 'ip') + asset_dict = {asset.id: asset for asset in assets} + accounts = AuthBook.objects.all() + if not accounts.exists(): + return - accounts = AuthBook.get_queryset().select_related('systemuser') - if not accounts.first(): - return data_map - - header_fields = cls.get_header_fields(AccountSecretSerializer(accounts.first())) + header_fields = cls.get_header_fields(AccountBackUpSerializer(accounts.first())) for account in accounts: - account.load_auth() - row = cls.create_row(account, AccountSecretSerializer, header_fields) - if sheet_name not in data_map: - data_map[sheet_name].append(list(row.keys())) - data_map[sheet_name].append(list(row.values())) - + cls.replace_account_info(account, asset_dict, system_user_dict) + data = AccountBackUpSerializer(accounts, many=True).data + data_map = cls.add_rows(data, header_fields, sheet_name) logger.info('\n\033[33m- 共收集 {} 条资产账号\033[0m'.format(accounts.count())) return data_map @@ -101,18 +131,36 @@ class AppAccountHandler(BaseAccountHandler): return filename @classmethod - def create_data_map(cls): - data_map = defaultdict(list) - accounts = Account.get_queryset().select_related('systemuser') - for account in accounts: - account.load_auth() - app_type = account.type + def replace_account_info(cls, account, app_dict, system_user_dict): + app = app_dict.get(account.app_id) + account.type = app.type if app else '' + account.app_display = app.name if app else '' + account.category = app.category if app else '' + account = cls.replace_auth(account, system_user_dict) + return account + + @classmethod + def create_data_map(cls, system_user_dict): + apps = Application.objects.only('id', 'type', 'name', 'category') + app_dict = {app.id: app for app in apps} + qs = Account.objects.all().annotate(app_type=F('app__type')) + if not qs.exists(): + return + + account_type_map = defaultdict(list) + for i in qs: + account_type_map[i.app_type].append(i) + data_map = {} + for app_type, accounts in account_type_map.items(): sheet_name = AppType.get_label(app_type) - row = cls.create_row(account, AppAccountSecretSerializer) - if sheet_name not in data_map: - data_map[sheet_name].append(list(row.keys())) - data_map[sheet_name].append(list(row.values())) - logger.info('\n\033[33m- 共收集{}条应用账号\033[0m'.format(accounts.count())) + header_fields = cls.get_header_fields(AppAccountBackUpSerializer(tp=app_type)) + if not accounts: + continue + for account in accounts: + cls.replace_account_info(account, app_dict, system_user_dict) + data = AppAccountBackUpSerializer(accounts, many=True, tp=app_type).data + data_map.update(cls.add_rows(data, header_fields, sheet_name)) + logger.info('\n\033[33m- 共收集{}条应用账号\033[0m'.format(qs.count())) return data_map @@ -137,12 +185,16 @@ class AccountBackupHandler: # Print task start date time_start = time.time() files = [] + system_user_qs = SystemUser.objects.only( + 'id', 'username', 'password', 'private_key', 'public_key' + ) + system_user_dict = {i.id: i for i in system_user_qs} for account_type in self.execution.types: handler = handler_map.get(account_type) if not handler: continue - data_map = handler.create_data_map() + data_map = handler.create_data_map(system_user_dict) if not data_map: continue diff --git a/apps/authentication/backends/oauth2/urls.py b/apps/authentication/backends/oauth2/urls.py index 94c044a7d..c44dd7c74 100644 --- a/apps/authentication/backends/oauth2/urls.py +++ b/apps/authentication/backends/oauth2/urls.py @@ -7,5 +7,6 @@ from . import views urlpatterns = [ path('login/', views.OAuth2AuthRequestView.as_view(), name='login'), - path('callback/', views.OAuth2AuthCallbackView.as_view(), name='login-callback') + path('callback/', views.OAuth2AuthCallbackView.as_view(), name='login-callback'), + path('logout/', views.OAuth2EndSessionView.as_view(), name='logout') ] diff --git a/apps/authentication/backends/oauth2/views.py b/apps/authentication/backends/oauth2/views.py index dd295fe86..d3f4865a2 100644 --- a/apps/authentication/backends/oauth2/views.py +++ b/apps/authentication/backends/oauth2/views.py @@ -1,6 +1,6 @@ from django.views import View from django.conf import settings -from django.contrib.auth import login +from django.contrib import auth from django.http import HttpResponseRedirect from django.urls import reverse from django.utils.http import urlencode @@ -48,7 +48,7 @@ class OAuth2AuthCallbackView(View): user = authenticate(code=callback_params['code'], request=request) if user and user.is_valid: logger.debug(log_prompt.format('Login: {}'.format(user))) - login(self.request, user) + auth.login(self.request, user) logger.debug(log_prompt.format('Redirect')) return HttpResponseRedirect( settings.AUTH_OAUTH2_AUTHENTICATION_REDIRECT_URI @@ -56,3 +56,33 @@ class OAuth2AuthCallbackView(View): logger.debug(log_prompt.format('Redirect')) return HttpResponseRedirect(settings.AUTH_OAUTH2_AUTHENTICATION_FAILURE_REDIRECT_URI) + + +class OAuth2EndSessionView(View): + http_method_names = ['get', 'post', ] + + def get(self, request): + """ Processes GET requests. """ + log_prompt = "Process GET requests [OAuth2EndSessionView]: {}" + logger.debug(log_prompt.format('Start')) + return self.post(request) + + def post(self, request): + """ Processes POST requests. """ + log_prompt = "Process POST requests [OAuth2EndSessionView]: {}" + logger.debug(log_prompt.format('Start')) + + logout_url = settings.LOGOUT_REDIRECT_URL or '/' + + # Log out the current user. + if request.user.is_authenticated: + logger.debug(log_prompt.format('Log out the current user: {}'.format(request.user))) + auth.logout(request) + + if settings.AUTH_OAUTH2_LOGOUT_COMPLETELY: + logger.debug(log_prompt.format('Log out OAUTH2 platform user session synchronously')) + next_url = settings.AUTH_OAUTH2_PROVIDER_END_SESSION_ENDPOINT + return HttpResponseRedirect(next_url) + + logger.debug(log_prompt.format('Redirect')) + return HttpResponseRedirect(logout_url) diff --git a/apps/authentication/backends/saml2/views.py b/apps/authentication/backends/saml2/views.py index e91fd0660..e0fa97590 100644 --- a/apps/authentication/backends/saml2/views.py +++ b/apps/authentication/backends/saml2/views.py @@ -3,7 +3,7 @@ import copy from urllib import parse from django.views import View -from django.contrib import auth as auth +from django.contrib import auth from django.urls import reverse from django.conf import settings from django.views.decorators.csrf import csrf_exempt @@ -271,7 +271,10 @@ class Saml2AuthCallbackView(View, PrepareRequestMixin): auth.login(self.request, user) logger.debug(log_prompt.format('Redirect')) - next_url = saml_instance.redirect_to(post_data.get('RelayState', '/')) + redir = post_data.get('RelayState') + if not redir or len(redir) == 0: + redir = "/" + next_url = saml_instance.redirect_to(redir) return HttpResponseRedirect(next_url) @csrf_exempt diff --git a/apps/authentication/views/login.py b/apps/authentication/views/login.py index 88f580279..19720b587 100644 --- a/apps/authentication/views/login.py +++ b/apps/authentication/views/login.py @@ -330,6 +330,8 @@ class UserLogoutView(TemplateView): return settings.CAS_LOGOUT_URL_NAME elif 'saml2' in backend: return settings.SAML2_LOGOUT_URL_NAME + elif 'oauth2' in backend: + return settings.AUTH_OAUTH2_LOGOUT_URL_NAME return None def get(self, request, *args, **kwargs): diff --git a/apps/common/permissions.py b/apps/common/permissions.py index 869107a58..7ce39e1a4 100644 --- a/apps/common/permissions.py +++ b/apps/common/permissions.py @@ -62,15 +62,22 @@ class UserConfirmation(permissions.BasePermission): confirm_level = request.session.get('CONFIRM_LEVEL') confirm_time = request.session.get('CONFIRM_TIME') - + ttl = self.get_ttl() if not confirm_level or not confirm_time or \ confirm_level < self.min_level or \ - confirm_time < time.time() - self.ttl: + confirm_time < time.time() - ttl: raise UserConfirmRequired(code=self.confirm_type) return True + def get_ttl(self): + if self.confirm_type == ConfirmType.MFA: + ttl = settings.SECURITY_MFA_VERIFY_TTL + else: + ttl = self.ttl + return ttl + @classmethod - def require(cls, confirm_type=ConfirmType.ReLogin, ttl=300): + def require(cls, confirm_type=ConfirmType.ReLogin, ttl=60 * 5): min_level = ConfirmType.values.index(confirm_type) + 1 name = 'UserConfirmationLevel{}TTL{}'.format(min_level, ttl) return type(name, (cls,), {'min_level': min_level, 'ttl': ttl, 'confirm_type': confirm_type}) diff --git a/apps/common/sdk/sms/endpoint.py b/apps/common/sdk/sms/endpoint.py index 3bcaa8559..044cf28a2 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') + HUAWEI = 'huawei', _('Huawei Cloud') CMPP2 = 'cmpp2', _('CMPP v2.0') diff --git a/apps/common/sdk/sms/huawei.py b/apps/common/sdk/sms/huawei.py new file mode 100644 index 000000000..c5d6bb116 --- /dev/null +++ b/apps/common/sdk/sms/huawei.py @@ -0,0 +1,94 @@ +import base64 +import hashlib +import time +import uuid + +import requests + +from collections import OrderedDict + +from django.conf import settings +from common.exceptions import JMSException +from common.utils import get_logger + +from .base import BaseSMSClient + +logger = get_logger(__file__) + + +class HuaweiClient: + def __init__(self, app_key, app_secret, url, sign_channel_num): + self.url = url[:-1] if url.endswith('/') else url + self.app_key = app_key + self.app_secret = app_secret + self.sign_channel_num = sign_channel_num + + def build_wsse_header(self): + now = time.strftime('%Y-%m-%dT%H:%M:%SZ') + nonce = str(uuid.uuid4()).replace('-', '') + digest = hashlib.sha256((nonce + now + self.app_secret).encode()).hexdigest() + digestBase64 = base64.b64encode(digest.encode()).decode() + formatter = 'UsernameToken Username="{}",PasswordDigest="{}",Nonce="{}",Created="{}"' + return formatter.format(self.app_key, digestBase64, nonce, now) + + def send_sms(self, receiver, signature, template_id, template_param): + sms_url = '%s/%s' % (self.url, 'sms/batchSendSms/v1') + headers = { + 'Authorization': 'WSSE realm="SDP",profile="UsernameToken",type="Appkey"', + 'X-WSSE': self.build_wsse_header() + } + body = { + 'from': self.sign_channel_num, 'to': receiver, 'templateId': template_id, + 'templateParas': template_param, 'signature': signature + } + try: + response = requests.post(sms_url, headers=headers, data=body) + msg = response.json() + except Exception as error: + raise JMSException(code='response_bad', detail=error) + return msg + + +class HuaweiSMS(BaseSMSClient): + SIGN_AND_TMPL_SETTING_FIELD_PREFIX = 'HUAWEI' + + @classmethod + def new_from_settings(cls): + return cls( + app_key=settings.HUAWEI_APP_KEY, + app_secret=settings.HUAWEI_APP_SECRET, + url=settings.HUAWEI_SMS_ENDPOINT, + sign_channel_num=settings.HUAWEI_SIGN_CHANNEL_NUM + ) + + def __init__(self, app_key: str, app_secret: str, url: str, sign_channel_num: str): + self.client = HuaweiClient(app_key, app_secret, url, sign_channel_num) + + def send_sms( + self, phone_numbers: list, sign_name: str, template_code: str, + template_param: OrderedDict, **kwargs + ): + phone_numbers_str = ','.join(phone_numbers) + template_param = '["%s"]' % template_param.get('code') + req_params = { + 'receiver': phone_numbers_str, 'signature': sign_name, + 'template_id': template_code, 'template_param': template_param + } + try: + logger.info(f'Huawei sms send: ' + f'phone_numbers={phone_numbers} ' + f'sign_name={sign_name} ' + f'template_code={template_code} ' + f'template_param={template_param}') + + resp_msg = self.client.send_sms(**req_params) + + except Exception as error: + raise JMSException(code='response_bad', detail=error) + + if resp_msg.get('code') != '000000': + raise JMSException(code='response_bad', detail=resp_msg) + return resp_msg + + +client = HuaweiSMS diff --git a/apps/common/utils/file.py b/apps/common/utils/file.py index 9529fbdca..efc652870 100644 --- a/apps/common/utils/file.py +++ b/apps/common/utils/file.py @@ -4,6 +4,10 @@ import csv import pyzipper import requests +from hashlib import md5 + +from django.conf import settings + def create_csv_file(filename, headers, rows, ): with open(filename, 'w', encoding='utf-8-sig')as f: @@ -28,3 +32,18 @@ def download_file(src, path): with open(path, 'wb') as f: for chunk in r.iter_content(chunk_size=8192): f.write(chunk) + + +def save_content_to_temp_path(content, file_mode=0o400): + if not content: + return + + project_dir = settings.PROJECT_DIR + tmp_dir = os.path.join(project_dir, 'tmp') + filename = '.' + md5(content.encode('utf-8')).hexdigest() + filepath = os.path.join(tmp_dir, filename) + if not os.path.exists(filepath): + with open(filepath, 'w') as f: + f.write(content) + os.chmod(filepath, file_mode) + return filepath diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 5ec858821..f31f4250a 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -334,8 +334,10 @@ class Config(dict): 'AUTH_OAUTH2_CLIENT_ID': 'client-id', 'AUTH_OAUTH2_SCOPE': '', 'AUTH_OAUTH2_CLIENT_SECRET': '', + 'AUTH_OAUTH2_LOGOUT_COMPLETELY': True, 'AUTH_OAUTH2_PROVIDER_AUTHORIZATION_ENDPOINT': 'https://oauth2.example.com/authorize', 'AUTH_OAUTH2_PROVIDER_USERINFO_ENDPOINT': 'https://oauth2.example.com/userinfo', + 'AUTH_OAUTH2_PROVIDER_END_SESSION_ENDPOINT': 'https://oauth2.example.com/logout', 'AUTH_OAUTH2_ACCESS_TOKEN_ENDPOINT': 'https://oauth2.example.com/access_token', 'AUTH_OAUTH2_ACCESS_TOKEN_METHOD': 'GET', 'AUTH_OAUTH2_USER_ATTR_MAP': { @@ -379,6 +381,13 @@ class Config(dict): 'TENCENT_VERIFY_SIGN_NAME': '', 'TENCENT_VERIFY_TEMPLATE_CODE': '', + 'HUAWEI_APP_KEY': '', + 'HUAWEI_APP_SECRET': '', + 'HUAWEI_SMS_ENDPOINT': '', + 'HUAWEI_SIGN_CHANNEL_NUM': '', + 'HUAWEI_VERIFY_SIGN_NAME': '', + 'HUAWEI_VERIFY_TEMPLATE_CODE': '', + 'CMPP2_HOST': '', 'CMPP2_PORT': 7890, 'CMPP2_SP_ID': '', diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index 4aafdd35b..462aefc57 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -164,6 +164,7 @@ AUTH_OAUTH2_USER_ATTR_MAP = CONFIG.AUTH_OAUTH2_USER_ATTR_MAP AUTH_OAUTH2_AUTH_LOGIN_CALLBACK_URL_NAME = 'authentication:oauth2:login-callback' AUTH_OAUTH2_AUTHENTICATION_REDIRECT_URI = '/' AUTH_OAUTH2_AUTHENTICATION_FAILURE_REDIRECT_URI = '/' +AUTH_OAUTH2_LOGOUT_URL_NAME = "authentication:oauth2:logout" # 临时 token AUTH_TEMP_TOKEN = CONFIG.AUTH_TEMP_TOKEN diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index a65266a1f..3c929e97a 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -142,6 +142,7 @@ WSGI_APPLICATION = 'jumpserver.wsgi.application' LOGIN_REDIRECT_URL = reverse_lazy('index') LOGIN_URL = reverse_lazy('authentication:login') +LOGOUT_REDIRECT_URL = CONFIG.LOGOUT_REDIRECT_URL SESSION_COOKIE_DOMAIN = CONFIG.SESSION_COOKIE_DOMAIN CSRF_COOKIE_DOMAIN = CONFIG.SESSION_COOKIE_DOMAIN diff --git a/apps/jumpserver/settings/custom.py b/apps/jumpserver/settings/custom.py index 0bcdc77d9..1fdb530cb 100644 --- a/apps/jumpserver/settings/custom.py +++ b/apps/jumpserver/settings/custom.py @@ -111,6 +111,8 @@ HTTP_LISTEN_PORT = CONFIG.HTTP_LISTEN_PORT WS_LISTEN_PORT = CONFIG.WS_LISTEN_PORT LOGIN_LOG_KEEP_DAYS = CONFIG.LOGIN_LOG_KEEP_DAYS TASK_LOG_KEEP_DAYS = CONFIG.TASK_LOG_KEEP_DAYS +OPERATE_LOG_KEEP_DAYS = CONFIG.OPERATE_LOG_KEEP_DAYS +FTP_LOG_KEEP_DAYS = CONFIG.FTP_LOG_KEEP_DAYS ORG_CHANGE_TO_URL = CONFIG.ORG_CHANGE_TO_URL WINDOWS_SKIP_ALL_MANUAL_PASSWORD = CONFIG.WINDOWS_SKIP_ALL_MANUAL_PASSWORD diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 4378759fd..e43defdca 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:d7d4ace7d7ec976b0321bde41789f994f02e3ab6f034828cbfb7e675a313611f -size 131531 +oid sha256:4d5dcc300fa64f04b513b670af0d9717fcdb108b54ddf264971b355cc72178de +size 132193 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index a5cb194ad..ea517add0 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-17 16:28+0800\n" +"POT-Creation-Date: 2022-09-15 15:52+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -32,7 +32,7 @@ msgstr "Acls" #: 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:665 +#: users/models/group.py:15 users/models/user.py:669 #: xpack/plugins/cloud/models.py:28 msgid "Name" msgstr "名前" @@ -64,7 +64,7 @@ msgstr "アクティブ" #: 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:702 +#: users/models/group.py:16 users/models/user.py:706 #: xpack/plugins/change_auth_plan/models/base.py:44 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:116 #: xpack/plugins/gathered_user/models.py:26 @@ -94,7 +94,7 @@ msgstr "ログイン確認" #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 #: terminal/models/sharing.py:33 terminal/notifications.py:91 #: terminal/notifications.py:139 tickets/models/comment.py:21 users/const.py:14 -#: users/models/user.py:894 users/models/user.py:925 +#: users/models/user.py:899 users/models/user.py:930 #: users/serializers/group.py:19 msgid "User" msgstr "ユーザー" @@ -120,8 +120,8 @@ msgid "Login acl" msgstr "ログインacl" #: acls/models/login_asset_acl.py:21 -#: applications/serializers/application.py:122 -#: applications/serializers/application.py:167 +#: applications/serializers/application.py:124 +#: applications/serializers/application.py:164 msgid "System User" msgstr "システムユーザー" @@ -160,7 +160,7 @@ msgstr "コンマ区切り文字列の形式。* はすべて一致すること #: 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:663 +#: ops/models/adhoc.py:159 users/forms/profile.py:32 users/models/user.py:667 #: users/templates/users/_msg_user_created.html:12 #: xpack/plugins/change_auth_plan/models/asset.py:34 #: xpack/plugins/change_auth_plan/models/asset.py:195 @@ -301,7 +301,7 @@ msgid "Can change application account secret" msgstr "アプリケーションアカウントの秘密を変更できます" #: applications/models/application.py:222 -#: applications/serializers/application.py:99 assets/models/label.py:21 +#: applications/serializers/application.py:101 assets/models/label.py:21 #: perms/models/application_permission.py:21 #: perms/serializers/application/user_permission.py:33 #: tickets/models/ticket/apply_application.py:15 @@ -310,7 +310,7 @@ msgid "Category" msgstr "カテゴリ" #: applications/models/application.py:225 -#: applications/serializers/application.py:101 assets/models/backup.py:49 +#: applications/serializers/application.py:103 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 #: perms/serializers/application/user_permission.py:34 @@ -329,7 +329,7 @@ msgid "Domain" msgstr "ドメイン" #: applications/models/application.py:231 xpack/plugins/cloud/models.py:33 -#: xpack/plugins/cloud/serializers/account.py:61 +#: xpack/plugins/cloud/serializers/account.py:63 msgid "Attrs" msgstr "ツールバーの" @@ -341,14 +341,14 @@ msgstr "アプリケーションを一致させることができます" msgid "Application user" msgstr "アプリケーションユーザー" -#: applications/serializers/application.py:70 -#: applications/serializers/application.py:100 assets/serializers/label.py:13 +#: applications/serializers/application.py:72 +#: applications/serializers/application.py:102 assets/serializers/label.py:13 #: perms/serializers/application/permission.py:18 msgid "Category display" msgstr "カテゴリ表示" -#: applications/serializers/application.py:71 -#: applications/serializers/application.py:102 +#: applications/serializers/application.py:73 +#: applications/serializers/application.py:104 #: 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 @@ -356,7 +356,7 @@ msgstr "カテゴリ表示" msgid "Type display" msgstr "タイプ表示" -#: applications/serializers/application.py:103 assets/models/asset.py:230 +#: applications/serializers/application.py:105 assets/models/asset.py:230 #: assets/models/base.py:181 assets/models/cluster.py:26 #: assets/models/domain.py:26 assets/models/gathered_user.py:19 #: assets/models/group.py:22 assets/models/label.py:25 @@ -364,12 +364,12 @@ msgstr "タイプ表示" #: 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:72 orgs/models.py:223 perms/models/base.py:92 -#: users/models/group.py:18 users/models/user.py:926 +#: users/models/group.py:18 users/models/user.py:931 #: xpack/plugins/cloud/models.py:125 msgid "Date created" msgstr "作成された日付" -#: applications/serializers/application.py:104 assets/models/base.py:182 +#: applications/serializers/application.py:106 assets/models/base.py:182 #: 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 @@ -377,12 +377,12 @@ msgstr "作成された日付" msgid "Date updated" msgstr "更新日" -#: applications/serializers/application.py:121 -#: applications/serializers/application.py:166 authentication/models.py:99 +#: applications/serializers/application.py:123 +#: applications/serializers/application.py:163 authentication/models.py:99 msgid "Application display" msgstr "アプリケーション表示" -#: applications/serializers/application.py:123 +#: applications/serializers/application.py:125 msgid "account" 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:56 terminal/models/endpoint.py:11 +#: settings/serializers/auth/sms.py:65 terminal/models/endpoint.py:11 #: xpack/plugins/cloud/serializers/account_attrs.py:72 msgid "Host" msgstr "ホスト" @@ -407,11 +407,32 @@ 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:57 +#: settings/serializers/auth/radius.py:15 settings/serializers/auth/sms.py:66 #: xpack/plugins/cloud/serializers/account_attrs.py:73 msgid "Port" msgstr "ポート" +#: applications/serializers/attrs/application_category/db.py:16 +#: settings/serializers/email.py:36 +msgid "Use SSL" +msgstr "SSLの使用" + +#: applications/serializers/attrs/application_category/db.py:18 +msgid "CA certificate" +msgstr "CA 証明書" + +#: applications/serializers/attrs/application_category/db.py:21 +msgid "Client certificate file" +msgstr "クライアント証明書" + +#: applications/serializers/attrs/application_category/db.py:24 +msgid "Certificate key file" +msgstr "証明書キー" + +#: applications/serializers/attrs/application_category/db.py:26 +msgid "Allow invalid cert" +msgstr "証明書チェックを無視" + #: applications/serializers/attrs/application_category/remote_app.py:34 msgid "Asset Info" msgstr "資産情報" @@ -529,7 +550,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:162 +#: xpack/plugins/cloud/serializers/account_attrs.py:179 msgid "Platform" msgstr "プラットフォーム" @@ -629,7 +650,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:71 -#: orgs/models.py:225 perms/models/base.py:91 users/models/user.py:710 +#: orgs/models.py:225 perms/models/base.py:91 users/models/user.py:714 #: 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 @@ -774,7 +795,7 @@ msgstr "OK" #: assets/models/base.py:32 audits/models.py:118 #: xpack/plugins/change_auth_plan/serializers/app.py:88 #: xpack/plugins/change_auth_plan/serializers/asset.py:199 -#: xpack/plugins/cloud/const.py:33 +#: xpack/plugins/cloud/const.py:35 msgid "Failed" msgstr "失敗しました" @@ -825,7 +846,7 @@ msgstr "帯域幅" msgid "Contact" msgstr "連絡先" -#: assets/models/cluster.py:22 users/models/user.py:685 +#: assets/models/cluster.py:22 users/models/user.py:689 msgid "Phone" msgstr "電話" @@ -851,7 +872,7 @@ msgid "Default" msgstr "デフォルト" #: assets/models/cluster.py:36 assets/models/label.py:14 rbac/const.py:6 -#: users/models/user.py:911 +#: users/models/user.py:916 msgid "System" msgstr "システム" @@ -860,7 +881,7 @@ msgid "Default Cluster" msgstr "デフォルトクラスター" #: assets/models/cmd_filter.py:34 perms/models/base.py:86 -#: users/models/group.py:31 users/models/user.py:671 +#: users/models/group.py:31 users/models/user.py:675 msgid "User group" msgstr "ユーザーグループ" @@ -1101,7 +1122,7 @@ msgstr "" "されていません-個人情報にアクセスしてください-> ファイル暗号化パスワードを設" "定してください暗号化パスワード" -#: assets/serializers/account.py:36 assets/serializers/account.py:87 +#: assets/serializers/account.py:36 assets/serializers/account.py:83 #: assets/serializers/account_history.py:10 authentication/models.py:87 msgid "System user display" msgstr "システムユーザー表示" @@ -1159,7 +1180,7 @@ msgstr "定期的なパフォーマンス" msgid "Currently only mail sending is supported" msgstr "現在、メール送信のみがサポートされています" -#: assets/serializers/base.py:16 users/models/user.py:693 +#: assets/serializers/base.py:16 users/models/user.py:697 msgid "Private key" msgstr "ssh秘密鍵" @@ -1537,7 +1558,7 @@ msgstr "ユーザーエージェント" #: audits/models.py:126 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 -#: users/forms/profile.py:65 users/models/user.py:688 +#: users/forms/profile.py:65 users/models/user.py:692 #: users/serializers/profile.py:126 msgid "MFA" msgstr "MFA" @@ -1616,19 +1637,19 @@ msgstr "認証トークン" #: audits/signal_handlers.py:53 authentication/notifications.py:73 #: authentication/views/login.py:73 authentication/views/wecom.py:178 -#: notifications/backends/__init__.py:11 users/models/user.py:724 +#: notifications/backends/__init__.py:11 users/models/user.py:728 msgid "WeCom" msgstr "企業微信" #: audits/signal_handlers.py:54 authentication/views/feishu.py:144 #: authentication/views/login.py:85 notifications/backends/__init__.py:14 -#: users/models/user.py:726 +#: users/models/user.py:730 msgid "FeiShu" msgstr "本を飛ばす" #: audits/signal_handlers.py:55 authentication/views/dingtalk.py:179 #: authentication/views/login.py:79 notifications/backends/__init__.py:12 -#: users/models/user.py:725 +#: users/models/user.py:729 msgid "DingTalk" msgstr "DingTalk" @@ -1816,6 +1837,11 @@ msgstr "現在のユーザーはmfaタイプをサポートしていません: { msgid "Authentication" msgstr "認証" +#: authentication/backends/custom.py:58 +#: authentication/backends/oauth2/backends.py:158 authentication/models.py:158 +msgid "User invalid, disabled or expired" +msgstr "ユーザーが無効、無効、または期限切れです" + #: authentication/backends/drf.py:56 msgid "Invalid signature header. No credentials provided." msgstr "署名ヘッダーが無効です。資格情報は提供されていません。" @@ -1869,10 +1895,6 @@ msgstr "" msgid "Invalid token or cache refreshed." msgstr "無効なトークンまたはキャッシュの更新。" -#: authentication/backends/oauth2/backends.py:155 authentication/models.py:158 -msgid "User invalid, disabled or expired" -msgstr "ユーザーが無効、無効、または期限切れです" - #: authentication/confirm/password.py:16 msgid "Authentication failed password incorrect" msgstr "認証に失敗しました (ユーザー名またはパスワードが正しくありません)" @@ -2152,7 +2174,7 @@ msgstr "ひみつ" #: authentication/models.py:74 authentication/models.py:264 #: perms/models/base.py:90 tickets/models/ticket/apply_application.py:30 -#: tickets/models/ticket/apply_asset.py:24 users/models/user.py:707 +#: tickets/models/ticket/apply_asset.py:24 users/models/user.py:711 msgid "Date expired" msgstr "期限切れの日付" @@ -2324,7 +2346,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:390 ops/tasks.py:145 ops/tasks.py:148 +#: jumpserver/conf.py:402 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 @@ -2473,7 +2495,7 @@ msgid "Copy success" msgstr "コピー成功" #: authentication/utils.py:28 common/utils/ip/geoip/utils.py:24 -#: xpack/plugins/cloud/const.py:24 +#: xpack/plugins/cloud/const.py:26 msgid "LAN" msgstr "ローカルエリアネットワーク" @@ -2571,11 +2593,11 @@ msgstr "" msgid "No ticket found" msgstr "チケットが見つかりません" -#: authentication/views/login.py:346 +#: authentication/views/login.py:348 msgid "Logout success" msgstr "ログアウト成功" -#: authentication/views/login.py:347 +#: authentication/views/login.py:349 msgid "Logout success, return login page" msgstr "ログアウト成功、ログインページを返す" @@ -2747,15 +2769,19 @@ msgstr "アリ雲" msgid "Tencent cloud" msgstr "テンセント雲" -#: common/sdk/sms/endpoint.py:18 +#: common/sdk/sms/endpoint.py:18 xpack/plugins/cloud/const.py:13 +msgid "Huawei Cloud" +msgstr "華為雲" + +#: common/sdk/sms/endpoint.py:19 msgid "CMPP v2.0" msgstr "CMPP v2.0" -#: common/sdk/sms/endpoint.py:29 +#: common/sdk/sms/endpoint.py:30 msgid "SMS provider not support: {}" msgstr "SMSプロバイダーはサポートしていません: {}" -#: common/sdk/sms/endpoint.py:50 +#: common/sdk/sms/endpoint.py:51 msgid "SMS verification code signature or template invalid" msgstr "SMS検証コードの署名またはテンプレートが無効" @@ -2787,11 +2813,11 @@ msgstr "特殊文字を含むべきではない" msgid "The mobile phone number format is incorrect" msgstr "携帯電話番号の形式が正しくありません" -#: jumpserver/conf.py:389 +#: jumpserver/conf.py:401 msgid "Create account successfully" msgstr "アカウントを正常に作成" -#: jumpserver/conf.py:391 +#: jumpserver/conf.py:403 msgid "Your account has been created successfully" msgstr "アカウントが正常に作成されました" @@ -2836,7 +2862,7 @@ msgid "Notifications" msgstr "通知" #: notifications/backends/__init__.py:10 users/forms/profile.py:102 -#: users/models/user.py:667 +#: users/models/user.py:671 msgid "Email" msgstr "メール" @@ -3070,7 +3096,7 @@ msgid "Can view all joined org" msgstr "参加しているすべての組織を表示できます" #: orgs/models.py:222 rbac/models/role.py:46 rbac/models/rolebinding.py:44 -#: users/models/user.py:675 +#: users/models/user.py:679 msgid "Role" msgstr "ロール" @@ -3488,7 +3514,7 @@ msgid "Execute batch command" msgstr "バッチ実行コマンド" #: settings/api/dingtalk.py:31 settings/api/feishu.py:36 -#: settings/api/sms.py:131 settings/api/wecom.py:37 +#: settings/api/sms.py:148 settings/api/wecom.py:37 msgid "Test success" msgstr "テストの成功" @@ -3516,11 +3542,11 @@ msgstr "Ldapユーザーを取得するにはNone" msgid "Imported {} users successfully (Organization: {})" msgstr "{} 人のユーザーを正常にインポートしました (組織: {})" -#: settings/api/sms.py:113 +#: settings/api/sms.py:130 msgid "Invalid SMS platform" msgstr "無効なショートメッセージプラットフォーム" -#: settings/api/sms.py:119 +#: settings/api/sms.py:136 msgid "test_phone is required" msgstr "携帯番号をテストこのフィールドは必須です" @@ -3620,7 +3646,8 @@ msgstr "サービス側アドレス" msgid "Proxy server url" msgstr "コールバックアドレス" -#: settings/serializers/auth/cas.py:16 settings/serializers/auth/saml2.py:32 +#: settings/serializers/auth/cas.py:16 settings/serializers/auth/oauth2.py:53 +#: settings/serializers/auth/saml2.py:32 msgid "Logout completely" msgstr "同期ログアウト" @@ -3677,7 +3704,7 @@ msgstr "ユーザー検索フィルター" msgid "Choice may be (cn|uid|sAMAccountName)=%(user)s)" msgstr "選択は (cnまたはuidまたはsAMAccountName)=%(user)s)" -#: settings/serializers/auth/ldap.py:57 settings/serializers/auth/oauth2.py:51 +#: settings/serializers/auth/ldap.py:57 settings/serializers/auth/oauth2.py:55 #: settings/serializers/auth/oidc.py:36 msgid "User attr map" msgstr "ユーザー属性マッピング" @@ -3739,7 +3766,11 @@ msgstr "クライアント認証方式" msgid "Provider userinfo endpoint" msgstr "プロバイダーuserinfoエンドポイント" -#: settings/serializers/auth/oauth2.py:54 settings/serializers/auth/oidc.py:92 +#: settings/serializers/auth/oauth2.py:51 settings/serializers/auth/oidc.py:74 +msgid "Provider end session endpoint" +msgstr "プロバイダーのセッション終了エンドポイント" + +#: settings/serializers/auth/oauth2.py:58 settings/serializers/auth/oidc.py:92 #: settings/serializers/auth/saml2.py:33 msgid "Always update user" msgstr "常にユーザーを更新" @@ -3784,10 +3815,6 @@ msgstr "プロバイダーエンドポイント" msgid "Provider jwks endpoint" msgstr "プロバイダーjwksエンドポイント" -#: settings/serializers/auth/oidc.py:74 -msgid "Provider end session endpoint" -msgstr "プロバイダーのセッション終了エンドポイント" - #: settings/serializers/auth/oidc.py:77 msgid "Provider sign alg" msgstr "プロビダーサインalg" @@ -3857,13 +3884,13 @@ msgid "SMS provider / Protocol" msgstr "SMSプロバイダ / プロトコル" #: 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 +#: settings/serializers/auth/sms.py:51 settings/serializers/auth/sms.py:60 +#: settings/serializers/auth/sms.py:71 settings/serializers/email.py:65 msgid "Signature" msgstr "署名" #: settings/serializers/auth/sms.py:23 settings/serializers/auth/sms.py:44 -#: settings/serializers/auth/sms.py:52 +#: settings/serializers/auth/sms.py:52 settings/serializers/auth/sms.py:61 msgid "Template code" msgstr "テンプレートコード" @@ -3872,26 +3899,34 @@ msgid "Test phone" msgstr "テスト電話" #: settings/serializers/auth/sms.py:58 +msgid "App Access Address" +msgstr "アプリケーションアドレス" + +#: settings/serializers/auth/sms.py:59 +msgid "Signature channel number" +msgstr "署名チャネル番号" + +#: settings/serializers/auth/sms.py:67 msgid "Enterprise code(SP id)" msgstr "企業コード(SP id)" -#: settings/serializers/auth/sms.py:59 +#: settings/serializers/auth/sms.py:68 msgid "Shared secret(Shared secret)" msgstr "パスワードを共有する(Shared secret)" -#: settings/serializers/auth/sms.py:60 +#: settings/serializers/auth/sms.py:69 msgid "Original number(Src id)" msgstr "元の番号(Src id)" -#: settings/serializers/auth/sms.py:61 +#: settings/serializers/auth/sms.py:70 msgid "Business type(Service id)" msgstr "ビジネス・タイプ(Service id)" -#: settings/serializers/auth/sms.py:64 +#: settings/serializers/auth/sms.py:73 msgid "Template" msgstr "テンプレート" -#: settings/serializers/auth/sms.py:65 +#: settings/serializers/auth/sms.py:74 #, python-brace-format msgid "" "Template need contain {code} and Signature + template length does not exceed " @@ -3902,12 +3937,12 @@ msgstr "" "満です。たとえば、認証コードは{code}で、有効期間は5分です。他の人には言わない" "でください。" -#: settings/serializers/auth/sms.py:74 +#: settings/serializers/auth/sms.py:83 #, python-brace-format msgid "The template needs to contain {code}" msgstr "テンプレートには{code}を含める必要があります" -#: settings/serializers/auth/sms.py:77 +#: settings/serializers/auth/sms.py:86 msgid "Signature + Template must not exceed 65 words" msgstr "署名+テンプレートの長さは65文字以内" @@ -3925,7 +3960,7 @@ msgid "SSO auth key TTL" msgstr "Token有効期間" #: settings/serializers/auth/sso.py:15 -#: xpack/plugins/cloud/serializers/account_attrs.py:159 +#: xpack/plugins/cloud/serializers/account_attrs.py:176 msgid "Unit: second" msgstr "単位: 秒" @@ -4061,10 +4096,6 @@ msgstr "テスト受信者" msgid "Tips: Used only as a test mail recipient" msgstr "ヒント: テストメールの受信者としてのみ使用" -#: settings/serializers/email.py:36 -msgid "Use SSL" -msgstr "SSLの使用" - #: settings/serializers/email.py:37 msgid "If SMTP port is 465, may be select" msgstr "SMTPポートが465の場合は、" @@ -5763,7 +5794,7 @@ msgstr "公開鍵は古いものと同じであってはなりません。" msgid "Not a valid ssh public key" msgstr "有効なssh公開鍵ではありません" -#: users/forms/profile.py:161 users/models/user.py:696 +#: users/forms/profile.py:161 users/models/user.py:700 msgid "Public key" msgstr "公開キー" @@ -5775,55 +5806,55 @@ msgstr "強制有効" msgid "Local" msgstr "ローカル" -#: users/models/user.py:677 users/serializers/user.py:149 +#: users/models/user.py:681 users/serializers/user.py:149 msgid "Is service account" msgstr "サービスアカウントです" -#: users/models/user.py:679 +#: users/models/user.py:683 msgid "Avatar" msgstr "アバター" -#: users/models/user.py:682 +#: users/models/user.py:686 msgid "Wechat" msgstr "微信" -#: users/models/user.py:699 +#: users/models/user.py:703 msgid "Secret key" msgstr "秘密キー" -#: users/models/user.py:715 +#: users/models/user.py:719 msgid "Source" msgstr "ソース" -#: users/models/user.py:719 +#: users/models/user.py:723 msgid "Date password last updated" msgstr "最終更新日パスワード" -#: users/models/user.py:722 +#: users/models/user.py:726 msgid "Need update password" msgstr "更新パスワードが必要" -#: users/models/user.py:896 +#: users/models/user.py:901 msgid "Can invite user" msgstr "ユーザーを招待できます" -#: users/models/user.py:897 +#: users/models/user.py:902 msgid "Can remove user" msgstr "ユーザーを削除できます" -#: users/models/user.py:898 +#: users/models/user.py:903 msgid "Can match user" msgstr "ユーザーに一致できます" -#: users/models/user.py:907 +#: users/models/user.py:912 msgid "Administrator" msgstr "管理者" -#: users/models/user.py:910 +#: users/models/user.py:915 msgid "Administrator is the super user of system" msgstr "管理者はシステムのスーパーユーザーです" -#: users/models/user.py:935 +#: users/models/user.py:940 msgid "User password history" msgstr "ユーザーパスワード履歴" @@ -6433,10 +6464,6 @@ msgstr "Azure (中国)" msgid "Azure (International)" msgstr "Azure (国際)" -#: xpack/plugins/cloud/const.py:13 -msgid "Huawei Cloud" -msgstr "華為雲" - #: xpack/plugins/cloud/const.py:14 msgid "Baidu Cloud" msgstr "百度雲" @@ -6450,58 +6477,66 @@ msgid "Tencent Cloud" msgstr "テンセント雲" #: xpack/plugins/cloud/const.py:17 +msgid "Tencent Cloud (Lighthouse)" +msgstr "テンセント雲(軽量アプリケーション)" + +#: xpack/plugins/cloud/const.py:18 msgid "VMware" msgstr "VMware" -#: xpack/plugins/cloud/const.py:18 xpack/plugins/cloud/providers/nutanix.py:13 +#: xpack/plugins/cloud/const.py:19 xpack/plugins/cloud/providers/nutanix.py:13 msgid "Nutanix" msgstr "Nutanix" -#: xpack/plugins/cloud/const.py:19 +#: xpack/plugins/cloud/const.py:20 msgid "Huawei Private Cloud" msgstr "華為私有雲" -#: xpack/plugins/cloud/const.py:20 +#: xpack/plugins/cloud/const.py:21 msgid "Qingyun Private Cloud" msgstr "青雲私有雲" -#: xpack/plugins/cloud/const.py:21 +#: xpack/plugins/cloud/const.py:22 +msgid "CTYun Private Cloud" +msgstr "スカイウィング私有雲" + +#: xpack/plugins/cloud/const.py:23 msgid "OpenStack" msgstr "OpenStack" -#: xpack/plugins/cloud/const.py:22 +#: xpack/plugins/cloud/const.py:24 msgid "Google Cloud Platform" msgstr "谷歌雲" -#: xpack/plugins/cloud/const.py:23 +#: xpack/plugins/cloud/const.py:25 msgid "Fusion Compute" msgstr "" -#: xpack/plugins/cloud/const.py:28 +#: xpack/plugins/cloud/const.py:30 msgid "Instance name" msgstr "インスタンス名" -#: xpack/plugins/cloud/const.py:29 +#: xpack/plugins/cloud/const.py:31 msgid "Instance name and Partial IP" msgstr "インスタンス名と部分IP" -#: xpack/plugins/cloud/const.py:34 +#: xpack/plugins/cloud/const.py:36 msgid "Succeed" msgstr "成功" -#: xpack/plugins/cloud/const.py:38 +#: xpack/plugins/cloud/const.py:40 msgid "Unsync" msgstr "同期していません" -#: xpack/plugins/cloud/const.py:39 +#: xpack/plugins/cloud/const.py:41 msgid "New Sync" msgstr "新しい同期" -#: xpack/plugins/cloud/const.py:40 +#: xpack/plugins/cloud/const.py:42 msgid "Synced" msgstr "同期済み" -#: xpack/plugins/cloud/const.py:41 +#: xpack/plugins/cloud/const.py:43 msgid "Released" msgstr "リリース済み" @@ -6771,11 +6806,11 @@ msgstr "華南-広州-友好ユーザー環境" msgid "CN East-Suqian" msgstr "華東-宿遷" -#: xpack/plugins/cloud/serializers/account.py:62 +#: xpack/plugins/cloud/serializers/account.py:64 msgid "Validity display" msgstr "有効表示" -#: xpack/plugins/cloud/serializers/account.py:63 +#: xpack/plugins/cloud/serializers/account.py:65 msgid "Provider display" msgstr "プロバイダ表示" @@ -6793,7 +6828,8 @@ msgstr "サブスクリプションID" #: xpack/plugins/cloud/serializers/account_attrs.py:95 #: xpack/plugins/cloud/serializers/account_attrs.py:100 -#: xpack/plugins/cloud/serializers/account_attrs.py:124 +#: xpack/plugins/cloud/serializers/account_attrs.py:116 +#: xpack/plugins/cloud/serializers/account_attrs.py:141 msgid "API Endpoint" msgstr "APIエンドポイント" @@ -6810,24 +6846,32 @@ msgid "User domain" msgstr "ユーザードメイン" #: xpack/plugins/cloud/serializers/account_attrs.py:117 +msgid "Cert File" +msgstr "証明書ファイル" + +#: xpack/plugins/cloud/serializers/account_attrs.py:118 +msgid "Key File" +msgstr "キーファイル" + +#: xpack/plugins/cloud/serializers/account_attrs.py:134 msgid "Service account key" msgstr "サービスアカウントキー" -#: xpack/plugins/cloud/serializers/account_attrs.py:118 +#: xpack/plugins/cloud/serializers/account_attrs.py:135 msgid "The file is in JSON format" msgstr "ファイルはJSON形式です。" -#: xpack/plugins/cloud/serializers/account_attrs.py:131 +#: xpack/plugins/cloud/serializers/account_attrs.py:148 msgid "IP address invalid `{}`, {}" msgstr "IPアドレスが無効: '{}', {}" -#: xpack/plugins/cloud/serializers/account_attrs.py:137 +#: xpack/plugins/cloud/serializers/account_attrs.py:154 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:141 +#: xpack/plugins/cloud/serializers/account_attrs.py:158 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 " @@ -6837,19 +6881,19 @@ msgstr "" "実行されると、有効な IP アドレスのみが同期されます。
ポートが0の場合、す" "べてのIPアドレスが有効です。" -#: xpack/plugins/cloud/serializers/account_attrs.py:149 +#: xpack/plugins/cloud/serializers/account_attrs.py:166 msgid "Hostname prefix" msgstr "ホスト名プレフィックス" -#: xpack/plugins/cloud/serializers/account_attrs.py:152 +#: xpack/plugins/cloud/serializers/account_attrs.py:169 msgid "IP segment" msgstr "IP セグメント" -#: xpack/plugins/cloud/serializers/account_attrs.py:156 +#: xpack/plugins/cloud/serializers/account_attrs.py:173 msgid "Test port" msgstr "テストポート" -#: xpack/plugins/cloud/serializers/account_attrs.py:159 +#: xpack/plugins/cloud/serializers/account_attrs.py:176 msgid "Test timeout" msgstr "テストタイムアウト" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 1b7f36e83..dd47ce08a 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:114dc04325f5a778a7cd0fb1b4d5aa71dfb60ada57b1b4f3ae43d89c1c818e0f -size 108398 +oid sha256:618dce0f2521591410fb16b3d0afa536333d2e4f317d75d1955fe413dc0e64cb +size 108949 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 0eed25b45..946eaa1f0 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-17 16:28+0800\n" +"POT-Creation-Date: 2022-09-15 15:52+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -31,7 +31,7 @@ msgstr "访问控制" #: 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:665 +#: users/models/group.py:15 users/models/user.py:669 #: xpack/plugins/cloud/models.py:28 msgid "Name" msgstr "名称" @@ -63,7 +63,7 @@ msgstr "激活中" #: 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:702 +#: users/models/group.py:16 users/models/user.py:706 #: xpack/plugins/change_auth_plan/models/base.py:44 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:116 #: xpack/plugins/gathered_user/models.py:26 @@ -93,7 +93,7 @@ msgstr "登录复核" #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 #: terminal/models/sharing.py:33 terminal/notifications.py:91 #: terminal/notifications.py:139 tickets/models/comment.py:21 users/const.py:14 -#: users/models/user.py:894 users/models/user.py:925 +#: users/models/user.py:899 users/models/user.py:930 #: users/serializers/group.py:19 msgid "User" msgstr "用户" @@ -119,8 +119,8 @@ msgid "Login acl" msgstr "登录访问控制" #: acls/models/login_asset_acl.py:21 -#: applications/serializers/application.py:122 -#: applications/serializers/application.py:167 +#: applications/serializers/application.py:124 +#: applications/serializers/application.py:164 msgid "System User" msgstr "系统用户" @@ -159,7 +159,7 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. " #: 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:663 +#: ops/models/adhoc.py:159 users/forms/profile.py:32 users/models/user.py:667 #: users/templates/users/_msg_user_created.html:12 #: xpack/plugins/change_auth_plan/models/asset.py:34 #: xpack/plugins/change_auth_plan/models/asset.py:195 @@ -296,7 +296,7 @@ msgid "Can change application account secret" msgstr "可以查看应用账号密码" #: applications/models/application.py:222 -#: applications/serializers/application.py:99 assets/models/label.py:21 +#: applications/serializers/application.py:101 assets/models/label.py:21 #: perms/models/application_permission.py:21 #: perms/serializers/application/user_permission.py:33 #: tickets/models/ticket/apply_application.py:15 @@ -305,7 +305,7 @@ msgid "Category" msgstr "类别" #: applications/models/application.py:225 -#: applications/serializers/application.py:101 assets/models/backup.py:49 +#: applications/serializers/application.py:103 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 #: perms/serializers/application/user_permission.py:34 @@ -324,7 +324,7 @@ msgid "Domain" msgstr "网域" #: applications/models/application.py:231 xpack/plugins/cloud/models.py:33 -#: xpack/plugins/cloud/serializers/account.py:61 +#: xpack/plugins/cloud/serializers/account.py:63 msgid "Attrs" msgstr "属性" @@ -336,14 +336,14 @@ msgstr "匹配应用" msgid "Application user" msgstr "应用用户" -#: applications/serializers/application.py:70 -#: applications/serializers/application.py:100 assets/serializers/label.py:13 +#: applications/serializers/application.py:72 +#: applications/serializers/application.py:102 assets/serializers/label.py:13 #: perms/serializers/application/permission.py:18 msgid "Category display" msgstr "类别名称" -#: applications/serializers/application.py:71 -#: applications/serializers/application.py:102 +#: applications/serializers/application.py:73 +#: applications/serializers/application.py:104 #: 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 @@ -351,7 +351,7 @@ msgstr "类别名称" msgid "Type display" msgstr "类型名称" -#: applications/serializers/application.py:103 assets/models/asset.py:230 +#: applications/serializers/application.py:105 assets/models/asset.py:230 #: assets/models/base.py:181 assets/models/cluster.py:26 #: assets/models/domain.py:26 assets/models/gathered_user.py:19 #: assets/models/group.py:22 assets/models/label.py:25 @@ -359,12 +359,12 @@ msgstr "类型名称" #: 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:72 orgs/models.py:223 perms/models/base.py:92 -#: users/models/group.py:18 users/models/user.py:926 +#: users/models/group.py:18 users/models/user.py:931 #: xpack/plugins/cloud/models.py:125 msgid "Date created" msgstr "创建日期" -#: applications/serializers/application.py:104 assets/models/base.py:182 +#: applications/serializers/application.py:106 assets/models/base.py:182 #: 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 @@ -372,12 +372,12 @@ msgstr "创建日期" msgid "Date updated" msgstr "更新日期" -#: applications/serializers/application.py:121 -#: applications/serializers/application.py:166 authentication/models.py:99 +#: applications/serializers/application.py:123 +#: applications/serializers/application.py:163 authentication/models.py:99 msgid "Application display" msgstr "应用名称" -#: applications/serializers/application.py:123 +#: applications/serializers/application.py:125 msgid "account" 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:56 terminal/models/endpoint.py:11 +#: settings/serializers/auth/sms.py:65 terminal/models/endpoint.py:11 #: xpack/plugins/cloud/serializers/account_attrs.py:72 msgid "Host" msgstr "主机" @@ -402,11 +402,32 @@ 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:57 +#: settings/serializers/auth/radius.py:15 settings/serializers/auth/sms.py:66 #: xpack/plugins/cloud/serializers/account_attrs.py:73 msgid "Port" msgstr "端口" +#: applications/serializers/attrs/application_category/db.py:16 +#: settings/serializers/email.py:36 +msgid "Use SSL" +msgstr "使用 SSL" + +#: applications/serializers/attrs/application_category/db.py:18 +msgid "CA certificate" +msgstr "CA 证书" + +#: applications/serializers/attrs/application_category/db.py:21 +msgid "Client certificate file" +msgstr "客户端证书" + +#: applications/serializers/attrs/application_category/db.py:24 +msgid "Certificate key file" +msgstr "证书秘钥" + +#: applications/serializers/attrs/application_category/db.py:26 +msgid "Allow invalid cert" +msgstr "忽略证书校验" + #: applications/serializers/attrs/application_category/remote_app.py:34 msgid "Asset Info" msgstr "资产信息" @@ -524,7 +545,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:162 +#: xpack/plugins/cloud/serializers/account_attrs.py:179 msgid "Platform" msgstr "系统平台" @@ -624,7 +645,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:71 -#: orgs/models.py:225 perms/models/base.py:91 users/models/user.py:710 +#: orgs/models.py:225 perms/models/base.py:91 users/models/user.py:714 #: 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 @@ -769,7 +790,7 @@ msgstr "成功" #: assets/models/base.py:32 audits/models.py:118 #: xpack/plugins/change_auth_plan/serializers/app.py:88 #: xpack/plugins/change_auth_plan/serializers/asset.py:199 -#: xpack/plugins/cloud/const.py:33 +#: xpack/plugins/cloud/const.py:35 msgid "Failed" msgstr "失败" @@ -820,7 +841,7 @@ msgstr "带宽" msgid "Contact" msgstr "联系人" -#: assets/models/cluster.py:22 users/models/user.py:685 +#: assets/models/cluster.py:22 users/models/user.py:689 msgid "Phone" msgstr "手机" @@ -846,7 +867,7 @@ msgid "Default" msgstr "默认" #: assets/models/cluster.py:36 assets/models/label.py:14 rbac/const.py:6 -#: users/models/user.py:911 +#: users/models/user.py:916 msgid "System" msgstr "系统" @@ -855,7 +876,7 @@ msgid "Default Cluster" msgstr "默认Cluster" #: assets/models/cmd_filter.py:34 perms/models/base.py:86 -#: users/models/group.py:31 users/models/user.py:671 +#: users/models/group.py:31 users/models/user.py:675 msgid "User group" msgstr "用户组" @@ -1093,7 +1114,7 @@ msgstr "" "{} - 账号备份任务已完成: 未设置加密密码 - 请前往个人信息 -> 文件加密密码中设" "置加密密码" -#: assets/serializers/account.py:36 assets/serializers/account.py:87 +#: assets/serializers/account.py:36 assets/serializers/account.py:83 #: assets/serializers/account_history.py:10 authentication/models.py:87 msgid "System user display" msgstr "系统用户名称" @@ -1151,7 +1172,7 @@ msgstr "定时执行" msgid "Currently only mail sending is supported" msgstr "当前只支持邮件发送" -#: assets/serializers/base.py:16 users/models/user.py:693 +#: assets/serializers/base.py:16 users/models/user.py:697 msgid "Private key" msgstr "ssh私钥" @@ -1525,7 +1546,7 @@ msgstr "用户代理" #: audits/models.py:126 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 -#: users/forms/profile.py:65 users/models/user.py:688 +#: users/forms/profile.py:65 users/models/user.py:692 #: users/serializers/profile.py:126 msgid "MFA" msgstr "MFA" @@ -1604,19 +1625,19 @@ msgstr "认证令牌" #: audits/signal_handlers.py:53 authentication/notifications.py:73 #: authentication/views/login.py:73 authentication/views/wecom.py:178 -#: notifications/backends/__init__.py:11 users/models/user.py:724 +#: notifications/backends/__init__.py:11 users/models/user.py:728 msgid "WeCom" msgstr "企业微信" #: audits/signal_handlers.py:54 authentication/views/feishu.py:144 #: authentication/views/login.py:85 notifications/backends/__init__.py:14 -#: users/models/user.py:726 +#: users/models/user.py:730 msgid "FeiShu" msgstr "飞书" #: audits/signal_handlers.py:55 authentication/views/dingtalk.py:179 #: authentication/views/login.py:79 notifications/backends/__init__.py:12 -#: users/models/user.py:725 +#: users/models/user.py:729 msgid "DingTalk" msgstr "钉钉" @@ -1804,6 +1825,11 @@ msgstr "当前用户不支持 MFA 类型: {}" msgid "Authentication" msgstr "认证" +#: authentication/backends/custom.py:58 +#: authentication/backends/oauth2/backends.py:158 authentication/models.py:158 +msgid "User invalid, disabled or expired" +msgstr "用户无效,已禁用或已过期" + #: authentication/backends/drf.py:56 msgid "Invalid signature header. No credentials provided." msgstr "不合法的签名头" @@ -1855,10 +1881,6 @@ msgstr "无效的令牌头。符号字符串不应包含无效字符。" msgid "Invalid token or cache refreshed." msgstr "刷新的令牌或缓存无效。" -#: authentication/backends/oauth2/backends.py:155 authentication/models.py:158 -msgid "User invalid, disabled or expired" -msgstr "用户无效,已禁用或已过期" - #: authentication/confirm/password.py:16 msgid "Authentication failed password incorrect" msgstr "认证失败 (用户名或密码不正确)" @@ -2131,7 +2153,7 @@ msgstr "密钥" #: authentication/models.py:74 authentication/models.py:264 #: perms/models/base.py:90 tickets/models/ticket/apply_application.py:30 -#: tickets/models/ticket/apply_asset.py:24 users/models/user.py:707 +#: tickets/models/ticket/apply_asset.py:24 users/models/user.py:711 msgid "Date expired" msgstr "失效日期" @@ -2299,7 +2321,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:390 ops/tasks.py:145 ops/tasks.py:148 +#: jumpserver/conf.py:402 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 @@ -2439,7 +2461,7 @@ msgid "Copy success" msgstr "复制成功" #: authentication/utils.py:28 common/utils/ip/geoip/utils.py:24 -#: xpack/plugins/cloud/const.py:24 +#: xpack/plugins/cloud/const.py:26 msgid "LAN" msgstr "局域网" @@ -2537,11 +2559,11 @@ msgstr "" msgid "No ticket found" msgstr "没有发现工单" -#: authentication/views/login.py:346 +#: authentication/views/login.py:348 msgid "Logout success" msgstr "退出登录成功" -#: authentication/views/login.py:347 +#: authentication/views/login.py:349 msgid "Logout success, return login page" msgstr "退出登录成功,返回到登录页面" @@ -2713,15 +2735,19 @@ msgstr "阿里云" msgid "Tencent cloud" msgstr "腾讯云" -#: common/sdk/sms/endpoint.py:18 +#: common/sdk/sms/endpoint.py:18 xpack/plugins/cloud/const.py:13 +msgid "Huawei Cloud" +msgstr "华为云" + +#: common/sdk/sms/endpoint.py:19 msgid "CMPP v2.0" msgstr "CMPP v2.0" -#: common/sdk/sms/endpoint.py:29 +#: common/sdk/sms/endpoint.py:30 msgid "SMS provider not support: {}" msgstr "短信服务商不支持:{}" -#: common/sdk/sms/endpoint.py:50 +#: common/sdk/sms/endpoint.py:51 msgid "SMS verification code signature or template invalid" msgstr "短信验证码签名或模版无效" @@ -2753,11 +2779,11 @@ msgstr "不能包含特殊字符" msgid "The mobile phone number format is incorrect" msgstr "手机号格式不正确" -#: jumpserver/conf.py:389 +#: jumpserver/conf.py:401 msgid "Create account successfully" msgstr "创建账号成功" -#: jumpserver/conf.py:391 +#: jumpserver/conf.py:403 msgid "Your account has been created successfully" msgstr "你的账号已创建成功" @@ -2797,7 +2823,7 @@ msgid "Notifications" msgstr "通知" #: notifications/backends/__init__.py:10 users/forms/profile.py:102 -#: users/models/user.py:667 +#: users/models/user.py:671 msgid "Email" msgstr "邮件" @@ -3030,7 +3056,7 @@ msgid "Can view all joined org" msgstr "可以查看所有加入的组织" #: orgs/models.py:222 rbac/models/role.py:46 rbac/models/rolebinding.py:44 -#: users/models/user.py:675 +#: users/models/user.py:679 msgid "Role" msgstr "角色" @@ -3445,7 +3471,7 @@ msgid "Execute batch command" msgstr "执行批量命令" #: settings/api/dingtalk.py:31 settings/api/feishu.py:36 -#: settings/api/sms.py:131 settings/api/wecom.py:37 +#: settings/api/sms.py:148 settings/api/wecom.py:37 msgid "Test success" msgstr "测试成功" @@ -3473,11 +3499,11 @@ msgstr "获取 LDAP 用户为 None" msgid "Imported {} users successfully (Organization: {})" msgstr "成功导入 {} 个用户 ( 组织: {} )" -#: settings/api/sms.py:113 +#: settings/api/sms.py:130 msgid "Invalid SMS platform" msgstr "无效的短信平台" -#: settings/api/sms.py:119 +#: settings/api/sms.py:136 msgid "test_phone is required" msgstr "测试手机号 该字段是必填项。" @@ -3577,7 +3603,8 @@ msgstr "服务端地址" msgid "Proxy server url" msgstr "回调地址" -#: settings/serializers/auth/cas.py:16 settings/serializers/auth/saml2.py:32 +#: settings/serializers/auth/cas.py:16 settings/serializers/auth/oauth2.py:53 +#: settings/serializers/auth/saml2.py:32 msgid "Logout completely" msgstr "同步注销" @@ -3634,7 +3661,7 @@ msgstr "用户过滤器" msgid "Choice may be (cn|uid|sAMAccountName)=%(user)s)" msgstr "可能的选项是(cn或uid或sAMAccountName=%(user)s)" -#: settings/serializers/auth/ldap.py:57 settings/serializers/auth/oauth2.py:51 +#: settings/serializers/auth/ldap.py:57 settings/serializers/auth/oauth2.py:55 #: settings/serializers/auth/oidc.py:36 msgid "User attr map" msgstr "用户属性映射" @@ -3696,7 +3723,11 @@ msgstr "客户端认证方式" msgid "Provider userinfo endpoint" msgstr "用户信息端点地址" -#: settings/serializers/auth/oauth2.py:54 settings/serializers/auth/oidc.py:92 +#: settings/serializers/auth/oauth2.py:51 settings/serializers/auth/oidc.py:74 +msgid "Provider end session endpoint" +msgstr "注销会话端点地址" + +#: settings/serializers/auth/oauth2.py:58 settings/serializers/auth/oidc.py:92 #: settings/serializers/auth/saml2.py:33 msgid "Always update user" msgstr "总是更新用户信息" @@ -3741,10 +3772,6 @@ msgstr "端点地址" msgid "Provider jwks endpoint" msgstr "jwks 端点地址" -#: settings/serializers/auth/oidc.py:74 -msgid "Provider end session endpoint" -msgstr "注销会话端点地址" - #: settings/serializers/auth/oidc.py:77 msgid "Provider sign alg" msgstr "签名算法" @@ -3814,13 +3841,13 @@ msgid "SMS provider / Protocol" msgstr "短信服务商 / 协议" #: 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 +#: settings/serializers/auth/sms.py:51 settings/serializers/auth/sms.py:60 +#: settings/serializers/auth/sms.py:71 settings/serializers/email.py:65 msgid "Signature" msgstr "签名" #: settings/serializers/auth/sms.py:23 settings/serializers/auth/sms.py:44 -#: settings/serializers/auth/sms.py:52 +#: settings/serializers/auth/sms.py:52 settings/serializers/auth/sms.py:61 msgid "Template code" msgstr "模板" @@ -3829,26 +3856,34 @@ msgid "Test phone" msgstr "测试手机号" #: settings/serializers/auth/sms.py:58 +msgid "App Access Address" +msgstr "应用地址" + +#: settings/serializers/auth/sms.py:59 +msgid "Signature channel number" +msgstr "签名通道号" + +#: settings/serializers/auth/sms.py:67 msgid "Enterprise code(SP id)" msgstr "企业代码(SP id)" -#: settings/serializers/auth/sms.py:59 +#: settings/serializers/auth/sms.py:68 msgid "Shared secret(Shared secret)" msgstr "共享密码(Shared secret)" -#: settings/serializers/auth/sms.py:60 +#: settings/serializers/auth/sms.py:69 msgid "Original number(Src id)" msgstr "原始号码(Src id)" -#: settings/serializers/auth/sms.py:61 +#: settings/serializers/auth/sms.py:70 msgid "Business type(Service id)" msgstr "业务类型(Service id)" -#: settings/serializers/auth/sms.py:64 +#: settings/serializers/auth/sms.py:73 msgid "Template" msgstr "模板" -#: settings/serializers/auth/sms.py:65 +#: settings/serializers/auth/sms.py:74 #, python-brace-format msgid "" "Template need contain {code} and Signature + template length does not exceed " @@ -3858,12 +3893,12 @@ msgstr "" "模板需要包含 {code},并且模板+签名长度不能超过67个字。例如, 您的验证码是 " "{code}, 有效期为5分钟。请不要泄露给其他人。" -#: settings/serializers/auth/sms.py:74 +#: settings/serializers/auth/sms.py:83 #, python-brace-format msgid "The template needs to contain {code}" msgstr "模板需要包含 {code}" -#: settings/serializers/auth/sms.py:77 +#: settings/serializers/auth/sms.py:86 msgid "Signature + Template must not exceed 65 words" msgstr "模板+签名不能超过65个字" @@ -3880,7 +3915,7 @@ msgid "SSO auth key TTL" msgstr "Token 有效期" #: settings/serializers/auth/sso.py:15 -#: xpack/plugins/cloud/serializers/account_attrs.py:159 +#: xpack/plugins/cloud/serializers/account_attrs.py:176 msgid "Unit: second" msgstr "单位: 秒" @@ -4014,10 +4049,6 @@ msgstr "测试收件人" msgid "Tips: Used only as a test mail recipient" msgstr "提示:仅用来作为测试邮件收件人" -#: settings/serializers/email.py:36 -msgid "Use SSL" -msgstr "使用 SSL" - #: settings/serializers/email.py:37 msgid "If SMTP port is 465, may be select" msgstr "如果SMTP端口是465,通常需要启用 SSL" @@ -5680,7 +5711,7 @@ msgstr "不能和原来的密钥相同" msgid "Not a valid ssh public key" msgstr "SSH密钥不合法" -#: users/forms/profile.py:161 users/models/user.py:696 +#: users/forms/profile.py:161 users/models/user.py:700 msgid "Public key" msgstr "SSH公钥" @@ -5692,55 +5723,55 @@ msgstr "强制启用" msgid "Local" msgstr "数据库" -#: users/models/user.py:677 users/serializers/user.py:149 +#: users/models/user.py:681 users/serializers/user.py:149 msgid "Is service account" msgstr "服务账号" -#: users/models/user.py:679 +#: users/models/user.py:683 msgid "Avatar" msgstr "头像" -#: users/models/user.py:682 +#: users/models/user.py:686 msgid "Wechat" msgstr "微信" -#: users/models/user.py:699 +#: users/models/user.py:703 msgid "Secret key" msgstr "Secret key" -#: users/models/user.py:715 +#: users/models/user.py:719 msgid "Source" msgstr "来源" -#: users/models/user.py:719 +#: users/models/user.py:723 msgid "Date password last updated" msgstr "最后更新密码日期" -#: users/models/user.py:722 +#: users/models/user.py:726 msgid "Need update password" msgstr "需要更新密码" -#: users/models/user.py:896 +#: users/models/user.py:901 msgid "Can invite user" msgstr "可以邀请用户" -#: users/models/user.py:897 +#: users/models/user.py:902 msgid "Can remove user" msgstr "可以移除用户" -#: users/models/user.py:898 +#: users/models/user.py:903 msgid "Can match user" msgstr "可以匹配用户" -#: users/models/user.py:907 +#: users/models/user.py:912 msgid "Administrator" msgstr "管理员" -#: users/models/user.py:910 +#: users/models/user.py:915 msgid "Administrator is the super user of system" msgstr "Administrator是初始的超级管理员" -#: users/models/user.py:935 +#: users/models/user.py:940 msgid "User password history" msgstr "用户密码历史" @@ -6337,10 +6368,6 @@ msgstr "Azure (中国)" msgid "Azure (International)" msgstr "Azure (国际)" -#: xpack/plugins/cloud/const.py:13 -msgid "Huawei Cloud" -msgstr "华为云" - #: xpack/plugins/cloud/const.py:14 msgid "Baidu Cloud" msgstr "百度云" @@ -6354,58 +6381,66 @@ msgid "Tencent Cloud" msgstr "腾讯云" #: xpack/plugins/cloud/const.py:17 +msgid "Tencent Cloud (Lighthouse)" +msgstr "腾讯云(轻量服务器应用)" + +#: xpack/plugins/cloud/const.py:18 msgid "VMware" msgstr "VMware" -#: xpack/plugins/cloud/const.py:18 xpack/plugins/cloud/providers/nutanix.py:13 +#: xpack/plugins/cloud/const.py:19 xpack/plugins/cloud/providers/nutanix.py:13 msgid "Nutanix" msgstr "Nutanix" -#: xpack/plugins/cloud/const.py:19 +#: xpack/plugins/cloud/const.py:20 msgid "Huawei Private Cloud" msgstr "华为私有云" -#: xpack/plugins/cloud/const.py:20 +#: xpack/plugins/cloud/const.py:21 msgid "Qingyun Private Cloud" msgstr "青云私有云" -#: xpack/plugins/cloud/const.py:21 +#: xpack/plugins/cloud/const.py:22 +msgid "CTYun Private Cloud" +msgstr "天翼私有云" + +#: xpack/plugins/cloud/const.py:23 msgid "OpenStack" msgstr "OpenStack" -#: xpack/plugins/cloud/const.py:22 +#: xpack/plugins/cloud/const.py:24 msgid "Google Cloud Platform" msgstr "谷歌云" -#: xpack/plugins/cloud/const.py:23 +#: xpack/plugins/cloud/const.py:25 msgid "Fusion Compute" msgstr "" -#: xpack/plugins/cloud/const.py:28 +#: xpack/plugins/cloud/const.py:30 msgid "Instance name" msgstr "实例名称" -#: xpack/plugins/cloud/const.py:29 +#: xpack/plugins/cloud/const.py:31 msgid "Instance name and Partial IP" msgstr "实例名称和部分IP" -#: xpack/plugins/cloud/const.py:34 +#: xpack/plugins/cloud/const.py:36 msgid "Succeed" msgstr "成功" -#: xpack/plugins/cloud/const.py:38 +#: xpack/plugins/cloud/const.py:40 msgid "Unsync" msgstr "未同步" -#: xpack/plugins/cloud/const.py:39 +#: xpack/plugins/cloud/const.py:41 msgid "New Sync" msgstr "新同步" -#: xpack/plugins/cloud/const.py:40 +#: xpack/plugins/cloud/const.py:42 msgid "Synced" msgstr "已同步" -#: xpack/plugins/cloud/const.py:41 +#: xpack/plugins/cloud/const.py:43 msgid "Released" msgstr "已释放" @@ -6675,11 +6710,11 @@ msgstr "华南-广州-友好用户环境" msgid "CN East-Suqian" msgstr "华东-宿迁" -#: xpack/plugins/cloud/serializers/account.py:62 +#: xpack/plugins/cloud/serializers/account.py:64 msgid "Validity display" msgstr "有效性显示" -#: xpack/plugins/cloud/serializers/account.py:63 +#: xpack/plugins/cloud/serializers/account.py:65 msgid "Provider display" msgstr "服务商显示" @@ -6697,7 +6732,8 @@ msgstr "订阅 ID" #: xpack/plugins/cloud/serializers/account_attrs.py:95 #: xpack/plugins/cloud/serializers/account_attrs.py:100 -#: xpack/plugins/cloud/serializers/account_attrs.py:124 +#: xpack/plugins/cloud/serializers/account_attrs.py:116 +#: xpack/plugins/cloud/serializers/account_attrs.py:141 msgid "API Endpoint" msgstr "API 端点" @@ -6714,24 +6750,32 @@ msgid "User domain" msgstr "用户域" #: xpack/plugins/cloud/serializers/account_attrs.py:117 +msgid "Cert File" +msgstr "证书文件" + +#: xpack/plugins/cloud/serializers/account_attrs.py:118 +msgid "Key File" +msgstr "秘钥文件" + +#: xpack/plugins/cloud/serializers/account_attrs.py:134 msgid "Service account key" msgstr "服务账号密钥" -#: xpack/plugins/cloud/serializers/account_attrs.py:118 +#: xpack/plugins/cloud/serializers/account_attrs.py:135 msgid "The file is in JSON format" msgstr "JSON 格式的文件" -#: xpack/plugins/cloud/serializers/account_attrs.py:131 +#: xpack/plugins/cloud/serializers/account_attrs.py:148 msgid "IP address invalid `{}`, {}" msgstr "IP 地址无效: `{}`, {}" -#: xpack/plugins/cloud/serializers/account_attrs.py:137 +#: xpack/plugins/cloud/serializers/account_attrs.py:154 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:141 +#: xpack/plugins/cloud/serializers/account_attrs.py:158 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 " @@ -6740,19 +6784,19 @@ msgstr "" "端口用来检测 IP 地址的有效性,在同步任务执行时,只会同步有效的 IP 地址。
" "如果端口为 0,则表示所有 IP 地址均有效。" -#: xpack/plugins/cloud/serializers/account_attrs.py:149 +#: xpack/plugins/cloud/serializers/account_attrs.py:166 msgid "Hostname prefix" msgstr "主机名前缀" -#: xpack/plugins/cloud/serializers/account_attrs.py:152 +#: xpack/plugins/cloud/serializers/account_attrs.py:169 msgid "IP segment" msgstr "IP 网段" -#: xpack/plugins/cloud/serializers/account_attrs.py:156 +#: xpack/plugins/cloud/serializers/account_attrs.py:173 msgid "Test port" msgstr "测试端口" -#: xpack/plugins/cloud/serializers/account_attrs.py:159 +#: xpack/plugins/cloud/serializers/account_attrs.py:176 msgid "Test timeout" msgstr "测试超时时间" diff --git a/apps/settings/api/settings.py b/apps/settings/api/settings.py index 0f487c280..3e22b0bf8 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, + 'huawei': serializers.HuaweiSMSSettingSerializer, 'cmpp2': serializers.CMPP2SMSSettingSerializer, } diff --git a/apps/settings/api/sms.py b/apps/settings/api/sms.py index 668b5ec56..301f4e203 100644 --- a/apps/settings/api/sms.py +++ b/apps/settings/api/sms.py @@ -38,6 +38,7 @@ class SMSTestingAPI(GenericAPIView): backends_serializer = { 'alibaba': serializers.AlibabaSMSSettingSerializer, 'tencent': serializers.TencentSMSSettingSerializer, + 'huawei': serializers.HuaweiSMSSettingSerializer, 'cmpp2': serializers.CMPP2SMSSettingSerializer } rbac_perms = { @@ -82,6 +83,22 @@ class SMSTestingAPI(GenericAPIView): } return init_params, send_sms_params + def get_huawei_params(self, data): + init_params = { + 'app_key': data['HUAWEI_APP_KEY'], + 'app_secret': self.get_or_from_setting( + 'HUAWEI_APP_SECRET', data.get('HUAWEI_APP_SECRET') + ), + 'url': data['HUAWEI_SMS_ENDPOINT'], + 'sign_channel_num': data['HUAWEI_SIGN_CHANNEL_NUM'], + } + send_sms_params = { + 'sign_name': data['HUAWEI_VERIFY_SIGN_NAME'], + 'template_code': data['HUAWEI_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'], diff --git a/apps/settings/serializers/auth/oauth2.py b/apps/settings/serializers/auth/oauth2.py index 279f3c34f..a2230750a 100644 --- a/apps/settings/serializers/auth/oauth2.py +++ b/apps/settings/serializers/auth/oauth2.py @@ -47,6 +47,10 @@ class OAuth2SettingSerializer(serializers.Serializer): AUTH_OAUTH2_PROVIDER_USERINFO_ENDPOINT = serializers.CharField( required=True, max_length=1024, label=_('Provider userinfo endpoint') ) + AUTH_OAUTH2_PROVIDER_END_SESSION_ENDPOINT = serializers.CharField( + required=False, max_length=1024, label=_('Provider end session endpoint') + ) + AUTH_OAUTH2_LOGOUT_COMPLETELY = serializers.BooleanField(required=False, label=_('Logout completely')) AUTH_OAUTH2_USER_ATTR_MAP = serializers.DictField( required=True, label=_('User attr map') ) diff --git a/apps/settings/serializers/auth/sms.py b/apps/settings/serializers/auth/sms.py index 1278dea06..dda38b586 100644 --- a/apps/settings/serializers/auth/sms.py +++ b/apps/settings/serializers/auth/sms.py @@ -7,7 +7,7 @@ from common.sdk.sms import BACKENDS __all__ = [ 'SMSSettingSerializer', 'AlibabaSMSSettingSerializer', 'TencentSMSSettingSerializer', - 'CMPP2SMSSettingSerializer' + 'HuaweiSMSSettingSerializer', 'CMPP2SMSSettingSerializer' ] @@ -52,6 +52,15 @@ class TencentSMSSettingSerializer(BaseSMSSettingSerializer): TENCENT_VERIFY_TEMPLATE_CODE = serializers.CharField(max_length=256, required=True, label=_('Template code')) +class HuaweiSMSSettingSerializer(BaseSMSSettingSerializer): + HUAWEI_APP_KEY = serializers.CharField(max_length=256, required=True, label='App key') + HUAWEI_APP_SECRET = EncryptedField(max_length=256, required=False, label='App secret') + HUAWEI_SMS_ENDPOINT = serializers.CharField(max_length=1024, required=True, label=_('App Access Address')) + HUAWEI_SIGN_CHANNEL_NUM = serializers.CharField(max_length=1024, required=True, label=_('Signature channel number')) + HUAWEI_VERIFY_SIGN_NAME = serializers.CharField(max_length=256, required=True, label=_('Signature')) + HUAWEI_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')) diff --git a/apps/settings/utils/telnet.py b/apps/settings/utils/telnet.py index 9785b43ae..b8a7e81ef 100644 --- a/apps/settings/utils/telnet.py +++ b/apps/settings/utils/telnet.py @@ -13,7 +13,7 @@ def telnet(dest_addr, port_number=23, timeout=10): 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') + return True, output.decode('utf-8', 'ignore') if __name__ == "__main__": diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index c95c06c2c..b6bb6c6a4 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -1549,10 +1549,13 @@ function encryptPassword(password) { if (!password) { return '' } - const aesKey = (Math.random() + 1).toString(36).substring(2) // public key 是 base64 存储的 - const rsaPublicKeyText = getCookie('jms_public_key') - .replaceAll('"', '') + let rsaPublicKeyText = getCookie('jms_public_key') + if (!rsaPublicKeyText) { + return password + } + const aesKey = (Math.random() + 1).toString(36).substring(2) + rsaPublicKeyText = rsaPublicKeyText.replaceAll('"', '') const rsaPublicKey = atob(rsaPublicKeyText) const keyCipher = rsaEncrypt(aesKey, rsaPublicKey) const passwordCipher = aesEncrypt(password, aesKey) diff --git a/apps/tickets/filters.py b/apps/tickets/filters.py index bf20014cc..659556c12 100644 --- a/apps/tickets/filters.py +++ b/apps/tickets/filters.py @@ -1,5 +1,6 @@ from django_filters import rest_framework as filters -from django.db.models import Subquery, OuterRef +from django.db.models.functions import Concat +from django.db.models import Subquery, OuterRef, Value, F, Q from common.drf.filters import BaseFilterSet @@ -11,6 +12,10 @@ from tickets.models import ( class TicketFilter(BaseFilterSet): assignees__id = filters.UUIDFilter(method='filter_assignees_id') + relevant_app = filters.CharFilter(method='filter_relevant_app') + relevant_asset = filters.CharFilter(method='filter_relevant_asset') + relevant_system_user = filters.CharFilter(method='filter_relevant_system_user') + relevant_command = filters.CharFilter(method='filter_relevant_command') class Meta: model = Ticket @@ -27,6 +32,72 @@ class TicketFilter(BaseFilterSet): ticket_steps__ticket_assignees__assignee__id=value ) + def filter_relevant_asset(self, queryset, name, value): + asset_ids = ApplyAssetTicket.objects.annotate( + asset_str=Concat( + F('apply_assets__hostname'), Value('('), + F('apply_assets__ip'), Value(')') + ) + ).filter( + asset_str__icontains=value + ).values_list('id', flat=True) + + login_asset_ids = ApplyLoginAssetTicket.objects.annotate( + asset_str=Concat( + F('apply_login_asset__hostname'), Value('('), + F('apply_login_asset__ip'), Value(')') + ) + ).filter( + asset_str__icontains=value + ).values_list('id', flat=True) + + command_ids = ApplyCommandTicket.objects.filter( + apply_run_asset__icontains=value + ).values_list('id', flat=True) + + ticket_ids = list(set(list(asset_ids) + list(login_asset_ids) + list(command_ids))) + return queryset.filter(id__in=ticket_ids) + + def filter_relevant_app(self, queryset, name, value): + app_ids = ApplyApplicationTicket.objects.filter( + apply_applications__name__icontains=value + ).values_list('id', flat=True) + + command_ids = ApplyCommandTicket.objects.filter( + apply_run_asset__icontains=value + ).values_list('id', flat=True) + + ticket_ids = list(set(list(app_ids) + list(command_ids))) + return queryset.filter(id__in=ticket_ids) + + def filter_relevant_system_user(self, queryset, name, value): + system_user_query = Q(apply_system_users__name__icontains=value) + asset_ids = ApplyAssetTicket.objects.filter( + system_user_query + ).values_list('id', flat=True) + + app_ids = ApplyApplicationTicket.objects.filter( + system_user_query + ).values_list('id', flat=True) + + login_asset_ids = ApplyLoginAssetTicket.objects.filter( + apply_login_system_user__name__icontains=value + ).values_list('id', flat=True) + + command_ids = ApplyCommandTicket.objects.filter( + apply_run_system_user__name__icontains=value + ).values_list('id', flat=True) + ticket_ids = list( + set(list(asset_ids) + list(app_ids) + list(login_asset_ids) + list(command_ids)) + ) + return queryset.filter(id__in=ticket_ids) + + def filter_relevant_command(self, queryset, name, value): + command_ids = ApplyCommandTicket.objects.filter( + apply_run_command__icontains=value + ).values_list('id', flat=True) + return queryset.filter(id__in=list(command_ids)) + class ApplyAssetTicketFilter(BaseFilterSet): class Meta: diff --git a/entrypoint.sh b/entrypoint.sh index fe81b1470..58ed0b104 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -11,6 +11,9 @@ action="${1-start}" service="${2-all}" trap cleanup EXIT + +rm -f /opt/jumpserver/tmp/*.pid + if [[ "$action" == "bash" || "$action" == "sh" ]];then bash elif [[ "$action" == "sleep" ]];then @@ -19,4 +22,3 @@ elif [[ "$action" == "sleep" ]];then else python jms "${action}" "${service}" fi - diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 8232a52b8..3850821d4 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.15 django-bootstrap3==14.2.0 django-filter==2.4.0 django-formtools==2.2 @@ -91,7 +91,7 @@ eventlet==0.33.1 greenlet==1.1.2 gunicorn==20.1.0 celery==5.2.7 -flower==1.0.0 +flower==1.2.0 django-celery-beat==2.3.0 kombu==5.2.4 # Auth @@ -134,9 +134,10 @@ django-mysql==3.9.0 django-redis==5.2.0 python-redis-lock==3.7.0 redis==4.3.3 +pymongo==4.2.0 # Debug ipython==8.4.0 ForgeryPy3==0.3.1 django-debug-toolbar==3.5 Pympler==1.0.1 -IPy==1.1 \ No newline at end of file +IPy==1.1