mirror of https://github.com/jumpserver/jumpserver
pref: 修改 secret encrypt
parent
6a33129349
commit
9b44ed55c2
|
@ -34,6 +34,11 @@ class AccountViewSet(OrgBulkModelViewSet):
|
|||
account = super().get_object()
|
||||
task = test_accounts_connectivity_manual.delay([account.id])
|
||||
return Response(data={'task': task.id})
|
||||
#
|
||||
# @action(methods=['get'], detail=True, url_path='secret')
|
||||
# def get_secret(self, request, *args, **kwargs):
|
||||
# account = super().get_object()
|
||||
# return Response(data={'secret': account.secret})
|
||||
|
||||
|
||||
class AccountSecretsViewSet(RecordViewLogMixin, AccountViewSet):
|
||||
|
|
|
@ -35,6 +35,7 @@ class BaseType(TextChoices):
|
|||
if choices == '__self__':
|
||||
choices = [tp]
|
||||
protocols = [{'name': name, **settings.get(name, {})} for name in choices]
|
||||
protocols[0]['primary'] = True
|
||||
return protocols
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -36,6 +36,13 @@ class AllTypes(ChoicesMixin):
|
|||
cls.set_automation_methods(category, tp, constraints)
|
||||
return constraints
|
||||
|
||||
@classmethod
|
||||
def get_primary_protocol_name(cls, category, tp):
|
||||
constraints = cls.get_constraints(category, tp)
|
||||
if not constraints:
|
||||
return None
|
||||
return constraints.get('protocols')[0]['name']
|
||||
|
||||
@classmethod
|
||||
def set_automation_methods(cls, category, tp, constraints):
|
||||
from assets.automations import filter_platform_methods
|
||||
|
@ -189,7 +196,9 @@ class AllTypes(ChoicesMixin):
|
|||
automation.save()
|
||||
|
||||
platform.protocols.all().delete()
|
||||
[PlatformProtocol.objects.create(**p, platform=platform) for p in protocols_data]
|
||||
for p in protocols_data:
|
||||
p.pop('primary', None)
|
||||
PlatformProtocol.objects.create(**p, platform=platform)
|
||||
|
||||
@classmethod
|
||||
def create_or_update_internal_platforms(cls):
|
||||
|
|
|
@ -165,6 +165,15 @@ class AccountFilterSet(BaseFilterSet):
|
|||
asset = drf_filters.CharFilter(field_name="asset_id", lookup_expr='exact')
|
||||
assets = drf_filters.CharFilter(field_name='asset_id', lookup_expr='in')
|
||||
nodes = drf_filters.CharFilter(method='filter_nodes')
|
||||
has_secret = drf_filters.BooleanFilter(method='filter_has_secret')
|
||||
|
||||
@staticmethod
|
||||
def filter_has_secret(queryset, name, has_secret):
|
||||
q = Q(secret__isnull=True) | Q(secret='')
|
||||
if has_secret:
|
||||
return queryset.exclude(q)
|
||||
else:
|
||||
return queryset.filter(q)
|
||||
|
||||
@staticmethod
|
||||
def filter_nodes(queryset, name, value):
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 3.2.14 on 2022-10-17 06:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0110_gatherfactsautomation'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='platformprotocol',
|
||||
name='default',
|
||||
field=models.BooleanField(default=True, verbose_name='Default'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platformprotocol',
|
||||
name='required',
|
||||
field=models.BooleanField(default=False, verbose_name='Required'),
|
||||
),
|
||||
]
|
|
@ -135,7 +135,10 @@ class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel):
|
|||
|
||||
@lazyproperty
|
||||
def primary_protocol(self):
|
||||
return self.protocols.first()
|
||||
from assets.const.types import AllTypes
|
||||
primary_protocol_name = AllTypes.get_primary_protocol_name(self.category, self.type)
|
||||
protocol = self.protocols.get(name=primary_protocol_name)
|
||||
return protocol
|
||||
|
||||
@lazyproperty
|
||||
def protocol(self):
|
||||
|
|
|
@ -72,18 +72,13 @@ class BaseAccount(OrgModelMixin):
|
|||
date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated"))
|
||||
created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by'))
|
||||
|
||||
@property
|
||||
def has_secret(self):
|
||||
return bool(self.secret)
|
||||
|
||||
@property
|
||||
def password(self):
|
||||
return self.secret
|
||||
|
||||
@password.setter
|
||||
def password(self, value):
|
||||
self.secret = value
|
||||
self.secret_type = 'password'
|
||||
@property
|
||||
def has_secret(self):
|
||||
return bool(self.secret)
|
||||
|
||||
@property
|
||||
def private_key(self):
|
||||
|
|
|
@ -17,6 +17,8 @@ class PlatformProtocol(models.Model):
|
|||
'sftp_enabled': True,
|
||||
'sftp_home': '/tmp'
|
||||
}
|
||||
default = models.BooleanField(default=False, verbose_name=_('Default'))
|
||||
required = models.BooleanField(default=False, verbose_name=_('Required'))
|
||||
name = models.CharField(max_length=32, verbose_name=_('Name'))
|
||||
port = models.IntegerField(verbose_name=_('Port'))
|
||||
setting = models.JSONField(verbose_name=_('Setting'), default=dict)
|
||||
|
@ -25,6 +27,13 @@ class PlatformProtocol(models.Model):
|
|||
def __str__(self):
|
||||
return '{}/{}'.format(self.name, self.port)
|
||||
|
||||
@property
|
||||
def primary(self):
|
||||
primary_protocol_name = AllTypes.get_primary_protocol_name(
|
||||
self.platform.category, self.platform.type
|
||||
)
|
||||
return self.name == primary_protocol_name
|
||||
|
||||
@property
|
||||
def secret_types(self):
|
||||
return Protocol.settings().get(self.name, {}).get('secret_types')
|
||||
|
@ -83,9 +92,10 @@ class Platform(models.Model):
|
|||
)
|
||||
return linux.id
|
||||
|
||||
@staticmethod
|
||||
def set_default_platforms_ops(platform_model):
|
||||
pass
|
||||
@property
|
||||
def primary_protocol(self):
|
||||
primary_protocol_name = AllTypes.get_primary_protocol_name(self.category, self.type)
|
||||
return self.protocols.filter(name=primary_protocol_name).first()
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
|
|
@ -82,9 +82,7 @@ class AccountSerializer(AccountSerializerCreateMixin, BaseAccountSerializer):
|
|||
class AccountSecretSerializer(SecretReadableMixin, AccountSerializer):
|
||||
class Meta(AccountSerializer.Meta):
|
||||
extra_kwargs = {
|
||||
'password': {'write_only': False},
|
||||
'private_key': {'write_only': False},
|
||||
'public_key': {'write_only': False},
|
||||
'secret': {'write_only': False},
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -117,6 +117,34 @@ class AssetSerializer(JMSWritableNestedModelSerializer):
|
|||
if not node_id:
|
||||
return []
|
||||
|
||||
def validate_protocols(self, protocols_data):
|
||||
if not protocols_data:
|
||||
protocols_data = []
|
||||
platform_id = self.initial_data.get('platform')
|
||||
if isinstance(platform_id, dict):
|
||||
platform_id = platform_id.get('id') or platform_id.get('pk')
|
||||
platform = Platform.objects.filter(id=platform_id).first()
|
||||
if not platform:
|
||||
raise serializers.ValidationError({'platform': _("Platform not exist")})
|
||||
|
||||
protocols_data_map = {p['name']: p for p in protocols_data}
|
||||
platform_protocols = platform.protocols.all()
|
||||
protocols_default = [p for p in platform_protocols if p.default]
|
||||
protocols_required = [p for p in platform_protocols if p.required or p.primary]
|
||||
|
||||
if not protocols_data_map:
|
||||
protocols_data_map = {
|
||||
p.name: {'name': p.name, 'port': p.port}
|
||||
for p in protocols_required + protocols_default
|
||||
}
|
||||
|
||||
protocols_not_found = [p.name for p in protocols_required if p.name not in protocols_data_map]
|
||||
if protocols_not_found:
|
||||
raise serializers.ValidationError({
|
||||
'protocols': _("Protocol is required: {}").format(', '.join(protocols_not_found))
|
||||
})
|
||||
return protocols_data_map.values()
|
||||
|
||||
@atomic
|
||||
def create(self, validated_data):
|
||||
nodes_display = validated_data.pop('nodes_display', '')
|
||||
|
|
|
@ -50,9 +50,9 @@ class PlatformAutomationSerializer(serializers.ModelSerializer):
|
|||
'gather_facts_method': {'label': '收集信息方式'},
|
||||
'verify_account_enabled': {'label': '启用校验账号'},
|
||||
'verify_account_method': {'label': '校验账号方式'},
|
||||
'create_account_enabled': {'label': '启用创建账号'},
|
||||
'create_account_method': {'label': '创建账号方式'},
|
||||
'change_secret_enabled': {'label': '启用账号创建改密'},
|
||||
'create_account_enabled': {'label': '启用推送账号'},
|
||||
'create_account_method': {'label': '推送账号方式'},
|
||||
'change_secret_enabled': {'label': '启用账号改密'},
|
||||
'change_secret_method': {'label': '账号创建改密方式'},
|
||||
'gather_accounts_enabled': {'label': '启用账号收集'},
|
||||
'gather_accounts_method': {'label': '收集账号方式'},
|
||||
|
@ -61,10 +61,14 @@ class PlatformAutomationSerializer(serializers.ModelSerializer):
|
|||
|
||||
class PlatformProtocolsSerializer(serializers.ModelSerializer):
|
||||
setting = ProtocolSettingSerializer(required=False, allow_null=True)
|
||||
primary = serializers.BooleanField(read_only=True, label=_("Primary"))
|
||||
|
||||
class Meta:
|
||||
model = PlatformProtocol
|
||||
fields = ['id', 'name', 'port', 'secret_types', 'setting']
|
||||
fields = [
|
||||
'id', 'name', 'port', 'primary', 'default',
|
||||
'required', 'secret_types', 'setting',
|
||||
]
|
||||
|
||||
|
||||
class PlatformSerializer(JMSWritableNestedModelSerializer):
|
||||
|
|
|
@ -117,10 +117,10 @@ class EncryptMixin:
|
|||
return signer.unsign(value) or ''
|
||||
|
||||
def from_db_value(self, value, expression, connection, context=None):
|
||||
if value is None:
|
||||
if not value:
|
||||
return value
|
||||
value = force_text(value)
|
||||
|
||||
value = force_text(value)
|
||||
plain_value = crypto.decrypt(value)
|
||||
|
||||
# 如果没有解开,使用原来的signer解密
|
||||
|
@ -134,7 +134,7 @@ class EncryptMixin:
|
|||
return plain_value
|
||||
|
||||
def get_prep_value(self, value):
|
||||
if value is None:
|
||||
if not value:
|
||||
return value
|
||||
|
||||
# 先 json 再解密
|
||||
|
|
|
@ -86,5 +86,5 @@ class GroupedChoiceSerializer(ChoiceSerializer):
|
|||
children = ChoiceSerializer(many=True, label=_("Children"))
|
||||
|
||||
|
||||
class JMSWritableNestedModelSerializer(WritableNestedModelSerializer):
|
||||
class JMSWritableNestedModelSerializer(ModelSerializer):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue