Commit a0684985 authored by yumaojun's avatar yumaojun

Merge branch 'dev' of https://git.coding.net/jumpserver/jumpserver into dev

# Conflicts:
#	jperm/ansible_api.py
parents bf98aa54 d337b929
This diff is collapsed.
#coding:utf-8
import django
import os
import sys
import random
import datetime
sys.path.append('../')
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
#django.setup()
from juser.views import db_add_user, md5_crypt, CRYPTOR, db_add_group
from jasset.models import Asset, IDC, BisGroup
from juser.models import UserGroup, DEPT, User
from jperm.models import CmdGroup
from jlog.models import Log
def install():
IDC.objects.create(name='ALL', comment='ALL')
IDC.objects.create(name='默认', comment='默认')
DEPT.objects.create(name="默认", comment="默认部门")
DEPT.objects.create(name="超管部", comment="超级管理员部门")
dept = DEPT.objects.get(name='超管部')
dept2 = DEPT.objects.get(name='默认')
UserGroup.objects.create(name='ALL', dept=dept, comment='ALL')
UserGroup.objects.create(name='默认', dept=dept, comment='默认')
BisGroup.objects.create(name='ALL', dept=dept, comment='ALL')
BisGroup.objects.create(name='默认', dept=dept, comment='默认')
User(id=5000, username="admin", password=md5_crypt('admin'),
name='admin', email='admin@jumpserver.org', role='SU', is_active=True, dept=dept).save()
User(id=5001, username="group_admin", password=md5_crypt('group_admin'),
name='group_admin', email='group_admin@jumpserver.org', role='DA', is_active=True, dept=dept2).save()
def test_add_idc():
for i in range(1, 20):
name = 'IDC' + str(i)
IDC.objects.create(name=name, comment='')
print 'Add: %s' % name
def test_add_dept():
for i in range(1, 100):
name = 'DEPT' + str(i)
print "Add: %s" % name
DEPT.objects.create(name=name, comment=name)
def test_add_group():
dept_all = DEPT.objects.all()
for i in range(1, 100):
name = 'UserGroup' + str(i)
UserGroup.objects.create(name=name, dept=random.choice(dept_all), comment=name)
print 'Add: %s' % name
def test_add_cmd_group():
for i in range(1, 20):
name = 'CMD' + str(i)
cmd = '/sbin/ping%s, /sbin/ifconfig/' % str(i)
CmdGroup.objects.create(name=name, cmd=cmd, comment=name)
print 'Add: %s' % name
def test_add_user():
for i in range(1, 500):
username = "test" + str(i)
dept_all = DEPT.objects.all()
group_all = UserGroup.objects.all()
group_all_id = [group.id for group in group_all]
db_add_user(username=username,
password=md5_crypt(username),
dept=random.choice(dept_all),
name=username, email='%s@jumpserver.org' % username,
groups=[random.choice(group_all_id) for i in range(1, 4)], role='CU',
ssh_key_pwd=CRYPTOR.encrypt(username),
ldap_pwd=CRYPTOR.encrypt(username),
is_active=True,
date_joined=datetime.datetime.now())
print "Add: %s" % username
def test_add_asset_group():
dept = DEPT.objects.get(name='默认')
for i in range(1, 20):
name = 'AssetGroup' + str(i)
group = BisGroup(name=name, dept=dept, comment=name)
group.save()
print 'Add: %s' % name
def test_add_asset():
idc_all = IDC.objects.all()
test_idc = random.choice(idc_all)
bis_group_all = BisGroup.objects.all()
dept_all = DEPT.objects.all()
for i in range(1, 500):
ip = '192.168.5.' + str(i)
asset = Asset(ip=ip, port=22, login_type='L', idc=test_idc, is_active=True, comment='test')
asset.save()
asset.bis_group = [random.choice(bis_group_all) for i in range(2)]
asset.dept = [random.choice(dept_all) for i in range(2)]
print "Add: %s" % ip
def test_add_log():
li_date = []
today = datetime.date.today()
oneday = datetime.timedelta(days=1)
for i in range(0, 7):
today = today-oneday
li_date.append(today)
user_list = ['马云', '马化腾', '丁磊', '周鸿祎', '雷军', '柳传志', '陈天桥', '李彦宏', '李开复', '罗永浩']
for i in range(1, 1000):
user = random.choice(user_list)
ip = random.randint(1, 20)
start_time = random.choice(li_date)
end_time = datetime.datetime.now()
log_path = '/var/log/jumpserver/test.log'
host = '192.168.1.' + str(ip)
Log.objects.create(user=user, host=host, remote_ip='8.8.8.8', dept_name='运维部', log_path=log_path, pid=168, start_time=start_time,
is_finished=1, log_finished=1, end_time=end_time)
if __name__ == '__main__':
# install()
# test_add_dept()
# test_add_group()
# test_add_user()
# test_add_idc()
# test_add_asset_group()
test_add_asset()
# test_add_log()
...@@ -7,22 +7,3 @@ ...@@ -7,22 +7,3 @@
email: admin@jumpserver.org email: admin@jumpserver.org
role: SU role: SU
is_active: 1 is_active: 1
- model: juser.user
pk: 5001
fields:
username: group_admin
name: group_admin
password: pbkdf2_sha256$20000$ttObUWd15q10$NJoyZf2OZz9oiw2g4j2TkTh9zGgyVDRFdUkhn8X0nB0=
email: group_admin@jumpserver.org
role: GA
is_active: 1
- model: juser.usergroup
pk: 1
fields:
name: ALL
comment: ALL
- model: juser.usergroup
pk: 2
fields:
name: 默认
comment: 默认
#coding:utf-8
import django
import os
import sys
import random
import datetime
sys.path.append('../')
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
#django.setup()
from juser.views import db_add_user, md5_crypt, CRYPTOR, db_add_group
from jasset.models import Asset, IDC, BisGroup
from juser.models import UserGroup, DEPT, User
from jasset.views import jasset_group_add
from jperm.models import CmdGroup
from jlog.models import Log
def install():
IDC.objects.create(name='ALL', comment='ALL')
IDC.objects.create(name='默认', comment='默认')
DEPT.objects.create(name="默认", comment="默认部门")
DEPT.objects.create(name="超管部", comment="超级管理员部门")
dept = DEPT.objects.get(name='超管部')
dept2 = DEPT.objects.get(name='默认')
UserGroup.objects.create(name='ALL', dept=dept, comment='ALL')
UserGroup.objects.create(name='默认', dept=dept, comment='默认')
BisGroup.objects.create(name='ALL', dept=dept, comment='ALL')
BisGroup.objects.create(name='默认', dept=dept, comment='默认')
User(id=5000, username="admin", password=md5_crypt('admin'),
name='admin', email='admin@jumpserver.org', role='SU', is_active=True, dept=dept).save()
User(id=5001, username="group_admin", password=md5_crypt('group_admin'),
name='group_admin', email='group_admin@jumpserver.org', role='DA', is_active=True, dept=dept2).save()
def test_add_idc():
for i in range(1, 20):
name = 'IDC' + str(i)
IDC.objects.create(name=name, comment='')
print 'Add: %s' % name
def test_add_dept():
for i in range(1, 100):
name = 'DEPT' + str(i)
print "Add: %s" % name
DEPT.objects.create(name=name, comment=name)
def test_add_group():
dept_all = DEPT.objects.all()
for i in range(1, 100):
name = 'UserGroup' + str(i)
UserGroup.objects.create(name=name, dept=random.choice(dept_all), comment=name)
print 'Add: %s' % name
def test_add_cmd_group():
for i in range(1, 20):
name = 'CMD' + str(i)
cmd = '/sbin/ping%s, /sbin/ifconfig/' % str(i)
CmdGroup.objects.create(name=name, cmd=cmd, comment=name)
print 'Add: %s' % name
def test_add_user():
for i in range(1, 500):
username = "test" + str(i)
dept_all = DEPT.objects.all()
group_all = UserGroup.objects.all()
group_all_id = [group.id for group in group_all]
db_add_user(username=username,
password=md5_crypt(username),
dept=random.choice(dept_all),
name=username, email='%s@jumpserver.org' % username,
groups=[random.choice(group_all_id) for i in range(1, 4)], role='CU',
ssh_key_pwd=CRYPTOR.encrypt(username),
ldap_pwd=CRYPTOR.encrypt(username),
is_active=True,
date_joined=datetime.datetime.now())
print "Add: %s" % username
def test_add_asset_group():
dept = DEPT.objects.get(name='默认')
for i in range(1, 20):
name = 'AssetGroup' + str(i)
group = BisGroup(name=name, dept=dept, comment=name)
group.save()
print 'Add: %s' % name
def test_add_asset():
idc_all = IDC.objects.all()
test_idc = random.choice(idc_all)
bis_group_all = BisGroup.objects.all()
dept_all = DEPT.objects.all()
for i in range(1, 500):
ip = '192.168.1.' + str(i)
asset = Asset(ip=ip, port=22, login_type='L', idc=test_idc, is_active=True, comment='test')
asset.save()
asset.bis_group = [random.choice(bis_group_all) for i in range(2)]
asset.dept = [random.choice(dept_all) for i in range(2)]
print "Add: %s" % ip
def test_add_log():
li_date = []
today = datetime.date.today()
oneday = datetime.timedelta(days=1)
for i in range(0, 7):
today = today-oneday
li_date.append(today)
user_list = ['马云', '马化腾', '丁磊', '周鸿祎', '雷军', '柳传志', '陈天桥', '李彦宏', '李开复', '罗永浩']
for i in range(1, 1000):
user = random.choice(user_list)
ip = random.randint(1, 20)
start_time = random.choice(li_date)
end_time = datetime.datetime.now()
log_path = '/var/log/jumpserver/test.log'
host = '192.168.1.' + str(ip)
Log.objects.create(user=user, host=host, log_path=log_path, pid=168, start_time=start_time,
is_finished=1, log_finished=1, end_time=end_time)
if __name__ == '__main__':
install()
sphinx-me==0.3 #sphinx-me==0.3
django==1.6 django==1.6
pycrypto==2.6.1 pycrypto==2.6.1
paramiko==1.15.2 paramiko==1.16.0
ecdsa==0.13 ecdsa==0.13
MySQL-python==1.2.5 MySQL-python==1.2.5
django-uuidfield==0.5.0 #django-uuidfield==0.5.0
psutil==2.2.1 psutil==3.3.0
xlsxwriter==0.7.7 xlsxwriter==0.7.7
xlrd==0.9.4 xlrd==0.9.4
django-bootstrap-form django-bootstrap-form==3.2
tornado tornado==4.3
ansible ansible==1.9.4
pyinotify pyinotify==0.9.6
passlib passlib==1.6.5
argparse argparse==1.4.0
\ No newline at end of file django_crontab==0.6.0
\ No newline at end of file
# coding: utf-8 # coding: utf-8
from __future__ import division
import xlrd import xlrd
import xlsxwriter import xlsxwriter
from django.db.models import AutoField from django.db.models import AutoField
...@@ -6,6 +7,7 @@ from jumpserver.api import * ...@@ -6,6 +7,7 @@ from jumpserver.api import *
from jasset.models import ASSET_STATUS, ASSET_TYPE, ASSET_ENV, IDC, AssetRecord from jasset.models import ASSET_STATUS, ASSET_TYPE, ASSET_ENV, IDC, AssetRecord
from jperm.ansible_api import MyRunner from jperm.ansible_api import MyRunner
from jperm.perm_api import gen_resource from jperm.perm_api import gen_resource
from jumpserver.templatetags.mytags import get_disk_info
def group_add_asset(group, asset_id=None, asset_ip=None): def group_add_asset(group, asset_id=None, asset_ip=None):
...@@ -75,83 +77,6 @@ def db_asset_update(**kwargs): ...@@ -75,83 +77,6 @@ def db_asset_update(**kwargs):
Asset.objects.filter(id=asset_id).update(**kwargs) Asset.objects.filter(id=asset_id).update(**kwargs)
#
#
# def batch_host_edit(host_alter_dic, j_user='', j_password=''):
# """ 批量修改主机函数 """
# j_id, j_ip, j_idc, j_port, j_type, j_group, j_dept, j_active, j_comment = host_alter_dic
# groups, depts = [], []
# is_active = {u'是': '1', u'否': '2'}
# login_types = {'LDAP': 'L', 'MAP': 'M'}
# a = Asset.objects.get(id=j_id)
# if '...' in j_group[0].split():
# groups = a.bis_group.all()
# else:
# for group in j_group[0].split():
# c = BisGroup.objects.get(name=group.strip())
# groups.append(c)
#
# if '...' in j_dept[0].split():
# depts = a.dept.all()
# else:
# for d in j_dept[0].split():
# p = DEPT.objects.get(name=d.strip())
# depts.append(p)
#
# j_type = login_types[j_type]
# j_idc = IDC.objects.get(name=j_idc)
# if j_type == 'M':
# if a.password != j_password:
# j_password = cryptor.decrypt(j_password)
# a.ip = j_ip
# a.port = j_port
# a.login_type = j_type
# a.idc = j_idc
# a.is_active = j_active
# a.comment = j_comment
# a.username = j_user
# a.password = j_password
# else:
# a.ip = j_ip
# a.port = j_port
# a.idc = j_idc
# a.login_type = j_type
# a.is_active = is_active[j_active]
# a.comment = j_comment
# a.save()
# a.bis_group = groups
# a.dept = depts
# a.save()
#
#
# def db_host_delete(request, host_id):
# """ 删除主机操作 """
# if is_group_admin(request) and not validate(request, asset=[host_id]):
# return httperror(request, '删除失败, 您无权删除!')
#
# asset = Asset.objects.filter(id=host_id)
# if asset:
# asset.delete()
# else:
# return httperror(request, '删除失败, 没有此主机!')
#
#
# def db_idc_delete(request, idc_id):
# """ 删除IDC操作 """
# if idc_id == 1:
# return httperror(request, '删除失败, 默认IDC不能删除!')
#
# default_idc = IDC.objects.get(id=1)
#
# idc = IDC.objects.filter(id=idc_id)
# if idc:
# idc_class = idc[0]
# idc_class.asset_set.update(idc=default_idc)
# idc.delete()
# else:
# return httperror(request, '删除失败, 没有这个IDC!')
def sort_ip_list(ip_list): def sort_ip_list(ip_list):
""" ip地址排序 """ """ ip地址排序 """
ip_list.sort(key=lambda s: map(int, s.split('.'))) ip_list.sort(key=lambda s: map(int, s.split('.')))
...@@ -232,7 +157,7 @@ def db_asset_alert(asset, username, alert_dic): ...@@ -232,7 +157,7 @@ def db_asset_alert(asset, username, alert_dic):
for group_id in value[1]: for group_id in value[1]:
group_name = AssetGroup.objects.get(id=int(group_id)).name group_name = AssetGroup.objects.get(id=int(group_id)).name
new.append(group_name) new.append(group_name)
if old == new: if sorted(old) == sorted(new):
continue continue
else: else:
alert_info = [field_name, ','.join(old), ','.join(new)] alert_info = [field_name, ','.join(old), ','.join(new)]
...@@ -274,28 +199,32 @@ def write_excel(asset_all): ...@@ -274,28 +199,32 @@ def write_excel(asset_all):
workbook = xlsxwriter.Workbook('static/files/excels/%s' % file_name) workbook = xlsxwriter.Workbook('static/files/excels/%s' % file_name)
worksheet = workbook.add_worksheet(u'CMDB数据') worksheet = workbook.add_worksheet(u'CMDB数据')
worksheet.set_first_sheet() worksheet.set_first_sheet()
worksheet.set_column('A:Z', 14) worksheet.set_column('A:E', 15)
title = [u'主机名', u'IP', u'IDC', u'MAC', u'远控IP', u'CPU', u'内存', u'硬盘', u'操作系统', u'机柜位置', worksheet.set_column('F:F', 40)
u'所属主机组', u'机器状态', u'备注'] worksheet.set_column('G:Z', 15)
title = [u'主机名', u'IP', u'IDC', u'所属主机组', u'操作系统', u'CPU', u'内存(G)', u'硬盘(G)',
u'机柜位置', u'MAC', u'远控IP', u'机器状态', u'备注']
for asset in asset_all: for asset in asset_all:
group_list = [] group_list = []
for p in asset.group.all(): for p in asset.group.all():
group_list.append(p.name) group_list.append(p.name)
disk = get_disk_info(asset.disk)
group_all = '/'.join(group_list) group_all = '/'.join(group_list)
status = asset.get_status_display() status = asset.get_status_display()
idc_name = asset.idc.name if asset.idc else u'' idc_name = asset.idc.name if asset.idc else u''
system_type = asset.system_type if asset.idc else u'' system_type = asset.system_type if asset.system_type else u''
system_version = asset.system_version if asset.idc else u'' system_version = asset.system_version if asset.system_version else u''
system_os = unicode(system_type) + unicode(system_version) system_os = unicode(system_type) + unicode(system_version)
alter_dic = [asset.hostname, asset.ip, idc_name, asset.mac, asset.remote_ip, asset.cpu, asset.memory, alter_dic = [asset.hostname, asset.ip, idc_name, group_all, system_os, asset.cpu, asset.memory,
asset.disk, system_os, asset.cabinet, group_all, status, disk, asset.cabinet, asset.mac, asset.remote_ip, status, asset.comment]
asset.comment]
data.append(alter_dic) data.append(alter_dic)
format = workbook.add_format() format = workbook.add_format()
format.set_border(1) format.set_border(1)
format.set_align('center') format.set_align('center')
format.set_align('vcenter')
format.set_text_wrap()
format_title = workbook.add_format() format_title = workbook.add_format()
format_title.set_border(1) format_title.set_border(1)
...@@ -384,12 +313,21 @@ def excel_to_db(excel_file): ...@@ -384,12 +313,21 @@ def excel_to_db(excel_file):
def get_ansible_asset_info(asset_ip, setup_info): def get_ansible_asset_info(asset_ip, setup_info):
disk_all = setup_info.get("ansible_devices") print asset_ip
disk_need = {} disk_need = {}
for disk_name, disk_info in disk_all.iteritems(): disk_all = setup_info.get("ansible_devices")
if disk_name.startswith('sd') or disk_name.startswith('hd') or disk_name.startswith('vd'): if disk_all:
disk_need[disk_name] = disk_info.get("size") for disk_name, disk_info in disk_all.iteritems():
print disk_name, disk_info
if disk_name.startswith('sd') or disk_name.startswith('hd') or disk_name.startswith('vd'):
disk_size = disk_info.get("size", '')
if 'M' in disk_size:
disk_format = round(float(disk_size[:-2]) / 1000, 0)
elif 'T' in disk_size:
disk_format = round(float(disk_size[:-2]) * 1000, 0)
else:
disk_format = float(disk_size[:-2])
disk_need[disk_name] = disk_format
all_ip = setup_info.get("ansible_all_ipv4_addresses") all_ip = setup_info.get("ansible_all_ipv4_addresses")
other_ip_list = all_ip.remove(asset_ip) if asset_ip in all_ip else [] other_ip_list = all_ip.remove(asset_ip) if asset_ip in all_ip else []
other_ip = ','.join(other_ip_list) if other_ip_list else '' other_ip = ','.join(other_ip_list) if other_ip_list else ''
...@@ -401,13 +339,17 @@ def get_ansible_asset_info(asset_ip, setup_info): ...@@ -401,13 +339,17 @@ def get_ansible_asset_info(asset_ip, setup_info):
cpu_cores = setup_info.get("ansible_processor_count") cpu_cores = setup_info.get("ansible_processor_count")
cpu = cpu_type + ' * ' + unicode(cpu_cores) cpu = cpu_type + ' * ' + unicode(cpu_cores)
memory = setup_info.get("ansible_memtotal_mb") memory = setup_info.get("ansible_memtotal_mb")
try:
memory_format = int(round((int(memory) / 1000), 0))
except Exception:
memory_format = memory
disk = disk_need disk = disk_need
system_type = setup_info.get("ansible_distribution") system_type = setup_info.get("ansible_distribution")
system_version = setup_info.get("ansible_distribution_version") system_version = setup_info.get("ansible_distribution_version")
system_arch = setup_info.get("ansible_architecture")
# asset_type = setup_info.get("ansible_system") # asset_type = setup_info.get("ansible_system")
sn = setup_info.get("ansible_product_serial") sn = setup_info.get("ansible_product_serial")
asset_info = [other_ip, mac, cpu, memory, disk, sn, system_type, system_version, brand] asset_info = [other_ip, mac, cpu, memory_format, disk, sn, system_type, system_version, brand, system_arch]
return asset_info return asset_info
...@@ -415,6 +357,7 @@ def asset_ansible_update(obj_list, name=''): ...@@ -415,6 +357,7 @@ def asset_ansible_update(obj_list, name=''):
resource = gen_resource(obj_list) resource = gen_resource(obj_list)
ansible_instance = MyRunner(resource) ansible_instance = MyRunner(resource)
ansible_asset_info = ansible_instance.run(module_name='setup', pattern='*') ansible_asset_info = ansible_instance.run(module_name='setup', pattern='*')
logger.debug('获取硬件信息: %s' % ansible_asset_info)
for asset in obj_list: for asset in obj_list:
try: try:
setup_info = ansible_asset_info['contacted'][asset.hostname]['ansible_facts'] setup_info = ansible_asset_info['contacted'][asset.hostname]['ansible_facts']
...@@ -422,7 +365,7 @@ def asset_ansible_update(obj_list, name=''): ...@@ -422,7 +365,7 @@ def asset_ansible_update(obj_list, name=''):
continue continue
else: else:
asset_info = get_ansible_asset_info(asset.ip, setup_info) asset_info = get_ansible_asset_info(asset.ip, setup_info)
other_ip, mac, cpu, memory, disk, sn, system_type, system_version, brand = asset_info other_ip, mac, cpu, memory, disk, sn, system_type, system_version, brand, system_arch = asset_info
asset_dic = {"other_ip": other_ip, asset_dic = {"other_ip": other_ip,
"mac": mac, "mac": mac,
"cpu": cpu, "cpu": cpu,
...@@ -431,6 +374,7 @@ def asset_ansible_update(obj_list, name=''): ...@@ -431,6 +374,7 @@ def asset_ansible_update(obj_list, name=''):
"sn": sn, "sn": sn,
"system_type": system_type, "system_type": system_type,
"system_version": system_version, "system_version": system_version,
"system_arch": system_arch,
"brand": brand "brand": brand
} }
......
...@@ -12,7 +12,8 @@ class AssetForm(forms.ModelForm): ...@@ -12,7 +12,8 @@ class AssetForm(forms.ModelForm):
fields = [ fields = [
"ip", "other_ip", "hostname", "port", "group", "username", "password", "use_default_auth", "ip", "other_ip", "hostname", "port", "group", "username", "password", "use_default_auth",
"idc", "mac", "remote_ip", "brand", "cpu", "memory", "disk", "system_type", "system_version", "idc", "mac", "remote_ip", "brand", "cpu", "memory", "disk", "system_type", "system_version",
"cabinet", "position", "number", "status", "asset_type", "env", "sn", "is_active", "comment" "cabinet", "position", "number", "status", "asset_type", "env", "sn", "is_active", "comment",
"system_arch"
] ]
......
...@@ -78,6 +78,7 @@ class Asset(models.Model): ...@@ -78,6 +78,7 @@ class Asset(models.Model):
disk = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'硬盘') disk = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'硬盘')
system_type = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"系统类型") system_type = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"系统类型")
system_version = models.CharField(max_length=8, blank=True, null=True, verbose_name=u"系统版本号") system_version = models.CharField(max_length=8, blank=True, null=True, verbose_name=u"系统版本号")
system_arch = models.CharField(max_length=16, blank=True, null=True, verbose_name=u"系统平台")
cabinet = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机柜号') cabinet = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机柜号')
position = models.IntegerField(blank=True, null=True, verbose_name=u'机器位置') position = models.IntegerField(blank=True, null=True, verbose_name=u'机器位置')
number = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'资产编号') number = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'资产编号')
......
...@@ -6,8 +6,7 @@ from jumpserver.api import * ...@@ -6,8 +6,7 @@ from jumpserver.api import *
from jumpserver.models import Setting from jumpserver.models import Setting
from jasset.forms import AssetForm, IdcForm from jasset.forms import AssetForm, IdcForm
from jasset.models import Asset, IDC, AssetGroup, ASSET_TYPE, ASSET_STATUS from jasset.models import Asset, IDC, AssetGroup, ASSET_TYPE, ASSET_STATUS
from jperm.ansible_api import Tasks, MyRunner from jperm.perm_api import get_group_asset_perm, get_group_user_perm
from jperm.perm_api import gen_resource
@require_role('admin') @require_role('admin')
...@@ -96,7 +95,9 @@ def group_list(request): ...@@ -96,7 +95,9 @@ def group_list(request):
header_title, path1, path2 = u'查看资产组', u'资产管理', u'查看资产组' header_title, path1, path2 = u'查看资产组', u'资产管理', u'查看资产组'
keyword = request.GET.get('keyword', '') keyword = request.GET.get('keyword', '')
asset_group_list = AssetGroup.objects.all() asset_group_list = AssetGroup.objects.all()
group_id = request.GET.get('id')
if group_id:
asset_group_list = asset_group_list.filter(id=group_id)
if keyword: if keyword:
asset_group_list = asset_group_list.filter(Q(name__contains=keyword) | Q(comment__contains=keyword)) asset_group_list = asset_group_list.filter(Q(name__contains=keyword) | Q(comment__contains=keyword))
...@@ -256,11 +257,13 @@ def asset_list(request): ...@@ -256,11 +257,13 @@ def asset_list(request):
asset list view asset list view
""" """
header_title, path1, path2 = u'查看资产', u'资产管理', u'查看资产' header_title, path1, path2 = u'查看资产', u'资产管理', u'查看资产'
username = request.user.username
user_perm = request.session['role_id']
idc_all = IDC.objects.filter() idc_all = IDC.objects.filter()
asset_group_all = AssetGroup.objects.all() asset_group_all = AssetGroup.objects.all()
asset_types = ASSET_TYPE asset_types = ASSET_TYPE
asset_status = ASSET_STATUS asset_status = ASSET_STATUS
asset_id = request.GET.get('id')
idc_name = request.GET.get('idc', '') idc_name = request.GET.get('idc', '')
group_name = request.GET.get('group', '') group_name = request.GET.get('group', '')
asset_type = request.GET.get('asset_type', '') asset_type = request.GET.get('asset_type', '')
...@@ -279,12 +282,19 @@ def asset_list(request): ...@@ -279,12 +282,19 @@ def asset_list(request):
if idc: if idc:
asset_find = Asset.objects.filter(idc=idc) asset_find = Asset.objects.filter(idc=idc)
else: else:
asset_find = Asset.objects.all() if user_perm != 0:
asset_find = Asset.objects.all()
else:
user = get_object(User, username=username)
asset_perm = get_group_user_perm(user) if user else {'asset': ''}
asset_find = asset_perm['asset'].keys()
asset_group_all = list(asset_perm['asset_group'])
if idc_name: if idc_name:
asset_find = asset_find.filter(idc__name__contains=idc_name) asset_find = asset_find.filter(idc__name__contains=idc_name)
if group_name: if group_name:
print asset_find, type(asset_find)
asset_find = asset_find.filter(group__name__contains=group_name) asset_find = asset_find.filter(group__name__contains=group_name)
if asset_type: if asset_type:
...@@ -293,6 +303,9 @@ def asset_list(request): ...@@ -293,6 +303,9 @@ def asset_list(request):
if status: if status:
asset_find = asset_find.filter(status__contains=status) asset_find = asset_find.filter(status__contains=status)
if asset_id:
asset_find = asset_find.filter(id=asset_id)
if keyword: if keyword:
asset_find = asset_find.filter( asset_find = asset_find.filter(
Q(hostname__contains=keyword) | Q(hostname__contains=keyword) |
...@@ -318,7 +331,10 @@ def asset_list(request): ...@@ -318,7 +331,10 @@ def asset_list(request):
smg = u'excel文件已生成,请点击下载!' smg = u'excel文件已生成,请点击下载!'
return my_render('jasset/asset_excel_download.html', locals(), request) return my_render('jasset/asset_excel_download.html', locals(), request)
assets_list, p, assets, page_range, current_page, show_first, show_end = pages(asset_find, request) assets_list, p, assets, page_range, current_page, show_first, show_end = pages(asset_find, request)
return my_render('jasset/asset_list.html', locals(), request) if user_perm != 0:
return my_render('jasset/asset_list.html', locals(), request)
else:
return my_render('jasset/asset_cu_list.html', locals(), request)
@require_role('admin') @require_role('admin')
...@@ -410,6 +426,18 @@ def asset_detail(request): ...@@ -410,6 +426,18 @@ def asset_detail(request):
header_title, path1, path2 = u'主机详细信息', u'资产管理', u'主机详情' header_title, path1, path2 = u'主机详细信息', u'资产管理', u'主机详情'
asset_id = request.GET.get('id', '') asset_id = request.GET.get('id', '')
asset = get_object(Asset, id=asset_id) asset = get_object(Asset, id=asset_id)
perm_info = get_group_asset_perm(asset)
log = Log.objects.filter(host=asset.hostname)
if perm_info:
user_perm = []
for perm, value in perm_info.items():
if perm == 'user':
for user, role_dic in value.items():
user_perm.append([user, role_dic.get('role', '')])
elif perm == 'user_group' or perm == 'rule':
user_group_perm = value
print perm_info
asset_record = AssetRecord.objects.filter(asset=asset).order_by('-alert_time') asset_record = AssetRecord.objects.filter(asset=asset).order_by('-alert_time')
return my_render('jasset/asset_detail.html', locals(), request) return my_render('jasset/asset_detail.html', locals(), request)
......
...@@ -3,7 +3,7 @@ from django.db import models ...@@ -3,7 +3,7 @@ from django.db import models
class Log(models.Model): class Log(models.Model):
user = models.CharField(max_length=20, null=True) user = models.CharField(max_length=20, null=True)
host = models.CharField(max_length=20, null=True) host = models.CharField(max_length=200, null=True)
remote_ip = models.CharField(max_length=100) remote_ip = models.CharField(max_length=100)
login_type = models.CharField(max_length=100) login_type = models.CharField(max_length=100)
log_path = models.CharField(max_length=100) log_path = models.CharField(max_length=100)
...@@ -24,5 +24,26 @@ class Alert(models.Model): ...@@ -24,5 +24,26 @@ class Alert(models.Model):
class TtyLog(models.Model): class TtyLog(models.Model):
log = models.ForeignKey(Log) log = models.ForeignKey(Log)
datetime = models.DateTimeField() datetime = models.DateTimeField(auto_now=True)
cmd = models.CharField(max_length=200) cmd = models.CharField(max_length=200)
class ExecLog(models.Model):
user = models.CharField(max_length=100)
host = models.TextField()
cmd = models.TextField()
remote_ip = models.CharField(max_length=100)
result = models.TextField(default='')
datetime = models.DateTimeField(auto_now=True)
class FileLog(models.Model):
user = models.CharField(max_length=100)
host = models.TextField()
filename = models.TextField()
type = models.CharField(max_length=20)
remote_ip = models.CharField(max_length=100)
result = models.TextField(default='')
datetime = models.DateTimeField(auto_now=True)
...@@ -3,11 +3,11 @@ from django.conf.urls import patterns, include, url ...@@ -3,11 +3,11 @@ from django.conf.urls import patterns, include, url
from jlog.views import * from jlog.views import *
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^$', log_list), (r'^$', log_list),
url(r'^log_list/(\w+)/$', log_list), (r'^log_list/(\w+)/$', log_list),
url(r'^history/$', log_history), (r'^log_detail/(\w+)/$', log_detail),
url(r'^log_kill/', log_kill), (r'^history/$', log_history),
url(r'^record/$', log_record), (r'^log_kill/', log_kill),
url(r'^web_terminal/$', web_terminal), (r'^record/$', log_record),
url(r'^get_role_name/$', get_role_name), (r'^web_terminal/$', web_terminal),
) )
\ No newline at end of file
...@@ -8,7 +8,7 @@ from jperm.perm_api import user_have_perm ...@@ -8,7 +8,7 @@ from jperm.perm_api import user_have_perm
from django.http import HttpResponseNotFound from django.http import HttpResponseNotFound
from jlog.log_api import renderTemplate from jlog.log_api import renderTemplate
from models import Log from jlog.models import Log, ExecLog, FileLog
from jumpserver.settings import WEB_SOCKET_HOST from jumpserver.settings import WEB_SOCKET_HOST
...@@ -21,9 +21,24 @@ def log_list(request, offset): ...@@ -21,9 +21,24 @@ def log_list(request, offset):
username_list = request.GET.getlist('username', []) username_list = request.GET.getlist('username', [])
host_list = request.GET.getlist('host', []) host_list = request.GET.getlist('host', [])
cmd = request.GET.get('cmd', '') cmd = request.GET.get('cmd', '')
print date_seven_day, date_now_str
if offset == 'online': if offset == 'online':
keyword = request.GET.get('keyword', '')
posts = Log.objects.filter(is_finished=False).order_by('-start_time') posts = Log.objects.filter(is_finished=False).order_by('-start_time')
if keyword:
posts = posts.filter(Q(user__icontains=keyword) | Q(host__icontains=keyword) |
Q(login_type_icontains=keyword))
elif offset == 'exec':
posts = ExecLog.objects.all().order_by('-id')
keyword = request.GET.get('keyword', '')
if keyword:
posts = posts.filter(Q(user__icontains=keyword)|Q(host__icontains=keyword)|Q(cmd__icontains=keyword))
elif offset == 'file':
posts = FileLog.objects.all().order_by('-id')
keyword = request.GET.get('keyword', '')
if keyword:
posts = posts.filter(Q(user__icontains=keyword)|Q(host__icontains=keyword)|Q(filename__icontains=keyword))
else: else:
posts = Log.objects.filter(is_finished=True).order_by('-start_time') posts = Log.objects.filter(is_finished=True).order_by('-start_time')
username_all = set([log.user for log in Log.objects.all()]) username_all = set([log.user for log in Log.objects.all()])
...@@ -57,6 +72,11 @@ def log_list(request, offset): ...@@ -57,6 +72,11 @@ def log_list(request, offset):
return render_to_response('jlog/log_%s.html' % offset, locals(), context_instance=RequestContext(request)) return render_to_response('jlog/log_%s.html' % offset, locals(), context_instance=RequestContext(request))
@require_role('admin')
def log_detail(request):
return my_render('jlog/exec_detail.html', locals(), request)
@require_role('admin') @require_role('admin')
def log_kill(request): def log_kill(request):
""" 杀掉connect进程 """ """ 杀掉connect进程 """
...@@ -107,16 +127,6 @@ def log_record(request): ...@@ -107,16 +127,6 @@ def log_record(request):
return HttpResponse('无日志记录!') return HttpResponse('无日志记录!')
@require_role('user')
def get_role_name(request):
asset_id = request.GET.get('id', 9999)
asset = get_object(Asset, id=asset_id)
if asset:
role = user_have_perm(request.user, asset=asset)
return HttpResponse(','.join([i.name for i in role]))
return HttpResponse('error')
@require_role('user') @require_role('user')
def web_terminal(request): def web_terminal(request):
asset_id = request.GET.get('id') asset_id = request.GET.get('id')
...@@ -124,3 +134,21 @@ def web_terminal(request): ...@@ -124,3 +134,21 @@ def web_terminal(request):
web_terminal_uri = 'ws://%s/terminal?id=%s&role=%s' % (WEB_SOCKET_HOST, asset_id, role_name) web_terminal_uri = 'ws://%s/terminal?id=%s&role=%s' % (WEB_SOCKET_HOST, asset_id, role_name)
return render_to_response('jlog/web_terminal.html', locals()) return render_to_response('jlog/web_terminal.html', locals())
@require_role('admin')
def log_detail(request, offset):
log_id = request.GET.get('id')
if offset == 'exec':
log = get_object(ExecLog, id=log_id)
assets_hostname = log.host.split(' ')
result = eval(str(log.result))
return my_render('jlog/exec_detail.html', locals(), request)
elif offset == 'file':
log = get_object(FileLog, id=log_id)
assets_hostname = log.host.split(' ')
file_list = log.filename.split(' ')
try:
result = eval(str(log.result))
except (SyntaxError, NameError):
result = {}
return my_render('jlog/file_detail.html', locals(), request)
This diff is collapsed.
...@@ -55,6 +55,6 @@ class PermPush(models.Model): ...@@ -55,6 +55,6 @@ class PermPush(models.Model):
is_public_key = models.BooleanField(default=False) is_public_key = models.BooleanField(default=False)
is_password = models.BooleanField(default=False) is_password = models.BooleanField(default=False)
success = models.BooleanField(default=False) success = models.BooleanField(default=False)
result = models.TextField() result = models.TextField(default='')
date_added = models.DateTimeField(auto_now=True) date_added = models.DateTimeField(auto_now=True)
...@@ -43,13 +43,16 @@ def get_group_user_perm(ob): ...@@ -43,13 +43,16 @@ def get_group_user_perm(ob):
asset_groups = rule.asset_group.all() asset_groups = rule.asset_group.all()
assets = rule.asset.all() assets = rule.asset.all()
perm_roles = rule.role.all() perm_roles = rule.role.all()
group_assets = []
for asset_group in asset_groups:
group_assets.extend(asset_group.asset_set.all())
# 获取一个规则授权的角色和对应主机 # 获取一个规则授权的角色和对应主机
for role in perm_roles: for role in perm_roles:
if perm_role.get('role'): if perm_role.get(role):
perm_role[role]['asset'] = perm_role[role].get('asset', set()).union(set(assets)) perm_role[role]['asset'] = perm_role[role].get('asset', set()).union(set(assets).union(set(group_assets)))
perm_role[role]['asset_group'] = perm_role[role].get('asset_group', set()).union(set(asset_groups)) perm_role[role]['asset_group'] = perm_role[role].get('asset_group', set()).union(set(asset_groups))
else: else:
perm_role[role] = {'asset': set(assets), 'asset_group': set(asset_groups)} perm_role[role] = {'asset': set(assets).union(set(group_assets)), 'asset_group': set(asset_groups)}
# 获取一个规则用户授权的资产 # 获取一个规则用户授权的资产
for asset in assets: for asset in assets:
...@@ -161,23 +164,42 @@ def gen_resource(ob, perm=None): ...@@ -161,23 +164,42 @@ def gen_resource(ob, perm=None):
user = ob.get('user') user = ob.get('user')
if not perm: if not perm:
perm = get_group_user_perm(user) perm = get_group_user_perm(user)
roles = perm.get('role', {}).keys()
if role not in roles:
return {}
role_assets_all = perm.get('role').get(role).get('asset')
assets = set(role_assets_all) & set(asset_r)
for asset in assets: if role:
asset_info = get_asset_info(asset) roles = perm.get('role', {}).keys() # 获取用户所有授权角色
info = {'hostname': asset.hostname, if role not in roles:
'ip': asset.ip, return {}
'port': asset_info.get('port', 22),
'username': role.name, role_assets_all = perm.get('role').get(role).get('asset') # 获取用户该角色所有授权主机
'password': CRYPTOR.decrypt(role.password), assets = set(role_assets_all) & set(asset_r) # 获取用户提交中合法的主机
'ssh_key': get_role_key(user, role)
} for asset in assets:
res.append(info) asset_info = get_asset_info(asset)
info = {'hostname': asset.hostname,
'ip': asset.ip,
'port': asset_info.get('port', 22),
'username': role.name,
'password': CRYPTOR.decrypt(role.password),
'ssh_key': get_role_key(user, role)
}
res.append(info)
else:
for asset, asset_info in perm.get('asset').items():
if asset not in asset_r:
continue
asset_info = get_asset_info(asset)
try:
role = sorted(list(perm.get('asset').get(asset).get('role')))[0]
except IndexError:
continue
info = {'hostname': asset.hostname,
'ip': asset.ip,
'port': asset_info.get('port', 22),
'username': role.name,
'password': CRYPTOR.decrypt(role.password),
'ssh_key': get_role_key(user, role)
}
res.append(info)
elif isinstance(ob, User): elif isinstance(ob, User):
if not perm: if not perm:
...@@ -198,6 +220,7 @@ def gen_resource(ob, perm=None): ...@@ -198,6 +220,7 @@ def gen_resource(ob, perm=None):
for asset in ob: for asset in ob:
info = get_asset_info(asset) info = get_asset_info(asset)
res.append(info) res.append(info)
logger.debug('生成res: %s' % res)
return res return res
...@@ -281,6 +304,7 @@ def get_role_push_host(role): ...@@ -281,6 +304,7 @@ def get_role_push_host(role):
asset_no_push = set(asset_all) - set(asset_pushed.keys()) asset_no_push = set(asset_all) - set(asset_pushed.keys())
return asset_pushed, asset_no_push return asset_pushed, asset_no_push
if __name__ == "__main__": if __name__ == "__main__":
print get_role_info(1) print get_role_info(1)
......
...@@ -14,6 +14,7 @@ urlpatterns = patterns('jperm.views', ...@@ -14,6 +14,7 @@ urlpatterns = patterns('jperm.views',
(r'^role/perm_role_edit/$', perm_role_edit), (r'^role/perm_role_edit/$', perm_role_edit),
(r'^role/push/$', perm_role_push), (r'^role/push/$', perm_role_push),
(r'^role/recycle/$', perm_role_recycle), (r'^role/recycle/$', perm_role_recycle),
(r'^role/get/$', perm_role_get),
(r'^sudo/$', perm_sudo_list), (r'^sudo/$', perm_sudo_list),
(r'^sudo/perm_sudo_add/$', perm_sudo_add), (r'^sudo/perm_sudo_add/$', perm_sudo_add),
(r'^sudo/perm_sudo_delete/$', perm_sudo_delete), (r'^sudo/perm_sudo_delete/$', perm_sudo_delete),
......
...@@ -10,11 +10,8 @@ from uuid import uuid4 ...@@ -10,11 +10,8 @@ from uuid import uuid4
from jumpserver.api import CRYPTOR from jumpserver.api import CRYPTOR
from os import makedirs from os import makedirs
from django.template.loader import get_template
from django.template import Context
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
from jumpserver.settings import KEY_DIR from jumpserver.settings import KEY_DIR
...@@ -72,45 +69,6 @@ def gen_keys(key="", key_path_dir=""): ...@@ -72,45 +69,6 @@ def gen_keys(key="", key_path_dir=""):
return key_path_dir return key_path_dir
def gen_sudo(role_custom, role_name, role_chosen):
"""
生成sudo file, 仅测试了cenos7
role_custom: 自定义支持的sudo 命令 格式: 'CMD1, CMD2, CMD3, ...'
role_name: role name
role_chosen: 选择那些sudo的命令别名:
    NETWORKING, SOFTWARE, SERVICES, STORAGE,
    DELEGATING, PROCESSES, LOCATE, DRIVERS
:return:
"""
sudo_file_basename = os.path.join(os.path.dirname(KEY_DIR), 'role_sudo_file')
makedirs(sudo_file_basename)
sudo_file_path = os.path.join(sudo_file_basename, role_name)
t = get_template('role_sudo.j2')
content = t.render(Context({"role_custom": role_custom,
"role_name": role_name,
"role_chosen": role_chosen,
}))
with open(sudo_file_path, 'w') as f:
f.write(content)
return sudo_file_path
def get_add_sudo_script(role_chosen_aliase, sudo_alias):
"""
get the sudo file
:param kwargs:
:return:
"""
sudo_j2 = get_template('jperm/role_sudo.j2')
sudo_content = sudo_j2.render(Context({"role_chosen_aliase": role_chosen_aliase,
"sudo_alias": sudo_alias}))
sudo_file = NamedTemporaryFile(delete=False)
sudo_file.write(sudo_content)
sudo_file.close()
print(sudo_file.name)
return sudo_file.name
if __name__ == "__main__": if __name__ == "__main__":
print gen_keys() print gen_keys()
......
This diff is collapsed.
...@@ -9,6 +9,7 @@ import hashlib ...@@ -9,6 +9,7 @@ import hashlib
import datetime import datetime
import random import random
import subprocess import subprocess
import uuid
import json import json
import logging import logging
...@@ -47,9 +48,16 @@ def set_log(level): ...@@ -47,9 +48,16 @@ def set_log(level):
return logger_f return logger_f
def list_drop_str(a_list, a_str):
for i in a_list:
if i == a_str:
a_list.remove(a_str)
return a_list
def get_asset_info(asset): def get_asset_info(asset):
""" """
获取资产的相关账号端口信息 获取资产的相关管理账号端口等信息
""" """
default = get_object(Setting, name='default') default = get_object(Setting, name='default')
info = {'hostname': asset.hostname, 'ip': asset.ip} info = {'hostname': asset.hostname, 'ip': asset.ip}
...@@ -70,17 +78,6 @@ def get_asset_info(asset): ...@@ -70,17 +78,6 @@ def get_asset_info(asset):
return info return info
def get_role(user, asset):
"""
获取用户在这个资产上的授权角色列表
"""
roles = []
rules = PermRule.objects.filter(user=user, asset=asset)
for rule in rules:
roles.extend(list(rule.role.all()))
return roles
def get_role_key(user, role): def get_role_key(user, role):
""" """
由于role的key的权限是所有人可以读的, ansible执行命令等要求为600,所以拷贝一份到特殊目录 由于role的key的权限是所有人可以读的, ansible执行命令等要求为600,所以拷贝一份到特殊目录
...@@ -95,7 +92,7 @@ def get_role_key(user, role): ...@@ -95,7 +92,7 @@ def get_role_key(user, role):
with open(os.path.join(role.key_path, 'id_rsa')) as fk: with open(os.path.join(role.key_path, 'id_rsa')) as fk:
with open(user_role_key_path, 'w') as fu: with open(user_role_key_path, 'w') as fu:
fu.write(fk.read()) fu.write(fk.read())
logger.debug("创建新的用户角色key %s" % user_role_key_path) logger.debug(u"创建新的用户角色key %s, Owner: %s" % (user_role_key_path, user.username))
chown(user_role_key_path, user.username) chown(user_role_key_path, user.username)
os.chmod(user_role_key_path, 0600) os.chmod(user_role_key_path, 0600)
return user_role_key_path return user_role_key_path
...@@ -482,5 +479,10 @@ def my_render(template, data, request): ...@@ -482,5 +479,10 @@ def my_render(template, data, request):
return render_to_response(template, data, context_instance=RequestContext(request)) return render_to_response(template, data, context_instance=RequestContext(request))
def get_tmp_dir():
dir_name = os.path.join('/tmp', uuid.uuid4().hex)
mkdir(dir_name, mode=0777)
return dir_name
CRYPTOR = PyCrypt(KEY) CRYPTOR = PyCrypt(KEY)
logger = set_log(LOG_LEVEL) logger = set_log(LOG_LEVEL)
...@@ -7,7 +7,7 @@ import time ...@@ -7,7 +7,7 @@ import time
from django import template from django import template
from jperm.models import PermPush from jperm.models import PermPush
from jumpserver.api import * from jumpserver.api import *
from jasset.models import AssetAlias from jperm.perm_api import get_group_user_perm
register = template.Library() register = template.Library()
...@@ -237,7 +237,7 @@ def key_exist(username): ...@@ -237,7 +237,7 @@ def key_exist(username):
""" """
ssh key is exist or not ssh key is exist or not
""" """
if os.path.isfile(os.path.join(KEY_DIR, 'user', username)): if os.path.isfile(os.path.join(KEY_DIR, 'user', username+'.pem')):
return True return True
else: else:
return False return False
...@@ -272,3 +272,35 @@ def get_push_info(push_id, arg): ...@@ -272,3 +272,35 @@ def get_push_info(push_id, arg):
return [role.name for role in push.role.all()] return [role.name for role in push.role.all()]
else: else:
return [] return []
@register.filter(name='get_cpu_core')
def get_cpu_core(cpu_info):
cpu_core = cpu_info.split('* ')[1] if cpu_info and '*' in cpu_info else cpu_info
return cpu_core
@register.filter(name='get_disk_info')
def get_disk_info(disk_info):
try:
disk_size = 0
if disk_info:
disk_dic = ast.literal_eval(disk_info)
for disk, size in disk_dic.items():
disk_size += size
disk_size = int(disk_size)
else:
disk_size = ''
except Exception:
disk_size = ''
return disk_size
@register.filter(name='user_perm_asset_num')
def user_perm_asset_num(user_id):
user = get_object(User, id=user_id)
if user:
user_perm_info = get_group_user_perm(user)
return len(user_perm_info.get('asset').keys())
else:
return 0
...@@ -6,19 +6,14 @@ urlpatterns = patterns('', ...@@ -6,19 +6,14 @@ urlpatterns = patterns('',
(r'^$', 'jumpserver.views.index'), (r'^$', 'jumpserver.views.index'),
(r'^api/user/$', 'jumpserver.api.api_user'), (r'^api/user/$', 'jumpserver.api.api_user'),
(r'^skin_config/$', 'jumpserver.views.skin_config'), (r'^skin_config/$', 'jumpserver.views.skin_config'),
(r'^install/$', 'jumpserver.views.install'),
(r'^base/$', 'jumpserver.views.base'),
(r'^login/$', 'jumpserver.views.Login'), (r'^login/$', 'jumpserver.views.Login'),
(r'^logout/$', 'jumpserver.views.Logout'), (r'^logout/$', 'jumpserver.views.Logout'),
(r'^exec_cmd/$', 'jumpserver.views.exec_cmd'),
(r'^file/upload/$', 'jumpserver.views.upload'), (r'^file/upload/$', 'jumpserver.views.upload'),
(r'^file/download/$', 'jumpserver.views.download'), (r'^file/download/$', 'jumpserver.views.download'),
(r'^setting', 'jumpserver.views.setting'), (r'^setting', 'jumpserver.views.setting'),
(r'^error/$', 'jumpserver.views.httperror'),
(r'^juser/', include('juser.urls')), (r'^juser/', include('juser.urls')),
(r'^jasset/', include('jasset.urls')), (r'^jasset/', include('jasset.urls')),
(r'^jlog/', include('jlog.urls')), (r'^jlog/', include('jlog.urls')),
(r'^jperm/', include('jperm.urls')), (r'^jperm/', include('jperm.urls')),
(r'^node_auth/', 'jumpserver.views.node_auth'),
(r'download/(\d{4}/\d\d/\d\d/.*)', 'jumpserver.views.download_file'),
(r'test2', 'jumpserver.views.test2'),
) )
This diff is collapsed.
...@@ -25,9 +25,6 @@ urlpatterns = patterns('juser.views', ...@@ -25,9 +25,6 @@ urlpatterns = patterns('juser.views',
(r'^forget_password/$', forget_password), (r'^forget_password/$', forget_password),
(r'^change_info/$', 'change_info'), (r'^change_info/$', 'change_info'),
(r'^change_role/$', 'chg_role'),
(r'^regen_ssh_key/$', 'regen_ssh_key'), (r'^regen_ssh_key/$', 'regen_ssh_key'),
(r'^down_key/$', 'down_key'), (r'^down_key/$', 'down_key'),
(r'runcommand/$', 'RunCommand'),
) )
...@@ -129,8 +129,8 @@ def gen_ssh_key(username, password='', ...@@ -129,8 +129,8 @@ def gen_ssh_key(username, password='',
生成一个用户ssh密钥对 生成一个用户ssh密钥对
""" """
logger.debug('生成ssh key, 并设置authorized_keys') logger.debug('生成ssh key, 并设置authorized_keys')
private_key_file = os.path.join(key_dir, username) private_key_file = os.path.join(key_dir, username+'.pem')
mkdir(key_dir, mode=777) mkdir(key_dir, mode=0700)
if os.path.isfile(private_key_file): if os.path.isfile(private_key_file):
os.unlink(private_key_file) os.unlink(private_key_file)
ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password)) ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password))
...@@ -166,7 +166,7 @@ def user_add_mail(user, kwargs): ...@@ -166,7 +166,7 @@ def user_add_mail(user, kwargs):
mail_msg = u""" mail_msg = u"""
Hi, %s Hi, %s
您的用户名: %s 您的用户名: %s
您的角色%s 您的权限%s
您的web登录密码: %s 您的web登录密码: %s
您的ssh密钥文件密码: %s 您的ssh密钥文件密码: %s
密钥下载地址: %s/juser/down_key/?uuid=%s 密钥下载地址: %s/juser/down_key/?uuid=%s
...@@ -195,9 +195,9 @@ def get_display_msg(user, password, ssh_key_pwd, ssh_key_login_need, send_mail_n ...@@ -195,9 +195,9 @@ def get_display_msg(user, password, ssh_key_pwd, ssh_key_login_need, send_mail_n
用户名:%s 用户名:%s
密码:%s 密码:%s
密钥密码:%s 密钥密码:%s
密钥下载url: %s/juser/down_key/?id=%s 密钥下载url: %s/juser/down_key/?uuid=%s
该账号密码可以登陆web和跳板机。 该账号密码可以登陆web和跳板机。
""" % (URL, user.username, password, ssh_key_pwd, URL, user.id) """ % (URL, user.username, password, ssh_key_pwd, URL, user.uuid)
else: else:
msg = u""" msg = u"""
跳板机地址: %s \n 跳板机地址: %s \n
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ import sys ...@@ -8,7 +8,7 @@ import sys
import os.path import os.path
import threading import threading
import datetime import datetime
import urllib import re
import tornado.ioloop import tornado.ioloop
import tornado.options import tornado.options
...@@ -23,8 +23,8 @@ from tornado.options import define, options ...@@ -23,8 +23,8 @@ from tornado.options import define, options
from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE, IN_MODIFY, AsyncNotifier from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE, IN_MODIFY, AsyncNotifier
import select import select
from connect import Tty, User, Asset, PermRole, logger, get_object from connect import Tty, User, Asset, PermRole, logger, get_object, PermRole, gen_resource
from connect import TtyLog, Log, Session, user_have_perm from connect import TtyLog, Log, Session, user_have_perm, get_group_user_perm, MyRunner, ExecLog
try: try:
import simplejson as json import simplejson as json
...@@ -67,22 +67,6 @@ def require_auth(role='user'): ...@@ -67,22 +67,6 @@ def require_auth(role='user'):
except AttributeError: except AttributeError:
pass pass
logger.warning('Websocket: Request auth failed.') logger.warning('Websocket: Request auth failed.')
# asset_id = int(request.get_argument('id', 9999))
# print asset_id
# asset = Asset.objects.filter(id=asset_id)
# if asset:
# asset = asset[0]
# request.asset = asset
# else:
# request.close()
#
# if user:
# user = user[0]
# request.user = user
#
# else:
# print("No session user.")
# request.close()
return _deco2 return _deco2
return _deco return _deco
...@@ -138,6 +122,7 @@ class Application(tornado.web.Application): ...@@ -138,6 +122,7 @@ class Application(tornado.web.Application):
(r'/monitor', MonitorHandler), (r'/monitor', MonitorHandler),
(r'/terminal', WebTerminalHandler), (r'/terminal', WebTerminalHandler),
(r'/kill', WebTerminalKillHandler), (r'/kill', WebTerminalKillHandler),
(r'/exec', ExecHandler),
] ]
setting = { setting = {
...@@ -206,7 +191,6 @@ class MonitorHandler(tornado.websocket.WebSocketHandler): ...@@ -206,7 +191,6 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
class WebTty(Tty): class WebTty(Tty):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(WebTty, self).__init__(*args, **kwargs) super(WebTty, self).__init__(*args, **kwargs)
self.login_type = 'web'
self.ws = None self.ws = None
self.data = '' self.data = ''
self.input_mode = False self.input_mode = False
...@@ -225,6 +209,82 @@ class WebTerminalKillHandler(tornado.web.RequestHandler): ...@@ -225,6 +209,82 @@ class WebTerminalKillHandler(tornado.web.RequestHandler):
logger.debug('Websocket: web terminal client num: %s' % len(WebTerminalHandler.clients)) logger.debug('Websocket: web terminal client num: %s' % len(WebTerminalHandler.clients))
class ExecHandler(tornado.websocket.WebSocketHandler):
clients = []
tasks = []
def __init__(self, *args, **kwargs):
self.id = 0
self.user = None
self.role = None
self.runner = None
self.assets = []
self.perm = {}
self.remote_ip = ''
super(ExecHandler, self).__init__(*args, **kwargs)
def check_origin(self, origin):
return True
@require_auth('user')
def open(self):
logger.debug('Websocket: Open exec request')
role_name = self.get_argument('role', 'sb')
self.remote_ip = self.request.remote_ip
logger.debug('Web执行命令: 请求角色 %s' % role_name)
self.role = get_object(PermRole, name=role_name)
self.perm = get_group_user_perm(self.user)
roles = self.perm.get('role').keys()
if self.role not in roles:
self.write_message('No perm that role %s' % role_name)
self.close()
self.assets = self.perm.get('role').get(self.role).get('asset')
res = gen_resource({'user': self.user, 'asset': self.assets, 'role': self.role})
self.runner = MyRunner(res)
message = '有权限的主机: ' + ', '.join([asset.hostname for asset in self.assets])
self.__class__.clients.append(self)
self.write_message(message)
def on_message(self, message):
data = json.loads(message)
pattern = data.get('pattern', '')
command = data.get('command', '')
asset_name_str = ''
if pattern and command:
for inv in self.runner.inventory.get_hosts(pattern=pattern):
asset_name_str += '%s ' % inv.name
self.write_message('匹配主机: ' + asset_name_str)
self.write_message('<span style="color: yellow">Ansible> %s</span>\n\n' % command)
self.__class__.tasks.append(MyThread(target=self.run_cmd, args=(command, pattern)))
ExecLog(host=asset_name_str, cmd=command, user=self.user.username, remote_ip=self.remote_ip).save()
for t in self.__class__.tasks:
if t.is_alive():
continue
try:
t.setDaemon(True)
t.start()
except RuntimeError:
pass
def run_cmd(self, command, pattern):
self.runner.run('shell', command, pattern=pattern)
for k, v in self.runner.results.items():
for host, output in v.items():
if k == 'ok':
header = "<span style='color: green'>[ %s => %s]</span>\n" % (host, 'Ok')
else:
header = "<span style='color: red'>[ %s => %s]</span>\n" % (host, 'failed')
self.write_message(header)
self.write_message(output)
self.write_message('\n~o~ Task finished ~o~\n')
def on_close(self):
logger.debug('关闭web_exec请求')
class WebTerminalHandler(tornado.websocket.WebSocketHandler): class WebTerminalHandler(tornado.websocket.WebSocketHandler):
clients = [] clients = []
tasks = [] tasks = []
...@@ -236,6 +296,8 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): ...@@ -236,6 +296,8 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
self.log = None self.log = None
self.id = 0 self.id = 0
self.user = None self.user = None
self.ssh = None
self.channel = None
super(WebTerminalHandler, self).__init__(*args, **kwargs) super(WebTerminalHandler, self).__init__(*args, **kwargs)
def check_origin(self, origin): def check_origin(self, origin):
...@@ -250,7 +312,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): ...@@ -250,7 +312,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
if asset: if asset:
roles = user_have_perm(self.user, asset) roles = user_have_perm(self.user, asset)
logger.debug(roles) logger.debug(roles)
logger.debug('rolename: %s' % role_name) logger.debug('角色: %s' % role_name)
login_role = '' login_role = ''
for role in roles: for role in roles:
if role.name == role_name: if role.name == role_name:
...@@ -267,10 +329,10 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): ...@@ -267,10 +329,10 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
return return
logger.debug('Websocket: request web terminal Host: %s User: %s Role: %s' % (asset.hostname, self.user.username, logger.debug('Websocket: request web terminal Host: %s User: %s Role: %s' % (asset.hostname, self.user.username,
login_role.name)) login_role.name))
self.term = WebTty(self.user, asset, login_role) self.term = WebTty(self.user, asset, login_role, login_type='web')
self.term.remote_ip = self.request.remote_ip self.term.remote_ip = self.request.remote_ip
self.term.get_connection() self.ssh = self.term.get_connection()
self.term.channel = self.term.ssh.invoke_shell(term='xterm') self.channel = self.ssh.invoke_shell(term='xterm')
WebTerminalHandler.tasks.append(MyThread(target=self.forward_outbound)) WebTerminalHandler.tasks.append(MyThread(target=self.forward_outbound))
WebTerminalHandler.clients.append(self) WebTerminalHandler.clients.append(self)
...@@ -303,7 +365,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): ...@@ -303,7 +365,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
self.term.vim_data = '' self.term.vim_data = ''
self.term.data = '' self.term.data = ''
self.term.input_mode = False self.term.input_mode = False
self.term.channel.send(data['data']) self.channel.send(data['data'])
def on_close(self): def on_close(self):
logger.debug('Websocket: Close request') logger.debug('Websocket: Close request')
...@@ -326,9 +388,9 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): ...@@ -326,9 +388,9 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
data = '' data = ''
pre_timestamp = time.time() pre_timestamp = time.time()
while True: while True:
r, w, e = select.select([self.term.channel, sys.stdin], [], []) r, w, e = select.select([self.channel, sys.stdin], [], [])
if self.term.channel in r: if self.channel in r:
recv = self.term.channel.recv(1024) recv = self.channel.recv(1024)
if not len(recv): if not len(recv):
return return
data += recv data += recv
...@@ -347,8 +409,8 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): ...@@ -347,8 +409,8 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
data = '' data = ''
except UnicodeDecodeError: except UnicodeDecodeError:
pass pass
finally: except IndexError:
self.close() pass
if __name__ == '__main__': if __name__ == '__main__':
tornado.options.parse_command_line() tornado.options.parse_command_line()
......
...@@ -2822,7 +2822,9 @@ body.body-small .footer.fixed { ...@@ -2822,7 +2822,9 @@ body.body-small .footer.fixed {
.table > thead > tr > td, .table > thead > tr > td,
.table > tbody > tr > td, .table > tbody > tr > td,
.table > tfoot > tr > td { .table > tfoot > tr > td {
border-top: 1px solid #e7eaec; /*border-top: 1px solid #e7eaec;*/
border-bottom: 1px solid #e7eaec;
border-top: none;
line-height: 1.42857; line-height: 1.42857;
padding: 8px; padding: 8px;
vertical-align: top; vertical-align: top;
......
...@@ -16,9 +16,9 @@ function check_all(form) { ...@@ -16,9 +16,9 @@ function check_all(form) {
} }
} }
function checkAll(){ function checkAll(id, name){
var checklist = document.getElementsByName ("checked"); var checklist = document.getElementsByName(name);
if(document.getElementById("check_all").checked) if(document.getElementById(id).checked)
{ {
for(var i=0;i<checklist.length;i++) for(var i=0;i<checklist.length;i++)
{ {
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
...@@ -12,8 +11,6 @@ ...@@ -12,8 +11,6 @@
{% include 'link_css.html' %} {% include 'link_css.html' %}
{% include 'head_script.html' %} {% include 'head_script.html' %}
{% block self_head_css_js %} {% endblock %} {% block self_head_css_js %} {% endblock %}
</head> </head>
<body> <body>
......
{% extends 'base.html' %} {% extends 'base.html' %}
{% load mytags %} {% load mytags %}
{% block self_head_css_js %}
<link href="/static/css/plugins/datepicker/datepicker3.css" rel="stylesheet">
<link href="/static/css/plugins/chosen/chosen.css" rel="stylesheet">
<script src="/static/js/plugins/chosen/chosen.jquery.js"></script>
{% endblock %}
{% block content %} {% block content %}
{% include 'nav_cat_bar.html' %} {% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeIn"> <div class="wrapper wrapper-content animated fadeIn">
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-sm-12">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5>下载文件</h5> <h5>下载文件</h5>
...@@ -16,30 +21,62 @@ ...@@ -16,30 +21,62 @@
<a class="dropdown-toggle" data-toggle="dropdown" href="#"> <a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">Config option 1</a>
</li>
<li><a href="#">Config option 2</a>
</li>
</ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>
</div> </div>
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<h2>下载文件可联系管理员在服务器安装lrzsz,使用sz命令下载。 </h2> <form id="downForm" class="form-horizontal" method="post">
<div> {% if error %}
{% for document in documents %} <div class="alert alert-warning text-center">{{ error }}</div>
<a href="/download/{{ document }}">{{ document }}</a> {% endif %}
{% endfor %} {% if msg %}
</div> <div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
<div class="form-group">
<label for="file_path" class="col-sm-2 control-label">文件路径<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="file_path" name="file_path" placeholder="File Path" type="text" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="user" class="col-sm-2 control-label">选择主机<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="asset_ids" id="asset_ids" data-placeholder="请输入" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset in assets %}
<option value="{{ asset.id }}">{{ asset.hostname }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">取消</button>
<button id="submit_button" class="btn btn-primary" type="submit">下载</button>
</div>
</div>
</form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% endblock %}
{% block self_footer_js %}
<script>
var config = {
'.chosen-select' : {},
'.chosen-select-deselect' : {allow_single_deselect:true},
'.chosen-select-no-single' : {disable_search_threshold:10},
'.chosen-select-no-results': {no_results_text:'Oops, nothing found!'},
'.chosen-select-width' : {width:"95%"}
};
for (var selector in config) {
$(selector).chosen(config[selector]);
}
</script>
{% endblock %} {% endblock %}
\ No newline at end of file
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=320, initial-scale=1">
<title>Jumpserver Exec Terminal</title>
<style type="text/css"></style>
</head>
<body>
<div id="wrapper">
<div id="chat_box" class="content">
<p class="system"></p>
</div>
<div id="footer">
<div class="content">
<input type="text" id="pattern" value="{{ check_assets }}" placeholder="Ansible Pattern">
<input type="text" id="command" placeholder="Command to execute">
<input type="button" id="send_btn" value="Send" onclick="sendMessage()">
</div>
</div>
</div>
<script type="text/javascript">
var wsUri = "{{ web_terminal_uri }}"; //请求的websocket url
var ws = new WebSocket(wsUri);
function createSystemMessage(message) {
var message = document.createTextNode(message);
var messageBox = document.createElement('p');
messageBox.className = 'system';
messageBox.appendChild(message);
var chat = document.getElementById('chat_box');
chat.appendChild(messageBox);
}
function createUserMessage(message) {
message = message.replace('/\n/g', '<br>');
var messageOb = document.createElement('div');
messageOb.innerHTML = message;
var messageBox = document.createElement('p');
messageBox.appendChild(messageOb);
var chat = document.getElementById('chat_box');
chat.appendChild(messageBox);
}
ws.onopen = function(ev) {
createSystemMessage('[Connected]');
};
ws.onclose = function(ev) {
createSystemMessage('[Disconnected]');
};
ws.onmessage = function(ev) {
createUserMessage(ev.data);
var chat = document.getElementById('chat_box');
chat.scrollTop = chat.scrollHeight;
};
function sendMessage() {
var pattern = document.getElementById('pattern');
var command = document.getElementById('command');
var data = {
pattern: pattern.value,
command: command.value,
{# ts: (new Date()).getTime()#}
};
ws.send(JSON.stringify(data));
command.value = ''
}
</script>
<style type="text/css">
* {
font-family: "Monaco", "DejaVu Sans Mono", "Liberation Mono", monospace;
font-size: 11px;
}
html, body {
margin: 0;
padding: 0;
height: 100%;
background-color: #fff;
}
#wrapper {
{# background-color: #ecf0f1;#}
{# border: #000 solid 5px;#}
background: #000;
width: 800px;
box-shadow: rgba(0, 0, 0, 0.8) 2px 2px 20px;
color: #fff;
}
#chat_box {
box-sizing: border-box;
height: 100%;
overflow: auto;
padding-bottom: 50px;
}
#footer {
box-sizing: border-box;
position: fixed;
bottom: 0;
height: 50px;
width: 800px;
{# border: #000 solid -10px;#}
background-color: #2980b9;
}
#footer .content {
padding-top: 4px;
position: relative;
}
#pattern { width: 25%; }
#command { width: 60%; }
#send_btn {
width: 10%;
{# position: absolute;#}
margin-left: 5px;
right: 0;
bottom: 0;
}
.content {
width: 800px;
margin-left: 5px;
}
input[type="text"],
input[type="button"] {
border: 0;
color: #fff;
}
input[type="text"] {
background-color: #146EA8;
padding: 3px 10px;
}
input[type="button"] {
background-color: #f39c12;
border-right: 2px solid #e67e22;
border-bottom: 2px solid #e67e22;
min-width: 70px;
display: inline-block;
}
input[type="button"]:hover {
background-color: #e67e22;
border-right: 2px solid #f39c12;
border-bottom: 2px solid #f39c12;
cursor: pointer;
}
.system,
.username {
color: #aaa;
font-style: italic;
font-family: monospace;
font-size: 16px;
}
@media(max-width: 1000px) {
.content { width: 90%; }
}
@media(max-width: 780px) {
#footer { height: 91px; }
#chat_box { padding-bottom: 91px; }
#user { width: 100%; }
#message { width: 80%; }
}
@media(max-width: 400px) {
#footer { height: 135px; }
#chat_box { padding-bottom: 135px; }
#message { width: 100%; }
#send_btn {
position: relative;
margin-top: 3px;
width: 100%;
}
}
</style>
</body>
<div></div>
<div></div>
</html>
\ No newline at end of file
<div class="footer fixed"> <div class="footer fixed">
<div class="pull-right"> <div class="pull-right">
Version <strong>0.2.0</strong> GPL. Version <strong>0.3.0</strong> GPL.
</div> </div>
<div> <div>
<strong>Copyright</strong> Jumpserver.org Team &copy; 2014-2015 <strong>Copyright</strong> Jumpserver.org Team &copy; 2014-2015
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<div class="wrapper wrapper-content"> <div class="wrapper wrapper-content">
<div class="row"> <div class="row">
<div class="col-lg-3"> <div class="col-sm-3">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-success pull-right">Users</span> <span class="label label-success pull-right">Users</span>
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-3"> <div class="col-sm-3">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-info pull-right">Hosts</span> <span class="label label-info pull-right">Hosts</span>
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
</div> </div>
</div> </div>
<div class="col-lg-3"> <div class="col-sm-3">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-primary pull-right">Online</span> <span class="label label-primary pull-right">Online</span>
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
</div> </div>
</div> </div>
<div class="col-lg-3"> <div class="col-sm-3">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-danger pull-right">Connected</span> <span class="label label-danger pull-right">Connected</span>
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
</ul> </ul>
</div> </div>
<div class="col-sm-7" id="top10" style="margin-left: -15px;height: 346px;padding: 15px 0 15px 0;"></div> <div class="col-sm-7" id="top10" style="margin-left: -15px;height: 346px;padding: 15px 0 15px 0;"></div>
<div class="col-lg-3 white-bg" id="top1" style="margin-left: -15px;height: 346px"> <div class="col-sm-3 white-bg" id="top1" style="margin-left: -15px;height: 346px">
<div class="statistic-box"> <div class="statistic-box">
<h4> <h4>
活跃用户资产占比 活跃用户资产占比
...@@ -83,13 +83,13 @@ ...@@ -83,13 +83,13 @@
以下图形分别描述一个月活跃用户和资产占所有用户主机的百分比 以下图形分别描述一个月活跃用户和资产占所有用户主机的百分比
</p> </p>
<div class="row text-center"> <div class="row text-center">
<div class="col-lg-6"> <div class="col-sm-6">
<div id="activeUser" style="width: 140px; height: 140px;"> <div id="activeUser" style="width: 140px; height: 140px;">
</div> </div>
<h5>用户</h5> <h5>用户</h5>
</div> </div>
<div class="col-lg-6"> <div class="col-sm-6">
<div id="activeAsset" style="width: 140px; height: 140px;"></div> <div id="activeAsset" style="width: 140px; height: 140px;"></div>
<h5>主机</h5> <h5>主机</h5>
</div> </div>
...@@ -103,7 +103,7 @@ ...@@ -103,7 +103,7 @@
<br/> <br/>
<div class="row"> <div class="row">
<div class="col-lg-4"> <div class="col-sm-4">
{# <div class="ibox float-e-margins">#} {# <div class="ibox float-e-margins">#}
{# <div class="ibox-title">#} {# <div class="ibox-title">#}
{# <h5>权限申请</h5>#} {# <h5>权限申请</h5>#}
...@@ -192,7 +192,7 @@ ...@@ -192,7 +192,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5>最近十次登录</h5> <h5>最近十次登录</h5>
...@@ -258,7 +258,7 @@ ...@@ -258,7 +258,7 @@
</div> </div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5>一周Top10用户</h5> <h5>一周Top10用户</h5>
......
This diff is collapsed.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
{% include 'nav_cat_bar.html' %} {% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 填写资产基本信息 </h5> <h5> 填写资产基本信息 </h5>
...@@ -76,9 +76,9 @@ ...@@ -76,9 +76,9 @@
<div class="form-group" id="id_port"> <div class="form-group" id="id_port">
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<label class="col-sm-2 control-label"> 端口<span class="red-fonts">*</span> </label> <label class="col-sm-2 control-label"> 端口<span class="red-fonts">*</span> </label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="text" placeholder="Port" name="port" class="form-control" value="{{ default_port }}"> <input type="text" placeholder="Port" name="port" class="form-control" value="{{ default_port }}">
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
...@@ -118,14 +118,23 @@ ...@@ -118,14 +118,23 @@
{% block self_footer_js %} {% block self_footer_js %}
<script> <script>
$('document').ready(function(){ $('document').ready(function(){
$('#id_use_default_auth').click(function(){ var check_default = "{{ default_setting.name }}";
if ($(this).is(':checked')){ console.log(check_default);
$('#admin_account').css('display', 'none'); if (check_default != 'default'){
} $('#id_use_default_auth').attr('disabled', true);
else { $('#id_use_default_auth').attr('checked', false);
$('#admin_account').css('display', 'block'); $('#admin_account').css('display', 'block');
} } else {
}) $('#id_use_default_auth').click(function(){
if ($(this).is(':checked')){
$('#admin_account').css('display', 'none');
}
else {
$('#admin_account').css('display', 'block');
}
})
}
}); });
var required_fields = ["id_hostname", "id_port"]; var required_fields = ["id_hostname", "id_port"];
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
</style> </style>
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 填写主机基本信息 </h5> <h5> 填写主机基本信息 </h5>
......
This diff is collapsed.
This diff is collapsed.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
{% include 'nav_cat_bar.html' %} {% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 修改资产基本信息 </h5> <h5> 修改资产基本信息 </h5>
...@@ -46,6 +46,9 @@ ...@@ -46,6 +46,9 @@
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
{{ af.remote_ip|bootstrap_horizontal }} {{ af.remote_ip|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
{{ af.mac|bootstrap_horizontal }}
{# <div class="hr-line-dashed"></div>#} {# <div class="hr-line-dashed"></div>#}
{# {{ af.port|bootstrap_horizontal }}#} {# {{ af.port|bootstrap_horizontal }}#}
...@@ -105,6 +108,9 @@ ...@@ -105,6 +108,9 @@
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
{{ af.system_version|bootstrap_horizontal }} {{ af.system_version|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
{{ af.system_arch|bootstrap_horizontal }}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
{{ af.number|bootstrap_horizontal }} {{ af.number|bootstrap_horizontal }}
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<body> <body>
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
{# <div class="ibox-title">#} {# <div class="ibox-title">#}
{# <h5 class="text-center"> 填写修改主机信息. </h5>#} {# <h5 class="text-center"> 填写修改主机信息. </h5>#}
......
This diff is collapsed.
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 填写主机组基本信息 </h5> <h5> 填写主机组基本信息 </h5>
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 填写主机组基本信息 </h5> <h5> 填写主机组基本信息 </h5>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5> 主机组详细信息列表</h5> <h5> 主机组详细信息列表</h5>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
{% include 'nav_cat_bar.html' %} {% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 填写IDC基本信息 </h5> <h5> 填写IDC基本信息 </h5>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
{% include 'nav_cat_bar.html' %} {% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 填写IDC基本信息 </h5> <h5> 填写IDC基本信息 </h5>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5> IDC详细信息列表</h5> <h5> IDC详细信息列表</h5>
......
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="label label-primary"><b>{{ log.id }}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div>
<div class="text-left">
<table class="table">
<tr>
<td class="text-navy">ID</td>
<td>{{ log.id }}</td>
</tr>
<tr>
<td class="text-navy">用户名</td>
<td>{{ log.user }}</td>
</tr>
<tr>
<td class="text-navy">来源IP</td>
<td>{{ log.remote_ip }}</td>
</tr>
<tr>
<td class="text-navy">日期</td>
<td>{{ log.datetime|date:"Y-m-d H:i:s" }}</td>
</tr>
<tr>
<td class="text-navy">主机</td>
<td>
<table class="table">
{% for asset_name in assets_hostname %}
{% if asset_name %}
<tr>
<td>{{ asset_name }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-8">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>结果</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content inspinia-timeline">
<div>
<div class="text-left">
<table class="table">
<tr>
<td class="text-navy">命令</td>
<td>{{ log.cmd }}</td>
</tr>
{% for result, info in result.items %}
{% for host, msg in info.items %}
{% ifequal result 'failed' %}
<tr>
<td class="text-navy" style="color: #ed5565">{{ host }}</td>
<td>{{ msg }}</td>
</tr>
{% else %}
<tr>
<td class="text-navy">{{ host }}</td>
<td>{{ msg }}</td>
</tr>
{% endifequal %}
{% endfor %}
{% endfor %}
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('#show').click(function(){
$('#last').css('display', 'none');
$('#all').css('display', 'block');
})
})
</script>
{% endblock %}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-sm-12">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 用户日志详细信息列表 </h5> <h5> 用户日志详细信息列表 </h5>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-sm-12">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 用户{{ username }}日志详细信息列表 </h5> <h5> 用户{{ username }}日志详细信息列表 </h5>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5> {{ user_group.name }}授权修改</h5> <h5> {{ user_group.name }}授权修改</h5>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment