perf: Admin connection token

pull/14431/head
feng 2024-11-12 10:26:34 +08:00 committed by feng626
parent 0b9887d18f
commit 914110b64c
6 changed files with 92 additions and 13 deletions

View File

@ -15,17 +15,17 @@ class Migration(migrations.Migration):
name="risk",
field=models.CharField(
choices=[
("zombie", "Long time no login"),
("ghost", "Not managed"),
("long_time_password", "Long time no change"),
("weak_password", "Weak password"),
("group_changed", "Group change"),
("sudo_changed", "Sudo changed"),
("account_deleted", "Account delete"),
("password_expired", "Password expired"),
("no_admin_account", "No admin account"),
("password_error", "Password error"),
("others", "Others"),
('zombie', 'Long time no login'),
('ghost', 'Not managed'),
('long_time_password', 'Long time no change'),
('weak_password', 'Weak password'),
('password_error', 'Password error'),
('password_expired', 'Password expired'),
('group_changed', 'Group change'),
('sudo_changed', 'Sudo changed'),
('account_deleted', 'Account delete'),
('no_admin_account', 'No admin account'),
('others', 'Others')
],
max_length=128,
verbose_name="Risk",

View File

@ -29,14 +29,14 @@ from terminal.models import EndpointRule, Endpoint
from users.const import FileNameConflictResolution
from users.const import RDPSmartSize, RDPColorQuality
from users.models import Preference
from ..models import ConnectionToken, date_expired_default
from ..models import ConnectionToken, AdminConnectionToken, date_expired_default
from ..serializers import (
ConnectionTokenSerializer, ConnectionTokenSecretSerializer,
SuperConnectionTokenSerializer, ConnectTokenAppletOptionSerializer,
ConnectionTokenReusableSerializer, ConnectTokenVirtualAppOptionSerializer
)
__all__ = ['ConnectionTokenViewSet', 'SuperConnectionTokenViewSet']
__all__ = ['ConnectionTokenViewSet', 'SuperConnectionTokenViewSet', 'AdminConnectionTokenViewSet']
logger = get_logger(__name__)
@ -558,3 +558,14 @@ class SuperConnectionTokenViewSet(ConnectionTokenViewSet):
else:
logger.error('Release applet account error: {}'.format(lock_key))
return Response({'error': 'not found or expired'}, status=400)
class AdminConnectionTokenViewSet(SuperConnectionTokenViewSet):
def check_permissions(self, request):
user = request.user
if not user.is_superuser:
self.permission_denied(request)
def get_queryset(self):
return AdminConnectionToken.objects.all()

View File

@ -37,3 +37,9 @@ class MFAType(TextChoices):
SMS = MFASms.name, MFASms.display_name
Radius = MFARadius.name, MFARadius.display_name
Custom = MFACustom.name, MFACustom.display_name
class ConnectionTokenType(TextChoices):
ADMIN = 'admin', 'Admin'
SUPER = 'super', 'Super'
USER = 'user', 'User'

View File

@ -0,0 +1,30 @@
# Generated by Django 4.1.13 on 2024-11-11 11:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0003_sshkey'),
]
operations = [
migrations.AddField(
model_name='connectiontoken',
name='type',
field=models.CharField(choices=[('admin', 'Admin'), ('super', 'Super'), ('user', 'User')], default='user', max_length=16, verbose_name='Type'),
),
migrations.CreateModel(
name='AdminConnectionToken',
fields=[
],
options={
'verbose_name': 'Admin connection token',
'proxy': True,
'indexes': [],
'constraints': [],
},
bases=('authentication.connectiontoken',),
),
]

View File

@ -12,6 +12,7 @@ from rest_framework.exceptions import PermissionDenied
from accounts.models import VirtualAccount
from assets.const import Protocol
from assets.const.host import GATEWAY_NAME
from authentication.const import ConnectionTokenType
from common.db.fields import EncryptTextField
from common.exceptions import JMSException
from common.utils import lazyproperty, pretty_string, bulk_get
@ -26,6 +27,8 @@ def date_expired_default():
class ConnectionToken(JMSOrgBaseModel):
_type = ConnectionTokenType.USER
value = models.CharField(max_length=64, default='', verbose_name=_("Value"))
user = models.ForeignKey(
'users.User', on_delete=models.SET_NULL, null=True, blank=True,
@ -52,6 +55,11 @@ class ConnectionToken(JMSOrgBaseModel):
)
is_active = models.BooleanField(default=True, verbose_name=_("Active"))
type = models.CharField(
max_length=16, choices=ConnectionTokenType.choices,
default=ConnectionTokenType.USER, verbose_name=_('Type')
)
class Meta:
ordering = ('-date_expired',)
permissions = [
@ -60,6 +68,10 @@ class ConnectionToken(JMSOrgBaseModel):
]
verbose_name = _('Connection token')
def save(self, *args, **kwargs):
self.type = self._meta.model._type
return super().save(*args, **kwargs)
@property
def is_expired(self):
return self.date_expired < timezone.now()
@ -268,9 +280,28 @@ class ConnectionToken(JMSOrgBaseModel):
class SuperConnectionToken(ConnectionToken):
_type = ConnectionTokenType.SUPER
class Meta:
proxy = True
permissions = [
('view_superconnectiontokensecret', _('Can view super connection token secret'))
]
verbose_name = _("Super connection token")
class AdminConnectionTokenManager(models.Manager):
def get_queryset(self):
queryset = super().get_queryset()
queryset = queryset.filter(type=ConnectionTokenType.ADMIN)
return queryset
class AdminConnectionToken(ConnectionToken):
_type = ConnectionTokenType.ADMIN
objects = AdminConnectionTokenManager()
class Meta:
proxy = True
verbose_name = _("Admin connection token")

View File

@ -13,6 +13,7 @@ router.register('sso', api.SSOViewSet, 'sso')
router.register('temp-tokens', api.TempTokenViewSet, 'temp-token')
router.register('connection-token', api.ConnectionTokenViewSet, 'connection-token')
router.register('super-connection-token', api.SuperConnectionTokenViewSet, 'super-connection-token')
router.register('admin-connection-token', api.AdminConnectionTokenViewSet, 'admin-connection-token')
router.register('confirm', api.UserConfirmationViewSet, 'confirm')
router.register('ssh-key', api.SSHkeyViewSet, 'ssh-key')