diff --git a/apps/audits/__init__.py b/apps/audits/__init__.py deleted file mode 100644 index 8b1378917..000000000 --- a/apps/audits/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/audits/api.py b/apps/audits/api.py deleted file mode 100644 index d8a7b21de..000000000 --- a/apps/audits/api.py +++ /dev/null @@ -1,92 +0,0 @@ -# ~*~ coding: utf-8 ~*~ -# - - -from __future__ import absolute_import, unicode_literals - -from rest_framework import generics, viewsets -from rest_framework_bulk import BulkModelViewSet - -from audits.backends import command_store, record_store -from audits.backends.command.serializers import CommandLogSerializer -from audits.backends.record.serializers import RecordSerializer -from . import models, serializers -from .hands import IsSuperUserOrAppUser, IsAppUser - - -class ProxyLogReceiveView(generics.CreateAPIView): - queryset = models.ProxyLog.objects.all() - serializer_class = serializers.ProxyLogSerializer - permission_classes = (IsAppUser,) - - def get_serializer(self, *args, **kwargs): - kwargs['data']['terminal'] = self.request.user.terminal.name - return super(ProxyLogReceiveView, self).get_serializer(*args, **kwargs) - - -class ProxyLogViewSet(viewsets.ModelViewSet): - """User proxy to backend server need call this api. - - params: { - "username": "", - "name": "", - "hostname": "", - "ip": "", - "terminal": "", - "login_type": "", - "system_user": "", - "was_failed": "", - "date_start": "" - } - - """ - - queryset = models.ProxyLog.objects.all() - serializer_class = serializers.ProxyLogSerializer - permission_classes = (IsSuperUserOrAppUser,) - - -class CommandLogViewSet(BulkModelViewSet): - """接受app发送来的command log, 格式如下 - { - "proxy_log_id": 23, - "user": "admin", - "asset": "localhost", - "system_user": "web", - "command_no": 1, - "command": "whoami", - "output": "d2hvbWFp", # base64.b64encode(s) - "timestamp": 1485238673.0 - } - - """ - queryset = command_store.all() - serializer_class = CommandLogSerializer - permission_classes = (IsSuperUserOrAppUser,) - - -class RecordLogViewSet(BulkModelViewSet): - """接受app发送来的record log, 格式如下 - { - "proxy_log_id": 23, - "output": "d2hvbWFp", # base64.b64encode(s) - "timestamp": 1485238673.0 - } - """ - - serializer_class = RecordSerializer - permission_classes = (IsSuperUserOrAppUser,) - - def get_queryset(self): - filter_kwargs = {} - proxy_log_id = self.request.query_params.get('proxy_log_id') - data_from_ts = self.request.query_params.get('date_from_ts') - if proxy_log_id: - filter_kwargs['proxy_log_id'] = proxy_log_id - if data_from_ts: - filter_kwargs['date_from_ts'] = data_from_ts - if filter_kwargs: - return record_store.filter(**filter_kwargs) - else: - return record_store.all() - diff --git a/apps/audits/apps.py b/apps/audits/apps.py deleted file mode 100644 index d376c1e65..000000000 --- a/apps/audits/apps.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals - -from django.apps import AppConfig - - -class AuditsConfig(AppConfig): - name = 'audits' diff --git a/apps/audits/backends/__init__.py b/apps/audits/backends/__init__.py deleted file mode 100644 index 5a2a38ec7..000000000 --- a/apps/audits/backends/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -from importlib import import_module -from django.conf import settings - -command_engine = import_module(settings.COMMAND_STORE_BACKEND) -command_store = command_engine.CommandStore() -record_engine = import_module(settings.RECORD_STORE_BACKEND) -record_store = record_engine.RecordStore() -from .command.serializers import CommandLogSerializer - - diff --git a/apps/audits/backends/command/__init__.py b/apps/audits/backends/command/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/audits/backends/command/base.py b/apps/audits/backends/command/base.py deleted file mode 100644 index 54279f133..000000000 --- a/apps/audits/backends/command/base.py +++ /dev/null @@ -1,19 +0,0 @@ -# coding: utf-8 -import abc - - -class CommandBase(object): - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def save(self, proxy_log_id, user, asset, system_user, - command_no, command, output, timestamp): - pass - - @abc.abstractmethod - def filter(self, date_from_ts=None, date_to_ts=None, user='', - asset='', system_user='', command='', proxy_log_id=0): - pass - - - diff --git a/apps/audits/backends/command/db.py b/apps/audits/backends/command/db.py deleted file mode 100644 index 26441e41f..000000000 --- a/apps/audits/backends/command/db.py +++ /dev/null @@ -1,45 +0,0 @@ -# ~*~ coding: utf-8 ~*~ - -from .base import CommandBase -from audits.models import CommandLog - - -class CommandStore(CommandBase): - model = CommandLog - queryset = [] - - def save(self, proxy_log_id, user, asset, system_user, - command_no, command, output, timestamp): - self.model.objects.create( - proxy_log_id=proxy_log_id, user=user, asset=asset, - system_user=system_user, command_no=command_no, - command=command, output=output, timestamp=timestamp - ) - - def filter(self, date_from_ts=None, date_to_ts=None, user='', - asset='', system_user='', command='', proxy_log_id=0): - filter_kwargs = {} - - if date_from_ts: - filter_kwargs['timestamp__gte'] = date_from_ts - if date_to_ts: - filter_kwargs['timestamp__lte'] = date_to_ts - if user: - filter_kwargs['user'] = user - if asset: - filter_kwargs['asset'] = asset - if system_user: - filter_kwargs['system_user'] = system_user - if command: - filter_kwargs['command__icontains'] = command - if proxy_log_id: - filter_kwargs['proxy_log_id'] = proxy_log_id - - if filter_kwargs: - self.queryset = self.model.objects.filter(**filter_kwargs) - return self.queryset - - def all(self): - """返回所有数据""" - return self.model.objects.iterator() - diff --git a/apps/audits/backends/command/serializers.py b/apps/audits/backends/command/serializers.py deleted file mode 100644 index 32da6bcea..000000000 --- a/apps/audits/backends/command/serializers.py +++ /dev/null @@ -1,21 +0,0 @@ -# ~*~ coding: utf-8 ~*~ -import base64 -from rest_framework import serializers -from audits.models import CommandLog -from audits.backends import command_store - - -class CommandLogSerializer(serializers.ModelSerializer): - """使用这个类作为基础Command Log Serializer类, 用来序列化""" - - class Meta: - model = CommandLog - fields = '__all__' - - def create(self, validated_data): - try: - output = validated_data['output'] - validated_data['output'] = base64.b64decode(output) - except IndexError: - pass - return command_store.save(**dict(validated_data)) diff --git a/apps/audits/backends/record/__init__.py b/apps/audits/backends/record/__init__.py deleted file mode 100644 index 3e0d2fd0f..000000000 --- a/apps/audits/backends/record/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# ~*~ coding: utf-8 ~*~ - diff --git a/apps/audits/backends/record/base.py b/apps/audits/backends/record/base.py deleted file mode 100644 index e96b8b131..000000000 --- a/apps/audits/backends/record/base.py +++ /dev/null @@ -1,14 +0,0 @@ -# coding: utf-8 -import abc - - -class RecordBase(object): - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def save(self, proxy_log_id, output, timestamp): - pass - - @abc.abstractmethod - def filter(self, date_from_ts=None, proxy_log_id=None): - pass diff --git a/apps/audits/backends/record/db.py b/apps/audits/backends/record/db.py deleted file mode 100644 index e55211f65..000000000 --- a/apps/audits/backends/record/db.py +++ /dev/null @@ -1,31 +0,0 @@ -# ~*~ coding: utf-8 ~*~ - -from .base import RecordBase -from audits.models import RecordLog - - -class RecordStore(RecordBase): - model = RecordLog - queryset = [] - - def save(self, proxy_log_id, output, timestamp): - return self.model.objects.create( - proxy_log_id=proxy_log_id, output=output, timestamp=timestamp - ) - - def filter(self, date_from_ts=None, proxy_log_id=''): - filter_kwargs = {} - - if date_from_ts: - filter_kwargs['timestamp__gte'] = date_from_ts - if proxy_log_id: - filter_kwargs['proxy_log_id'] = proxy_log_id - - if filter_kwargs: - self.queryset = self.model.objects.filter(**filter_kwargs) - return self.queryset - - def all(self): - """返回所有数据""" - return self.model.objects.all() - diff --git a/apps/audits/backends/record/serializers.py b/apps/audits/backends/record/serializers.py deleted file mode 100644 index 30a5867e1..000000000 --- a/apps/audits/backends/record/serializers.py +++ /dev/null @@ -1,20 +0,0 @@ -# ~*~ coding: utf-8 ~*~ -import base64 -from rest_framework import serializers -from audits.models import RecordLog -from audits.backends import record_store - - -class RecordSerializer(serializers.ModelSerializer): - """使用这个类作为基础Command Log Serializer类, 用来序列化""" - class Meta: - model = RecordLog - fields = '__all__' - - def create(self, validated_data): - try: - output = validated_data['output'] - validated_data['output'] = base64.b64decode(output) - except IndexError: - pass - return record_store.save(**dict(validated_data)) diff --git a/apps/audits/hands.py b/apps/audits/hands.py deleted file mode 100644 index 11ba2e765..000000000 --- a/apps/audits/hands.py +++ /dev/null @@ -1,8 +0,0 @@ -# ~*~ coding: utf-8 ~*~ -# - -from users.utils import AdminUserRequiredMixin -from users.models import User -from assets.models import Asset, SystemUser -from users.permissions import IsSuperUserOrAppUser, IsAppUser -from terminal.models import Terminal diff --git a/apps/audits/migrations/__init__.py b/apps/audits/migrations/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/audits/models.py b/apps/audits/models.py deleted file mode 100644 index 6d03b0231..000000000 --- a/apps/audits/models.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- -# - -from __future__ import unicode_literals - -import uuid - -from django.db import models -from django.utils.translation import ugettext_lazy as _ - - -class LoginLog(models.Model): - LOGIN_TYPE_CHOICE = ( - ('W', 'Web'), - ('ST', 'SSH Terminal'), - ('WT', 'Web Terminal') - ) - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - username = models.CharField(max_length=20, verbose_name=_('Username')) - name = models.CharField(max_length=20, blank=True, verbose_name=_('Name')) - login_type = models.CharField(choices=LOGIN_TYPE_CHOICE, max_length=2, - verbose_name=_('Login type')) - login_ip = models.GenericIPAddressField(verbose_name=_('Login ip')) - login_city = models.CharField(max_length=254, blank=True, null=True, - verbose_name=_('Login city')) - user_agent = models.CharField(max_length=254, blank=True, null=True, - verbose_name=_('User agent')) - date_login = models.DateTimeField(auto_now_add=True, - verbose_name=_('Date login')) - - class Meta: - db_table = 'login_log' - ordering = ['-date_login', 'username'] - - -class ProxyLog(models.Model): - LOGIN_TYPE_CHOICE = ( - ('ST', 'SSH Terminal'), - ('WT', 'Web Terminal'), - ) - - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - user = models.CharField(max_length=32, verbose_name=_('User')) - asset = models.CharField(max_length=32, verbose_name=_('Asset')) - system_user = models.CharField(max_length=32, verbose_name=_('System user')) - login_type = models.CharField( - choices=LOGIN_TYPE_CHOICE, max_length=2, blank=True, - null=True, verbose_name=_('Login type')) - terminal = models.CharField( - max_length=32, blank=True, null=True, verbose_name=_('Terminal')) - is_failed = models.BooleanField( - default=False, verbose_name=_('Did connect failed')) - is_finished = models.BooleanField( - default=False, verbose_name=_('Is finished')) - date_start = models.DateTimeField( - auto_created=True, verbose_name=_('Date start')) - date_finished = models.DateTimeField( - null=True, verbose_name=_('Date finished')) - - def __unicode__(self): - return '%s-%s-%s' % (self.user, self.asset, self.system_user) - - def commands(self): - from audits.backends import command_store - return command_store.filter(proxy_log_id=self.id) - - class Meta: - ordering = ['-date_start', 'user'] - - -class CommandLog(models.Model): - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - proxy_log_id = models.IntegerField(db_index=True) - user = models.CharField(max_length=48, db_index=True) - asset = models.CharField(max_length=128, db_index=True) - system_user = models.CharField(max_length=48, db_index=True) - command_no = models.IntegerField() - command = models.TextField(max_length=767, blank=True) - output = models.TextField(blank=True) - timestamp = models.FloatField(db_index=True) - - def __unicode__(self): - return '%s: %s' % (self.id, self.command) - - class Meta: - ordering = ['command_no', 'command'] - - -class RecordLog(models.Model): - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - proxy_log_id = models.IntegerField(db_index=True) - output = models.TextField(verbose_name=_('Output')) - timestamp = models.FloatField(db_index=True) - - def __unicode__(self): - return 'Record: %s' % self.proxy_log_id - - class Meta: - ordering = ['timestamp'] diff --git a/apps/audits/serializers.py b/apps/audits/serializers.py deleted file mode 100644 index 2f474ff7e..000000000 --- a/apps/audits/serializers.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -# -from __future__ import absolute_import, unicode_literals -from rest_framework import serializers - -from common.utils import timesince -from . import models - - -class ProxyLogSerializer(serializers.ModelSerializer): - time = serializers.SerializerMethodField() - command_length = serializers.SerializerMethodField() - - class Meta: - model = models.ProxyLog - fields = '__all__' - - @staticmethod - def get_time(obj): - if not obj.is_finished: - return '' - else: - return timesince(obj.date_start, since=obj.date_finished) - - @staticmethod - def get_command_length(obj): - return 2 - diff --git a/apps/audits/templates/audits/command_log_list.html b/apps/audits/templates/audits/command_log_list.html deleted file mode 100644 index 04bb976fb..000000000 --- a/apps/audits/templates/audits/command_log_list.html +++ /dev/null @@ -1,109 +0,0 @@ -{% extends '_base_list.html' %} -{% load i18n %} -{% load static %} -{% load common_tags %} -{% block content_left_head %} - - - -{% endblock %} - -{% block table_search %} -
-
-
- - - to - -
-
-
- -
-
- -
-
- -
-
- -
-
-
- -
-
-
-{% endblock %} -{% block table_container %} - - - - - - - - - - - - - - - {% for command in command_list %} - - - - - - - - - - - {% endfor %} - -
IDCommandUsernameIPSystem userProxy logDatetimeOutput
{{ command.id }}{{ command.command }}{{ command.user }}{{ command.asset }}{{ command.system_user }}{{ command.proxy_log_id}}{{ command.timestamp|ts_to_date }}
{{ command.output|to_html|safe }}
-{% endblock %} - -{% block custom_foot_js %} - - - -{% endblock %} - - diff --git a/apps/audits/templates/audits/login_log_list.html b/apps/audits/templates/audits/login_log_list.html deleted file mode 100644 index eb7a4a813..000000000 --- a/apps/audits/templates/audits/login_log_list.html +++ /dev/null @@ -1,101 +0,0 @@ -{% extends '_base_list.html' %} -{% load i18n %} -{% load static %} -{% load common_tags %} -{% block content_left_head %} - - -{% endblock %} - - -{% block table_search %} -
-
-
- - - to - -
-
-
- -
-
- -
-
-
- -
-
-
-{% endblock %} - -{% block table_head %} - {% trans 'ID' %} - {% trans 'Username' %} - {% trans 'Name' %} - {% trans 'Type' %} - {% trans 'UA' %} - {% trans 'IP' %} - {% trans 'City' %} - {% trans 'Date' %} -{% endblock %} - -{% block table_body %} - {% for login_log in login_log_list %} - - - {{ login_log.id }} -{# {{ login_log.id }}#} - - {{ login_log.username }} - {{ login_log.name }} - {{ login_log.get_login_type_display }} - {% if login_log.login_type == 'W' %} - - {{ login_log.user_agent | truncatechars:20 }} - - {% else %} - {{ login_log.terminal }} - {% endif %} - {{ login_log.login_ip }} - {{ login_log.login_city }} - {{ login_log.date_login }} - - {% endfor %} -{% endblock %} - -{% block custom_foot_js %} - - -{% endblock %} - diff --git a/apps/audits/templates/audits/proxy_log_commands_list_modal.html b/apps/audits/templates/audits/proxy_log_commands_list_modal.html deleted file mode 100644 index fca95de6e..000000000 --- a/apps/audits/templates/audits/proxy_log_commands_list_modal.html +++ /dev/null @@ -1,58 +0,0 @@ -{% load static %} - - - - - - - {% include '_head_css_js.html' %} - - - - - - - -
-
-
- - - - - - - - - - - - {% for command in object_list %} - - - - - - - {% endfor %} - - - - - - -
IDCommandOutputDatetime
{{ command.command_no }}{{ command.command }}{{ command.output_decode |safe }}{{ command.datetime }}
-
    -
    -
    -
    -
    - - - - diff --git a/apps/audits/templates/audits/proxy_log_detail.html b/apps/audits/templates/audits/proxy_log_detail.html deleted file mode 100644 index 0fa28b517..000000000 --- a/apps/audits/templates/audits/proxy_log_detail.html +++ /dev/null @@ -1,85 +0,0 @@ -{% extends 'base.html' %} -{% load static %} -{% load i18n %} -{% load common_tags %} - -{% block custom_head_css_js %} - -{% endblock %} -{% block content %} -
    -
    -
    -
    - -
    -
    -
    -
    - {% trans 'Command log list' %} {{ user_object.name }} -
    - - - - - - - - - - -
    -
    -
    - - - - - - - - - - - {% for command in object_list %} - - - - - - - {% endfor %} - - - - - - -
    IDCommandOutputDatetime
    {{ command.command_no }}{{ command.command }}
    {{ command.output|to_html|safe}}
    {{ command.timestamp|ts_to_date}}
    -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - -{% endblock %} -{% block custom_foot_js %} - - -{% endblock %} diff --git a/apps/audits/templates/audits/proxy_log_offline_list.html b/apps/audits/templates/audits/proxy_log_offline_list.html deleted file mode 100644 index 7dcac94b7..000000000 --- a/apps/audits/templates/audits/proxy_log_offline_list.html +++ /dev/null @@ -1,159 +0,0 @@ -{% extends '_base_list.html' %} -{% load i18n %} -{% load static %} -{% block content_left_head %} - - -{% endblock %} - - -{% block table_search %} -
      -
      -
      - - - to - -
      -
      -
      - -
      -
      - -
      -
      - -
      -
      - -
      -
      -
      - -
      -
      -
      -{% endblock %} - -{% block table_head %} - - {% trans 'ID' %} - {% trans 'User' %} - {% trans 'Asset' %} - {% trans 'System user' %} - {% trans 'Terminal' %} - {% trans 'Command' %} - {% trans 'Success' %} - {% trans 'Finished' %} - {% trans 'Play' %} - {% trans 'Date start' %} - {% trans 'Time' %} -{% endblock %} - -{% block table_body %} - {% for proxy_log in proxy_log_list %} - - - - {{ proxy_log.id }} - - {{ proxy_log.user }} - {{ proxy_log.asset }} - {{ proxy_log.system_user }} - {{ proxy_log.terminal }} - {{ proxy_log.commands.all|length}} - - {% if proxy_log.is_failed %} - - {% else %} - - {% endif %} - - {% if proxy_log.is_finished %} - - - - - - - {% else %} - - - - - - - {% endif %} - {{ proxy_log.date_start }} - {{ proxy_log.date_finished|timeuntil:proxy_log.date_start }} - - {% endfor %} -{% endblock %} - - -{% block custom_foot_js %} - - -{% endblock %} - diff --git a/apps/audits/templates/audits/proxy_log_online_list.html b/apps/audits/templates/audits/proxy_log_online_list.html deleted file mode 100644 index 099ab3fca..000000000 --- a/apps/audits/templates/audits/proxy_log_online_list.html +++ /dev/null @@ -1,173 +0,0 @@ -{% extends '_base_list.html' %} -{% load i18n %} -{% load static %} -{% block content_left_head %} - - -{% endblock %} - - -{% block table_search %} -
      -
      -
      - - - to - -
      -
      -
      - -
      -
      - -
      -
      - -
      -
      - -
      -
      -
      - -
      -
      -
      -{% endblock %} - -{% block table_head %} - - {% trans 'ID' %} - {% trans 'User' %} - {% trans 'Asset' %} - {% trans 'System user' %} - {% trans 'Terminal' %} - {% trans 'Command' %} - {% trans 'Success' %} - {% trans 'Finished' %} - {% trans 'Monitor' %} - {% trans 'Date start' %} - {% trans 'Time' %} -{% endblock %} - -{% block table_body %} - {% for proxy_log in proxy_log_list %} - - - - {{ proxy_log.id }} - - {{ proxy_log.user }} - {{ proxy_log.asset }} - {{ proxy_log.system_user }} - {{ proxy_log.terminal }} - {{ proxy_log.commands.all|length}} - - {% if proxy_log.is_failed %} - - {% else %} - - {% endif %} - - {% if proxy_log.is_finished %} - - - - - - - {% else %} - - - - - - - {% endif %} - {{ proxy_log.date_start }} - {{ proxy_log.date_finished|timeuntil:proxy_log.date_start }} - - {% endfor %} -{% endblock %} - -{% block content_bottom_left %} -
      -
      - -
      - -
      -
      -
      -{% endblock %} - -{% block custom_foot_js %} - - -{% endblock %} - diff --git a/apps/audits/templatetags/example_tags.py b/apps/audits/templatetags/example_tags.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/audits/tests.py b/apps/audits/tests.py deleted file mode 100644 index 7ce503c2d..000000000 --- a/apps/audits/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/apps/audits/urls/__init__.py b/apps/audits/urls/__init__.py deleted file mode 100644 index 8b1378917..000000000 --- a/apps/audits/urls/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/audits/urls/api_urls.py b/apps/audits/urls/api_urls.py deleted file mode 100644 index b9226d1b4..000000000 --- a/apps/audits/urls/api_urls.py +++ /dev/null @@ -1,18 +0,0 @@ -from django.conf.urls import url -from rest_framework import routers - -from .. import api - -app_name = 'audits' - -router = routers.DefaultRouter() -router.register(r'v1/proxy-log', api.ProxyLogViewSet, 'proxy-log') -router.register(r'v1/command-log', api.CommandLogViewSet, 'command-log') -router.register(r'v1/replay-log', api.RecordLogViewSet, 'replay-log') - -urlpatterns = [ - url(r'^v1/proxy-log/receive/$', api.ProxyLogReceiveView.as_view(), - name='proxy-log-receive'), -] - -urlpatterns += router.urls diff --git a/apps/audits/urls/views_urls.py b/apps/audits/urls/views_urls.py deleted file mode 100644 index b36af1858..000000000 --- a/apps/audits/urls/views_urls.py +++ /dev/null @@ -1,19 +0,0 @@ -from django.conf.urls import url -from .. import views - -app_name = 'audits' - -urlpatterns = [ - url(r'^proxy-log-offline/$', views.ProxyLogOfflineListView.as_view(), - name='proxy-log-offline-list'), - url(r'^proxy-log-online/$', views.ProxyLogOnlineListView.as_view(), - name='proxy-log-online-list'), - url(r'^proxy-log/(?P[0-9a-zA-Z\-]+)/$', views.ProxyLogDetailView.as_view(), - name='proxy-log-detail'), - url(r'^command-log/$', views.CommandLogListView.as_view(), - name='command-log-list'), - url(r'^login-log/$', views.LoginLogListView.as_view(), - name='login-log-list'), -] - - diff --git a/apps/audits/utils.py b/apps/audits/utils.py deleted file mode 100644 index 4f57619d7..000000000 --- a/apps/audits/utils.py +++ /dev/null @@ -1,49 +0,0 @@ -# ~*~ coding: utf-8 ~*~ -# -from __future__ import unicode_literals -import requests -import ipaddress - -from .models import LoginLog - - -def validate_ip(ip): - try: - ipaddress.ip_address(ip) - return True - except ValueError: - print('valid error') - return False - - -def write_login_log(username, name='', login_type='', - login_ip='', user_agent=''): - if not (login_ip and validate_ip(login_ip)): - login_ip = '0.0.0.0' - if not name: - name = username - login_city = get_ip_city(login_ip) - LoginLog.objects.create(username=username, name=name, login_type=login_type, - login_ip=login_ip, login_city=login_city, user_agent=user_agent) - - -def get_ip_city(ip, timeout=10): - # Taobao ip api: http://ip.taobao.com//service/getIpInfo.php?ip=8.8.8.8 - # Sina ip api: http://int.dpool.sina.com.cn/iplookup/iplookup.php?ip=8.8.8.8&format=json - - url = 'http://int.dpool.sina.com.cn/iplookup/iplookup.php?ip=%s&format=json' % ip - try: - r = requests.get(url, timeout=timeout) - except requests.Timeout: - r = None - city = 'Unknown' - if r and r.status_code == 200: - try: - data = r.json() - if not isinstance(data, int) and data['ret'] == 1: - city = data['country'] + ' ' + data['city'] - except ValueError: - pass - return city - - diff --git a/apps/audits/views.py b/apps/audits/views.py deleted file mode 100644 index 9767b54bd..000000000 --- a/apps/audits/views.py +++ /dev/null @@ -1,272 +0,0 @@ -# ~*~ coding: utf-8 ~*~ -# -import time -from datetime import datetime - -from django.views.generic import ListView, UpdateView, DeleteView, DetailView, TemplateView -from django.views.generic.edit import SingleObjectMixin -from django.utils.translation import ugettext as _ -from django.utils import timezone -from django.utils.module_loading import import_string -from django.urls import reverse_lazy -from django.http import HttpResponse -from django.conf import settings -from django.db.models import Q - -from .models import ProxyLog, CommandLog, LoginLog -from .hands import User, Asset, SystemUser, AdminUserRequiredMixin -from audits.backends import command_store -from audits.backends import CommandLogSerializer - - -class ProxyLogListView(AdminUserRequiredMixin, ListView): - model = ProxyLog - template_name = 'audits/proxy_log_online_list.html' - context_object_name = 'proxy_log_list' - paginate_by = settings.CONFIG.DISPLAY_PER_PAGE - keyword = username = hostname = system_user = date_from_s = date_to_s = '' - ordering = ['is_finished', '-id'] - date_format = '%m/%d/%Y' - - def get_queryset(self): - date_now = timezone.localtime(timezone.now()) - date_to_default = date_now.strftime(self.date_format) - date_from_default = (date_now-timezone.timedelta(7))\ - .strftime(self.date_format) - - self.queryset = super(ProxyLogListView, self).get_queryset() - self.keyword = self.request.GET.get('keyword', '') - self.username = self.request.GET.get('username') - self.ip = self.request.GET.get('ip') - self.system_user = self.request.GET.get('system_user') - self.date_from_s = self.request.GET.get('date_from', date_from_default) - self.date_to_s = self.request.GET.get('date_to', date_to_default) - - filter_kwargs = {} - if self.date_from_s: - date_from = datetime.strptime(self.date_from_s, self.date_format) - date_from = date_from.replace(tzinfo=timezone.get_current_timezone()) - filter_kwargs['date_start__gt'] = date_from - if self.date_to_s: - date_to = timezone.datetime.strptime( - self.date_to_s + ' 23:59:59', '%m/%d/%Y %H:%M:%S') - date_to = date_to.replace(tzinfo=timezone.get_current_timezone()) - filter_kwargs['date_start__lt'] = date_to - if self.username: - filter_kwargs['user'] = self.username - if self.ip: - filter_kwargs['asset'] = self.ip - if self.system_user: - filter_kwargs['system_user'] = self.system_user - if self.keyword: - self.queryset = self.queryset.filter( - Q(user__icontains=self.keyword) | - Q(asset__icontains=self.keyword) | - Q(system_user__icontains=self.keyword)).distinct() - if filter_kwargs: - self.queryset = self.queryset.filter(**filter_kwargs) - return self.queryset - - def get_context_data(self, **kwargs): - context = { - 'app': _('Audits'), - 'action': _('Proxy log list'), - 'user_list': set( - list(ProxyLog.objects.values_list('user', flat=True))), - 'asset_list': set( - list(ProxyLog.objects.values_list('asset', flat=True))), - 'system_user_list': set( - list(ProxyLog.objects.values_list('system_user', flat=True))), - 'keyword': self.keyword, - 'date_from': self.date_from_s, - 'date_to': self.date_to_s, - 'username': self.username, - 'ip': self.ip, - 'system_user': self.system_user, - } - kwargs.update(context) - return super(ProxyLogListView, self).get_context_data(**kwargs) - - -class ProxyLogOfflineListView(ProxyLogListView): - template_name = 'audits/proxy_log_offline_list.html' - - def get_queryset(self): - queryset = super(ProxyLogOfflineListView, self).get_queryset() - queryset = queryset.filter(is_finished=True) - return queryset - - def get_context_data(self, **kwargs): - context = { - 'action': _('Proxy log offline list'), - } - kwargs.update(context) - return super(ProxyLogOfflineListView, self).get_context_data(**kwargs) - - -class ProxyLogOnlineListView(ProxyLogListView): - template_name = 'audits/proxy_log_online_list.html' - - def get_queryset(self): - queryset = super(ProxyLogOnlineListView, self).get_queryset() - queryset = queryset.filter(is_finished=False) - return queryset - - def get_context_data(self, **kwargs): - context = { - 'action': _('Proxy log online list'), - } - kwargs.update(context) - return super(ProxyLogOnlineListView, self).get_context_data(**kwargs) - - -class ProxyLogDetailView(AdminUserRequiredMixin, - SingleObjectMixin, - ListView): - template_name = 'audits/proxy_log_detail.html' - context_object_name = 'proxy_log' - object = '' - - def get(self, request, *args, **kwargs): - self.object = self.get_object(queryset=ProxyLog.objects.all()) - return super(ProxyLogDetailView, self).get(request, *args, **kwargs) - - def get_queryset(self): - return list(command_store.filter(proxy_log_id=self.object.id)) - - def get_context_data(self, **kwargs): - context = { - 'app': 'Audits', - 'action': 'Proxy log detail', - } - kwargs.update(context) - return super(ProxyLogDetailView, self).get_context_data(**kwargs) - - -# class ProxyLogCommandsListView(AdminUserRequiredMixin, -# SingleObjectMixin, -# ListView): -# template_name = 'audits/proxy_log_commands_list_modal.html' -# object = '' -# -# def get(self, request, *args, **kwargs): -# self.object = self.get_object(queryset=ProxyLog.objects.all()) -# return super(ProxyLogCommandsListView, self).\ -# get(request, *args, **kwargs) -# -# def get_queryset(self): -# return list(self.object.command_log.all()) - - -class CommandLogListView(AdminUserRequiredMixin, ListView): - template_name = 'audits/command_log_list.html' - paginate_by = settings.CONFIG.DISPLAY_PER_PAGE - context_object_name = 'command_list' - username = ip = system_user = command = date_from_s = date_to_s = '' - date_format = '%m/%d/%Y' - ordering = ['-id'] - - def get_queryset(self): - date_now = timezone.localtime(timezone.now()) - date_to_default = date_now.strftime(self.date_format) - date_from_default = (date_now - timezone.timedelta(7)) \ - .strftime(self.date_format) - self.command = self.request.GET.get('command', '') - self.username = self.request.GET.get('username') - self.ip = self.request.GET.get('ip') - self.system_user = self.request.GET.get('system_user') - self.date_from_s = \ - self.request.GET.get('date_from', date_from_default) - self.date_to_s = \ - self.request.GET.get('date_to', date_to_default) - - filter_kwargs = {} - if self.date_from_s: - date_from = datetime.strptime(self.date_from_s, self.date_format)\ - .replace(tzinfo=timezone.get_current_timezone()) - # date_from_utc = date_from.astimezone(pytz.utc) - date_from_ts = time.mktime(date_from.timetuple()) - filter_kwargs['date_from_ts'] = date_from_ts - if self.date_to_s: - date_to = datetime.strptime( - self.date_to_s + ' 23:59:59', '%m/%d/%Y %H:%M:%S')\ - .replace(tzinfo=timezone.get_current_timezone()) - date_to_ts = time.mktime(date_to.timetuple()) - filter_kwargs['date_to_ts'] = date_to_ts - if self.username: - filter_kwargs['user'] = self.username - if self.ip: - filter_kwargs['asset'] = self.ip - if self.system_user: - filter_kwargs['system_user'] = self.system_user - if self.command: - filter_kwargs['command'] = self.command - self.queryset = command_store.filter(**filter_kwargs).order_by(*self.ordering) - return self.queryset - - def get_context_data(self, **kwargs): - context = { - 'app': _('Audits'), - 'action': _('Command log list'), - 'user_list': User.objects.all().order_by('username'), - 'asset_list': Asset.objects.all().order_by('ip'), - 'system_user_list': SystemUser.objects.all().order_by('username'), - 'command': self.command, - 'date_from': self.date_from_s, - 'date_to': self.date_to_s, - 'username': self.username, - 'ip': self.ip, - 'system_user': self.system_user, - } - kwargs.update(context) - return super(CommandLogListView, self).get_context_data(**kwargs) - - -class LoginLogListView(AdminUserRequiredMixin, ListView): - model = LoginLog - paginate_by = settings.CONFIG.DISPLAY_PER_PAGE - template_name = 'audits/login_log_list.html' - context_object_name = 'login_log_list' - keyword = username = date_from_s = date_to_s = '' - - def get_queryset(self): - date_now = timezone.localtime(timezone.now()) - now_s = date_now.strftime('%m/%d/%Y') - seven_days_ago_s = (date_now - timezone.timedelta(7))\ - .strftime('%m/%d/%Y') - self.queryset = super(LoginLogListView, self).get_queryset() - self.keyword = keyword = self.request.GET.get('keyword', '') - self.username = username = self.request.GET.get('username', '') - self.date_from_s = date_from_s = self.request.GET.get( - 'date_from', '%s' % seven_days_ago_s) - self.date_to_s = date_to_s = self.request.GET.get( - 'date_to', '%s' % now_s) - - if date_from_s: - date_from = timezone.datetime.strptime(date_from_s, '%m/%d/%Y') - self.queryset = self.queryset.filter(date_login__gt=date_from) - if date_to_s: - date_to = timezone.datetime.strptime( - date_to_s + ' 23:59:59', '%m/%d/%Y %H:%M:%S') - self.queryset = self.queryset.filter(date_login__lt=date_to) - if username: - self.queryset = self.queryset.filter(username=username) - if keyword: - self.queryset = self.queryset.filter( - Q(username__contains=keyword) | - Q(name__icontains=keyword) | - Q(login_ip=keyword)).distinct() - return self.queryset - - def get_context_data(self, **kwargs): - context = { - 'app': _('Audits'), - 'action': _('Proxy log list'), - 'user_list': User.objects.all().order_by('username'), - 'keyword': self.keyword, - 'date_from': self.date_from_s, - 'date_to': self.date_to_s, - 'username': self.username, - } - kwargs.update(context) - return super(LoginLogListView, self).get_context_data(**kwargs) diff --git a/apps/common/templatetags/common_tags.py b/apps/common/templatetags/common_tags.py index ee6c4bdfb..12a30927d 100644 --- a/apps/common/templatetags/common_tags.py +++ b/apps/common/templatetags/common_tags.py @@ -3,7 +3,6 @@ from django import template from django.utils import timezone from django.utils.html import escape -from audits.backends import command_store register = template.Library() @@ -70,6 +69,6 @@ def to_html(s): return escape(s).replace('\n', '
      ') -@register.filter -def proxy_log_commands(log_id): - return command_store.filter(proxy_log_id=log_id) +# @register.filter +# def proxy_log_commands(log_id): +# return 1 diff --git a/apps/common/views.py b/apps/common/views.py index 5663b8b19..4cee32ba7 100644 --- a/apps/common/views.py +++ b/apps/common/views.py @@ -1,4 +1,2 @@ from __future__ import absolute_import, unicode_literals -from django.shortcuts import render -from django.views.generic import TemplateView diff --git a/apps/jumpserver/middleware.py b/apps/jumpserver/middleware.py index 28e718d7d..f93edf73a 100644 --- a/apps/jumpserver/middleware.py +++ b/apps/jumpserver/middleware.py @@ -9,7 +9,7 @@ from django.shortcuts import HttpResponse DEMO_MODE = os.environ.get("DEMO_MODE", "") -SAFE_URL = r'^/users/login|^/api/terminal/v1/.*|/api/audits/.*|/api/users/v1/auth/|/api/users/v1/profile/' +SAFE_URL = r'^/users/login|^/api/terminal/v1/.*|/api/terminal/.*|/api/users/v1/auth/|/api/users/v1/profile/' class TimezoneMiddleware(MiddlewareMixin): diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py index 00290db0d..795223d84 100644 --- a/apps/jumpserver/settings.py +++ b/apps/jumpserver/settings.py @@ -59,7 +59,7 @@ INSTALLED_APPS = [ 'assets.apps.AssetsConfig', 'perms.apps.PermsConfig', 'ops.apps.OpsConfig', - 'audits.apps.AuditsConfig', + # 'audits.apps.AuditsConfig', 'common.apps.CommonConfig', 'terminal.apps.ApplicationsConfig', 'rest_framework', @@ -364,7 +364,7 @@ CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_dots',) CAPTCHA_TEST_MODE = CONFIG.CAPTCHA_TEST_MODE COMMAND_STORE_BACKEND = 'terminal.backends.command.db' -RECORD_STORE_BACKEND = 'terminal.backends.replay.db' +REPLAY_STORE_BACKEND = 'terminal.backends.replay.db' # Django bootstrap3 setting, more see http://django-bootstrap3.readthedocs.io/en/latest/settings.html diff --git a/apps/jumpserver/urls.py b/apps/jumpserver/urls.py index 80e8df1f2..cf5270d29 100644 --- a/apps/jumpserver/urls.py +++ b/apps/jumpserver/urls.py @@ -16,7 +16,7 @@ urlpatterns = [ url(r'^users/', include('users.urls.views_urls', namespace='users')), url(r'^assets/', include('assets.urls.views_urls', namespace='assets')), url(r'^perms/', include('perms.urls.views_urls', namespace='perms')), - url(r'^audits/', include('audits.urls.views_urls', namespace='audits')), + # url(r'^audits/', include('audits.urls.views_urls', namespace='audits')), url(r'^terminal/', include('terminal.urls.views_urls', namespace='terminal')), url(r'^ops/', include('ops.urls.view_urls', namespace='ops')), @@ -24,7 +24,7 @@ urlpatterns = [ url(r'^api/users/', include('users.urls.api_urls', namespace='api-users')), url(r'^api/assets/', include('assets.urls.api_urls', namespace='api-assets')), url(r'^api/perms/', include('perms.urls.api_urls', namespace='api-perms')), - url(r'^api/audits/', include('audits.urls.api_urls', namespace='api-audits')), + # url(r'^api/audits/', include('audits.urls.api_urls', namespace='api-audits')), url(r'^api/terminal/', include('terminal.urls.api_urls', namespace='api-terminal')), url(r'^api/ops/', include('ops.urls.api_urls', namespace='api-ops')), url(r'^captcha/', include('captcha.urls')), diff --git a/apps/jumpserver/views.py b/apps/jumpserver/views.py index e08956de0..08ddbf3db 100644 --- a/apps/jumpserver/views.py +++ b/apps/jumpserver/views.py @@ -6,70 +6,146 @@ from django.shortcuts import redirect from users.models import User from assets.models import Asset -from audits.models import ProxyLog +from terminal.models import Session class IndexView(LoginRequiredMixin, TemplateView): template_name = 'index.html' + session_week = None + session_month = None + session_month_dates = [] + session_month_dates_archive = [] + def get(self, request, *args, **kwargs): if not request.user.is_superuser: return redirect('assets:user-asset-list') return super(IndexView, self).get(request, *args, **kwargs) - def get_context_data(self, **kwargs): - seven_days_ago = timezone.now() - timezone.timedelta(days=7) - month_ago = timezone.now() - timezone.timedelta(days=30) - proxy_log_seven_days = ProxyLog.objects.filter(date_start__gt=seven_days_ago, is_failed=False) - proxy_log_month = ProxyLog.objects.filter(date_start__gt=month_ago, is_failed=False) - month_dates = proxy_log_month.dates('date_start', 'day') - month_total_visit = [ProxyLog.objects.filter(date_start__date=d) for d in month_dates] - month_str = [d.strftime('%m-%d') for d in month_dates] or ['0'] - month_total_visit_count = [p.count() for p in month_total_visit] or [0] - month_user = [p.values('user').distinct().count() for p in month_total_visit] or [0] - month_asset = [p.values('asset').distinct().count() for p in month_total_visit] or [0] - month_user_active = User.objects.filter(last_login__gt=month_ago).count() - month_user_inactive = User.objects.filter(last_login__lt=month_ago).count() - month_user_disabled = User.objects.filter(is_active=False).count() - month_asset_active = proxy_log_month.values('asset').distinct().count() - month_asset_inactive = Asset.objects.all().count() - month_asset_active - month_asset_disabled = Asset.objects.filter(is_active=False).count() - week_asset_hot_ten = list(proxy_log_seven_days.values('asset').annotate(total=Count('asset')).order_by('-total')[:10]) - for p in week_asset_hot_ten: - last_login = ProxyLog.objects.filter(asset=p['asset']).order_by('date_start').last() - p['last'] = last_login - last_login_ten = ProxyLog.objects.all().order_by('-date_start')[:10] - for p in last_login_ten: + @staticmethod + def get_user_count(): + return User.objects.filter(role__in=('Admin', 'User')).count() + + @staticmethod + def get_asset_count(): + return Asset.objects.all().count() + + @staticmethod + def get_online_user_count(): + return len(set(Session.objects.filter(is_finished=False).values_list('user', flat=True))) + + @staticmethod + def get_online_session_count(): + return Session.objects.filter(is_finished=False).count() + + def get_top5_user_a_week(self): + return self.session_week.values('user').annotate(total=Count('user')).order_by('-total')[:5] + + def get_week_login_user_count(self): + return self.session_week.values('user').distinct().count() + + def get_week_login_asset_count(self): + return self.session_week.values('asset').distinct().count() + + def get_month_day_metrics(self): + month_str = [d.strftime('%m-%d') for d in self.session_month_dates] or ['0'] + return month_str + + def get_month_login_metrics(self): + return [self.session_month.filter(date_start__date=d).count() + for d in self.session_month_dates] + + def get_month_active_user_metrics(self): + if self.session_month_dates_archive: + return [q.values('user').distinct().count() + for q in self.session_month_dates_archive] + else: + return [0] + + def get_month_active_asset_metrics(self): + if self.session_month_dates_archive: + return [q.values('asset').distinct().count() + for q in self.session_month_dates_archive] + else: + return [0] + + def get_month_active_user_total(self): + return self.session_month.values('user').distinct().count() + + def get_month_inactive_user_total(self): + return User.objects.all().count() - self.get_month_active_user_total() + + def get_month_active_asset_total(self): + return self.session_month.values('asset').distinct().count() + + def get_month_inactive_asset_total(self): + return Asset.objects.all().count() - self.get_month_active_asset_total() + + @staticmethod + def get_user_disabled_total(): + return User.objects.filter(is_active=False).count() + + @staticmethod + def get_asset_disabled_total(): + return Asset.objects.filter(is_active=False).count() + + def get_week_top10_asset(self): + assets = list(self.session_week.values('asset').annotate(total=Count('asset')).order_by('-total')[:10]) + for asset in assets: + last_login = self.session_week.filter(asset=asset["asset"]).order_by('date_start').last() + asset['last'] = last_login + print(asset) + return assets + + def get_week_top10_user(self): + users = list(self.session_week.values('user').annotate( + total=Count('asset')).order_by('-total')[:10]) + for user in users: + last_login = self.session_week.filter(user=user["user"]).order_by('date_start').last() + user['last'] = last_login + return users + + def get_last10_sessions(self): + sessions = self.session_week.order_by('-date_start')[:10] + for session in sessions: try: - p.avatar_url = User.objects.get(username=p.user).avatar_url() + session.avatar_url = User.objects.get(username=session.user).avatar_url() except User.DoesNotExist: - p.avatar_url = User.objects.first().avatar_url() - week_user_hot_ten = list(proxy_log_seven_days.values('user').annotate(total=Count('user')).order_by('-total')[:10]) - for p in week_user_hot_ten: - last_login = ProxyLog.objects.filter(user=p['user']).order_by('date_start').last() - p['last'] = last_login + session.avatar_url = User.objects.first().avatar_url() + return sessions + + def get_context_data(self, **kwargs): + week_ago = timezone.now() - timezone.timedelta(weeks=1) + month_ago = timezone.now() - timezone.timedelta(days=30) + self.session_week = Session.objects.filter(date_start__gt=week_ago) + self.session_month = Session.objects.filter(date_start__gt=month_ago) + self.session_month_dates = self.session_month.dates('date_start', 'day') + self.session_month_dates_archive = [ + self.session_month.filter(date_start__date=d) + for d in self.session_month_dates + ] context = { - 'assets_count': Asset.objects.count(), - 'users_count': User.objects.filter(role__in=('Admin', 'User')).count(), - 'online_user_count': ProxyLog.objects.filter(is_finished=False).values('user').distinct().count(), - 'online_asset_count': ProxyLog.objects.filter(is_finished=False).values('asset').distinct().count(), - 'user_visit_count_weekly': proxy_log_seven_days.values('user').distinct().count(), - 'asset_visit_count_weekly': proxy_log_seven_days.count(), - 'user_visit_count_top_five': proxy_log_seven_days.values('user').annotate(total=Count('user')).order_by('-total')[:5], - 'month_str': month_str, - 'month_total_visit_count': month_total_visit_count, - 'month_user': month_user, - 'mouth_asset': month_asset, - 'month_user_active': month_user_active, - 'month_user_inactive': month_user_inactive, - 'month_user_disabled': month_user_disabled, - 'month_asset_active': month_asset_active, - 'month_asset_inactive': month_asset_inactive, - 'month_asset_disabled': month_asset_disabled, - 'week_asset_hot_ten': week_asset_hot_ten, - 'last_login_ten': last_login_ten, - 'week_user_hot_ten': week_user_hot_ten, + 'assets_count': self.get_asset_count(), + 'users_count': self.get_user_count(), + 'online_user_count': self.get_online_user_count(), + 'online_asset_count': self.get_online_session_count(), + 'user_visit_count_weekly': self.get_week_login_user_count(), + 'asset_visit_count_weekly': self.get_week_login_asset_count(), + 'user_visit_count_top_five': self.get_top5_user_a_week(), + 'month_str': self.get_month_day_metrics(), + 'month_total_visit_count': self.get_month_login_metrics(), + 'month_user': self.get_month_active_user_metrics(), + 'mouth_asset': self.get_month_active_asset_metrics(), + 'month_user_active': self.get_month_active_user_total(), + 'month_user_inactive': self.get_month_inactive_user_total(), + 'month_user_disabled': self.get_user_disabled_total(), + 'month_asset_active': self.get_month_active_asset_total(), + 'month_asset_inactive': self.get_month_inactive_asset_total(), + 'month_asset_disabled': self.get_asset_disabled_total(), + 'week_asset_hot_ten': self.get_week_top10_asset(), + 'last_login_ten': self.get_last10_sessions(), + 'week_user_hot_ten': self.get_week_top10_user(), } kwargs.update(context) diff --git a/apps/templates/index.html b/apps/templates/index.html index 581751f22..5ddbc17ab 100644 --- a/apps/templates/index.html +++ b/apps/templates/index.html @@ -35,7 +35,7 @@
      在线用户
      -

      {{ online_user_count }}

      +

      {{ online_user_count }}

      Online user
      @@ -45,11 +45,11 @@
      Connected -
      已连接服务器
      +
      在线会话
      -

      {{ online_asset_count }}

      - Connected host +

      {{ online_asset_count }}

      + Online sessions
      diff --git a/apps/terminal/api.py b/apps/terminal/api.py index 681dca4c1..6fcd2fc18 100644 --- a/apps/terminal/api.py +++ b/apps/terminal/api.py @@ -1,10 +1,8 @@ # -*- coding: utf-8 -*- # -import base64 from collections import OrderedDict import copy import logging -import tarfile import os from rest_framework import viewsets, serializers @@ -18,7 +16,7 @@ from common.utils import get_object_or_none from .models import Terminal, Status, Session, Task from .serializers import TerminalSerializer, StatusSerializer, \ SessionSerializer, TaskSerializer -from .hands import IsSuperUserOrAppUser, IsAppUser, ProxyLog, \ +from .hands import IsSuperUserOrAppUser, IsAppUser, \ IsSuperUserOrAppUserOrUserReadonly from .backends import get_command_store, get_replay_store, SessionCommandSerializer @@ -221,7 +219,9 @@ class CommandViewSet(viewsets.ViewSet): else: return Response("Save error", status=500) else: - return Response({"msg": "Not valid: {}".format(serializer.errors)}, status=401) + msg = "Not valid: {}".format(serializer.errors) + logger.error(msg) + return Response({"msg": msg}, status=401) def list(self, request, *args, **kwargs): queryset = list(self.command_store.all()) diff --git a/apps/terminal/backends/__init__.py b/apps/terminal/backends/__init__.py index 813f7f88c..6a9d06079 100644 --- a/apps/terminal/backends/__init__.py +++ b/apps/terminal/backends/__init__.py @@ -12,6 +12,6 @@ def get_command_store(): def get_replay_store(): - replay_engine = import_module(settings.RECORD_STORE_BACKEND) - replay_store = replay_engine.RecordStore() + replay_engine = import_module(settings.REPLAY_STORE_BACKEND) + replay_store = replay_engine.ReplayStore() return replay_store diff --git a/apps/terminal/backends/replay/base.py b/apps/terminal/backends/replay/base.py index e96b8b131..46a2df845 100644 --- a/apps/terminal/backends/replay/base.py +++ b/apps/terminal/backends/replay/base.py @@ -2,7 +2,7 @@ import abc -class RecordBase(object): +class ReplayBase(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod diff --git a/apps/terminal/backends/replay/db.py b/apps/terminal/backends/replay/db.py index e55211f65..06d2c5ab3 100644 --- a/apps/terminal/backends/replay/db.py +++ b/apps/terminal/backends/replay/db.py @@ -1,31 +1,8 @@ # ~*~ coding: utf-8 ~*~ -from .base import RecordBase -from audits.models import RecordLog +from .base import ReplayBase -class RecordStore(RecordBase): - model = RecordLog - queryset = [] - - def save(self, proxy_log_id, output, timestamp): - return self.model.objects.create( - proxy_log_id=proxy_log_id, output=output, timestamp=timestamp - ) - - def filter(self, date_from_ts=None, proxy_log_id=''): - filter_kwargs = {} - - if date_from_ts: - filter_kwargs['timestamp__gte'] = date_from_ts - if proxy_log_id: - filter_kwargs['proxy_log_id'] = proxy_log_id - - if filter_kwargs: - self.queryset = self.model.objects.filter(**filter_kwargs) - return self.queryset - - def all(self): - """返回所有数据""" - return self.model.objects.all() +class ReplayStore(ReplayBase): + pass diff --git a/apps/terminal/backends/replay/serializers.py b/apps/terminal/backends/replay/serializers.py deleted file mode 100644 index 30a5867e1..000000000 --- a/apps/terminal/backends/replay/serializers.py +++ /dev/null @@ -1,20 +0,0 @@ -# ~*~ coding: utf-8 ~*~ -import base64 -from rest_framework import serializers -from audits.models import RecordLog -from audits.backends import record_store - - -class RecordSerializer(serializers.ModelSerializer): - """使用这个类作为基础Command Log Serializer类, 用来序列化""" - class Meta: - model = RecordLog - fields = '__all__' - - def create(self, validated_data): - try: - output = validated_data['output'] - validated_data['output'] = base64.b64decode(output) - except IndexError: - pass - return record_store.save(**dict(validated_data)) diff --git a/apps/terminal/hands.py b/apps/terminal/hands.py index 23a93691d..ce075bfc5 100644 --- a/apps/terminal/hands.py +++ b/apps/terminal/hands.py @@ -4,5 +4,4 @@ from users.models import User from users.permissions import IsSuperUserOrAppUser, IsAppUser, \ IsSuperUserOrAppUserOrUserReadonly -from audits.models import ProxyLog from users.utils import AdminUserRequiredMixin \ No newline at end of file diff --git a/apps/terminal/tasks.py b/apps/terminal/tasks.py index 4bcfae396..47b0748af 100644 --- a/apps/terminal/tasks.py +++ b/apps/terminal/tasks.py @@ -13,6 +13,7 @@ ASSETS_CACHE_KEY = "terminal__session__assets" USERS_CACHE_KEY = "terminal__session__users" SYSTEM_USER_CACHE_KEY = "terminal__session__system_users" CACHE_REFRESH_INTERVAL = 10 +RUNNING = False # Todo: 定期清理上报history @@ -46,7 +47,16 @@ def set_cache(): def main(): + global RUNNING + if RUNNING: + return + threads = [] thread = threading.Thread(target=set_cache) - thread.start() + threads.append(thread) + + for t in threads: + t.daemon = True + t.start() + RUNNING = True main() diff --git a/apps/users/api.py b/apps/users/api.py index aed67cc8c..522a47bb5 100644 --- a/apps/users/api.py +++ b/apps/users/api.py @@ -9,7 +9,7 @@ from rest_framework_bulk import BulkModelViewSet from django_filters.rest_framework import DjangoFilterBackend from . import serializers -from .hands import write_login_log_async +from .tasks import write_login_log_async from .models import User, UserGroup from .permissions import IsSuperUser, IsValidUser, IsCurrentUserOrReadOnly from .utils import check_user_valid, generate_token diff --git a/apps/users/hands.py b/apps/users/hands.py index b44b9bb84..bf47d775a 100644 --- a/apps/users/hands.py +++ b/apps/users/hands.py @@ -10,8 +10,8 @@ :license: GPL v2, see LICENSE for more details. """ -from terminal.models import Terminal -from audits.tasks import write_login_log_async -from users.models import User +# from terminal.models import Terminal +# from audits.tasks import write_login_log_async +# from users.models import User # from perms.models import AssetPermission # from perms.utils import get_user_granted_assets, get_user_granted_asset_groups diff --git a/apps/users/models/authentication.py b/apps/users/models/authentication.py index 954c7e5bc..61f84b81f 100644 --- a/apps/users/models/authentication.py +++ b/apps/users/models/authentication.py @@ -8,7 +8,7 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework.authtoken.models import Token from . import User -__all__ = ['AccessKey', 'PrivateToken'] +__all__ = ['AccessKey', 'PrivateToken', 'LoginLog'] class AccessKey(models.Model): @@ -34,3 +34,22 @@ class PrivateToken(Token): class Meta: verbose_name = _('Private Token') + + +class LoginLog(models.Model): + LOGIN_TYPE_CHOICE = ( + ('W', 'Web'), + ('ST', 'SSH Terminal'), + ('WT', 'Web Terminal') + ) + id = models.UUIDField(default=uuid.uuid4, primary_key=True) + username = models.CharField(max_length=20, verbose_name=_('Username')) + type = models.CharField(choices=LOGIN_TYPE_CHOICE, max_length=2, verbose_name=_('Login type')) + ip = models.GenericIPAddressField(verbose_name=_('Login ip')) + city = models.CharField(max_length=254, blank=True, null=True, verbose_name=_('Login city')) + user_agent = models.CharField(max_length=254, blank=True, null=True, verbose_name=_('User agent')) + datetime = models.DateTimeField(auto_now_add=True, verbose_name=_('Date login')) + + class Meta: + db_table = 'login_log' + ordering = ['-datetime', 'username'] diff --git a/apps/users/models/group.py b/apps/users/models/group.py index 0e75a16d5..c0950cf9f 100644 --- a/apps/users/models/group.py +++ b/apps/users/models/group.py @@ -24,9 +24,8 @@ class UserGroup(NoDeleteModelMixin): verbose_name=_('Date created')) created_by = models.CharField(max_length=100) - def __unicode__(self): + def __str__(self): return self.name - __str__ = __unicode__ def delete(self, using=None, keep_parents=False): if self.name != 'Default': diff --git a/apps/audits/tasks.py b/apps/users/tasks.py similarity index 76% rename from apps/audits/tasks.py rename to apps/users/tasks.py index f80aa5f75..8d8eb6553 100644 --- a/apps/audits/tasks.py +++ b/apps/users/tasks.py @@ -1,6 +1,5 @@ -#!/usr/bin/env python -# ~*~ coding: utf-8 ~*~ -# +# -*- coding: utf-8 -*- +# from celery import shared_task from .utils import write_login_log diff --git a/apps/users/utils.py b/apps/users/utils.py index 6610c2112..c62784e91 100644 --- a/apps/users/utils.py +++ b/apps/users/utils.py @@ -5,7 +5,8 @@ import base64 import logging import uuid -from paramiko.rsakey import RSAKey +import requests +import ipaddress from django.conf import settings from django.contrib.auth.mixins import UserPassesTestMixin from django.contrib.auth import authenticate @@ -14,13 +15,7 @@ from django.core.cache import cache from common.tasks import send_mail_async from common.utils import reverse, get_object_or_none -from .models import User - - -# try: -# from io import StringIO -# except ImportError: -# from StringIO import StringIO +from .models import User, LoginLog logger = logging.getLogger('jumpserver') @@ -172,3 +167,40 @@ def generate_token(request, user): return token +def validate_ip(ip): + try: + ipaddress.ip_address(ip) + return True + except ValueError: + pass + return False + + +def write_login_log(username, type='', ip='', user_agent=''): + if not (ip and validate_ip(ip)): + ip = '0.0.0.0' + city = get_ip_city(ip) + LoginLog.objects.create( + username=username, type=type, + ip=ip, city=city, user_agent=user_agent + ) + + +def get_ip_city(ip, timeout=10): + # Taobao ip api: http://ip.taobao.com//service/getIpInfo.php?ip=8.8.8.8 + # Sina ip api: http://int.dpool.sina.com.cn/iplookup/iplookup.php?ip=8.8.8.8&format=json + + url = 'http://int.dpool.sina.com.cn/iplookup/iplookup.php?ip=%s&format=json' % ip + try: + r = requests.get(url, timeout=timeout) + except requests.Timeout: + r = None + city = 'Unknown' + if r and r.status_code == 200: + try: + data = r.json() + if not isinstance(data, int) and data['ret'] == 1: + city = data['country'] + ' ' + data['city'] + except ValueError: + pass + return city diff --git a/apps/users/views/login.py b/apps/users/views/login.py index 115db0f1a..a09125c02 100644 --- a/apps/users/views/login.py +++ b/apps/users/views/login.py @@ -21,7 +21,7 @@ from django.conf import settings from common.utils import get_object_or_none from ..models import User from ..utils import send_reset_password_mail -from ..hands import write_login_log_async +from ..tasks import write_login_log_async from .. import forms