perf: add TERMINAL_SSH_KEY_LIMIT_COUNT conf

pull/13961/head
wangruidong 2024-08-13 16:06:01 +08:00 committed by Bryan
parent 3b1701b1aa
commit 32ae77c42d
12 changed files with 167 additions and 36 deletions

View File

@ -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()

View File

@ -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)

View File

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

View File

@ -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 "強制有効"

View File

@ -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 "强制启用"

View File

@ -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 "強制啟用"

View File

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

View File

@ -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

View File

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

View File

@ -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

View File

@ -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 *

View File

@ -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