2018-03-27 10:34:41 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
#
|
2021-12-30 02:47:46 +00:00
|
|
|
from io import StringIO
|
2018-03-27 10:34:41 +00:00
|
|
|
|
2022-01-27 07:06:15 +00:00
|
|
|
from django.utils.translation import ugettext_lazy as _
|
2018-03-27 10:34:41 +00:00
|
|
|
from rest_framework import serializers
|
2019-07-17 04:10:14 +00:00
|
|
|
|
2021-12-30 02:47:46 +00:00
|
|
|
from common.utils import ssh_pubkey_gen, ssh_private_key_gen, validate_ssh_private_key
|
2022-05-07 08:20:12 +00:00
|
|
|
from common.drf.fields import EncryptedField
|
2022-01-10 11:02:18 +00:00
|
|
|
from assets.models import Type
|
2022-06-14 10:04:53 +00:00
|
|
|
from .utils import validate_password_for_ansible
|
2018-03-27 10:34:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
class AuthSerializer(serializers.ModelSerializer):
|
2022-05-16 09:50:28 +00:00
|
|
|
password = EncryptedField(required=False, allow_blank=True, allow_null=True, max_length=1024, label=_('Password'))
|
2022-06-24 10:41:22 +00:00
|
|
|
private_key = EncryptedField(required=False, allow_blank=True, allow_null=True, max_length=16384, label=_('Private key'))
|
2018-03-27 10:34:41 +00:00
|
|
|
|
|
|
|
def gen_keys(self, private_key=None, password=None):
|
|
|
|
if private_key is None:
|
|
|
|
return None, None
|
|
|
|
public_key = ssh_pubkey_gen(private_key=private_key, password=password)
|
|
|
|
return private_key, public_key
|
|
|
|
|
|
|
|
def save(self, **kwargs):
|
2018-03-28 06:35:27 +00:00
|
|
|
password = self.validated_data.pop('password', None) or None
|
|
|
|
private_key = self.validated_data.pop('private_key', None) or None
|
2018-03-27 10:34:41 +00:00
|
|
|
self.instance = super().save(**kwargs)
|
|
|
|
if password or private_key:
|
|
|
|
private_key, public_key = self.gen_keys(private_key, password)
|
|
|
|
self.instance.set_auth(password=password, private_key=private_key,
|
|
|
|
public_key=public_key)
|
|
|
|
return self.instance
|
2019-06-24 12:16:18 +00:00
|
|
|
|
|
|
|
|
2021-12-30 02:47:46 +00:00
|
|
|
class AuthSerializerMixin(serializers.ModelSerializer):
|
2022-05-16 09:28:02 +00:00
|
|
|
password = EncryptedField(
|
2022-06-13 07:33:27 +00:00
|
|
|
label=_('Password'), required=False, allow_blank=True, allow_null=True, max_length=1024,
|
2022-06-14 10:04:53 +00:00
|
|
|
validators=[validate_password_for_ansible]
|
2022-05-16 09:28:02 +00:00
|
|
|
)
|
|
|
|
private_key = EncryptedField(
|
2022-06-24 10:41:22 +00:00
|
|
|
label=_('SSH private key'), required=False, allow_blank=True, allow_null=True, max_length=16384
|
2022-05-16 09:28:02 +00:00
|
|
|
)
|
2021-12-30 02:47:46 +00:00
|
|
|
passphrase = serializers.CharField(
|
|
|
|
allow_blank=True, allow_null=True, required=False, max_length=512,
|
|
|
|
write_only=True, label=_('Key password')
|
|
|
|
)
|
|
|
|
|
2019-07-08 07:35:20 +00:00
|
|
|
def validate_password(self, password):
|
|
|
|
return password
|
|
|
|
|
|
|
|
def validate_private_key(self, private_key):
|
|
|
|
if not private_key:
|
|
|
|
return
|
2021-12-30 02:47:46 +00:00
|
|
|
passphrase = self.initial_data.get('passphrase')
|
2022-01-19 02:39:17 +00:00
|
|
|
passphrase = passphrase if passphrase else None
|
2021-12-30 02:47:46 +00:00
|
|
|
valid = validate_ssh_private_key(private_key, password=passphrase)
|
2019-07-08 07:35:20 +00:00
|
|
|
if not valid:
|
2021-12-30 02:47:46 +00:00
|
|
|
raise serializers.ValidationError(_("private key invalid or passphrase error"))
|
|
|
|
|
|
|
|
private_key = ssh_private_key_gen(private_key, password=passphrase)
|
|
|
|
string_io = StringIO()
|
|
|
|
private_key.write_private_key(string_io)
|
|
|
|
private_key = string_io.getvalue()
|
2019-07-08 07:35:20 +00:00
|
|
|
return private_key
|
|
|
|
|
|
|
|
def validate_public_key(self, public_key):
|
|
|
|
return public_key
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def clean_auth_fields(validated_data):
|
|
|
|
for field in ('password', 'private_key', 'public_key'):
|
|
|
|
value = validated_data.get(field)
|
|
|
|
if not value:
|
|
|
|
validated_data.pop(field, None)
|
2021-12-30 02:47:46 +00:00
|
|
|
validated_data.pop('passphrase', None)
|
2019-08-01 09:10:02 +00:00
|
|
|
|
2019-07-08 07:35:20 +00:00
|
|
|
def create(self, validated_data):
|
|
|
|
self.clean_auth_fields(validated_data)
|
|
|
|
return super().create(validated_data)
|
|
|
|
|
|
|
|
def update(self, instance, validated_data):
|
|
|
|
self.clean_auth_fields(validated_data)
|
|
|
|
return super().update(instance, validated_data)
|
2022-01-10 11:02:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TypesField(serializers.MultipleChoiceField):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
kwargs['choices'] = Type.CHOICES
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
def to_representation(self, value):
|
|
|
|
return Type.value_to_choices(value)
|
|
|
|
|
|
|
|
def to_internal_value(self, data):
|
|
|
|
if data is None:
|
|
|
|
return data
|
|
|
|
return Type.choices_to_value(data)
|
|
|
|
|
|
|
|
|
|
|
|
class ActionsDisplayField(TypesField):
|
|
|
|
def to_representation(self, value):
|
|
|
|
values = super().to_representation(value)
|
|
|
|
choices = dict(Type.CHOICES)
|
|
|
|
return [choices.get(i) for i in values]
|