pref: 修改 secret encrypt

pull/8991/head
ibuler 2022-10-18 20:37:17 +08:00
parent 6a33129349
commit 9b44ed55c2
13 changed files with 109 additions and 24 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 再解密

View File

@ -86,5 +86,5 @@ class GroupedChoiceSerializer(ChoiceSerializer):
children = ChoiceSerializer(many=True, label=_("Children"))
class JMSWritableNestedModelSerializer(WritableNestedModelSerializer):
class JMSWritableNestedModelSerializer(ModelSerializer):
pass