mirror of https://github.com/jumpserver/jumpserver
Merge branch 'v3' of github.com:jumpserver/jumpserver into v3
commit
644f3f1783
|
@ -2,7 +2,9 @@ from django.utils.translation import ugettext as _
|
|||
from rest_framework import serializers
|
||||
from common.drf.serializers import BulkModelSerializer
|
||||
from common.drf.serializers import MethodSerializer
|
||||
from common.drf.fields import ObjectRelatedField
|
||||
from jumpserver.utils import has_valid_xpack_license
|
||||
from users.models import User
|
||||
from ..models import LoginACL
|
||||
from .rules import RuleSerializer
|
||||
|
||||
|
@ -12,8 +14,10 @@ common_help_text = _('Format for comma-delimited string, with * indicating a mat
|
|||
|
||||
|
||||
class LoginACLSerializer(BulkModelSerializer):
|
||||
user_display = serializers.ReadOnlyField(source='user.username', label=_('Username'))
|
||||
reviewers_display = serializers.SerializerMethodField(label=_('Reviewers'))
|
||||
user = ObjectRelatedField(queryset=User.objects, label=_('User'))
|
||||
reviewers = ObjectRelatedField(
|
||||
queryset=User.objects, label=_('Reviewers'), many=True, required=False
|
||||
)
|
||||
action_display = serializers.ReadOnlyField(source='get_action_display', label=_('Action'))
|
||||
reviewers_amount = serializers.IntegerField(read_only=True, source='reviewers.count')
|
||||
rules = MethodSerializer()
|
||||
|
@ -22,13 +26,11 @@ class LoginACLSerializer(BulkModelSerializer):
|
|||
model = LoginACL
|
||||
fields_mini = ['id', 'name']
|
||||
fields_small = fields_mini + [
|
||||
'priority', 'rules', 'action', 'action_display',
|
||||
'is_active', 'user', 'user_display',
|
||||
'date_created', 'date_updated', 'reviewers_amount',
|
||||
'comment', 'created_by'
|
||||
'priority', 'rules', 'action', 'action_display', 'is_active', 'user',
|
||||
'date_created', 'date_updated', 'reviewers_amount', 'comment', 'created_by',
|
||||
]
|
||||
fields_fk = ['user', 'user_display']
|
||||
fields_m2m = ['reviewers', 'reviewers_display']
|
||||
fields_fk = ['user']
|
||||
fields_m2m = ['reviewers']
|
||||
fields = fields_small + fields_fk + fields_m2m
|
||||
extra_kwargs = {
|
||||
'priority': {'default': 50},
|
||||
|
|
|
@ -111,8 +111,8 @@ class AutomationExecutionViewSet(
|
|||
serializer.is_valid(raise_exception=True)
|
||||
automation = serializer.validated_data.get('automation')
|
||||
tp = serializer.validated_data.get('type')
|
||||
model = AutomationTypes.get_model(tp)
|
||||
model = AutomationTypes.get_type_model(tp)
|
||||
task = execute_automation.delay(
|
||||
pid=automation.ok, trigger=Trigger.manual, model=model
|
||||
pid=automation.pk, trigger=Trigger.manual, model=model
|
||||
)
|
||||
return Response({'task': task.id}, status=status.HTTP_201_CREATED)
|
||||
|
|
|
@ -24,8 +24,8 @@ class ChangeSecretAutomationViewSet(OrgBulkModelViewSet):
|
|||
|
||||
class ChangeSecretRecordViewSet(mixins.ListModelMixin, OrgGenericViewSet):
|
||||
serializer_class = serializers.ChangeSecretRecordSerializer
|
||||
filter_fields = ['username', 'asset', 'reason', 'execution']
|
||||
search_fields = ['username', 'reason', 'asset__hostname']
|
||||
filter_fields = ['asset', 'execution_id']
|
||||
search_fields = ['asset__hostname']
|
||||
|
||||
def get_queryset(self):
|
||||
return ChangeSecretRecord.objects.all()
|
||||
|
@ -36,5 +36,5 @@ class ChangeSecretRecordViewSet(mixins.ListModelMixin, OrgGenericViewSet):
|
|||
execution = get_object_or_none(AutomationExecution, pk=eid)
|
||||
if execution:
|
||||
queryset = queryset.filter(execution=execution)
|
||||
queryset = queryset.order_by('is_success', '-date_start')
|
||||
queryset = queryset.order_by('-date_start')
|
||||
return queryset
|
||||
|
|
|
@ -232,5 +232,6 @@ class BasePlaybookManager:
|
|||
except Exception as e:
|
||||
self.on_runner_failed(runner, e)
|
||||
print('\n')
|
||||
self.execution.status = 'success'
|
||||
self.execution.date_finished = timezone.now()
|
||||
self.execution.save()
|
||||
|
|
|
@ -15,12 +15,8 @@ from assets.const import AutomationTypes
|
|||
|
||||
class BaseAutomation(CommonModelMixin, PeriodTaskModelMixin, OrgModelMixin):
|
||||
accounts = models.JSONField(default=list, verbose_name=_("Accounts"))
|
||||
nodes = models.ManyToManyField(
|
||||
'assets.Node', blank=True, verbose_name=_("Nodes")
|
||||
)
|
||||
assets = models.ManyToManyField(
|
||||
'assets.Asset', blank=True, verbose_name=_("Assets")
|
||||
)
|
||||
nodes = models.ManyToManyField('assets.Node', blank=True, verbose_name=_("Nodes"))
|
||||
assets = models.ManyToManyField('assets.Asset', blank=True, verbose_name=_("Assets"))
|
||||
type = models.CharField(max_length=16, choices=AutomationTypes.choices, verbose_name=_('Type'))
|
||||
is_active = models.BooleanField(default=True, verbose_name=_("Is active"))
|
||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||
|
@ -92,7 +88,7 @@ class AutomationExecution(OrgModelMixin):
|
|||
'BaseAutomation', related_name='executions', on_delete=models.CASCADE,
|
||||
verbose_name=_('Automation task')
|
||||
)
|
||||
status = models.CharField(max_length=16, default='pending')
|
||||
status = models.CharField(max_length=16, default='pending', verbose_name=_('Status'))
|
||||
date_created = models.DateTimeField(auto_now_add=True, verbose_name=_('Date created'))
|
||||
date_start = models.DateTimeField(null=True, verbose_name=_('Date start'), db_index=True)
|
||||
date_finished = models.DateTimeField(null=True, verbose_name=_("Date finished"))
|
||||
|
|
|
@ -13,3 +13,7 @@ class GatherAccountsAutomation(BaseAutomation):
|
|||
|
||||
class Meta:
|
||||
verbose_name = _("Gather asset accounts")
|
||||
|
||||
@property
|
||||
def executed_amount(self):
|
||||
return self.executions.count()
|
||||
|
|
|
@ -58,7 +58,6 @@ class AccountSerializer(AccountSerializerCreateMixin, BaseAccountSerializer):
|
|||
required=False, queryset=Asset.objects,
|
||||
label=_('Asset'), attrs=('id', 'name', 'address', 'platform_id')
|
||||
)
|
||||
secret_type = LabeledChoiceField(choices=SecretType.choices, label=_('Secret type'))
|
||||
|
||||
class Meta(BaseAccountSerializer.Meta):
|
||||
model = Account
|
||||
|
|
|
@ -6,6 +6,8 @@ from rest_framework import serializers
|
|||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from ops.mixin import PeriodTaskSerializerMixin
|
||||
from common.utils import get_logger
|
||||
from common.const.choices import Trigger
|
||||
from common.drf.fields import LabeledChoiceField
|
||||
|
||||
from assets.models import AccountBackupPlan, AccountBackupPlanExecution
|
||||
|
||||
|
@ -32,17 +34,12 @@ class AccountBackupPlanSerializer(PeriodTaskSerializerMixin, BulkOrgResourceMode
|
|||
|
||||
|
||||
class AccountBackupPlanExecutionSerializer(serializers.ModelSerializer):
|
||||
trigger_display = serializers.ReadOnlyField(
|
||||
source='get_trigger_display', label=_('Trigger mode')
|
||||
)
|
||||
trigger = LabeledChoiceField(choices=Trigger.choices, label=_('Trigger mode'))
|
||||
|
||||
class Meta:
|
||||
model = AccountBackupPlanExecution
|
||||
fields = [
|
||||
'id', 'date_start', 'timedelta', 'plan_snapshot', 'trigger', 'reason',
|
||||
'is_success', 'plan', 'org_id', 'recipients', 'trigger_display'
|
||||
]
|
||||
read_only_fields = (
|
||||
read_only_fields = [
|
||||
'id', 'date_start', 'timedelta', 'plan_snapshot', 'trigger', 'reason',
|
||||
'is_success', 'org_id', 'recipients'
|
||||
)
|
||||
]
|
||||
fields = read_only_fields + ['plan']
|
||||
|
|
|
@ -1,28 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from io import StringIO
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.utils import validate_ssh_private_key, ssh_private_key_gen
|
||||
from common.drf.fields import EncryptedField
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from assets.models import BaseAccount
|
||||
from assets.serializers.base import AuthValidateMixin
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
|
||||
__all__ = ['BaseAccountSerializer']
|
||||
|
||||
|
||||
class BaseAccountSerializer(BulkOrgResourceModelSerializer):
|
||||
secret = EncryptedField(
|
||||
label=_('Secret'), required=False, allow_blank=True,
|
||||
allow_null=True, max_length=40960
|
||||
)
|
||||
|
||||
class BaseAccountSerializer(AuthValidateMixin, BulkOrgResourceModelSerializer):
|
||||
class Meta:
|
||||
model = BaseAccount
|
||||
fields_mini = ['id', 'name', 'username']
|
||||
fields_small = fields_mini + [
|
||||
'secret_type', 'secret', 'has_secret',
|
||||
'secret_type', 'secret', 'has_secret', 'passphrase',
|
||||
'privileged', 'is_active', 'specific',
|
||||
]
|
||||
fields_other = ['created_by', 'date_created', 'date_updated', 'comment']
|
||||
|
@ -32,29 +23,5 @@ class BaseAccountSerializer(BulkOrgResourceModelSerializer):
|
|||
'date_verified', 'created_by', 'date_created',
|
||||
]
|
||||
extra_kwargs = {
|
||||
'secret': {'write_only': True},
|
||||
'passphrase': {'write_only': True},
|
||||
'specific': {'label': _('Specific')},
|
||||
}
|
||||
|
||||
def validate_private_key(self, private_key):
|
||||
if not private_key:
|
||||
return ''
|
||||
passphrase = self.initial_data.get('passphrase')
|
||||
passphrase = passphrase if passphrase else None
|
||||
valid = validate_ssh_private_key(private_key, password=passphrase)
|
||||
if not valid:
|
||||
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()
|
||||
return private_key
|
||||
|
||||
def validate_secret(self, value):
|
||||
secret_type = self.initial_data.get('secret_type')
|
||||
if secret_type == 'ssh_key':
|
||||
value = self.validate_private_key(value)
|
||||
return value
|
||||
|
||||
|
|
|
@ -3,9 +3,10 @@ from rest_framework import serializers
|
|||
|
||||
from ops.mixin import PeriodTaskSerializerMixin
|
||||
from assets.const import AutomationTypes
|
||||
from assets.models import Asset, BaseAutomation, AutomationExecution
|
||||
from assets.models import Asset, Node, BaseAutomation, AutomationExecution
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from common.utils import get_logger
|
||||
from common.drf.fields import ObjectRelatedField
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
@ -16,6 +17,9 @@ __all__ = [
|
|||
|
||||
|
||||
class BaseAutomationSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSerializer):
|
||||
assets = ObjectRelatedField(many=True, required=False, queryset=Asset.objects, label=_('Assets'))
|
||||
nodes = ObjectRelatedField(many=True, required=False, queryset=Node.objects, label=_('Nodes'))
|
||||
|
||||
class Meta:
|
||||
read_only_fields = [
|
||||
'date_created', 'date_updated', 'created_by', 'periodic_display'
|
||||
|
@ -26,6 +30,7 @@ class BaseAutomationSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSe
|
|||
]
|
||||
extra_kwargs = {
|
||||
'name': {'required': True},
|
||||
'type': {'read_only': True},
|
||||
'periodic_display': {'label': _('Periodic perform')},
|
||||
}
|
||||
|
||||
|
@ -37,10 +42,10 @@ class AutomationExecutionSerializer(serializers.ModelSerializer):
|
|||
|
||||
class Meta:
|
||||
model = AutomationExecution
|
||||
fields = [
|
||||
'id', 'automation', 'trigger', 'trigger_display',
|
||||
'date_start', 'date_finished', 'snapshot', 'type'
|
||||
read_only_fields = [
|
||||
'trigger_display', 'date_start', 'date_finished', 'snapshot', 'status'
|
||||
]
|
||||
fields = ['id', 'automation', 'trigger', 'type'] + read_only_fields
|
||||
|
||||
@staticmethod
|
||||
def get_snapshot(obj):
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
from django.utils.translation import ugettext as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from assets.serializers.base import AuthValidateMixin
|
||||
from assets.models import ChangeSecretAutomation, ChangeSecretRecord
|
||||
from assets.const import DEFAULT_PASSWORD_RULES, SecretType, SecretStrategy
|
||||
from common.utils import get_logger
|
||||
from common.drf.fields import LabeledChoiceField, ObjectRelatedField
|
||||
from assets.serializers.base import AuthValidateMixin
|
||||
from assets.const import DEFAULT_PASSWORD_RULES, SecretType, SecretStrategy, SSHKeyStrategy
|
||||
from assets.models import Asset, Account, ChangeSecretAutomation, ChangeSecretRecord, AutomationExecution
|
||||
|
||||
from .base import BaseAutomationSerializer
|
||||
|
||||
|
@ -20,19 +21,17 @@ __all__ = [
|
|||
|
||||
|
||||
class ChangeSecretAutomationSerializer(AuthValidateMixin, BaseAutomationSerializer):
|
||||
secret_strategy = LabeledChoiceField(
|
||||
choices=SecretStrategy.choices, required=True, label=_('Secret strategy')
|
||||
)
|
||||
ssh_key_change_strategy = LabeledChoiceField(
|
||||
choices=SSHKeyStrategy.choices, required=False, label=_('SSH Key strategy')
|
||||
)
|
||||
password_rules = serializers.DictField(default=DEFAULT_PASSWORD_RULES)
|
||||
secret_strategy_display = serializers.ReadOnlyField(
|
||||
source='get_secret_strategy_display', label=_('Secret strategy')
|
||||
)
|
||||
ssh_key_change_strategy_display = serializers.ReadOnlyField(
|
||||
source='get_ssh_key_strategy_display', label=_('SSH Key strategy')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = ChangeSecretAutomation
|
||||
read_only_fields = BaseAutomationSerializer.Meta.read_only_fields + [
|
||||
'secret_strategy_display', 'ssh_key_change_strategy_display'
|
||||
]
|
||||
read_only_fields = BaseAutomationSerializer.Meta.read_only_fields
|
||||
fields = BaseAutomationSerializer.Meta.fields + read_only_fields + [
|
||||
'secret_type', 'secret_strategy', 'secret', 'password_rules',
|
||||
'ssh_key_change_strategy', 'passphrase', 'recipients',
|
||||
|
@ -84,26 +83,21 @@ class ChangeSecretAutomationSerializer(AuthValidateMixin, BaseAutomationSerializ
|
|||
|
||||
|
||||
class ChangeSecretRecordSerializer(serializers.ModelSerializer):
|
||||
asset_display = serializers.SerializerMethodField(label=_('Asset display'))
|
||||
account_display = serializers.SerializerMethodField(label=_('Account display'))
|
||||
is_success = serializers.SerializerMethodField(label=_('Is success'))
|
||||
asset = ObjectRelatedField(queryset=Asset.objects, label=_('Asset'))
|
||||
account = ObjectRelatedField(queryset=Account.objects, label=_('Account'))
|
||||
execution = ObjectRelatedField(
|
||||
queryset=AutomationExecution.objects, label=_('Automation task execution')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = ChangeSecretRecord
|
||||
fields = [
|
||||
'id', 'asset', 'account', 'date_started', 'date_finished',
|
||||
'is_success', 'error', 'execution', 'asset_display', 'account_display'
|
||||
'id', 'asset', 'account', 'date_started',
|
||||
'date_finished', 'is_success', 'error', 'execution',
|
||||
]
|
||||
read_only_fields = fields
|
||||
|
||||
@staticmethod
|
||||
def get_asset_display(instance):
|
||||
return str(instance.asset)
|
||||
|
||||
@staticmethod
|
||||
def get_account_display(instance):
|
||||
return str(instance.account)
|
||||
|
||||
@staticmethod
|
||||
def get_is_success(obj):
|
||||
if obj.status == 'success':
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from assets.models import GatherAccountsAutomation
|
||||
from common.utils import get_logger
|
||||
|
||||
|
@ -15,6 +16,9 @@ __all__ = [
|
|||
class GatherAccountAutomationSerializer(BaseAutomationSerializer):
|
||||
class Meta:
|
||||
model = GatherAccountsAutomation
|
||||
read_only_fields = BaseAutomationSerializer.Meta.read_only_fields
|
||||
read_only_fields = BaseAutomationSerializer.Meta.read_only_fields + ['executed_amount']
|
||||
fields = BaseAutomationSerializer.Meta.fields + read_only_fields
|
||||
extra_kwargs = BaseAutomationSerializer.Meta.extra_kwargs
|
||||
|
||||
extra_kwargs = {**BaseAutomationSerializer.Meta.extra_kwargs, **{
|
||||
'executed_amount': {'label': _('Executed amount')}
|
||||
}}
|
||||
|
|
|
@ -3,15 +3,17 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.drf.fields import EncryptedField
|
||||
from assets.const import SecretType
|
||||
from common.drf.fields import EncryptedField, LabeledChoiceField
|
||||
from .utils import validate_password_for_ansible, validate_ssh_key
|
||||
|
||||
|
||||
class AuthValidateMixin(serializers.Serializer):
|
||||
secret_type = serializers.CharField(label=_('Secret type'), max_length=16, required=True)
|
||||
secret_type = LabeledChoiceField(
|
||||
choices=SecretType.choices, required=True, label=_('Secret type')
|
||||
)
|
||||
secret = EncryptedField(
|
||||
label=_('Secret'), required=False, max_length=16384, allow_blank=True,
|
||||
label=_('Secret'), required=False, max_length=40960, allow_blank=True,
|
||||
allow_null=True, write_only=True,
|
||||
)
|
||||
passphrase = serializers.CharField(
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.serializers import OrgResourceModelSerializerMixin
|
||||
from ..models import GatheredUser
|
||||
from common.drf.fields import ObjectRelatedField
|
||||
from ..models import GatheredUser, Asset
|
||||
|
||||
|
||||
class GatheredUserSerializer(OrgResourceModelSerializerMixin):
|
||||
asset = ObjectRelatedField(queryset=Asset.objects, label=_('Asset'))
|
||||
|
||||
class Meta:
|
||||
model = GatheredUser
|
||||
fields_mini = ['id']
|
||||
|
|
|
@ -8,6 +8,7 @@ from rest_framework.response import Response
|
|||
|
||||
from common.drf.api import JMSModelViewSet
|
||||
from common.permissions import IsServiceAccount
|
||||
from common.utils import is_uuid
|
||||
from orgs.utils import tmp_to_builtin_org
|
||||
from rbac.permissions import RBACPermission
|
||||
from terminal.models import AppletHost
|
||||
|
@ -63,6 +64,13 @@ class AppletHostAppletViewSet(HostMixin, JMSModelViewSet):
|
|||
host: AppletHost
|
||||
serializer_class = AppletPublicationSerializer
|
||||
|
||||
def get_object(self):
|
||||
pk = self.kwargs.get('pk')
|
||||
if not is_uuid(pk):
|
||||
return self.host.publications.get(applet__name=pk)
|
||||
else:
|
||||
return self.host.publications.get(pk=pk)
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = self.host.publications.all()
|
||||
return queryset
|
||||
|
|
|
@ -5,21 +5,24 @@ from rest_framework import serializers
|
|||
from orgs.models import Organization
|
||||
from orgs.utils import get_current_org_id
|
||||
from orgs.mixins.serializers import OrgResourceModelSerializerMixin
|
||||
from common.drf.fields import LabeledChoiceField
|
||||
from tickets.models import TicketFlow, ApprovalRule
|
||||
from tickets.const import TicketApprovalStrategy
|
||||
from tickets.const import TicketApprovalStrategy, TicketType
|
||||
|
||||
__all__ = ['TicketFlowSerializer']
|
||||
|
||||
|
||||
class TicketFlowApproveSerializer(serializers.ModelSerializer):
|
||||
strategy_display = serializers.ReadOnlyField(source='get_strategy_display', label=_('Approve strategy'))
|
||||
strategy = LabeledChoiceField(
|
||||
choices=TicketApprovalStrategy.choices, required=True, label=_('Approve strategy')
|
||||
)
|
||||
assignees_read_only = serializers.SerializerMethodField(label=_('Assignees'))
|
||||
assignees_display = serializers.SerializerMethodField(label=_('Assignees display'))
|
||||
|
||||
class Meta:
|
||||
model = ApprovalRule
|
||||
fields_small = [
|
||||
'level', 'strategy', 'assignees_read_only', 'assignees_display', 'strategy_display'
|
||||
'level', 'strategy', 'assignees_read_only', 'assignees_display',
|
||||
]
|
||||
fields_m2m = ['assignees', ]
|
||||
fields = fields_small + fields_m2m
|
||||
|
@ -46,14 +49,16 @@ class TicketFlowApproveSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class TicketFlowSerializer(OrgResourceModelSerializerMixin):
|
||||
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type display'))
|
||||
type = LabeledChoiceField(
|
||||
choices=TicketType.choices, required=True, label=_('Type')
|
||||
)
|
||||
rules = TicketFlowApproveSerializer(many=True, required=True)
|
||||
|
||||
class Meta:
|
||||
model = TicketFlow
|
||||
fields_mini = ['id', ]
|
||||
fields_small = fields_mini + [
|
||||
'type', 'type_display', 'approval_level', 'created_by', 'date_created', 'date_updated',
|
||||
'type', 'approval_level', 'created_by', 'date_created', 'date_updated',
|
||||
'org_id', 'org_name'
|
||||
]
|
||||
fields = fields_small + ['rules', ]
|
||||
|
|
Loading…
Reference in New Issue