mirror of https://github.com/jumpserver/jumpserver
perf: add TERMINAL_SSH_KEY_LIMIT_COUNT conf
parent
3b1701b1aa
commit
32ae77c42d
|
@ -1,8 +1,3 @@
|
||||||
from django.utils import timezone
|
|
||||||
from rest_framework.response import Response
|
|
||||||
from rest_framework.decorators import action
|
|
||||||
|
|
||||||
from rbac.permissions import RBACPermission
|
|
||||||
from common.api import JMSModelViewSet
|
from common.api import JMSModelViewSet
|
||||||
from common.permissions import IsValidUser
|
from common.permissions import IsValidUser
|
||||||
from ..serializers import SSHKeySerializer
|
from ..serializers import SSHKeySerializer
|
||||||
|
@ -14,6 +9,7 @@ class SSHkeyViewSet(JMSModelViewSet):
|
||||||
permission_classes = [IsValidUser]
|
permission_classes = [IsValidUser]
|
||||||
filterset_fields = ('name', 'is_active')
|
filterset_fields = ('name', 'is_active')
|
||||||
search_fields = ('name',)
|
search_fields = ('name',)
|
||||||
|
ordering = ('-date_last_used', '-date_created')
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.request.user.ssh_keys.all()
|
return self.request.user.ssh_keys.all()
|
||||||
|
|
|
@ -1,14 +1,22 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from django.utils import timezone
|
from django.db.models import TextChoices
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from common.serializers.fields import ReadableHiddenField
|
from common.serializers.fields import ReadableHiddenField, LabeledChoiceField
|
||||||
|
|
||||||
from ..models import SSHKey
|
from ..models import SSHKey
|
||||||
from common.utils import validate_ssh_public_key
|
from common.utils import validate_ssh_public_key
|
||||||
|
from users.exceptions import CreateSSHKeyExceedLimit
|
||||||
|
|
||||||
__all__ = ['SSHKeySerializer']
|
__all__ = ['SSHKeySerializer', 'GenerateKeyType']
|
||||||
|
|
||||||
|
|
||||||
|
class GenerateKeyType(TextChoices):
|
||||||
|
auto = 'auto', _('Automatically Generate Key Pair')
|
||||||
|
# 目前只支持sftp方式
|
||||||
|
load = 'load', _('Import Existing Key Pair')
|
||||||
|
|
||||||
|
|
||||||
class SSHKeySerializer(serializers.ModelSerializer):
|
class SSHKeySerializer(serializers.ModelSerializer):
|
||||||
|
@ -19,16 +27,22 @@ class SSHKeySerializer(serializers.ModelSerializer):
|
||||||
public_key_hash_md5 = serializers.CharField(
|
public_key_hash_md5 = serializers.CharField(
|
||||||
source='get_public_key_hash_md5', required=False, read_only=True, max_length=128
|
source='get_public_key_hash_md5', required=False, read_only=True, max_length=128
|
||||||
)
|
)
|
||||||
|
generate_key_type = LabeledChoiceField(
|
||||||
|
choices=GenerateKeyType.choices, label=_('Create Type'), default=GenerateKeyType.auto.value, required=False,
|
||||||
|
help_text=_(
|
||||||
|
'Please download the private key after creation. Each private key can only be downloaded once'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SSHKey
|
model = SSHKey
|
||||||
fields_mini = ['name']
|
fields_mini = ['name']
|
||||||
fields_small = fields_mini + [
|
fields_small = fields_mini + [
|
||||||
'public_key', 'is_active',
|
'public_key', 'is_active', 'comment'
|
||||||
]
|
]
|
||||||
read_only_fields = [
|
read_only_fields = [
|
||||||
'id', 'user', 'public_key_comment', 'public_key_hash_md5',
|
'id', 'user', 'public_key_comment', 'public_key_hash_md5',
|
||||||
'date_last_used', 'date_created', 'date_updated'
|
'date_last_used', 'date_created', 'date_updated', 'generate_key_type',
|
||||||
]
|
]
|
||||||
fields = fields_small + read_only_fields
|
fields = fields_small + read_only_fields
|
||||||
|
|
||||||
|
@ -42,3 +56,9 @@ class SSHKeySerializer(serializers.ModelSerializer):
|
||||||
if not validate_ssh_public_key(value):
|
if not validate_ssh_public_key(value):
|
||||||
raise serializers.ValidationError(_('Not a valid ssh public key'))
|
raise serializers.ValidationError(_('Not a valid ssh public key'))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
if not self.context["request"].user.can_create_ssh_key():
|
||||||
|
raise CreateSSHKeyExceedLimit()
|
||||||
|
validated_data.pop('generate_key_type', None)
|
||||||
|
return super().create(validated_data)
|
||||||
|
|
|
@ -63,6 +63,7 @@ urlpatterns = [
|
||||||
|
|
||||||
# Profile
|
# Profile
|
||||||
path('profile/mfa/', users_view.MFASettingView.as_view(), name='user-mfa-setting'),
|
path('profile/mfa/', users_view.MFASettingView.as_view(), name='user-mfa-setting'),
|
||||||
|
path('profile/pubkey/generate/', users_view.UserPublicKeyGenerateView.as_view(), name='user-pubkey-generate'),
|
||||||
|
|
||||||
# OTP Setting
|
# OTP Setting
|
||||||
path('profile/otp/enable/start/', users_view.UserOtpEnableStartView.as_view(), name='user-otp-enable-start'),
|
path('profile/otp/enable/start/', users_view.UserOtpEnableStartView.as_view(), name='user-otp-enable-start'),
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-08-12 18:34+0800\n"
|
"POT-Creation-Date: 2024-08-13 16:47+0800\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -1582,7 +1582,7 @@ msgid "Gather facts"
|
||||||
msgstr "資産情報の収集"
|
msgstr "資産情報の収集"
|
||||||
|
|
||||||
#: assets/const/base.py:32 audits/const.py:58
|
#: assets/const/base.py:32 audits/const.py:58
|
||||||
#: terminal/serializers/applet_host.py:32 users/models/user/_auth.py:31
|
#: terminal/serializers/applet_host.py:32 users/models/user/_auth.py:32
|
||||||
msgid "Disabled"
|
msgid "Disabled"
|
||||||
msgstr "無効"
|
msgstr "無効"
|
||||||
|
|
||||||
|
@ -2080,7 +2080,7 @@ msgstr "設定"
|
||||||
|
|
||||||
#: assets/models/platform.py:38 audits/const.py:59
|
#: assets/models/platform.py:38 audits/const.py:59
|
||||||
#: authentication/backends/passkey/models.py:11 settings/models.py:38
|
#: authentication/backends/passkey/models.py:11 settings/models.py:38
|
||||||
#: terminal/serializers/applet_host.py:33 users/models/user/_auth.py:32
|
#: terminal/serializers/applet_host.py:33 users/models/user/_auth.py:33
|
||||||
msgid "Enabled"
|
msgid "Enabled"
|
||||||
msgstr "有効化"
|
msgstr "有効化"
|
||||||
|
|
||||||
|
@ -3119,7 +3119,7 @@ msgstr "MFAコードを入力してください"
|
||||||
msgid "Please enter SMS code"
|
msgid "Please enter SMS code"
|
||||||
msgstr "SMSコードを入力してください"
|
msgstr "SMSコードを入力してください"
|
||||||
|
|
||||||
#: authentication/errors/failed.py:164 users/exceptions.py:15
|
#: authentication/errors/failed.py:164 users/exceptions.py:14
|
||||||
msgid "Phone not set"
|
msgid "Phone not set"
|
||||||
msgstr "電話が設定されていない"
|
msgstr "電話が設定されていない"
|
||||||
|
|
||||||
|
@ -3483,7 +3483,25 @@ msgstr "組織名"
|
||||||
msgid "The {} cannot be empty"
|
msgid "The {} cannot be empty"
|
||||||
msgstr "{} 空にしてはならない"
|
msgstr "{} 空にしてはならない"
|
||||||
|
|
||||||
#: authentication/serializers/ssh_key.py:43 users/forms/profile.py:161
|
#: authentication/serializers/ssh_key.py:17
|
||||||
|
msgid "Automatically Generate Key Pair"
|
||||||
|
msgstr "キーペアを自動作成"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:19
|
||||||
|
msgid "Import Existing Key Pair"
|
||||||
|
msgstr "既存のキーペアをインポート"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:31
|
||||||
|
msgid "Create Type"
|
||||||
|
msgstr "タイプを作成"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:33
|
||||||
|
msgid ""
|
||||||
|
"Please download the private key after creation. Each private key can only be "
|
||||||
|
"downloaded once"
|
||||||
|
msgstr "作成完了後、秘密鍵をダウンロードしてください。各秘密鍵のダウンロードは一度きりです"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:57 users/forms/profile.py:161
|
||||||
#: users/serializers/profile.py:133 users/serializers/profile.py:160
|
#: users/serializers/profile.py:133 users/serializers/profile.py:160
|
||||||
msgid "Not a valid ssh public key"
|
msgid "Not a valid ssh public key"
|
||||||
msgstr "有効なssh公開鍵ではありません"
|
msgstr "有効なssh公開鍵ではありません"
|
||||||
|
@ -8445,14 +8463,18 @@ msgstr "置換"
|
||||||
msgid "Suffix"
|
msgid "Suffix"
|
||||||
msgstr "接尾辞を付ける"
|
msgstr "接尾辞を付ける"
|
||||||
|
|
||||||
#: users/exceptions.py:10
|
#: users/exceptions.py:9
|
||||||
msgid "MFA not enabled"
|
msgid "MFA not enabled"
|
||||||
msgstr "MFAが有効化されていません"
|
msgstr "MFAが有効化されていません"
|
||||||
|
|
||||||
#: users/exceptions.py:20
|
#: users/exceptions.py:19
|
||||||
msgid "Unable to delete all users"
|
msgid "Unable to delete all users"
|
||||||
msgstr "すべてのユーザーを削除できません"
|
msgstr "すべてのユーザーを削除できません"
|
||||||
|
|
||||||
|
#: users/exceptions.py:24
|
||||||
|
msgid "Create failed. The number of SSH keys has reached the limit"
|
||||||
|
msgstr "作成に失敗しました。SSHキーの数が上限に達しました"
|
||||||
|
|
||||||
#: users/forms/profile.py:48
|
#: users/forms/profile.py:48
|
||||||
msgid ""
|
msgid ""
|
||||||
"When enabled, you will enter the MFA binding process the next time you log "
|
"When enabled, you will enter the MFA binding process the next time you log "
|
||||||
|
@ -8578,7 +8600,7 @@ msgstr "ユーザーに一致できます"
|
||||||
msgid "User password history"
|
msgid "User password history"
|
||||||
msgstr "ユーザーパスワード履歴"
|
msgstr "ユーザーパスワード履歴"
|
||||||
|
|
||||||
#: users/models/user/_auth.py:33
|
#: users/models/user/_auth.py:34
|
||||||
msgid "Force enabled"
|
msgid "Force enabled"
|
||||||
msgstr "強制有効"
|
msgstr "強制有効"
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-08-12 18:34+0800\n"
|
"POT-Creation-Date: 2024-08-13 16:47+0800\n"
|
||||||
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
||||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
||||||
|
@ -1571,7 +1571,7 @@ msgid "Gather facts"
|
||||||
msgstr "收集资产信息"
|
msgstr "收集资产信息"
|
||||||
|
|
||||||
#: assets/const/base.py:32 audits/const.py:58
|
#: assets/const/base.py:32 audits/const.py:58
|
||||||
#: terminal/serializers/applet_host.py:32 users/models/user/_auth.py:31
|
#: terminal/serializers/applet_host.py:32 users/models/user/_auth.py:32
|
||||||
msgid "Disabled"
|
msgid "Disabled"
|
||||||
msgstr "禁用"
|
msgstr "禁用"
|
||||||
|
|
||||||
|
@ -2067,7 +2067,7 @@ msgstr "设置"
|
||||||
|
|
||||||
#: assets/models/platform.py:38 audits/const.py:59
|
#: assets/models/platform.py:38 audits/const.py:59
|
||||||
#: authentication/backends/passkey/models.py:11 settings/models.py:38
|
#: authentication/backends/passkey/models.py:11 settings/models.py:38
|
||||||
#: terminal/serializers/applet_host.py:33 users/models/user/_auth.py:32
|
#: terminal/serializers/applet_host.py:33 users/models/user/_auth.py:33
|
||||||
msgid "Enabled"
|
msgid "Enabled"
|
||||||
msgstr "启用"
|
msgstr "启用"
|
||||||
|
|
||||||
|
@ -3083,7 +3083,7 @@ msgstr "请输入 MFA 验证码"
|
||||||
msgid "Please enter SMS code"
|
msgid "Please enter SMS code"
|
||||||
msgstr "请输入短信验证码"
|
msgstr "请输入短信验证码"
|
||||||
|
|
||||||
#: authentication/errors/failed.py:164 users/exceptions.py:15
|
#: authentication/errors/failed.py:164 users/exceptions.py:14
|
||||||
msgid "Phone not set"
|
msgid "Phone not set"
|
||||||
msgstr "手机号没有设置"
|
msgstr "手机号没有设置"
|
||||||
|
|
||||||
|
@ -3443,7 +3443,25 @@ msgstr "组织名称"
|
||||||
msgid "The {} cannot be empty"
|
msgid "The {} cannot be empty"
|
||||||
msgstr "{} 不能为空"
|
msgstr "{} 不能为空"
|
||||||
|
|
||||||
#: authentication/serializers/ssh_key.py:43 users/forms/profile.py:161
|
#: authentication/serializers/ssh_key.py:17
|
||||||
|
msgid "Automatically Generate Key Pair"
|
||||||
|
msgstr "自动创建密钥对"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:19
|
||||||
|
msgid "Import Existing Key Pair"
|
||||||
|
msgstr "导入已有密钥对"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:31
|
||||||
|
msgid "Create Type"
|
||||||
|
msgstr "创建类型"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:33
|
||||||
|
msgid ""
|
||||||
|
"Please download the private key after creation. Each private key can only be "
|
||||||
|
"downloaded once"
|
||||||
|
msgstr "创建完成后请下载私钥,每个私钥只有一次下载机会"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:57 users/forms/profile.py:161
|
||||||
#: users/serializers/profile.py:133 users/serializers/profile.py:160
|
#: users/serializers/profile.py:133 users/serializers/profile.py:160
|
||||||
msgid "Not a valid ssh public key"
|
msgid "Not a valid ssh public key"
|
||||||
msgstr "SSH密钥不合法"
|
msgstr "SSH密钥不合法"
|
||||||
|
@ -8293,14 +8311,18 @@ msgstr "替换"
|
||||||
msgid "Suffix"
|
msgid "Suffix"
|
||||||
msgstr "加后缀"
|
msgstr "加后缀"
|
||||||
|
|
||||||
#: users/exceptions.py:10
|
#: users/exceptions.py:9
|
||||||
msgid "MFA not enabled"
|
msgid "MFA not enabled"
|
||||||
msgstr "MFA 多因子认证没有开启"
|
msgstr "MFA 多因子认证没有开启"
|
||||||
|
|
||||||
#: users/exceptions.py:20
|
#: users/exceptions.py:19
|
||||||
msgid "Unable to delete all users"
|
msgid "Unable to delete all users"
|
||||||
msgstr "无法删除全部用户"
|
msgstr "无法删除全部用户"
|
||||||
|
|
||||||
|
#: users/exceptions.py:24
|
||||||
|
msgid "Create failed. The number of SSH keys has reached the limit"
|
||||||
|
msgstr "创建失败,SSH密钥数量已达到上限"
|
||||||
|
|
||||||
#: users/forms/profile.py:48
|
#: users/forms/profile.py:48
|
||||||
msgid ""
|
msgid ""
|
||||||
"When enabled, you will enter the MFA binding process the next time you log "
|
"When enabled, you will enter the MFA binding process the next time you log "
|
||||||
|
@ -8426,7 +8448,7 @@ msgstr "可以匹配用户"
|
||||||
msgid "User password history"
|
msgid "User password history"
|
||||||
msgstr "用户密码历史"
|
msgstr "用户密码历史"
|
||||||
|
|
||||||
#: users/models/user/_auth.py:33
|
#: users/models/user/_auth.py:34
|
||||||
msgid "Force enabled"
|
msgid "Force enabled"
|
||||||
msgstr "强制启用"
|
msgstr "强制启用"
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-08-12 18:34+0800\n"
|
"POT-Creation-Date: 2024-08-13 16:47+0800\n"
|
||||||
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
||||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
||||||
|
@ -1573,7 +1573,7 @@ msgid "Gather facts"
|
||||||
msgstr "收集資產資訊"
|
msgstr "收集資產資訊"
|
||||||
|
|
||||||
#: assets/const/base.py:32 audits/const.py:58
|
#: assets/const/base.py:32 audits/const.py:58
|
||||||
#: terminal/serializers/applet_host.py:32 users/models/user/_auth.py:31
|
#: terminal/serializers/applet_host.py:32 users/models/user/_auth.py:32
|
||||||
msgid "Disabled"
|
msgid "Disabled"
|
||||||
msgstr "禁用"
|
msgstr "禁用"
|
||||||
|
|
||||||
|
@ -2069,7 +2069,7 @@ msgstr "設置"
|
||||||
|
|
||||||
#: assets/models/platform.py:38 audits/const.py:59
|
#: assets/models/platform.py:38 audits/const.py:59
|
||||||
#: authentication/backends/passkey/models.py:11 settings/models.py:38
|
#: authentication/backends/passkey/models.py:11 settings/models.py:38
|
||||||
#: terminal/serializers/applet_host.py:33 users/models/user/_auth.py:32
|
#: terminal/serializers/applet_host.py:33 users/models/user/_auth.py:33
|
||||||
msgid "Enabled"
|
msgid "Enabled"
|
||||||
msgstr "啟用"
|
msgstr "啟用"
|
||||||
|
|
||||||
|
@ -3085,7 +3085,7 @@ msgstr "請輸入 MFA 驗證碼"
|
||||||
msgid "Please enter SMS code"
|
msgid "Please enter SMS code"
|
||||||
msgstr "請輸入簡訊驗證碼"
|
msgstr "請輸入簡訊驗證碼"
|
||||||
|
|
||||||
#: authentication/errors/failed.py:164 users/exceptions.py:15
|
#: authentication/errors/failed.py:164 users/exceptions.py:14
|
||||||
msgid "Phone not set"
|
msgid "Phone not set"
|
||||||
msgstr "手機號碼沒有設置"
|
msgstr "手機號碼沒有設置"
|
||||||
|
|
||||||
|
@ -3445,7 +3445,25 @@ msgstr "組織名稱"
|
||||||
msgid "The {} cannot be empty"
|
msgid "The {} cannot be empty"
|
||||||
msgstr "{} 不能為空"
|
msgstr "{} 不能為空"
|
||||||
|
|
||||||
#: authentication/serializers/ssh_key.py:43 users/forms/profile.py:161
|
#: authentication/serializers/ssh_key.py:17
|
||||||
|
msgid "Automatically Generate Key Pair"
|
||||||
|
msgstr "自動創建密鑰對"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:19
|
||||||
|
msgid "Import Existing Key Pair"
|
||||||
|
msgstr "導入已有密鑰對"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:31
|
||||||
|
msgid "Create Type"
|
||||||
|
msgstr "創建類型"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:33
|
||||||
|
msgid ""
|
||||||
|
"Please download the private key after creation. Each private key can only be "
|
||||||
|
"downloaded once"
|
||||||
|
msgstr "創建完成後請下載私鑰,每個私鑰僅有一次下載機會"
|
||||||
|
|
||||||
|
#: authentication/serializers/ssh_key.py:57 users/forms/profile.py:161
|
||||||
#: users/serializers/profile.py:133 users/serializers/profile.py:160
|
#: users/serializers/profile.py:133 users/serializers/profile.py:160
|
||||||
msgid "Not a valid ssh public key"
|
msgid "Not a valid ssh public key"
|
||||||
msgstr "SSH金鑰不合法"
|
msgstr "SSH金鑰不合法"
|
||||||
|
@ -8296,14 +8314,18 @@ msgstr "替換"
|
||||||
msgid "Suffix"
|
msgid "Suffix"
|
||||||
msgstr "加後綴"
|
msgstr "加後綴"
|
||||||
|
|
||||||
#: users/exceptions.py:10
|
#: users/exceptions.py:9
|
||||||
msgid "MFA not enabled"
|
msgid "MFA not enabled"
|
||||||
msgstr "MFA 多因子認證沒有開啟"
|
msgstr "MFA 多因子認證沒有開啟"
|
||||||
|
|
||||||
#: users/exceptions.py:20
|
#: users/exceptions.py:19
|
||||||
msgid "Unable to delete all users"
|
msgid "Unable to delete all users"
|
||||||
msgstr "無法刪除全部用戶"
|
msgstr "無法刪除全部用戶"
|
||||||
|
|
||||||
|
#: users/exceptions.py:24
|
||||||
|
msgid "Create failed. The number of SSH keys has reached the limit"
|
||||||
|
msgstr "創建失敗,SSH密鑰數量已達到上限"
|
||||||
|
|
||||||
#: users/forms/profile.py:48
|
#: users/forms/profile.py:48
|
||||||
msgid ""
|
msgid ""
|
||||||
"When enabled, you will enter the MFA binding process the next time you log "
|
"When enabled, you will enter the MFA binding process the next time you log "
|
||||||
|
@ -8429,7 +8451,7 @@ msgstr "可以匹配用戶"
|
||||||
msgid "User password history"
|
msgid "User password history"
|
||||||
msgstr "用戶密碼歷史"
|
msgstr "用戶密碼歷史"
|
||||||
|
|
||||||
#: users/models/user/_auth.py:33
|
#: users/models/user/_auth.py:34
|
||||||
msgid "Force enabled"
|
msgid "Force enabled"
|
||||||
msgstr "強制啟用"
|
msgstr "強制啟用"
|
||||||
|
|
||||||
|
|
|
@ -509,6 +509,7 @@ class Config(dict):
|
||||||
# Terminal配置
|
# Terminal配置
|
||||||
'TERMINAL_PASSWORD_AUTH': True,
|
'TERMINAL_PASSWORD_AUTH': True,
|
||||||
'TERMINAL_PUBLIC_KEY_AUTH': True,
|
'TERMINAL_PUBLIC_KEY_AUTH': True,
|
||||||
|
'TERMINAL_SSH_KEY_LIMIT_COUNT': 10,
|
||||||
'TERMINAL_HEARTBEAT_INTERVAL': 20,
|
'TERMINAL_HEARTBEAT_INTERVAL': 20,
|
||||||
'TERMINAL_ASSET_LIST_SORT_BY': 'name',
|
'TERMINAL_ASSET_LIST_SORT_BY': 'name',
|
||||||
'TERMINAL_ASSET_LIST_PAGE_SIZE': 'auto',
|
'TERMINAL_ASSET_LIST_PAGE_SIZE': 'auto',
|
||||||
|
|
|
@ -83,6 +83,7 @@ CACHE_LOGIN_PASSWORD_TTL = CONFIG.CACHE_LOGIN_PASSWORD_TTL
|
||||||
# Terminal other setting
|
# Terminal other setting
|
||||||
TERMINAL_PASSWORD_AUTH = CONFIG.TERMINAL_PASSWORD_AUTH
|
TERMINAL_PASSWORD_AUTH = CONFIG.TERMINAL_PASSWORD_AUTH
|
||||||
TERMINAL_PUBLIC_KEY_AUTH = CONFIG.TERMINAL_PUBLIC_KEY_AUTH
|
TERMINAL_PUBLIC_KEY_AUTH = CONFIG.TERMINAL_PUBLIC_KEY_AUTH
|
||||||
|
TERMINAL_SSH_KEY_LIMIT_COUNT = CONFIG.TERMINAL_SSH_KEY_LIMIT_COUNT
|
||||||
TERMINAL_HEARTBEAT_INTERVAL = CONFIG.TERMINAL_HEARTBEAT_INTERVAL
|
TERMINAL_HEARTBEAT_INTERVAL = CONFIG.TERMINAL_HEARTBEAT_INTERVAL
|
||||||
TERMINAL_ASSET_LIST_SORT_BY = CONFIG.TERMINAL_ASSET_LIST_SORT_BY
|
TERMINAL_ASSET_LIST_SORT_BY = CONFIG.TERMINAL_ASSET_LIST_SORT_BY
|
||||||
TERMINAL_ASSET_LIST_PAGE_SIZE = CONFIG.TERMINAL_ASSET_LIST_PAGE_SIZE
|
TERMINAL_ASSET_LIST_PAGE_SIZE = CONFIG.TERMINAL_ASSET_LIST_PAGE_SIZE
|
||||||
|
@ -239,4 +240,4 @@ ANSIBLE_RECEPTOR_TCP_LISTEN_ADDRESS = CONFIG.ANSIBLE_RECEPTOR_TCP_LISTEN_ADDRESS
|
||||||
LOKI_LOG_ENABLED = CONFIG.LOKI_LOG_ENABLED
|
LOKI_LOG_ENABLED = CONFIG.LOKI_LOG_ENABLED
|
||||||
LOKI_BASE_URL = CONFIG.LOKI_BASE_URL
|
LOKI_BASE_URL = CONFIG.LOKI_BASE_URL
|
||||||
|
|
||||||
TOOL_USER_ENABLED = CONFIG.TOOL_USER_ENABLED
|
TOOL_USER_ENABLED = CONFIG.TOOL_USER_ENABLED
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
|
||||||
from common.exceptions import JMSException
|
from common.exceptions import JMSException
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,3 +17,8 @@ class PhoneNotSet(JMSException):
|
||||||
class UnableToDeleteAllUsers(JMSException):
|
class UnableToDeleteAllUsers(JMSException):
|
||||||
default_code = 'unable_to_delete_all_users'
|
default_code = 'unable_to_delete_all_users'
|
||||||
default_detail = _('Unable to delete all users')
|
default_detail = _('Unable to delete all users')
|
||||||
|
|
||||||
|
|
||||||
|
class CreateSSHKeyExceedLimit(JMSException):
|
||||||
|
default_code = 'create_ssh_key_exceed_limit'
|
||||||
|
default_detail = _('Create failed. The number of SSH keys has reached the limit')
|
||||||
|
|
|
@ -18,6 +18,7 @@ from common.utils import (
|
||||||
lazyproperty,
|
lazyproperty,
|
||||||
)
|
)
|
||||||
from users.signals import post_user_change_password
|
from users.signals import post_user_change_password
|
||||||
|
from users.exceptions import CreateSSHKeyExceedLimit
|
||||||
|
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
|
@ -133,6 +134,15 @@ class AuthMixin:
|
||||||
post_user_change_password.send(self.__class__, user=self)
|
post_user_change_password.send(self.__class__, user=self)
|
||||||
super().set_password(raw_password) # noqa
|
super().set_password(raw_password) # noqa
|
||||||
|
|
||||||
|
def set_ssh_key(self, name, public_key, private_key):
|
||||||
|
if self.can_update_ssh_key():
|
||||||
|
from authentication.models import SSHKey
|
||||||
|
SSHKey.objects.create(name=name, public_key=public_key, private_key=private_key, user=self)
|
||||||
|
post_user_change_password.send(self.__class__, user=self)
|
||||||
|
|
||||||
|
def can_create_ssh_key(self):
|
||||||
|
return self.ssh_keys.count() < settings.TERMINAL_SSH_KEY_LIMIT_COUNT
|
||||||
|
|
||||||
def can_update_password(self):
|
def can_update_password(self):
|
||||||
return self.is_local
|
return self.is_local
|
||||||
|
|
||||||
|
|
|
@ -4,3 +4,4 @@ from .password import *
|
||||||
from .mfa import *
|
from .mfa import *
|
||||||
from .otp import *
|
from .otp import *
|
||||||
from .reset import *
|
from .reset import *
|
||||||
|
from .pubkey import *
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
# ~*~ coding: utf-8 ~*~
|
||||||
|
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
|
from common.utils import get_logger, ssh_key_gen
|
||||||
|
from common.permissions import IsValidUser
|
||||||
|
from common.views.mixins import PermissionsMixin
|
||||||
|
from users.exceptions import CreateSSHKeyExceedLimit
|
||||||
|
|
||||||
|
__all__ = ['UserPublicKeyGenerateView']
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class UserPublicKeyGenerateView(PermissionsMixin, View):
|
||||||
|
permission_classes = [IsValidUser]
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
username = request.user.username
|
||||||
|
key_name = request.GET.get('name', '')
|
||||||
|
if not request.user.can_create_ssh_key():
|
||||||
|
return HttpResponse(
|
||||||
|
CreateSSHKeyExceedLimit().default_detail, status=400
|
||||||
|
)
|
||||||
|
private, public = ssh_key_gen(username=username, hostname='jumpserver')
|
||||||
|
request.user.set_ssh_key(key_name, public, private)
|
||||||
|
response = HttpResponse(private, content_type='text/plain')
|
||||||
|
filename = "{0}-jumpserver.pem".format(username)
|
||||||
|
response['Content-Disposition'] = 'attachment; filename={}'.format(filename)
|
||||||
|
return response
|
Loading…
Reference in New Issue