[0-9]+)/delete/$', views.AssetTagDeleteView.as_view(), name='asset-tag-delete'),
-
# Resource idc url
url(r'^idc/$', views.IDCListView.as_view(), name='idc-list'),
url(r'^idc/create/$', views.IDCCreateView.as_view(), name='idc-create'),
diff --git a/apps/assets/utils.py b/apps/assets/utils.py
index 4eeb3ed65..cd064e942 100644
--- a/apps/assets/utils.py
+++ b/apps/assets/utils.py
@@ -1,40 +1,3 @@
# ~*~ coding: utf-8 ~*~
#
-from rest_framework import serializers
-from models import Tag
-from django.views.generic.edit import CreateView
-
-class CreateAssetTagsMiXin(CreateView):
- def get_form_kwargs(self):
- tags_list = self.request.POST.getlist('tags')
- kwargs = {
- 'initial': self.get_initial(),
- 'prefix': self.get_prefix(),
- }
- if self.request.method in ('POST', 'PUT'):
- post_data = self.request.POST.copy()
- if post_data.has_key('tags'):
- post_data.pop('tags')
- for t in tags_list:
- try:
- oTag = Tag.objects.get(pk=int(t))
- except (Tag.DoesNotExist, UnicodeEncodeError):
- oTag = Tag(name=t, created_by=self.request.user.username or 'Admin')
- oTag.save()
- post_data.update({'tags':oTag.pk})
- else:
- post_data.update({'tags':int(t)})
- kwargs.update({
- 'data': post_data,
- 'files': self.request.FILES,
- })
- return kwargs
-
-
-class UpdateAssetTagsMiXin(CreateAssetTagsMiXin):
- def get_form_kwargs(self):
- kwargs = super(UpdateAssetTagsMiXin, self).get_form_kwargs()
- if hasattr(self, 'object'):
- kwargs.update({'instance': self.object})
- return kwargs
\ No newline at end of file
diff --git a/apps/assets/views.py b/apps/assets/views.py
index e89500c75..51850a5d6 100644
--- a/apps/assets/views.py
+++ b/apps/assets/views.py
@@ -25,9 +25,8 @@ from django.utils import timezone
from common.mixins import JSONResponseMixin
from common.utils import get_object_or_none
-from .utils import CreateAssetTagsMiXin, UpdateAssetTagsMiXin
from . import forms
-from .models import Asset, AssetGroup, AdminUser, IDC, SystemUser, Tag
+from .models import Asset, AssetGroup, AdminUser, IDC, SystemUser
from .hands import AdminUserRequiredMixin
@@ -40,16 +39,13 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
'action': 'asset list',
'groups': AssetGroup.objects.all(),
'system_users': SystemUser.objects.all(),
- 'tag_list': [(i.id, i.name, i.assets.all().count())for i in Tag.objects.all().order_by('name')],
- 'tags': Tag.objects.all().order_by('name')
}
kwargs.update(context)
return super(AssetListView, self).get_context_data(**kwargs)
-class AssetCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, CreateView):
+class AssetCreateView(AdminUserRequiredMixin, CreateView):
model = Asset
- tag_type = 'asset'
form_class = forms.AssetCreateForm
template_name = 'assets/asset_create.html'
success_url = reverse_lazy('assets:asset-list')
@@ -69,7 +65,7 @@ class AssetCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, CreateView):
return super(AssetCreateView, self).get_context_data(**kwargs)
-class AssetModalCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, ListView):
+class AssetModalCreateView(AdminUserRequiredMixin, ListView):
model = Asset
form_class = forms.AssetCreateForm
template_name = 'assets/asset_modal_update.html'
@@ -97,31 +93,11 @@ class AssetModalCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, ListVie
return super(AssetModalCreateView, self).get_context_data(**kwargs)
-class AssetUpdateView(AdminUserRequiredMixin, UpdateAssetTagsMiXin, UpdateView):
+class AssetUpdateView(AdminUserRequiredMixin, UpdateView):
model = Asset
form_class = forms.AssetUpdateForm
template_name = 'assets/asset_update.html'
success_url = reverse_lazy('assets:asset-list')
- # new_form = ''
- # assets_ids = ''
-
- # def post(self, request, *args, **kwargs):
- # default_keys = [
- # 'csrfmiddlewaretoken',
- # 'assets_ids',
- # 'ip',
- # 'number',
- # 'hostname',
- # 'system_users',
- # 'admin_user',
- # ]
- # self.assets_ids = self.request.POST.getlist('assets_ids')
- # self.new_form = self.request.POST.copy()
- # for i in default_keys:
- # if self.new_form.has_key(i):
- # self.new_form.pop(i)
-
- # return super(AssetUpdateView, self).post(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = {
@@ -135,26 +111,6 @@ class AssetUpdateView(AdminUserRequiredMixin, UpdateAssetTagsMiXin, UpdateView):
print(form.errors)
return super(AssetUpdateView, self).form_invalid(form)
- # def form_valid(self, form):
- # asset = form.save(commit=False)
- #
- # def prn_obj_key(obj_form):
- # return obj_form.clean().keys()
- #
- # for i in prn_obj_key(form):
- # if i not in self.new_form.keys():
- # print i
-
- #delattr(asset, '"%s" % i')
- #del asset.i
- # asset.save()
- # asset.id = 27
- # # asset.created_by = self.request.user.username or 'Admin'
- # asset.save()
- # asset.id = 28
- # asset.save()
- # return super(AssetUpdateView, self).form_valid(form)
-
class AssetDeleteView(DeleteView):
model = Asset
@@ -192,7 +148,6 @@ class AssetModalListView(AdminUserRequiredMixin, ListView):
def get_context_data(self, **kwargs):
group_id = self.request.GET.get('group_id')
- tag_id = self.request.GET.get('tag_id')
plain_id_lists = self.request.GET.get('plain_id_lists')
self.s = self.request.GET.get('plain_id_lists')
assets = Asset.objects.all()
@@ -208,24 +163,15 @@ class AssetModalListView(AdminUserRequiredMixin, ListView):
plain_id_lists = [int(self.s)]
context = {
'all_assets': plain_id_lists,
- 'assets': assets
}
kwargs.update(context)
if group_id:
group = AssetGroup.objects.get(id=group_id)
- print group
context = {
'all_assets': [x.id for x in group.assets.all()],
'assets': assets
}
kwargs.update(context)
- if tag_id:
- tag = Tag.objects.get(id=tag_id)
- context = {
- 'all_assets': [x.id for x in tag.asset_set.all()],
- 'assets': assets
- }
- kwargs.update(context)
else:
context = {
'assets': assets
@@ -315,7 +261,6 @@ class AssetGroupUpdateView(AdminUserRequiredMixin, UpdateView):
'assets_on_list': assets_all,
'assets_count': len(assets_all),
'group_id': self.object.id,
- 'tags': Tag.objects.all()
}
kwargs.update(context)
return super(AssetGroupUpdateView, self).get_context_data(**kwargs)
@@ -401,7 +346,6 @@ class IDCAssetsView(AdminUserRequiredMixin, DetailView):
'action': _('Asset detail'),
'groups': AssetGroup.objects.all(),
'system_users': SystemUser.objects.all(),
- 'tags': Tag.objects.all(),
'assets_remain': assets_remain,
'assets': [asset for asset in Asset.objects.all() if asset not in assets_remain],
}
@@ -626,123 +570,8 @@ class SystemUserAssetView(AdminUserRequiredMixin, SingleObjectMixin, ListView):
return super(SystemUserAssetView, self).get_context_data(**kwargs)
-class TagView(ListView):
- context_object_name = 'asset_list'
- template_name = 'assets/asset_list.html'
-
- def get_queryset(self):
- asset_list = Asset.objects.filter(tags=self.kwargs['tag_id'])
- return asset_list
-
- def get_context_data(self, **kwargs):
- kwargs['app'] = 'Assets'
- kwargs['action']='asset list'
- kwargs['tag_list'] = [(i.id,i.name,i.asset_set.all().count() )for i in Tag.objects.all().order_by('name')]
- kwargs['tag_id'] = self.kwargs['tag_id']
- return super(TagView, self).get_context_data(**kwargs)
-
-
-class TagsListView(AdminUserRequiredMixin, ListView):
- model = Tag
- paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
- context_object_name = 'asset_tags_list'
- template_name = 'assets/asset_tags_list.html'
- ordering = '-id'
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': _('Tag'),
- 'action': _('Asset Tags list'),
- 'keyword': self.request.GET.get('keyword', '')
- }
- kwargs.update(context)
- return super(TagsListView, self).get_context_data(**kwargs)
-
-
-class AssetTagCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, CreateView):
- model = Tag
- form_class = forms.AssetTagForm
- template_name = 'assets/asset_tag_create.html'
- success_url = reverse_lazy('assets:asset-tag-list')
- #ordering = '-id'
-
- # Todo: Asset group create template select assets so hard, need be resolve next
-
- def get_context_data(self, **kwargs):
- context = {
- 'app': _('Tag'),
- 'action': _('Asset Tags list'),
- 'assets_count': 0,
- }
- kwargs.update(context)
- return super(AssetTagCreateView, self).get_context_data(**kwargs)
-
- def form_valid(self, form):
- asset_tag = form.save()
- assets_id_list = self.request.POST.getlist('assets', [])
- assets = [get_object_or_404(Asset, id=int(asset_id)) for asset_id in assets_id_list]
- asset_tag.created_by = self.request.user.username or 'Admin'
- asset_tag.assets.add(*tuple(assets))
- asset_tag.save()
- return super(AssetTagCreateView, self).form_valid(form)
-
-
-class AssetTagDetailView(SingleObjectMixin, AdminUserRequiredMixin, ListView):
- template_name = 'assets/asset_tag_detail.html'
- paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
-
- def get(self, request, *args, **kwargs):
- self.object = self.get_object(queryset=Tag.objects.all())
- return super(AssetTagDetailView, self).get(request, *args, **kwargs)
-
- def get_queryset(self):
- return self.object.assets.all()
-
- def get_context_data(self, **kwargs):
- assets_remain = Asset.objects.exclude(id__in=self.object.assets.all())
- context = {
- 'app': _('Tag'),
- 'action': _('Asset Tags detail'),
- 'asset_tag': self.object,
- 'assets_remain': assets_remain,
- 'assets': [asset for asset in Asset.objects.all() if asset not in assets_remain]
- }
- kwargs.update(context)
- return super(AssetTagDetailView, self).get_context_data(**kwargs)
-
-
-class AssetTagUpdateView(AdminUserRequiredMixin, UpdateView):
- model = Tag
- form_class = forms.AssetTagForm
- template_name = 'assets/asset_tag_create.html'
- success_url = reverse_lazy('assets:asset-tag-list')
-
- def get(self, request, *args, **kwargs):
- self.object = self.get_object(queryset=Tag.objects.all())
- return super(AssetTagUpdateView, self).get(request, *args, **kwargs)
-
- def get_context_data(self, **kwargs):
- assets_all = self.object.assets.all()
- context = {
- 'app': _('Tag'),
- 'action': _('Asset Tags detail'),
- 'assets_count': len(assets_all),
- 'assets_on_list': assets_all,
- 'tag_id':self.object.id,
- }
- kwargs.update(context)
- return super(AssetTagUpdateView, self).get_context_data(**kwargs)
-
-
-class AssetTagDeleteView(AdminUserRequiredMixin, DeleteView):
- template_name = 'assets/delete_confirm.html'
- model = Tag
- success_url = reverse_lazy('assets:asset-tag-list')
-
-
@method_decorator(csrf_exempt, name='dispatch')
class AssetExportView(View):
-
@staticmethod
def get_asset_attr(asset, attr):
if attr in ['admin_user', 'idc']:
diff --git a/apps/audits/api.py b/apps/audits/api.py
index 302fc3a69..d8a7b21de 100644
--- a/apps/audits/api.py
+++ b/apps/audits/api.py
@@ -90,8 +90,3 @@ class RecordLogViewSet(BulkModelViewSet):
else:
return record_store.all()
-
-
-
-
-
diff --git a/apps/audits/templates/audits/command_log_list.html b/apps/audits/templates/audits/command_log_list.html
index 3ed7d5d0b..04bb976fb 100644
--- a/apps/audits/templates/audits/command_log_list.html
+++ b/apps/audits/templates/audits/command_log_list.html
@@ -23,18 +23,18 @@
-
-
+
{% for a in asset_list %}
-
+
{% endfor %}
diff --git a/apps/audits/templates/audits/proxy_log_detail.html b/apps/audits/templates/audits/proxy_log_detail.html
index 909d66fe6..0fa28b517 100644
--- a/apps/audits/templates/audits/proxy_log_detail.html
+++ b/apps/audits/templates/audits/proxy_log_detail.html
@@ -1,6 +1,7 @@
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
+{% load common_tags %}
{% block custom_head_css_js %}
diff --git a/apps/audits/templates/audits/proxy_log_offline_list.html b/apps/audits/templates/audits/proxy_log_offline_list.html
new file mode 100644
index 000000000..ffe695662
--- /dev/null
+++ b/apps/audits/templates/audits/proxy_log_offline_list.html
@@ -0,0 +1,159 @@
+{% extends '_base_list.html' %}
+{% load i18n %}
+{% load static %}
+{% block content_left_head %}
+
+
+{% endblock %}
+
+
+{% block table_search %}
+
+{% 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_list.html b/apps/audits/templates/audits/proxy_log_online_list.html
similarity index 94%
rename from apps/audits/templates/audits/proxy_log_list.html
rename to apps/audits/templates/audits/proxy_log_online_list.html
index 6a3c815b0..500fe68b3 100644
--- a/apps/audits/templates/audits/proxy_log_list.html
+++ b/apps/audits/templates/audits/proxy_log_online_list.html
@@ -24,16 +24,16 @@
- {% for user in user_list %}
-
+ {% for u in user_list %}
+
{% endfor %}
- {% for asset in asset_list %}
-
+ {% for a in asset_list %}
+
{% endfor %}
@@ -68,7 +68,7 @@
{% trans 'Command' %} |
{% trans 'Success' %} |
{% trans 'Finished' %} |
- {% trans 'R/M' %} |
+ {% trans 'Monitor' %} |
{% trans 'Date start' %} |
{% trans 'Time' %} |
{% endblock %}
diff --git a/apps/audits/urls/views_urls.py b/apps/audits/urls/views_urls.py
index d28882704..1ad6439b3 100644
--- a/apps/audits/urls/views_urls.py
+++ b/apps/audits/urls/views_urls.py
@@ -4,14 +4,16 @@ from .. import views
app_name = 'audits'
urlpatterns = [
- url(r'^proxy-log$', views.ProxyLogListView.as_view(),
- name='proxy-log-list'),
- url(r'^proxy-log/(?P\d+)$', views.ProxyLogDetailView.as_view(),
+ 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\d+)/$', views.ProxyLogDetailView.as_view(),
name='proxy-log-detail'),
# url(r'^proxy-log/(?P\d+)/commands$', views.ProxyLogCommandsListView.as_view(), name='proxy-log-commands-list'),
- url(r'^command-log$', views.CommandLogListView.as_view(),
+ url(r'^command-log/$', views.CommandLogListView.as_view(),
name='command-log-list'),
- url(r'^login-log$', views.LoginLogListView.as_view(),
+ url(r'^login-log/$', views.LoginLogListView.as_view(),
name='login-log-list'),
]
diff --git a/apps/audits/views.py b/apps/audits/views.py
index 20bc3f8aa..de7cc9421 100644
--- a/apps/audits/views.py
+++ b/apps/audits/views.py
@@ -3,7 +3,6 @@
import time
from datetime import datetime
-import pytz
from django.views.generic import ListView, UpdateView, DeleteView, DetailView, TemplateView
from django.views.generic.edit import SingleObjectMixin
from django.utils.translation import ugettext as _
@@ -22,10 +21,10 @@ from audits.backends import CommandLogSerializer
class ProxyLogListView(AdminUserRequiredMixin, ListView):
model = ProxyLog
- template_name = 'audits/proxy_log_list.html'
+ template_name = 'audits/proxy_log_online_list.html'
context_object_name = 'proxy_log_list'
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
- keyword = user = asset = system_user = date_from_s = date_to_s = ''
+ keyword = username = hostname = system_user = date_from_s = date_to_s = ''
ordering = ['is_finished', '-id']
date_format = '%m/%d/%Y'
@@ -37,8 +36,8 @@ class ProxyLogListView(AdminUserRequiredMixin, ListView):
self.queryset = super(ProxyLogListView, self).get_queryset()
self.keyword = self.request.GET.get('keyword', '')
- self.user = self.request.GET.get('user')
- self.asset = self.request.GET.get('asset')
+ 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)
@@ -53,10 +52,10 @@ class ProxyLogListView(AdminUserRequiredMixin, ListView):
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.user:
- filter_kwargs['user'] = self.user
- if self.asset:
- filter_kwargs['asset'] = self.asset
+ if self.username:
+ filter_kwargs['user'] = self.username
+ if self.ip:
+ filter_kwargs['ip'] = self.ip
if self.system_user:
filter_kwargs['system_user'] = self.system_user
if self.keyword:
@@ -81,14 +80,46 @@ class ProxyLogListView(AdminUserRequiredMixin, ListView):
'keyword': self.keyword,
'date_from': self.date_from_s,
'date_to': self.date_to_s,
- 'user': self.user,
- 'asset': self.asset,
+ '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):
@@ -131,7 +162,7 @@ class CommandLogListView(AdminUserRequiredMixin, ListView):
template_name = 'audits/command_log_list.html'
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
context_object_name = 'command_list'
- user = asset = system_user = command = date_from_s = date_to_s = ''
+ username = ip = system_user = command = date_from_s = date_to_s = ''
date_format = '%m/%d/%Y'
ordering = ['-id']
@@ -141,8 +172,8 @@ class CommandLogListView(AdminUserRequiredMixin, ListView):
date_from_default = (date_now - timezone.timedelta(7)) \
.strftime(self.date_format)
self.command = self.request.GET.get('command', '')
- self.user = self.request.GET.get('user')
- self.asset = self.request.GET.get('asset')
+ 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)
@@ -162,10 +193,10 @@ class CommandLogListView(AdminUserRequiredMixin, ListView):
.replace(tzinfo=timezone.get_current_timezone())
date_to_ts = time.mktime(date_to.timetuple())
filter_kwargs['date_to_ts'] = date_to_ts
- if self.user:
- filter_kwargs['user'] = self.user
- if self.asset:
- filter_kwargs['asset'] = self.asset
+ 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:
@@ -183,8 +214,8 @@ class CommandLogListView(AdminUserRequiredMixin, ListView):
'command': self.command,
'date_from': self.date_from_s,
'date_to': self.date_to_s,
- 'user': self.user,
- 'asset': self.asset,
+ 'username': self.username,
+ 'ip': self.ip,
'system_user': self.system_user,
}
kwargs.update(context)
diff --git a/apps/common/utils.py b/apps/common/utils.py
index 3e543a107..1fa8e3915 100644
--- a/apps/common/utils.py
+++ b/apps/common/utils.py
@@ -2,6 +2,7 @@
#
from __future__ import unicode_literals
+from collections import OrderedDict
from six import string_types
import base64
import os
@@ -53,6 +54,7 @@ def get_object_or_none(model, **kwargs):
class Signer(object):
+ """用来加密,解密,和基于时间戳的方式验证token"""
def __init__(self, secret_key=SECRET_KEY):
self.secret_key = secret_key
@@ -330,13 +332,13 @@ def encrypt_password(password):
return None
-from collections import OrderedDict
def capacity_convert(size, expect='auto', rate=1000):
"""
- :param cap: '100MB', '1G'
+ :param size: '100MB', '1G'
:param expect: 'K, M, G, T
+ :param rate: Default 1000, may be 1024
:return:
"""
rate_mapping = (
diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py
index 758a93221..ed919cb47 100644
--- a/apps/jumpserver/settings.py
+++ b/apps/jumpserver/settings.py
@@ -320,8 +320,9 @@ CACHES = {
}
# Captcha settings, more see https://django-simple-captcha.readthedocs.io/en/latest/advanced.html
-CAPTCHA_IMAGE_SIZE = (75, 33)
+CAPTCHA_IMAGE_SIZE = (80, 33)
CAPTCHA_FOREGROUND_COLOR = '#001100'
+CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_dots',)
COMMAND_STORE_BACKEND = 'audits.backends.command.db'
RECORD_STORE_BACKEND = 'audits.backends.record.db'
diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py
index e9b2496d8..5c421e916 100644
--- a/apps/ops/ansible/inventory.py
+++ b/apps/ops/ansible/inventory.py
@@ -21,16 +21,16 @@ class JMSHost(Host):
# 添加密码和秘钥
if asset.get('password'):
self.set_variable('ansible_ssh_pass', asset['password'])
- if asset.get('key'):
+ if asset.get('private_key'):
self.set_variable('ansible_ssh_private_key_file', asset['private_key'])
# 添加become支持
- become = asset.get("become", None)
- if become is not None:
+ become = asset.get("become", False)
+ if become:
self.set_variable("ansible_become", True)
- self.set_variable("ansible_become_method", become.get('method'))
- self.set_variable("ansible_become_user", become.get('user'))
- self.set_variable("ansible_become_pass", become.get('pass'))
+ self.set_variable("ansible_become_method", become.get('method', 'sudo'))
+ self.set_variable("ansible_become_user", become.get('user', 'root'))
+ self.set_variable("ansible_become_pass", become.get('pass', ''))
else:
self.set_variable("ansible_become", False)
diff --git a/apps/ops/ansible/runner.py b/apps/ops/ansible/runner.py
index 1af3d7a0d..6496c4202 100644
--- a/apps/ops/ansible/runner.py
+++ b/apps/ops/ansible/runner.py
@@ -265,8 +265,10 @@ class AdHocRunner(object):
result['success'].append(host)
for host, msgs in self.results_callback.result_q['dark'].items():
- msg = '\n'.join(['{}: {}'.format(msg.get('invocation', {}).get('module_name'),
- msg.get('msg', '')) for msg in msgs])
+ msg = '\n'.join(['{} {}: {}'.format(
+ msg.get('module_stdout', ''),
+ msg.get('invocation', {}).get('module_name'),
+ msg.get('msg', '')) for msg in msgs])
result['failed'].append((host, msg))
return result
diff --git a/apps/ops/api.py b/apps/ops/api.py
new file mode 100644
index 000000000..3a9e45b25
--- /dev/null
+++ b/apps/ops/api.py
@@ -0,0 +1,15 @@
+# ~*~ coding: utf-8 ~*~
+
+
+from rest_framework import viewsets
+
+from .hands import IsSuperUser
+from .models import Task
+from .serializers import TaskSerializer
+
+
+class TaskViewSet(viewsets.ModelViewSet):
+ queryset = Task.objects.all()
+ serializer_class = TaskSerializer
+ permission_classes = (IsSuperUser,)
+
diff --git a/apps/ops/api/__init__.py b/apps/ops/api/__init__.py
deleted file mode 100644
index c8b15abe0..000000000
--- a/apps/ops/api/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from views import *
\ No newline at end of file
diff --git a/apps/ops/api/exc.py b/apps/ops/api/exc.py
deleted file mode 100644
index 81deb805c..000000000
--- a/apps/ops/api/exc.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# ~*~ coding: utf-8 ~*~
-from __future__ import unicode_literals, print_function
-
-from rest_framework.exceptions import APIException
-from django.utils.translation import ugettext as _
-
-
-class ServiceUnavailable(APIException):
- status_code = default_code = 503
- default_detail = _('Service temporarily unavailable, try again later.')
-
-
-class ServiceNotImplemented(APIException):
- status_code = default_code = 501
- default_detail = _('This service maybe implemented in the future, but now not implemented!')
-
diff --git a/apps/ops/api/permissions.py b/apps/ops/api/permissions.py
deleted file mode 100644
index 0fc0d0861..000000000
--- a/apps/ops/api/permissions.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# ~*~ coding: utf-8 ~*~
-from __future__ import unicode_literals
-
-from rest_framework import permissions
-
-
-class AdminUserRequired(permissions.BasePermission):
- """
- Custom permission to only allow admin user to access the resource.
- """
-
- def has_object_permission(self, request, view, obj):
- # Read permissions are allowed to any request,
- # so we'll always allow GET, HEAD or OPTIONS requests.
- if request.method in permissions.SAFE_METHODS:
- return True
-
- # Write permissions are only allowed to the admin role.
- return request.user.is_staff
diff --git a/apps/ops/api/serializers.py b/apps/ops/api/serializers.py
deleted file mode 100644
index af472b3cb..000000000
--- a/apps/ops/api/serializers.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# ~*~ coding: utf-8 ~*~
-from __future__ import unicode_literals
-
-
diff --git a/apps/ops/api/views.py b/apps/ops/api/views.py
deleted file mode 100644
index affa9cdc7..000000000
--- a/apps/ops/api/views.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# ~*~ coding: utf-8 ~*~
-from __future__ import unicode_literals
-from rest_framework import viewsets
-
-from serializers import *
-from permissions import *
-
diff --git a/apps/ops/hands.py b/apps/ops/hands.py
new file mode 100644
index 000000000..d7175db18
--- /dev/null
+++ b/apps/ops/hands.py
@@ -0,0 +1,4 @@
+# ~*~ coding: utf-8 ~*~
+
+from users.permissions import IsSuperUser
+
diff --git a/apps/ops/serializers.py b/apps/ops/serializers.py
new file mode 100644
index 000000000..986ee66e6
--- /dev/null
+++ b/apps/ops/serializers.py
@@ -0,0 +1,13 @@
+# ~*~ coding: utf-8 ~*~
+from __future__ import unicode_literals
+from rest_framework import serializers
+
+from .models import Task
+
+
+class TaskSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Task
+ fields = '__all__'
+
+
diff --git a/apps/ops/templates/ops/task_detail.html b/apps/ops/templates/ops/task_detail.html
index a0f38e86c..bc8fbf682 100644
--- a/apps/ops/templates/ops/task_detail.html
+++ b/apps/ops/templates/ops/task_detail.html
@@ -68,7 +68,17 @@
{% trans 'Is success ' %}: |
+ {% if object.is_finished %}
{{ object.is_success|yesno:"Yes,No,Unkown" }} |
+ {% else %}
+
+
+
+ 40% Complete (success)
+
+
+ |
+ {% endif %}
{% trans 'Assets ' %}: |
@@ -84,6 +94,31 @@
+
+
+
+
+
+{{ object.result }}
+
+
+
+
diff --git a/apps/ops/templates/ops/task_list.html b/apps/ops/templates/ops/task_list.html
index cb64849a4..dac614805 100644
--- a/apps/ops/templates/ops/task_list.html
+++ b/apps/ops/templates/ops/task_list.html
@@ -35,7 +35,7 @@
{% endblock %}
{% block table_head %}
-
|
+
|
{% trans 'Name' %} |
{% trans 'Asset' %} |
{% trans 'Success' %} |
@@ -69,6 +69,7 @@
{{ object.timedelta }} s |
{% trans "Run again" %}
+ {% trans "Delete" %}
|
{% endfor %}
@@ -92,45 +93,14 @@
forceParse: false,
autoclose: true
});
+
+ }).on('click', '.btn-del', function () {
+ var $this = $(this);
+ var name = $(this).closest("tr").find(":nth-child(2)").children('a').html();
+ var uid = $this.data('uid');
+ var the_url = '{% url "api-ops:task-detail" pk=99991937 %}'.replace('99991937', uid);
+ objectDelete($this, name, the_url);
})
-{# function terminateConnection(data) {#}
-{# function success() {#}
-{# window.setTimeout(function () {#}
-{# window.location.reload()#}
-{# }, 300)#}
-{# }#}
-{# var the_url = "{% url 'api-applications:terminate-connection' %}";#}
-{# APIUpdateAttr({url: the_url, method: 'POST', body: JSON.stringify(data), success: success, success_message: 'Terminate success'});#}
-{# }#}
-{# $(document).ready(function() {#}
-{# $('table').DataTable({#}
-{# "searching": false,#}
-{# "paging": false,#}
-{# "bInfo" : false,#}
-{# "order": []#}
-{# });#}
-{# $('.select2').select2();#}
-{# $('#date .input-daterange').datepicker({#}
-{# dateFormat: 'mm/dd/yy',#}
-{# keyboardNavigation: false,#}
-{# forceParse: false,#}
-{# autoclose: true#}
-{# });#}
-{# }).on('click', '.btn-term', function () {#}
-{# var $this = $(this);#}
-{# var proxy_log_id = $this.attr('value');#}
-{# var data = {#}
-{# proxy_log_id: proxy_log_id#}
-{# };#}
-{# terminateConnection(data)#}
-{# }).on('click', '#btn_bulk_update', function () {#}
-{# var data = [];#}
-{# $('.cbx-term:checked').each(function () {#}
-{# data.push({proxy_log_id: $(this).attr('value')})#}
-{# });#}
-{# terminateConnection(data)#}
-{# })#}
-{# #}
{% endblock %}
diff --git a/apps/ops/urls/api_urls.py b/apps/ops/urls/api_urls.py
index d97d28a4a..c96bfb926 100644
--- a/apps/ops/urls/api_urls.py
+++ b/apps/ops/urls/api_urls.py
@@ -2,6 +2,12 @@
from __future__ import unicode_literals
from rest_framework.routers import DefaultRouter
+from .. import api
-urlpatterns = []
\ No newline at end of file
+router = DefaultRouter()
+router.register(r'v1/tasks', api.TaskViewSet, 'task')
+
+urlpatterns = []
+
+urlpatterns += router.urls
diff --git a/apps/ops/utils.py b/apps/ops/utils.py
index d1b5190dd..0c3cbbc99 100644
--- a/apps/ops/utils.py
+++ b/apps/ops/utils.py
@@ -18,7 +18,7 @@ logger = get_logger(__file__)
def run_AdHoc(task_tuple, assets,
task_name='Ansible AdHoc runner',
task_id=None, pattern='all',
- record=True, verbose=False):
+ record=True, verbose=True):
"""
:param task_tuple: (('module_name', 'module_args'), ('module_name', 'module_args'))
:param assets: [asset1, asset2]
@@ -51,6 +51,11 @@ def run_AdHoc(task_tuple, assets,
else:
record = Task.objects.get(uuid=task_id)
record.date_start = timezone.now()
+ record.date_finished = None
+ record.timedelta = None
+ record.is_finished = False
+ record.is_success = False
+ record.save()
ts_start = time.time()
if verbose:
logger.debug('Start runner {}'.format(task_name))
@@ -61,7 +66,7 @@ def run_AdHoc(task_tuple, assets,
record.date_finished = timezone.now()
record.is_finished = True
if verbose:
- record.result = json.dumps(result)
+ record.result = json.dumps(result, indent=4, sort_keys=True)
record.summary = json.dumps(summary)
record.timedelta = timedelta
if len(summary['failed']) == 0:
diff --git a/apps/ops/views.py b/apps/ops/views.py
index dadf71faf..145f72534 100644
--- a/apps/ops/views.py
+++ b/apps/ops/views.py
@@ -1,5 +1,6 @@
# ~*~ coding: utf-8 ~*~
from __future__ import unicode_literals
+import time
import json
from datetime import datetime
@@ -81,4 +82,5 @@ class TaskRunView(View):
def get(self, request, *args, **kwargs):
pk = kwargs.get(self.pk_url_kwarg)
rerun_task.delay(pk)
+ time.sleep(0.5)
return redirect(reverse('ops:task-detail', kwargs={'pk': pk}))
diff --git a/apps/perms/tasks.py b/apps/perms/tasks.py
index 50ced1ee3..6bef200cd 100644
--- a/apps/perms/tasks.py
+++ b/apps/perms/tasks.py
@@ -35,10 +35,10 @@ def push_users(self, assets, users):
('authorized_key', "user={} state=present key='{}'".format(
user['username'], user['public_key'])),
('lineinfile',
- "name=/etc/sudoers state=present regexp='^{0} ALL=(ALL)' "
+ "dest=/etc/sudoers state=present regexp='^{0} ALL=' "
"line='{0} ALL=(ALL) NOPASSWD: {1}' "
"validate='visudo -cf %s'".format(
- user['username'], user.get('sudo', '/bin/whoami')
+ user['username'], user.get('sudo', '/sbin/ifconfig')
))
])
task_name = 'Push user {}'.format(','.join([user['name'] for user in users]))
diff --git a/apps/templates/_footer.html b/apps/templates/_footer.html
index c43bda248..95f0f82d3 100644
--- a/apps/templates/_footer.html
+++ b/apps/templates/_footer.html
@@ -1,8 +1,9 @@
\ No newline at end of file
diff --git a/apps/templates/_nav.html b/apps/templates/_nav.html
index 6792a22b2..d0a2b9073 100644
--- a/apps/templates/_nav.html
+++ b/apps/templates/_nav.html
@@ -23,7 +23,6 @@
{% trans 'IDC' %}
{% trans 'Admin user' %}
{% trans 'System user' %}
- {% trans 'Label' %}
@@ -56,8 +55,11 @@
{% trans 'Audits' %}
-
-
- {% trans 'File' %}
-
-
-
-
-
- {% trans 'Settings' %}
-
-
+{##}
+{# #}
+{# {% trans 'File' %}#}
+{# #}
+{# #}
+{##}
+{##}
+{# #}
+{# {% trans 'Settings' %}#}
+{# #}
+{##}
{% trans 'Visit us' %}
diff --git a/docs/install.md b/docs/install.md
new file mode 100644
index 000000000..75aa80a15
--- /dev/null
+++ b/docs/install.md
@@ -0,0 +1,129 @@
+## Jumpserver v0.4.0 版本安装详细过程
+### 环境
+- 系统: CentOS 6.5 x86\_64 mini_ - Python: 版本 2.7.13 (未来支持 3.5)
+- 安装目录
+ - /opt/jumpserver
+ - /opt/coco
+
+#### 一. 环境准备
+**1.1 安装基本工具和库**
+```
+`$ yum -y install sqlite-devel git epel-release
+```
+`
+**1.2 安装Python**
+这里可以参考 [https://segmentfault.com/a/1190000000654227][1]
+也可以下载我编译的rpm版本:
+```
+`$ wget http://repo.jumpserver.org/python27-2.7.13-1.el6.x86_64.rpm_
+$ yum localinstall -y python27-2.7.13-1.el6.x86_64.rpm
+$ bash
+$ python2.7 -V
+Python 2.7.13
+```
+`
+#### 二. Jumpserver安装
+**2.1 下载仓库代码 **
+
+```
+`$ cd /opt
+$ git clone [https://github.com/jumpserver/jumpserver.git][2]
+$ cd jumpserver
+$ git checkout dev
+```
+`**2.1 安装依赖**
+
+```
+`$ cd requirements
+$ sudo yum -y install `cat rpm_requirements.txt`
+$ pip2.7 install -r requirements.txt -i https://pypi.doubanio.com/simple
+```
+`**2.3 准备配置文件 **
+
+```
+`$ cd ..
+$ cp config_example.py config.py
+$ vim config.py
+
+// 默认使用的是 DevelpmentConfig 所以应该去修改这部分
+class DevelopmentConfig(Config):
+EMAIL_HOST = 'smtp.exmail.qq.com'
+EMAIL_PORT = 465
+EMAIL_HOST_USER = 'ask@jumpserver.org'
+EMAIL_HOST_PASSWORD = 'xxx'
+EMAIL_USE_SSL = True // 端口是 465 设置 True 否则 False
+EMAIL_USE_TLS = False // 端口是 587 设置为 True 否则 False
+SITE_URL = 'http://localhost:8080' // 发送邮件会使用这个地址
+```
+`
+**2.4 初始化数据库**
+```
+`$ cd utils
+$ sh make_migrations.sh
+$ sh init_db.sh
+```
+`
+**2.5 安装redis server**
+```
+`$ yum -y install redis
+$ service redis start
+```
+`
+**2.6 启动**
+```
+`$ cd ..
+$ python2.7 run_server.py
+```
+`访问 http://ip:8080
+账号密码: admin admin
+
+**2.7 测试使用**
+- 创建用户
+ 会发送邮件,测试是否正常修改密码,登录
+
+- 创建管理用户
+ 创建一个管理用户, 创建资产时需要关联
+
+- 创建资产
+ 创建一个 资产,关联刚创建的管理用户
+
+- 创建系统用户
+ 系统用户是用来登录资产的,授权时需要
+
+- 创建授权规则
+ 关联用户,资产,系统用户 形成授权规则,授权的系统用户会自动推送到资产上
+
+
+#### 三. 安装 SSH SERVER - COCO
+**3.1 下载代码库**
+```
+`$ cd /opt
+$[git clone https://github.com/jumpserver/coco.git][3]
+```
+`
+**3.2 安装依赖**
+```
+`$ pip2.7 install -r requirements.txt -i https://pypi.doubanio.com/simple
+```
+`
+**3.3 启动**
+
+```
+`$ python2.7 run_server.py
+```
+`
+说明: Coco启动后会向jumpserver注册,请去 jumpserver页面 - 应用程序 - terminal - coco - Accept 允许, 这时 coco就 运行在 2222端口,可以ssh来连接
+
+命令行:
+```
+`ssh admin@192.168.244.128 -p2222
+```
+`
+**3.5 测试**
+- 测试登录 ssh server
+- 测试跳转
+- 测试命令记录回
+
+[1]: https://segmentfault.com/a/1190000000654227
+[2]: https://github.com/jumpserver/jumpserver.git
+[3]: https://github.com/jumpserver/coco.git
\ No newline at end of file
diff --git a/requirements/requirements.txt b/requirements/requirements.txt
index bc82d5b0b..64dfed303 100644
--- a/requirements/requirements.txt
+++ b/requirements/requirements.txt
@@ -20,3 +20,4 @@ tornado==4.4.2
eventlet==0.20.1
django-filter==1.0.0
passlib==1.7.1
+sshpass
diff --git a/tmp/.gitkeep b/tmp/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/utils/export_fake_data.sh b/utils/export_fake_data.sh
index cd4b462d5..be610a9f1 100644
--- a/utils/export_fake_data.sh
+++ b/utils/export_fake_data.sh
@@ -1,17 +1,17 @@
#!/bin/bash
#
-python ../apps/manage.py shell << EOF
+python2.7 ../apps/manage.py shell << EOF
from users.models.utils import *
generate_fake()
from assets.models.utils import *
generate_fake()
EOF
-python ../apps/manage.py dbshell << EOF
+python2.7 ../apps/manage.py dbshell << EOF
delete from django_content_type;
delete from auth_permission;
EOF
-python ../apps/manage.py dumpdata > ../apps/fixtures/fake.json
+python2.7 ../apps/manage.py dumpdata > ../apps/fixtures/fake.json
diff --git a/utils/export_init_data.sh b/utils/export_init_data.sh
index 0f3fb659f..4a9c90e6e 100644
--- a/utils/export_init_data.sh
+++ b/utils/export_init_data.sh
@@ -1,7 +1,7 @@
#!/bin/bash
#
-python ../apps/manage.py shell << EOF
+python2.7 ../apps/manage.py shell << EOF
from users.models import *
init_all_models()
@@ -10,9 +10,9 @@ init_all_models()
EOF
-python ../apps/manage.py dbshell << EOF
+python2.7 ../apps/manage.py dbshell << EOF
delete from django_content_type;
delete from auth_permission;
EOF
-python ../apps/manage.py dumpdata > ../apps/fixtures/init.json
+python2.7 ../apps/manage.py dumpdata > ../apps/fixtures/init.json
diff --git a/utils/init_db.sh b/utils/init_db.sh
index 4073ad001..a036b53b3 100755
--- a/utils/init_db.sh
+++ b/utils/init_db.sh
@@ -1,4 +1,4 @@
#!/bin/bash
#
-python ../apps/manage.py loaddata init
+python2.7 ../apps/manage.py loaddata init
diff --git a/utils/load_fake_data.sh b/utils/load_fake_data.sh
index c5577798e..82f66efda 100644
--- a/utils/load_fake_data.sh
+++ b/utils/load_fake_data.sh
@@ -1,4 +1,4 @@
#!/bin/bash
#
-python ../apps/manage.py loaddata fake
+python2.7 ../apps/manage.py loaddata fake