feat: 账号模版切换至 (#10396)

Co-authored-by: feng <1304903146@qq.com>
pull/10410/head
fit2bot 2 years ago committed by GitHub
parent 6b6900cfd4
commit 1933e82587
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,4 +1,6 @@
from django_filters import rest_framework as drf_filters
from rest_framework.decorators import action
from rest_framework.response import Response
from accounts import serializers
from accounts.models import AccountTemplate
@ -38,8 +40,20 @@ class AccountTemplateViewSet(OrgBulkModelViewSet):
filterset_class = AccountTemplateFilterSet
search_fields = ('username', 'name')
serializer_classes = {
'default': serializers.AccountTemplateSerializer
'default': serializers.AccountTemplateSerializer,
}
rbac_perms = {
'su_from_account_templates': 'accounts.view_accounttemplate',
}
@action(methods=['get'], detail=False, url_path='su-from-account-templates')
def su_from_account_templates(self, request, *args, **kwargs):
pk = request.query_params.get('template_id')
template = AccountTemplate.objects.filter(pk=pk).first()
templates = AccountTemplate.get_su_from_account_templates(template)
templates = self.filter_queryset(templates)
serializer = self.get_serializer(templates, many=True)
return Response(data=serializer.data)
class AccountTemplateSecretsViewSet(RecordViewLogMixin, AccountTemplateViewSet):

@ -0,0 +1,29 @@
# Generated by Django 3.2.17 on 2023-05-06 06:43
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('accounts', '0010_gatheraccountsautomation_is_sync_account'),
]
operations = [
migrations.AddField(
model_name='accounttemplate',
name='su_from',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='accounts.accounttemplate', verbose_name='Su from'),
),
migrations.AlterField(
model_name='changesecretautomation',
name='ssh_key_change_strategy',
field=models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy'),
),
migrations.AlterField(
model_name='pushaccountautomation',
name='ssh_key_change_strategy',
field=models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy'),
),
]

@ -1,5 +1,5 @@
from django.db import models
from django.db.models import Count
from django.db.models import Count, Q
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from simple_history.models import HistoricalRecords
@ -108,6 +108,11 @@ class Account(AbsConnectivity, BaseAccount):
class AccountTemplate(BaseAccount):
su_from = models.ForeignKey(
'self', related_name='su_to', null=True,
on_delete=models.SET_NULL, verbose_name=_("Su from")
)
class Meta:
verbose_name = _('Account template')
unique_together = (
@ -118,6 +123,21 @@ class AccountTemplate(BaseAccount):
('change_accounttemplatesecret', _('Can change asset account template secret')),
]
@classmethod
def get_su_from_account_templates(cls, instance=None):
if not instance:
return cls.objects.all()
return cls.objects.exclude(Q(id=instance.id) | Q(su_from=instance))
def get_su_from_account(self, asset):
su_from = self.su_from
if su_from and asset.platform.su_enabled:
account = asset.accounts.filter(
username=su_from.username,
secret_type=su_from.secret_type
).first()
return account
def __str__(self):
return self.username

@ -91,7 +91,7 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer):
self._template = template
# Set initial data from template
ignore_fields = ['id', 'date_created', 'date_updated', 'org_id']
ignore_fields = ['id', 'date_created', 'date_updated', 'su_from', 'org_id']
field_names = [
field.name for field in template._meta.fields
if field.name not in ignore_fields
@ -151,6 +151,7 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer):
template = self._template
if template is None:
return
validated_data['source'] = Source.TEMPLATE
validated_data['source_id'] = str(template.id)
@ -238,6 +239,9 @@ class AssetAccountBulkSerializerResultSerializer(serializers.Serializer):
class AssetAccountBulkSerializer(
AccountCreateUpdateSerializerMixin, AuthValidateMixin, serializers.ModelSerializer
):
su_from_username = serializers.CharField(
max_length=128, required=False, write_only=True, allow_null=True, label=_("Su from")
)
assets = serializers.PrimaryKeyRelatedField(queryset=Asset.objects, many=True, label=_('Assets'))
class Meta:
@ -245,7 +249,7 @@ class AssetAccountBulkSerializer(
fields = [
'name', 'username', 'secret', 'secret_type',
'privileged', 'is_active', 'comment', 'template',
'on_invalid', 'push_now', 'assets',
'on_invalid', 'push_now', 'assets', 'su_from_username'
]
extra_kwargs = {
'name': {'required': False},
@ -293,8 +297,20 @@ class AssetAccountBulkSerializer(
raise serializers.ValidationError(_('Account already exists'))
return instance, True, 'created'
def generate_su_from_data(self, validated_data):
template = self._template
asset = validated_data['asset']
su_from = validated_data.get('su_from')
su_from_username = validated_data.pop('su_from_username', None)
if template:
su_from = template.get_su_from_account()
elif su_from_username:
su_from = asset.accounts.filter(username=su_from_username).first()
validated_data['su_from'] = su_from
def perform_create(self, vd, handler):
lookup = self.get_filter_lookup(vd)
self.generate_su_from_data(vd)
try:
instance, changed, state = handler(vd, lookup)
except IntegrityError:

@ -1,7 +1,9 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from accounts.models import AccountTemplate, Account
from common.serializers import SecretReadableMixin
from common.serializers.fields import ObjectRelatedField
from .base import BaseAccountSerializer
@ -9,9 +11,14 @@ class AccountTemplateSerializer(BaseAccountSerializer):
is_sync_account = serializers.BooleanField(default=False, write_only=True)
_is_sync_account = False
su_from = ObjectRelatedField(
required=False, queryset=AccountTemplate.objects, allow_null=True,
allow_empty=True, label=_('Su from'), attrs=('id', 'name', 'username')
)
class Meta(BaseAccountSerializer.Meta):
model = AccountTemplate
fields = BaseAccountSerializer.Meta.fields + ['is_sync_account']
fields = BaseAccountSerializer.Meta.fields + ['is_sync_account', 'su_from']
def sync_accounts_secret(self, instance, diff):
if not self._is_sync_account or 'secret' not in diff:

@ -0,0 +1,18 @@
# Generated by Django 3.2.17 on 2023-05-06 06:43
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0116_auto_20230418_1726'),
]
operations = [
migrations.AlterField(
model_name='baseautomation',
name='params',
field=models.JSONField(default=dict, verbose_name='Parameters'),
),
]

@ -109,6 +109,7 @@ class AssetPermissionSerializer(BulkOrgResourceModelSerializer):
if condition in username_secret_type_dict:
continue
account_data = {key: getattr(template, key) for key in account_attribute}
account_data['su_from'] = template.get_su_from_account(asset)
account_data['name'] = f"{account_data['name']}-{_('Account template')}"
need_create_accounts.append(Account(**{'asset_id': asset.id, **account_data}))
return Account.objects.bulk_create(need_create_accounts)

Loading…
Cancel
Save