mirror of https://github.com/jumpserver/jumpserver
pref: 暂存 客户端连接方式
parent
742cac1e90
commit
f6bdc7f81c
|
@ -11,6 +11,7 @@ from rest_framework.decorators import action
|
|||
from rest_framework.exceptions import PermissionDenied
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.serializers import ValidationError
|
||||
|
||||
from common.drf.api import JMSModelViewSet
|
||||
from common.http import is_true
|
||||
|
@ -18,6 +19,7 @@ from common.utils import random_string
|
|||
from orgs.mixins.api import RootOrgViewMixin
|
||||
from perms.models import ActionChoices
|
||||
from terminal.models import EndpointRule
|
||||
from terminal.const import NativeClient
|
||||
from ..models import ConnectionToken
|
||||
from ..serializers import (
|
||||
ConnectionTokenSerializer, ConnectionTokenSecretSerializer,
|
||||
|
@ -128,19 +130,20 @@ class RDPFileClientProtocolURLMixin:
|
|||
return true_value if is_true(os.getenv(env_key, env_default)) else false_value
|
||||
|
||||
def get_client_protocol_data(self, token: ConnectionToken):
|
||||
protocol = token.protocol
|
||||
username = token.user.username
|
||||
rdp_config = ssh_token = ''
|
||||
if protocol == 'rdp':
|
||||
filename, rdp_config = self.get_rdp_file_info(token)
|
||||
elif protocol == 'ssh':
|
||||
connect_method = token.connect_method
|
||||
|
||||
if connect_method == NativeClient.ssh:
|
||||
filename, ssh_token = self.get_ssh_token(token)
|
||||
elif connect_method == NativeClient.mstsc:
|
||||
filename, rdp_config = self.get_rdp_file_info(token)
|
||||
else:
|
||||
raise ValueError('Protocol not support: {}'.format(protocol))
|
||||
raise ValueError('Protocol not support: {}'.format(connect_method))
|
||||
|
||||
return {
|
||||
"filename": filename,
|
||||
"protocol": protocol,
|
||||
"protocol": token.protocol,
|
||||
"username": username,
|
||||
"token": ssh_token,
|
||||
"config": rdp_config
|
||||
|
@ -234,14 +237,25 @@ class ConnectionTokenViewSet(ExtraActionApiMixin, RootOrgViewMixin, JMSModelView
|
|||
rbac_perm = 'authentication.view_connectiontokensecret'
|
||||
if not request.user.has_perm(rbac_perm):
|
||||
raise PermissionDenied('Not allow to view secret')
|
||||
token_id = request.data.get('token') or ''
|
||||
|
||||
token_id = request.data.get('id') or ''
|
||||
token = get_object_or_404(ConnectionToken, pk=token_id)
|
||||
if token.is_expired:
|
||||
raise ValidationError({'id': 'Token is expired'})
|
||||
|
||||
token.is_valid()
|
||||
serializer = self.get_serializer(instance=token)
|
||||
expire_now = request.data.get('expire_now', True)
|
||||
if expire_now:
|
||||
token.expire()
|
||||
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
def get_queryset(self):
|
||||
return ConnectionToken.objects.filter(user=self.request.user)
|
||||
queryset = ConnectionToken.objects\
|
||||
.filter(user=self.request.user)\
|
||||
.filter(date_expired__lt=timezone.now())
|
||||
return queryset
|
||||
|
||||
def get_user(self, serializer):
|
||||
return self.request.user
|
||||
|
@ -299,7 +313,7 @@ class SuperConnectionTokenViewSet(ConnectionTokenViewSet):
|
|||
def renewal(self, request, *args, **kwargs):
|
||||
from common.utils.timezone import as_current_tz
|
||||
|
||||
token_id = request.data.get('token') or ''
|
||||
token_id = request.data.get('id') or ''
|
||||
token = get_object_or_404(ConnectionToken, pk=token_id)
|
||||
date_expired = as_current_tz(token.date_expired)
|
||||
if token.is_expired:
|
||||
|
|
|
@ -26,20 +26,20 @@ class Migration(migrations.Migration):
|
|||
old_name='username',
|
||||
new_name='input_username',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='connectiontoken',
|
||||
name='input_secret',
|
||||
field=common.db.fields.EncryptCharField(default='', max_length=128, verbose_name='Input Secret'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='connectiontoken',
|
||||
name='account_name',
|
||||
field=models.CharField(max_length=128, verbose_name='Account name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='connectiontoken',
|
||||
name='input_secret',
|
||||
field=common.db.fields.EncryptCharField(blank=True, default='', max_length=128, verbose_name='Input Secret'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='connectiontoken',
|
||||
name='input_username',
|
||||
field=models.CharField(default='', max_length=128, verbose_name='Input Username'),
|
||||
field=models.CharField(blank=True, default='', max_length=128, verbose_name='Input Username'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='connectiontoken',
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 3.2.14 on 2022-11-28 13:48
|
||||
|
||||
import common.db.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0016_auto_20221125_2240'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='connectiontoken',
|
||||
name='connect_method',
|
||||
field=models.CharField(default='web_ui', max_length=32, verbose_name='Connect method'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -34,6 +34,7 @@ class ConnectionToken(OrgModelMixin, JMSBaseModel):
|
|||
protocol = models.CharField(
|
||||
choices=Protocol.choices, max_length=16, default=Protocol.ssh, verbose_name=_("Protocol")
|
||||
)
|
||||
connect_method = models.CharField(max_length=32, verbose_name=_("Connect method"))
|
||||
user_display = models.CharField(max_length=128, default='', verbose_name=_("User display"))
|
||||
asset_display = models.CharField(max_length=128, default='', verbose_name=_("Asset display"))
|
||||
date_expired = models.DateTimeField(
|
||||
|
|
|
@ -109,16 +109,10 @@ class ConnectionTokenGatewaySerializer(serializers.ModelSerializer):
|
|||
|
||||
class Meta:
|
||||
model = Asset
|
||||
fields = ['id', 'address', 'port', 'username', 'password', 'private_key']
|
||||
|
||||
|
||||
class ConnectionTokenDomainSerializer(serializers.ModelSerializer):
|
||||
""" Domain """
|
||||
gateways = ConnectionTokenGatewaySerializer(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Domain
|
||||
fields = ['id', 'name', 'gateways']
|
||||
fields = [
|
||||
'id', 'address', 'port', 'username',
|
||||
'password', 'private_key'
|
||||
]
|
||||
|
||||
|
||||
class ConnectionTokenCmdFilterRuleSerializer(serializers.ModelSerializer):
|
||||
|
@ -143,6 +137,7 @@ class ConnectionTokenPlatform(PlatformSerializer):
|
|||
|
||||
|
||||
class ConnectionTokenSecretSerializer(OrgResourceModelSerializerMixin):
|
||||
expire_now = serializers.BooleanField(label=_('Expired now'), default=True)
|
||||
user = ConnectionTokenUserSerializer(read_only=True)
|
||||
asset = ConnectionTokenAssetSerializer(read_only=True)
|
||||
platform = ConnectionTokenPlatform(read_only=True)
|
||||
|
@ -155,7 +150,10 @@ class ConnectionTokenSecretSerializer(OrgResourceModelSerializerMixin):
|
|||
class Meta:
|
||||
model = ConnectionToken
|
||||
fields = [
|
||||
'id', 'value', 'user', 'asset', 'account',
|
||||
'protocol', 'domain', 'gateway',
|
||||
'actions', 'expire_at', 'platform',
|
||||
'id', 'value', 'user', 'asset', 'platform', 'account',
|
||||
'protocol', 'gateway', 'actions', 'expire_at', 'expire_now',
|
||||
]
|
||||
extra_kwargs = {
|
||||
'value': {'read_only': True},
|
||||
'expire_now': {'write_only': True},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# Generated by Django 3.2.14 on 2022-11-28 13:48
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('ops', '0035_jobexecution_org_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='job',
|
||||
options={'ordering': ['date_created']},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='jobexecution',
|
||||
options={'ordering': ['-date_created']},
|
||||
),
|
||||
]
|
|
@ -96,17 +96,21 @@ class NativeClient(TextChoices):
|
|||
@classmethod
|
||||
def get_launch_command(cls, name, os='windows'):
|
||||
commands = {
|
||||
'ssh': 'ssh {username}@{hostname} -p {port}',
|
||||
'putty': 'putty -ssh {username}@{hostname} -P {port}',
|
||||
'xshell': '-url ssh://root:passwd@192.168.10.100',
|
||||
'mysql': 'mysql -h {hostname} -P {port} -u {username} -p',
|
||||
'psql': {
|
||||
'default': 'psql -h {hostname} -p {port} -U {username} -W',
|
||||
'windows': 'psql /h {hostname} /p {port} /U {username} -W',
|
||||
cls.ssh: 'ssh {token.id}@{endpoint.ip} -p {endpoint.port}',
|
||||
cls.putty: 'putty-ssh {token.id}@{endpoint.ip} -P {endpoint.port}',
|
||||
cls.xshell: 'xshell -url ssh://{token.id}:{token.value}@{endpoint.ip}:{endpoint.port}',
|
||||
# 'mysql': 'mysql -h {hostname} -P {port} -u {username} -p',
|
||||
# 'psql': {
|
||||
# 'default': 'psql -h {hostname} -p {port} -U {username} -W',
|
||||
# 'windows': 'psql /h {hostname} /p {port} /U {username} -W',
|
||||
# },
|
||||
# 'sqlplus': 'sqlplus {username}/{password}@{hostname}:{port}',
|
||||
# 'redis': 'redis-cli -h {hostname} -p {port} -a {password}',
|
||||
cls.mstsc: {
|
||||
'command': "$open_file$",
|
||||
'file': {
|
||||
}
|
||||
},
|
||||
'sqlplus': 'sqlplus {username}/{password}@{hostname}:{port}',
|
||||
'redis': 'redis-cli -h {hostname} -p {port} -a {password}',
|
||||
'mstsc': 'mstsc /v:{hostname}:{port}',
|
||||
}
|
||||
command = commands.get(name)
|
||||
if isinstance(command, dict):
|
||||
|
|
Loading…
Reference in New Issue