Merge pull request #3976 from jumpserver/add-audits-apis

[Add] audits apis
pull/3980/head
老广 2020-05-08 08:04:14 -05:00 committed by GitHub
commit 9fa31be4bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 118 additions and 10 deletions

View File

@ -5,11 +5,15 @@ from rest_framework.mixins import ListModelMixin
from common.mixins.api import CommonApiMixin from common.mixins.api import CommonApiMixin
from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor, IsOrgAdmin from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor, IsOrgAdmin
from common.drf.filters import DatetimeRangeFilter from common.drf.filters import DatetimeRangeFilter, current_user_filter
from common.api import CommonGenericViewSet
from orgs.mixins.api import OrgGenericViewSet from orgs.mixins.api import OrgGenericViewSet
from orgs.utils import current_org from orgs.utils import current_org
from .models import FTPLog, UserLoginLog from ops.models import CommandExecution
from .serializers import FTPLogSerializer, UserLoginLogSerializer from .models import FTPLog, UserLoginLog, OperateLog, PasswordChangeLog
from .serializers import FTPLogSerializer, UserLoginLogSerializer, CommandExecutionSerializer
from .serializers import OperateLogSerializer, PasswordChangeLogSerializer
from .filters import CurrentOrgMembersFilter
class FTPLogViewSet(ListModelMixin, OrgGenericViewSet): class FTPLogViewSet(ListModelMixin, OrgGenericViewSet):
@ -24,9 +28,8 @@ class FTPLogViewSet(ListModelMixin, OrgGenericViewSet):
search_fields = ['filename'] search_fields = ['filename']
class UserLoginLogViewSet(CommonApiMixin, class UserLoginLogViewSet(ListModelMixin,
ListModelMixin, CommonGenericViewSet):
GenericViewSet):
queryset = UserLoginLog.objects.all() queryset = UserLoginLog.objects.all()
permission_classes = [IsOrgAdmin | IsOrgAuditor] permission_classes = [IsOrgAdmin | IsOrgAuditor]
serializer_class = UserLoginLogSerializer serializer_class = UserLoginLogSerializer
@ -48,3 +51,47 @@ class UserLoginLogViewSet(CommonApiMixin,
users = self.get_org_members() users = self.get_org_members()
queryset = queryset.filter(username__in=users) queryset = queryset.filter(username__in=users)
return queryset return queryset
class OperateLogViewSet(ListModelMixin, OrgGenericViewSet):
model = OperateLog
serializer_class = OperateLogSerializer
permission_classes = [IsOrgAdmin | IsOrgAuditor]
extra_filter_backends = [DatetimeRangeFilter]
date_range_filter_fields = [
('datetime', ('date_from', 'date_to'))
]
filterset_fields = ['user', 'action', 'resource_type']
search_fields = ['filename']
ordering_fields = ['-datetime']
class PasswordChangeLogViewSet(ListModelMixin, CommonGenericViewSet):
queryset = PasswordChangeLog.objects.all()
permission_classes = [IsOrgAdmin | IsOrgAuditor]
serializer_class = PasswordChangeLogSerializer
extra_filter_backends = [DatetimeRangeFilter]
date_range_filter_fields = [
('datetime', ('date_from', 'date_to'))
]
filterset_fields = ['user']
ordering_fields = ['-datetime']
def get_queryset(self):
users = current_org.get_org_members()
queryset = super().get_queryset().filter(
user__in=[user.__str__() for user in users]
)
return queryset
class CommandExecutionViewSet(ListModelMixin, OrgGenericViewSet):
model = CommandExecution
serializer_class = CommandExecutionSerializer
permission_classes = [IsOrgAdmin | IsOrgAuditor]
extra_filter_backends = [DatetimeRangeFilter, current_user_filter(), CurrentOrgMembersFilter]
date_range_filter_fields = [
('date_start', ('date_from', 'date_to'))
]
search_fields = ['command']
ordering_fields = ['-date_created']

32
apps/audits/filters.py Normal file
View File

@ -0,0 +1,32 @@
from rest_framework import filters
from rest_framework.compat import coreapi, coreschema
from orgs.utils import current_org
__all__ = ['CurrentOrgMembersFilter']
class CurrentOrgMembersFilter(filters.BaseFilterBackend):
def get_schema_fields(self, view):
return [
coreapi.Field(
name='user', location='query', required=False, type='string',
schema=coreschema.String(
title='user',
description='user'
)
)
]
def _get_user_list(self):
users = current_org.get_org_members(exclude=('Auditor',))
return users
def filter_queryset(self, request, queryset, view):
user_id = request.GET.get('user')
if user_id:
queryset = queryset.filter(user=user_id)
else:
queryset = queryset.filter(user__in=self._get_user_list())
return queryset

View File

@ -4,6 +4,7 @@
from rest_framework import serializers from rest_framework import serializers
from terminal.models import Session from terminal.models import Session
from ops.models import CommandExecution
from . import models from . import models
@ -12,7 +13,7 @@ class FTPLogSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.FTPLog model = models.FTPLog
fields = ( fields = (
'id', 'user', 'remote_addr', 'asset', 'system_user', 'user', 'remote_addr', 'asset', 'system_user',
'operate', 'filename', 'is_success', 'date_start' 'operate', 'filename', 'is_success', 'date_start'
) )
@ -33,13 +34,18 @@ class UserLoginLogSerializer(serializers.ModelSerializer):
class OperateLogSerializer(serializers.ModelSerializer): class OperateLogSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.OperateLog model = models.OperateLog
fields = '__all__' fields = (
'user', 'action', 'resource_type', 'resource',
'remote_addr', 'datetime'
)
class PasswordChangeLogSerializer(serializers.ModelSerializer): class PasswordChangeLogSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.PasswordChangeLog model = models.PasswordChangeLog
fields = '__all__' fields = (
'user', 'change_by', 'remote_addr', 'datetime'
)
class SessionAuditSerializer(serializers.ModelSerializer): class SessionAuditSerializer(serializers.ModelSerializer):
@ -47,3 +53,11 @@ class SessionAuditSerializer(serializers.ModelSerializer):
model = Session model = Session
fields = '__all__' fields = '__all__'
class CommandExecutionSerializer(serializers.ModelSerializer):
class Meta:
model = CommandExecution
fields = (
'hosts', 'run_as', 'command', 'user', 'is_finished',
'date_start', 'result', 'is_success'
)

View File

@ -13,6 +13,9 @@ app_name = "audits"
router = DefaultRouter() router = DefaultRouter()
router.register(r'ftp-logs', api.FTPLogViewSet, 'ftp-log') router.register(r'ftp-logs', api.FTPLogViewSet, 'ftp-log')
router.register(r'login-logs', api.UserLoginLogViewSet, 'login-log') router.register(r'login-logs', api.UserLoginLogViewSet, 'login-log')
router.register(r'operate-logs', api.OperateLogViewSet, 'operate-log')
router.register(r'password-change-logs', api.PasswordChangeLogViewSet, 'password-change-log')
router.register(r'command-execution-logs', api.CommandExecutionViewSet, 'command-execution-log')
urlpatterns = [ urlpatterns = [
] ]

View File

@ -9,10 +9,12 @@ from django.views.decorators.csrf import csrf_exempt
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import generics, serializers from rest_framework import generics, serializers
from rest_framework.viewsets import GenericViewSet
from .http import HttpResponseTemporaryRedirect from .http import HttpResponseTemporaryRedirect
from .const import KEY_CACHE_RESOURCES_ID from .const import KEY_CACHE_RESOURCES_ID
from .utils import get_logger from .utils import get_logger
from .mixins import CommonApiMixin
__all__ = [ __all__ = [
'LogTailApi', 'ResourcesIDCacheApi', 'LogTailApi', 'ResourcesIDCacheApi',
@ -100,3 +102,7 @@ def redirect_plural_name_api(request, *args, **kwargs):
full_path = org_full_path.replace(resource, resource+"s", 1) full_path = org_full_path.replace(resource, resource+"s", 1)
logger.debug("Redirect {} => {}".format(org_full_path, full_path)) logger.debug("Redirect {} => {}".format(org_full_path, full_path))
return HttpResponseTemporaryRedirect(full_path) return HttpResponseTemporaryRedirect(full_path)
class CommonGenericViewSet(CommonApiMixin, GenericViewSet):
pass

View File

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import coreapi
from rest_framework import filters from rest_framework import filters
from rest_framework.fields import DateTimeField from rest_framework.fields import DateTimeField
from rest_framework.serializers import ValidationError from rest_framework.serializers import ValidationError
@ -146,3 +145,10 @@ class CustomFilter(filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view): def filter_queryset(self, request, queryset, view):
return queryset return queryset
def current_user_filter(user_field='user'):
class CurrentUserFilter(filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
return queryset.filter(**{user_field: request.user})
return CurrentUserFilter