diff --git a/apps/assets/api.py b/apps/assets/api.py
index 526a375bf..2aa8c564c 100644
--- a/apps/assets/api.py
+++ b/apps/assets/api.py
@@ -1,18 +1,21 @@
# ~*~ coding: utf-8 ~*~
from rest_framework import serializers
-from rest_framework import viewsets, serializers,generics
-from .models import AssetGroup, Asset, IDC, AssetExtend
+from rest_framework import viewsets, serializers, generics
+from rest_framework.response import Response
+from rest_framework.views import APIView
+from rest_framework_bulk import BulkListSerializer, BulkSerializerMixin, ListBulkCreateUpdateDestroyAPIView
+
from common.mixins import BulkDeleteApiMixin
-from rest_framework_bulk import BulkListSerializer, BulkSerializerMixin,ListBulkCreateUpdateDestroyAPIView
-from .serializers import *
+from common.utils import get_object_or_none, signer
+from .hands import IsSuperUserOrTerminalUser, IsSuperUser
+from .models import AssetGroup, Asset, IDC, SystemUser
+from .serializers import AssetBulkUpdateSerializer
+
+
class AssetGroupSerializer(serializers.ModelSerializer):
class Meta:
model = AssetGroup
- # exclude = [
- # 'password', 'first_name', 'last_name', 'secret_key_otp',
- # 'private_key', 'public_key', 'avatar',
- # ]
class AssetSerializer(serializers.ModelSerializer):
@@ -45,10 +48,44 @@ class IDCViewSet(viewsets.ReadOnlyModelViewSet):
"""API endpoint that allows IDC to be viewed or edited."""
queryset = IDC.objects.all()
serializer_class = IDCSerializer
+ permission_classes = (IsSuperUser,)
+
class AssetListUpdateApi(BulkDeleteApiMixin, ListBulkCreateUpdateDestroyAPIView):
queryset = Asset.objects.all()
serializer_class = AssetBulkUpdateSerializer
+ permission_classes = (IsSuperUser,)
+
+
+class SystemUserAuthApi(APIView):
+ permission_classes = (IsSuperUserOrTerminalUser,)
+
+ def get(self, request, *args, **kwargs):
+ system_user_id = request.query_params.get('system_user_id', -1)
+ system_user_username = request.query_params.get('system_user_username', '')
+
+ system_user = get_object_or_none(SystemUser, id=system_user_id, username=system_user_username)
+
+ if system_user:
+ if system_user.password:
+ password = signer.sign(system_user.password)
+ else:
+ password = signer.sign('')
+
+ if system_user.private_key:
+ private_key = signer.sign(system_user.private_key)
+ else:
+ private_key = signer.sign(None)
+
+ response = {
+ 'id': system_user.id,
+ 'password': password,
+ 'private_key': private_key,
+ }
+
+ return Response(response)
+ else:
+ return Response({'msg': 'error system user id or username'}, status=401)
diff --git a/apps/assets/forms.py b/apps/assets/forms.py
index 8019645a8..5ec97d042 100644
--- a/apps/assets/forms.py
+++ b/apps/assets/forms.py
@@ -38,16 +38,14 @@ class AssetCreateForm(forms.ModelForm):
self.instance.tags.clear()
self.instance.tags.add(*tuple(tags))
-
class Meta:
model = Asset
-
+ tags = forms.ModelMultipleChoiceField(queryset=Tag.objects.all())
fields = [
'hostname', 'ip', 'port', 'type', 'comment', 'admin_user', 'system_users', 'idc', 'groups',
'other_ip', 'remote_card_ip', 'mac_address', 'brand', 'cpu', 'memory', 'disk', 'os', 'cabinet_no',
'cabinet_pos', 'number', 'status', 'env', 'sn', 'tags',
]
- tags = forms.ModelMultipleChoiceField(queryset=Tag.objects.all())
widgets = {
'groups': forms.SelectMultiple(attrs={'class': 'select2',
'data-placeholder': _('Select asset groups')}),
@@ -60,6 +58,8 @@ class AssetCreateForm(forms.ModelForm):
help_texts = {
'hostname': '* required',
'ip': '* required',
+ 'system_users': _('System user will be granted for user to login assets (using ansible create automatic)'),
+ 'admin_user': _('Admin user should be exist on asset already, And have sudo ALL permission'),
'tags': '最多5个标签,单个标签最长8个汉字,按回车确认'
}
@@ -243,7 +243,7 @@ class SystemUserForm(forms.ModelForm):
# Todo: Validate private key file, and generate public key
# Todo: Auto generate private key and public key
if private_key_file:
- system_user.private_key = private_key_file.read()
+ system_user.private_key = private_key_file.read().strip()
system_user.save()
return self.instance
@@ -264,6 +264,7 @@ class SystemUserForm(forms.ModelForm):
'auth_update': 'Auto update system user ssh key',
}
+
class AssetTagForm(forms.ModelForm):
assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(),
label=_('Asset'),
diff --git a/apps/assets/hands.py b/apps/assets/hands.py
index 70dedfeb4..acf0db52e 100644
--- a/apps/assets/hands.py
+++ b/apps/assets/hands.py
@@ -12,4 +12,5 @@
from users.utils import AdminUserRequiredMixin
+from users.backends import IsSuperUserOrTerminalUser, IsSuperUser
from users.models import User, UserGroup
diff --git a/apps/assets/models.py b/apps/assets/models.py
index db9f15a7e..1103d0b4c 100644
--- a/apps/assets/models.py
+++ b/apps/assets/models.py
@@ -7,7 +7,7 @@ from django.core import serializers
import logging
from django.utils.translation import ugettext_lazy as _
-from common.utils import encrypt, decrypt
+from common.utils import signer
logger = logging.getLogger(__name__)
@@ -111,23 +111,23 @@ class AdminUser(models.Model):
@password.setter
def password(self, password_raw):
- self._password = encrypt(password_raw)
+ self._password = signer.sign(password_raw)
@property
def private_key(self):
- return decrypt(self._private_key)
+ return signer.unsign(self._private_key)
@private_key.setter
def private_key(self, private_key_raw):
- self._private_key = encrypt(private_key_raw)
+ self._private_key = signer.sign(private_key_raw)
@property
def public_key(self):
- return decrypt(self._public_key)
+ return signer.unsign(self._public_key)
@public_key.setter
def public_key(self, public_key_raw):
- self._public_key = encrypt(public_key_raw)
+ self._public_key = signer.sign(public_key_raw)
class Meta:
db_table = 'admin_user'
@@ -179,27 +179,27 @@ class SystemUser(models.Model):
@property
def password(self):
- return decrypt(self._password)
+ return signer.unsign(self._password)
@password.setter
def password(self, password_raw):
- self._password = encrypt(password_raw)
+ self._password = signer.sign(password_raw)
@property
def private_key(self):
- return decrypt(self._private_key)
+ return signer.unsign(self._private_key)
@private_key.setter
def private_key(self, private_key_raw):
- self._private_key = encrypt(private_key_raw)
+ self._private_key = signer.sign(private_key_raw)
@property
def public_key(self):
- return decrypt(self._public_key)
+ return signer.unsign(self._public_key)
@public_key.setter
def public_key(self, public_key_raw):
- self._public_key = encrypt(public_key_raw)
+ self._public_key = signer.sign(public_key_raw)
def get_assets_inherit_from_asset_groups(self):
assets = set()
@@ -289,10 +289,10 @@ def get_default_idc():
class Asset(models.Model):
- ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'))
+ ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True)
other_ip = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('Other IP'))
remote_card_ip = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Remote card IP'))
- hostname = models.CharField(max_length=128, blank=True, verbose_name=_('Hostname'))
+ hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname'))
port = models.IntegerField(default=22, verbose_name=_('Port'))
groups = models.ManyToManyField(AssetGroup, blank=True, related_name='assets', verbose_name=_('Asset groups'))
admin_user = models.ForeignKey(AdminUser, null=True, blank=True, related_name='assets',
diff --git a/apps/assets/serializers.py b/apps/assets/serializers.py
index 59bbde18f..f5b53fb68 100644
--- a/apps/assets/serializers.py
+++ b/apps/assets/serializers.py
@@ -5,6 +5,7 @@ from .models import AssetGroup, Asset, IDC, AssetExtend
from common.mixins import BulkDeleteApiMixin
from rest_framework_bulk import BulkListSerializer, BulkSerializerMixin
+
class AssetBulkUpdateSerializer(BulkSerializerMixin, serializers.ModelSerializer):
# group_display = serializers.SerializerMethodField()
# active_display = serializers.SerializerMethodField()
diff --git a/apps/assets/templates/assets/admin_user_detail.html b/apps/assets/templates/assets/admin_user_detail.html
index b02cde2c0..85dba09ef 100644
--- a/apps/assets/templates/assets/admin_user_detail.html
+++ b/apps/assets/templates/assets/admin_user_detail.html
@@ -18,6 +18,9 @@
{% trans 'Detail' %}
+
+ Update
+
diff --git a/apps/assets/templates/assets/asset_detail.html b/apps/assets/templates/assets/asset_detail.html
index fcb04d049..bcb3560ce 100644
--- a/apps/assets/templates/assets/asset_detail.html
+++ b/apps/assets/templates/assets/asset_detail.html
@@ -22,6 +22,9 @@
{% trans 'Asset login log' %}
+
+ Update
+
@@ -54,6 +57,14 @@
{% trans 'IP' %}: |
{{ asset.ip }} |
+
+ {% trans 'Admin user' %}: |
+ {% if asset.admin_user %}
+ {{ asset.admin_user.name }} |
+ {% else %}
+ None |
+ {% endif %}
+
{% trans 'Other IP' %}: |
{{ asset.other_ip }} |
@@ -173,7 +184,15 @@
-
+
+ {% trans 'Repush system users' %}: |
+
+
+
+
+ |
+
+
@@ -215,6 +234,41 @@
+
+
+ {% trans 'Asset groups' %}
+
+
+
+
+
+ {% for system_user in system_users %}
+
+ {{ system_user.name }} |
+
+
+ |
+
+ {% endfor %}
+
+
+
+
diff --git a/apps/assets/templates/assets/asset_group_detail.html b/apps/assets/templates/assets/asset_group_detail.html
index 23a9e424b..50cf2a4a5 100644
--- a/apps/assets/templates/assets/asset_group_detail.html
+++ b/apps/assets/templates/assets/asset_group_detail.html
@@ -15,9 +15,11 @@
diff --git a/apps/assets/templates/assets/system_user_detail.html b/apps/assets/templates/assets/system_user_detail.html
index 68b00a0e8..4367b1c3a 100644
--- a/apps/assets/templates/assets/system_user_detail.html
+++ b/apps/assets/templates/assets/system_user_detail.html
@@ -23,6 +23,9 @@
{% trans 'Associate assets and asset groups' %}
+
+ Update
+
diff --git a/apps/assets/urls.py b/apps/assets/urls.py
index 50c4669cb..825b3e4ab 100644
--- a/apps/assets/urls.py
+++ b/apps/assets/urls.py
@@ -64,10 +64,10 @@ urlpatterns = [
]
urlpatterns += [
- #json
url(r'^v1/assets/$', api.AssetViewSet.as_view({'get':'list'}), name='assets-list-api'),
url(r'^v1/assets_bulk/$', api.AssetListUpdateApi.as_view(), name='asset-bulk-update-api'),
url(r'^v1/idc/$', api.IDCViewSet.as_view({'get':'list'}), name='idc-list-json'),
+ url(r'^v1/system-user/auth/', api.SystemUserAuthApi.as_view(), name='system-user-auth'),
]
diff --git a/apps/assets/views.py b/apps/assets/views.py
index f0b91c195..f15612de8 100644
--- a/apps/assets/views.py
+++ b/apps/assets/views.py
@@ -44,8 +44,6 @@ class AssetListView(AdminUserRequiredMixin, ListView):
return super(AssetListView, self).get_context_data(**kwargs)
-
-
class AssetCreateView(AdminUserRequiredMixin,CreateAssetTagsMiXin,CreateView):
model = Asset
tag_type = 'asset'
@@ -182,12 +180,16 @@ class AssetDetailView(DetailView):
def get_context_data(self, **kwargs):
asset_groups = self.object.groups.all()
+ system_users = self.object.system_users.all()
context = {
'app': 'Assets',
'action': 'Asset detail',
'asset_groups_remain': [asset_group for asset_group in AssetGroup.objects.all()
- if asset_group not in asset_groups],
+ if asset_group not in asset_groups],
'asset_groups': asset_groups,
+ 'system_users_remain': [system_user for system_user in SystemUser.objects.all()
+ if system_user not in system_users],
+ 'system_users': system_users,
}
kwargs.update(context)
return super(AssetDetailView, self).get_context_data(**kwargs)
diff --git a/apps/audits/hands.py b/apps/audits/hands.py
index f530b5e78..36358cbf5 100644
--- a/apps/audits/hands.py
+++ b/apps/audits/hands.py
@@ -1,5 +1,7 @@
# ~*~ coding: utf-8 ~*~
#
+from users.models import User
+from assets.models import Asset, SystemUser
from users.backends import IsSuperUserOrTerminalUser
from terminal.models import Terminal
diff --git a/apps/audits/models.py b/apps/audits/models.py
index 015f0bfb7..a98178a0d 100644
--- a/apps/audits/models.py
+++ b/apps/audits/models.py
@@ -71,7 +71,7 @@ class ProxyLog(models.Model):
class CommandLog(models.Model):
- proxy_log = models.ForeignKey(ProxyLog, on_delete=models.CASCADE, related_name='command_log')
+ proxy_log = models.ForeignKey(ProxyLog, on_delete=models.CASCADE, related_name='commands')
command_no = models.IntegerField()
command = models.CharField(max_length=1000, blank=True)
output = models.TextField(blank=True)
@@ -82,7 +82,10 @@ class CommandLog(models.Model):
@property
def output_decode(self):
- return base64.b64decode(self.output).replace('\n', '
')
+ try:
+ return base64.b64decode(self.output).replace('\n', '
')
+ except UnicodeDecodeError:
+ return 'UnicodeDecodeError'
class Meta:
db_table = 'command_log'
diff --git a/apps/audits/serializers.py b/apps/audits/serializers.py
index 881f84666..4d02ef5b4 100644
--- a/apps/audits/serializers.py
+++ b/apps/audits/serializers.py
@@ -14,7 +14,8 @@ class ProxyLogSerializer(serializers.ModelSerializer):
class Meta:
model = models.ProxyLog
fields = ['id', 'name', 'username', 'hostname', 'ip', 'system_user', 'login_type', 'terminal',
- 'log_file', 'was_failed', 'is_finished', 'date_start', 'time', 'command_length', "commands_dict"]
+ 'log_file', 'was_failed', 'is_finished', 'date_start', 'date_finished', 'time',
+ 'command_length', "commands_dict"]
@staticmethod
def get_time(obj):
@@ -25,7 +26,7 @@ class ProxyLogSerializer(serializers.ModelSerializer):
@staticmethod
def get_command_length(obj):
- return len(obj.command_log.all())
+ return len(obj.commands.all())
class CommandLogSerializer(serializers.ModelSerializer):
diff --git a/apps/audits/templates/audits/command_log_list.html b/apps/audits/templates/audits/command_log_list.html
index 6682273af..19a9a63e6 100644
--- a/apps/audits/templates/audits/command_log_list.html
+++ b/apps/audits/templates/audits/command_log_list.html
@@ -3,10 +3,61 @@
{% load static %}
{% load common_tags %}
{% block content_left_head %}
-{#
{% trans "Create permission" %} #}
+
{% endblock %}
+{% block table_search %}
+
+{% endblock %}
{% block table_container %}