diff --git a/.gitignore b/.gitignore
index 2c3064f75..983fedd49 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,6 +37,7 @@ nosetests.xml
.mr.developer.cfg
.project
.pydevproject
+*.log
logs/*
keys/*
jumpserver.conf
diff --git a/connect.py b/connect.py
index 60f0daebb..8558ed745 100644
--- a/connect.py
+++ b/connect.py
@@ -19,8 +19,8 @@ import struct, fcntl, signal, socket, select
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
if django.get_version() != '1.6':
django.setup()
-from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object
-from jumpserver.api import logger, mkdir, Log, TtyLog
+from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir
+from jumpserver.api import logger, Log, TtyLog
from jumpserver.settings import LOG_DIR
@@ -68,9 +68,6 @@ def check_vim_status(command, ssh):
return False
-
-
-
class Tty(object):
"""
A virtual tty class
@@ -252,6 +249,7 @@ class Tty(object):
log_file_path = os.path.join(today_connect_log_dir, '%s_%s_%s' % (self.username, self.asset_name, time_start))
try:
+ mkdir(os.path.dirname(today_connect_log_dir), mode=0777)
mkdir(today_connect_log_dir, mode=0777)
except OSError:
logger.debug('创建目录 %s 失败,请修改%s目录权限' % (today_connect_log_dir, tty_log_dir))
@@ -289,7 +287,7 @@ class Tty(object):
# 2. get 映射用户
# 3. get 映射用户的账号,密码或者key
# self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_key': ''}
- self.connect_info = {'user': 'a', 'asset': 'b', 'ip': '127.0.0.1', 'port': 22, 'role_name': 'root', 'role_pass': '', 'role_key': '/root/.ssh/id_rsa.bak'}
+ self.connect_info = {'user': 'a', 'asset': 'b', 'ip': '127.0.0.1', 'port': 22, 'role_name': 'root', 'role_pass': 'redhat', 'role_key': ''}
return self.connect_info
def get_connection(self):
@@ -452,7 +450,7 @@ class SshTty(Tty):
#print 'ok'+tmp+'ok'
# SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip()
# SSH_TTY = ''
- channel.send('clear\n')
+ # channel.send('clear\n')
# Make ssh interactive tunnel
self.posix_shell()
@@ -468,20 +466,83 @@ class SshTty(Tty):
pass
-def print_prompt():
- """
- Print prompt
- 打印提示导航
- """
- msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m
- 1) Type \033[32mIP or Part IP, Host Alias or Comments \033[0m To Login.
- 2) Type \033[32mP/p\033[0m To Print The Servers You Available.
- 3) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
- 4) Type \033[32mG/g(1-N)\033[0m To Print The Server Group Hosts You Available.
- 5) Type \033[32mE/e\033[0m To Execute Command On Several Servers.
- 6) Type \033[32mQ/q\033[0m To Quit.
- """
- print textwrap.dedent(msg)
+def print_user_asset_group_info(user):
+ asset_groups = AssetGroup.objects.all()
+ for asset_group in asset_groups:
+ if asset_group.comment:
+ print '[%-2s] %-10s %s' % (asset_group.id, asset_group.name, asset_group.comment)
+ else:
+ print '[%-2s] %-10s' % (asset_group.id, asset_group.name)
+ print
+
+
+class Nav(object):
+ def __init__(self, user):
+ self.user = user
+ self.search_result = {}
+
+ @staticmethod
+ def print_nav():
+ """
+ Print prompt
+ 打印提示导航
+ """
+ msg = """\n\033[1;32m### Welcome To Use JumpServer, A Open Source System . ### \033[0m
+ 1) Type \033[32mID\033[0m To Login.
+ 2) Type \033[32m/\033[0m + \033[32mIP, Host Name, Host Alias or Comments \033[0mTo Search.
+ 3) Type \033[32mP/p\033[0m To Print The Servers You Available.
+ 4) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
+ 5) Type \033[32mG/g\033[0m\033[0m + \033[32mGroup ID\033[0m To Print The Server Group You Available.
+ 6) Type \033[32mE/e\033[0m To Execute Command On Several Servers.
+ 7) Type \033[32mQ/q\033[0m To Quit.
+ """
+
+ msg = """\n\033[1;32m### 欢迎使用Jumpserver开源跳板机 ### \033[0m
+ 1) 输入 \033[32mID\033[0m 直接登录.
+ 2) 输入 \033[32m/\033[0m + \033[32mIP, 主机名, 主机别名 or 备注 \033[0m搜索.
+ 3) 输入 \033[32mP/p\033[0m 显示您有权限的主机.
+ 4) 输入 \033[32mG/g\033[0m 显示您有权限的主机组.
+ 5) 输入 \033[32mG/g\033[0m\033[0m + \033[32m组ID\033[0m 显示该组下主机.
+ 6) 输入 \033[32mE/e\033[0m 批量执行命令.
+ 7) 输入 \033[32mQ/q\033[0m 退出.
+ """
+ print textwrap.dedent(msg)
+
+ def search(self, str_r=''):
+ gid_pattern = re.compile(r'^g\d+$')
+ user_asset_all = list(Asset.objects.all())
+ user_asset_search = []
+ if str_r:
+ if gid_pattern.match(str_r):
+ user_asset_search = list(Asset.objects.all())
+ else:
+ for asset in user_asset_all:
+ if str_r in asset.ip or str_r in str(asset.comment):
+ user_asset_search.append(asset)
+ else:
+ user_asset_search = user_asset_all
+
+ self.search_result = dict(zip(range(len(user_asset_search)), user_asset_search))
+
+ print '\033[32m[%-3s] %-15s %-15s %-5s %-5s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment')
+ for index, asset in self.search_result.items():
+ if asset.comment:
+ print '[%-3s] %-15s %-15s %-5s %-5s %s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role', asset.comment)
+ else:
+ print '[%-3s] %-15s %-15s %-5s %-5s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role')
+ print
+
+ @staticmethod
+ def print_asset_group():
+ user_asset_group_all = AssetGroup.objects.all()
+
+ print '\033[32m[%-3s] %-15s %s \033[0m' % ('ID', 'GroupName', 'Comment')
+ for asset_group in user_asset_group_all:
+ if asset_group.comment:
+ print '[%-3s] %-15s %s' % (asset_group.id, asset_group.name, asset_group.comment)
+ else:
+ print '[%-3s] %-15s' % (asset_group.id, asset_group.name)
+ print
def main():
@@ -492,29 +553,26 @@ def main():
if not login_user: # 判断用户是否存在
color_print(u'没有该用户,或许你是以root运行的 No that user.', exits=True)
- print_prompt()
gid_pattern = re.compile(r'^g\d+$')
+ nav = Nav(login_user)
+ nav.print_nav()
try:
while True:
try:
- option = raw_input("\033[1;32mOpt or IP>:\033[0m ")
+ option = raw_input("\033[1;32mOpt or ID>:\033[0m ").strip()
except EOFError:
- print_prompt()
+ nav.print_nav()
continue
except KeyboardInterrupt:
sys.exit(0)
- if option in ['P', 'p']:
- login_user.get_asset_info(printable=True)
+ if option in ['P', 'p', '\n', '']:
+ nav.search()
continue
+ if option.startswith('/') or gid_pattern.match(option):
+ nav.search(option.lstrip('/'))
elif option in ['G', 'g']:
- login_user.get_asset_group_info(printable=True)
- continue
- elif gid_pattern.match(option):
- gid = option[1:].strip()
- asset_group = get_object(AssetGroup, id=gid)
- if asset_group and asset_group.is_permed(user=login_user):
- asset_group.get_asset_info(printable=True)
+ nav.print_asset_group()
continue
elif option in ['E', 'e']:
# exec_cmd_servers(login_name)
@@ -523,7 +581,11 @@ def main():
sys.exit()
else:
try:
- verify_connect(login_user, option)
+ asset = nav.search_result[int(option)]
+ ssh_tty = SshTty('a', 'b')
+ ssh_tty.connect()
+ except (KeyError, ValueError):
+ color_print('请输入正确ID', 'red')
except ServerError, e:
color_print(e, 'red')
except IndexError:
diff --git a/docs/requirements.txt b/docs/requirements.txt
index ea56ab0c6..28d7b9137 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,6 +1,5 @@
sphinx-me==0.3
django==1.6
-python-ldap==2.4.19
pycrypto==2.6.1
paramiko==1.15.2
ecdsa==0.13
@@ -9,4 +8,9 @@ django-uuidfield==0.5.0
psutil==2.2.1
xlsxwriter==0.7.7
xlrd==0.9.4
-django-bootstrap-form
\ No newline at end of file
+django-bootstrap-form
+tornado
+ansible
+pyinotify
+passlib
+argparse
\ No newline at end of file
diff --git a/jasset/asset_api.py b/jasset/asset_api.py
index 998d669c5..8103db23b 100644
--- a/jasset/asset_api.py
+++ b/jasset/asset_api.py
@@ -311,8 +311,12 @@ def write_excel(asset_all):
group_all = '/'.join(group_list)
status = asset.get_status_display()
idc_name = asset.idc.name if asset.idc else u''
+ system_type = asset.system_type if asset.idc else u''
+ system_version = asset.system_version if asset.idc else u''
+ 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,
- asset.disk, (asset.system_type + asset.system_version), asset.cabinet, group_all, status,
+ asset.disk, system_os, asset.cabinet, group_all, status,
asset.comment]
data.append(alter_dic)
format = workbook.add_format()
@@ -381,13 +385,13 @@ def excel_to_db(excel_file):
row = table.row_values(row_num)
if row:
ip, port, hostname, use_default_auth, username, password, group = row
- print ip
use_default_auth = 1 if use_default_auth == u'默认' else 0
if get_object(Asset, ip=ip):
continue
if ip and port:
asset = Asset(ip=ip,
port=port,
+ hostname=hostname,
use_default_auth=use_default_auth,
username=username,
password=password
diff --git a/jasset/models.py b/jasset/models.py
index e011302a2..f1e5b46fc 100644
--- a/jasset/models.py
+++ b/jasset/models.py
@@ -37,8 +37,8 @@ class AssetGroup(models.Model):
class IDC(models.Model):
name = models.CharField(max_length=32, verbose_name=u'机房名称')
bandwidth = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机房带宽')
- linkman = models.CharField(max_length=16, null=True, verbose_name=u'联系人')
- phone = models.CharField(max_length=32, verbose_name=u'联系电话')
+ linkman = models.CharField(max_length=16, blank=True, null=True, verbose_name=u'联系人')
+ phone = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'联系电话')
address = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"机房地址")
network = models.TextField(blank=True, null=True, verbose_name=u"IP地址段")
date_added = models.DateField(auto_now=True, null=True)
diff --git a/jasset/views.py b/jasset/views.py
index 8427f9f67..71448f22a 100644
--- a/jasset/views.py
+++ b/jasset/views.py
@@ -2,9 +2,9 @@
import ast
from django.db.models import Q
-from django.shortcuts import get_object_or_404
from jasset.asset_api import *
from jumpserver.api import *
+from jumpserver.models import Setting
from jasset.forms import AssetForm, IdcForm
from jasset.models import Asset, IDC, AssetGroup, ASSET_TYPE, ASSET_STATUS
from ansible_api import Tasks
@@ -13,7 +13,7 @@ from ansible_api import Tasks
@require_role('admin')
def group_add(request):
"""
- Add asset group
+ Group add view
添加资产组
"""
header_title, path1, path2 = u'添加资产组', u'资产管理', u'添加资产组'
@@ -47,7 +47,7 @@ def group_add(request):
@require_role('admin')
def group_edit(request):
"""
- Edit asset group
+ Group edit view
编辑资产组
"""
header_title, path1, path2 = u'编辑主机组', u'资产管理', u'编辑主机组'
@@ -89,7 +89,10 @@ def group_edit(request):
@require_role('admin')
def group_detail(request):
- """ 主机组详情 """
+ """
+ Group detail view
+ 主机组详情
+ """
header_title, path1, path2 = u'主机组详情', u'资产管理', u'主机组详情'
group_id = request.GET.get('id', '')
group = get_object(AssetGroup, id=group_id)
@@ -121,7 +124,7 @@ def group_list(request):
@require_role('admin')
def group_del(request):
"""
- del asset group
+ Group delete view
删除主机组
"""
group_ids = request.GET.get('id', '')
@@ -160,7 +163,7 @@ def asset_add(request):
asset_save = af_post.save(commit=False)
if not use_default_auth:
password = request.POST.get('password', '')
- password_encode = CRYPTOR.encrypt(password)
+ password_encode = password
asset_save.password = password_encode
asset_save.is_active = True if is_active else False
asset_save.save()
@@ -293,7 +296,7 @@ def asset_list(request):
s = write_excel(asset_find)
if s[0]:
file_name = s[1]
- smg = 'excel文件已生成,请点击下载!'
+ smg = u'excel文件已生成,请点击下载!'
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)
return my_render('jasset/asset_list.html', locals(), request)
@@ -330,13 +333,20 @@ def asset_update(request):
return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id)
name = request.session.get('username', 'admin')
if asset.use_default_auth:
- username = 'root'
- password = '123456'
+ default = Setting.objects.all()
+ if default:
+ default = default[0]
+ username = default.default_user
+ password = default.default_password
+ port = default.default_port
+ else:
+ return HttpResponse(u'没有设置默认用户名和密码!')
else:
username = asset.username
password = asset.password
+ port = asset.port
- resource = [{"hostname": asset.ip, "port": asset.port,
+ resource = [{"hostname": asset.ip, "port": port,
"username": username, "password": password}]
ansible_instance = Tasks(resource)
@@ -446,16 +456,17 @@ def idc_del(request):
"""
IDC delete view
"""
- uuid = request.GET.get('uuid', '')
- idc = get_object_or_404(IDC, uuid=uuid)
- idc.delete()
+ uuid = request.GET.get('id', '')
+ idc = get_object(IDC, id=uuid)
+ if idc:
+ idc.delete()
return HttpResponseRedirect('/jasset/idc_list/')
@require_role('admin')
def asset_upload(request):
"""
- Upload file view
+ Upload asset excel file view
"""
if request.method == 'POST':
excel_file = request.FILES.get('file_name', '')
diff --git a/jperm/ansible_api.py b/jperm/ansible_api.py
index 2e89008fc..4e66da246 100644
--- a/jperm/ansible_api.py
+++ b/jperm/ansible_api.py
@@ -15,11 +15,11 @@ from utils import get_rand_pass
import os.path
+
API_DIR = os.path.dirname(os.path.abspath(__file__))
ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks')
-
class AnsibleError(StandardError):
"""
the base AnsibleError which contains error(required),
@@ -61,7 +61,7 @@ class MyInventory(object):
[{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...]
"""
self.resource = resource
- self.inventory = Inventory()
+ self.inventory = Inventory(host_list=[])
self.gen_inventory()
def add_group(self, hosts, groupname, groupvars=None):
@@ -101,7 +101,7 @@ class MyInventory(object):
add hosts to inventory.
"""
if isinstance(self.resource, list):
- self.add_group(self.resource, 'my_group')
+ self.add_group(self.resource, 'default_group')
elif isinstance(self.resource, dict):
for groupname, hosts_and_vars in self.resource.iteritems():
self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
@@ -115,21 +115,23 @@ class Command(MyInventory):
super(Command, self).__init__(*args, **kwargs)
self.results = ''
- def run(self, command, module_name="command", timeout=5, forks=10, group='my_group'):
+ def run(self, command, module_name="command", timeout=10, forks=10, group='default_group', pattern='*'):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串, 比如
'uname -a'
"""
+
if module_name not in ["raw", "command", "shell"]:
- raise CommandValueError("module_name",
+ raise CommandValueError("module_name",
"module_name must be of the 'raw, command, shell'")
hoc = Runner(module_name=module_name,
module_args=command,
timeout=timeout,
inventory=self.inventory,
subset=group,
- forks=forks
+ pattern=pattern,
+ forks=forks,
)
self.results = hoc.run()
@@ -203,7 +205,7 @@ class Tasks(Command):
def __init__(self, *args, **kwargs):
super(Tasks, self).__init__(*args, **kwargs)
- def __run(self, module_args, module_name="command", timeout=5, forks=10, group='my_group'):
+ def __run(self, module_args, module_name="command", timeout=5, forks=10, group='default_group', pattern='*'):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串, 比如
@@ -214,7 +216,8 @@ class Tasks(Command):
timeout=timeout,
inventory=self.inventory,
subset=group,
- forks=forks
+ pattern=pattern,
+ forks=forks,
)
self.results = hoc.run()
@@ -425,7 +428,6 @@ class MyPlaybook(MyInventory):
def __init__(self, *args, **kwargs):
super(MyPlaybook, self).__init__(*args, **kwargs)
-
def run(self, playbook_relational_path, extra_vars=None):
"""
run ansible playbook,
@@ -464,7 +466,6 @@ class App(MyPlaybook):
if __name__ == "__main__":
- pass
# resource = {
# "group1": {
@@ -472,8 +473,10 @@ if __name__ == "__main__":
# "vars" : {"var1": "value1", "var2": "value2"},
# },
# }
-# command = Command(resource)
-# print command.run("who", group="group1")
+
+ resource = [{"hostname": "127.0.0.1", "port": "22", "username": "yumaojun", "password": "yusky0902"}]
+ command = Command(resource)
+ print command.run("who")
# resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}]
# task = Tasks(resource)
diff --git a/jperm/models.py b/jperm/models.py
index 2bcea14e3..dc8643b67 100644
--- a/jperm/models.py
+++ b/jperm/models.py
@@ -32,14 +32,13 @@ class PermRole(models.Model):
class PermRule(models.Model):
date_added = models.DateTimeField(auto_now=True)
- name = models.CharField(max_length=100)
+ name = models.CharField(max_length=100, unique=True)
comment = models.CharField(max_length=100)
asset = models.ManyToManyField(Asset, related_name='perm_rule')
asset_group = models.ManyToManyField(AssetGroup, related_name='perm_rule')
user = models.ManyToManyField(User, related_name='perm_rule')
user_group = models.ManyToManyField(UserGroup, related_name='perm_rule')
role = models.ManyToManyField(PermRole, related_name='perm_rule')
- ssh_type = models.BooleanField()
def __unicode__(self):
return self.name
\ No newline at end of file
diff --git a/jperm/perm_api.py b/jperm/perm_api.py
index c04aeda52..1b363f547 100644
--- a/jperm/perm_api.py
+++ b/jperm/perm_api.py
@@ -89,7 +89,7 @@ def perm_user_api(perm_info):
the_new_users = ','.join(new_username)
the_del_users = ','.join(del_username)
- playbook = get_playbook(os.path.join(BASE_DIR, 'playbook', 'user_perm.yaml'),
+ playbook = get_playbook(os.path.join(BASE_DIR, 'keys/../playbook', 'user_perm.yaml'),
{'the_new_group': 'new', 'the_del_group': 'del',
'the_new_users': the_new_users, 'the_del_users': the_del_users,
'KEY_DIR': os.path.join(SSH_KEY_DIR, 'sysuser')})
diff --git a/jperm/utils.py b/jperm/utils.py
index 12756b773..c8acff371 100644
--- a/jperm/utils.py
+++ b/jperm/utils.py
@@ -4,7 +4,7 @@ import random
import os.path
from paramiko.rsakey import RSAKey
-from os import chmod, mkdir
+from jumpserver.api import mkdir
from uuid import uuid4
from jumpserver.settings import KEY_DIR
@@ -45,9 +45,8 @@ def gen_keys():
:return: 返回目录名(uuid)
"""
key_basename = "key-" + uuid4().hex
- key_path_dir = os.path.join(KEY_DIR, key_basename)
- mkdir(key_path_dir, 0700)
-
+ key_path_dir = os.path.join(KEY_DIR, 'role_key', key_basename)
+ mkdir(key_path_dir, 0755)
key = RSAKey.generate(2048)
private_key = os.path.join(key_path_dir, 'id_rsa')
public_key = os.path.join(key_path_dir, 'id_rsa.pub')
@@ -62,8 +61,6 @@ def gen_keys():
return key_path_dir
-
-
if __name__ == "__main__":
print gen_keys()
diff --git a/jperm/views.py b/jperm/views.py
index 2685d6bd6..f961a8e07 100644
--- a/jperm/views.py
+++ b/jperm/views.py
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
-
from django.db.models import Q
from jperm.perm_api import *
from jperm.models import PermLog as Log
@@ -11,12 +10,13 @@ from juser.user_api import gen_ssh_key
from juser.models import User, UserGroup
from jasset.models import Asset, AssetGroup
from jperm.models import PermRole, PermRule
+from jumpserver.models import Setting
from jperm.utils import updates_dict, gen_keys, get_rand_pass
from jperm.ansible_api import Tasks
from jperm.perm_api import get_role_info
-from jumpserver.api import my_render, get_object
+from jumpserver.api import my_render, get_object, CRYPTOR
@require_role('admin')
@@ -62,7 +62,7 @@ def perm_rule_detail(request):
assets = asset_obj
return my_render('jperm/perm_rule_detail.html', locals(), request)
-
+
def perm_rule_add(request):
"""
@@ -89,7 +89,8 @@ def perm_rule_add(request):
asset_groups_select = request.POST.getlist('assetgroup', [])
roles_select = request.POST.getlist('role', [])
rule_name = request.POST.get('rulename')
- rule_comment = request.POST.get('comment')
+ rule_comment = request.POST.get('rule_comment')
+ rule_ssh_key = request.POST.get("use_publicKey")
# 获取需要授权的主机列表
assets_obj = [Asset.objects.get(ip=asset) for asset in assets_select]
@@ -115,7 +116,19 @@ def perm_rule_add(request):
rule.asset_group = asset_groups_obj
rule.role = roles_obj
rule.save()
- return HttpResponse(u"添加授权规则:%s" % rule.name)
+
+ msg = u"添加授权规则:%s" % rule.name
+ # 渲染数据
+ header_title, path1, path2 = "授权规则", "规则管理", "查看规则"
+ rules_list = PermRule.objects.all()
+
+ # TODO: 搜索和分页
+ keyword = request.GET.get('search', '')
+ if keyword:
+ rules_list = rules_list.filter(Q(name=keyword))
+ rules_list, p, rules, page_range, current_page, show_first, show_end = pages(rules_list, request)
+
+ return my_render('jperm/perm_rule_list.html', locals(), request)
@require_role('admin')
@@ -131,17 +144,69 @@ def perm_rule_edit(request):
rule = PermRule.objects.get(id=rule_id)
if request.method == 'GET' and rule_id:
- # 渲染数据, 获取所有的rule对象
- users = rule.user.all()
- user_groups = rule.user_group.all()
- assets = rule.asset.all()
- asset_groups = rule.asset_group.all()
- roles = rule.role.all()
+ # 渲染数据, 获取所选的rule对象
+ rule_comment = rule.comment
+ users_select = rule.user.all()
+ user_groups_select = rule.user_group.all()
+ assets_select = rule.asset.all()
+ asset_groups_select = rule.asset_group.all()
+ roles_select = rule.role.all()
+
+ users = User.objects.all()
+ user_groups = UserGroup.objects.all()
+ assets = Asset.objects.all()
+ asset_groups = AssetGroup.objects.all()
+ roles = PermRole.objects.all()
return my_render('jperm/perm_rule_edit.html', locals(), request)
elif request.method == 'POST' and rule_id:
- return HttpResponse("uncompleted")
+ # 获取用户选择的 用户,用户组,资产,资产组,用户角色
+ rule_name = request.POST.get('rule_name')
+ rule_comment = request.POST.get("rule_comment")
+ users_select = request.POST.getlist('user', [])
+ user_groups_select = request.POST.getlist('usergroup', [])
+ assets_select = request.POST.getlist('asset', [])
+ asset_groups_select = request.POST.getlist('assetgroup', [])
+ roles_select = request.POST.getlist('role', [])
+
+ # 获取需要授权的主机列表
+ assets_obj = [Asset.objects.get(ip=asset) for asset in assets_select]
+ asset_groups_obj = [AssetGroup.objects.get(name=group) for group in asset_groups_select]
+ group_assets_obj = [asset for asset in [group.asset_set.all() for group in asset_groups_obj]]
+ calc_assets = set(group_assets_obj) | set(assets_obj)
+
+ # 获取需要授权的用户列表
+ users_obj = [User.objects.get(name=user) for user in users_select]
+ user_groups_obj = [UserGroup.objects.get(name=group) for group in user_groups_select]
+ group_users_obj = [user for user in [group.user_set.all() for group in user_groups_obj]]
+ calc_users = set(group_users_obj) | set(users_obj)
+
+ # 获取授予的角色列表
+ roles_obj = [PermRole.objects.get(name=role) for role in roles_select]
+
+ # 仅授权成功的,写回数据库(授权规则,用户,用户组,资产,资产组,用户角色)
+ rule.user = users_obj
+ rule.usergroup = user_groups_obj
+ rule.asset = assets_obj
+ rule.asset_group = asset_groups_obj
+ rule.role = roles_obj
+ rule.name = rule_name
+ rule.comment = rule.comment
+ rule.save()
+
+ msg = u"更新授权规则:%s" % rule.name
+ # 渲染数据
+ header_title, path1, path2 = "授权规则", "规则管理", "查看规则"
+ rules_list = PermRule.objects.all()
+
+ # TODO: 搜索和分页
+ keyword = request.GET.get('search', '')
+ if keyword:
+ rules_list = rules_list.filter(Q(name=keyword))
+ rules_list, p, rules, page_range, current_page, show_first, show_end = pages(rules_list, request)
+
+ return my_render('jperm/perm_rule_list.html', locals(), request)
@require_role('admin')
@@ -201,12 +266,24 @@ def perm_role_add(request):
name = request.POST.get("role_name")
comment = request.POST.get("role_comment")
password = request.POST.get("role_password")
+ encrypt_pass = CRYPTOR.encrypt(password)
# 生成随机密码,生成秘钥对
key_path = gen_keys()
- role = PermRole(name=name, comment=comment, password=password, key_path=key_path)
+ role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
role.save()
- return HttpResponse(u"添加角色: %s" % name)
+
+ msg = u"添加角色: %s" % name
+ # 渲染 刷新数据
+ header_title, path1, path2 = "系统角色", "角色管理", "查看角色"
+ roles_list = PermRole.objects.all()
+ # TODO: 搜索和分页
+ keyword = request.GET.get('search', '')
+ if keyword:
+ roles_list = roles_list.filter(Q(name=keyword))
+
+ roles_list, p, roles, page_range, current_page, show_first, show_end = pages(roles_list, request)
+ return my_render('jperm/perm_role_list.html', locals(), request)
else:
return HttpResponse(u"不支持该操作")
@@ -252,8 +329,12 @@ def perm_role_detail(request):
role_info = get_role_info(role_id)
# 渲染数据
- for key, value in role_info.iteritems():
- key = value
+ rules = role_info.get("rules")
+ assets = role_info.get("assets")
+ asset_groups = role_info.get("asset_groups")
+ users = role_info.get("users")
+ user_groups = role_info.get("user_groups")
+
return my_render('jperm/perm_role_detail.html', locals(), request)
@@ -265,15 +346,40 @@ def perm_role_edit(request):
# 渲染数据
header_title, path1, path2 = "系统角色", "角色管理", "角色编辑"
+ # 渲染数据
+ role_id = request.GET.get("id")
+ role = PermRole.objects.get(id=role_id)
+ role_pass = CRYPTOR.decrypt(role.password)
if request.method == "GET":
- role_id = request.GET.get("id")
- # 渲染数据
- role = PermRole.objects.get(id=role_id)
-
return my_render('jperm/perm_role_edit.html', locals(), request)
if request.method == "POST":
- return HttpResponse(u"未实现")
+ # 获取 POST 数据
+ role_name = request.POST.get("role_name")
+ role_password = request.POST.get("role_password")
+ encrypt_role_pass = CRYPTOR.encrypt(role_password)
+ role_comment = request.POST.get("role_comment")
+
+ # 写入数据库
+ role.name = role_name
+ role.password = encrypt_role_pass
+ role.comment = role_comment
+
+ role.save()
+ msg = u"更新系统角色: %s" % role.name
+
+ # 渲染 刷新数据
+ header_title, path1, path2 = "系统角色", "角色管理", "查看角色"
+ roles_list = PermRole.objects.all()
+ # TODO: 搜索和分页
+ keyword = request.GET.get('search', '')
+ if keyword:
+ roles_list = roles_list.filter(Q(name=keyword))
+
+ roles_list, p, roles, page_range, current_page, show_first, show_end = pages(roles_list, request)
+ return my_render('jperm/perm_role_list.html', locals(), request)
+
+
@require_role('admin')
@@ -307,10 +413,20 @@ def perm_role_push(request):
calc_assets = set(assets_obj) | set(group_assets_obj)
# 生成Inventory
- push_resource = [{"hostname": asset.ip,
- "port": asset.port,
- "username": asset.username,
- "password": asset.password} for asset in calc_assets]
+ push_resource = []
+ for asset in calc_assets:
+ if asset.use_default_auth:
+ username = Setting.default_user
+ password = Setting.default_password
+ port = Setting.default_port
+ else:
+ username = asset.username
+ password = asset.password
+ port = asset.port
+ push_resource.append({"hostname": asset.ip,
+ "port": port,
+ "username": username,
+ "password": password})
# 获取角色的推送方式,以及推送需要的信息
roles_obj = [PermRole.objects.get(name=role_name) for role_name in role_names]
@@ -326,10 +442,13 @@ def perm_role_push(request):
task = Tasks(push_resource)
ret = {}
ret_failed = []
- if password_push:
- ret["password_push"] = task.add_multi_user(**role_pass)
- if ret["password_push"].get("status") != "success":
- ret_failed.append(1)
+
+ # 因为要先建立用户,所以password 是必选项,
+ # 而push key是在 password也完成的情况下的 可选项
+ ret["password_push"] = task.add_multi_user(**role_pass)
+ if ret["password_push"].get("status") != "success":
+ ret_failed.append(1)
+
if key_push:
ret["key_push"] = task.push_multi_key(**role_key)
if ret["key_push"].get("status") != "success":
diff --git a/jumpserver/api.py b/jumpserver/api.py
index 5b964586c..6dc1a1602 100644
--- a/jumpserver/api.py
+++ b/jumpserver/api.py
@@ -14,10 +14,8 @@ from django.core.paginator import Paginator, EmptyPage, InvalidPage
from django.http import HttpResponse, Http404
from django.template import RequestContext
from juser.models import User, UserGroup
+from jlog.models import Log
from jasset.models import Asset, AssetGroup
-# from jlog.models import Log
-from jlog.models import Log, TtyLog
-from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.core.mail import send_mail
@@ -197,9 +195,9 @@ def require_role(role='user'):
def _deco(func):
def __deco(request, *args, **kwargs):
+ request.session['pre_url'] = request.path
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/')
-
if role == 'admin':
# if request.session.get('role_id', 0) < 1:
if request.user.role == 'CU':
@@ -395,8 +393,9 @@ def mkdir(dir_name, username='root', mode=0755):
"""
if not os.path.isdir(dir_name):
os.makedirs(dir_name)
- bash("chown %s:%s '%s'" % (username, username, dir_name))
os.chmod(dir_name, mode)
+ if username:
+ bash('chown %s:%s %s' % (username, username, dir_name))
def http_success(request, msg):
@@ -414,4 +413,3 @@ def my_render(template, data, request):
CRYPTOR = PyCrypt(KEY)
logger = set_log(LOG_LEVEL)
-KEY_DIR = os.path.join(BASE_DIR, 'keys')
diff --git a/jumpserver/settings.py b/jumpserver/settings.py
index cc3f5a8c7..be8464d38 100644
--- a/jumpserver/settings.py
+++ b/jumpserver/settings.py
@@ -17,8 +17,8 @@ config = ConfigParser.ConfigParser()
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
config.read(os.path.join(BASE_DIR, 'jumpserver.conf'))
+KEY_DIR = os.path.join(BASE_DIR, 'keys')
-KEY_DIR = os.path.join(BASE_DIR, 'role_keys')
DB_HOST = config.get('db', 'host')
DB_PORT = config.getint('db', 'port')
@@ -37,7 +37,7 @@ EMAIL_TIMEOUT = 5
# ======== Log ==========
LOG_DIR = os.path.join(BASE_DIR, 'logs')
-SSH_KEY_DIR = os.path.join(BASE_DIR, 'role_keys')
+SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys/role_keys')
KEY = config.get('base', 'key')
URL = config.get('base', 'url')
LOG_LEVEL = config.get('base', 'log')
diff --git a/jumpserver/templatetags/mytags.py b/jumpserver/templatetags/mytags.py
index 8dcdf377c..5af20cdd6 100644
--- a/jumpserver/templatetags/mytags.py
+++ b/jumpserver/templatetags/mytags.py
@@ -226,3 +226,14 @@ def ip_str_to_list(ip_str):
ip str to list
"""
return ip_str.split(',')
+
+
+@register.filter(name='key_exist')
+def key_exist(username):
+ """
+ ssh key is exist or not
+ """
+ if os.path.isfile(os.path.join(KEY_DIR, 'user', username)):
+ return True
+ else:
+ return False
diff --git a/jumpserver/views.py b/jumpserver/views.py
index 3f8ba2fae..57ae3f5dd 100644
--- a/jumpserver/views.py
+++ b/jumpserver/views.py
@@ -15,7 +15,6 @@ from jumpserver.api import *
from jumpserver.models import Setting
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
-from settings import BASE_DIR
from jlog.models import Log
@@ -236,7 +235,7 @@ def Login(request):
request.session['role_id'] = 1
else:
request.session['role_id'] = 0
- return HttpResponseRedirect(request.GET.get('next', '/'), )
+ return HttpResponseRedirect(request.session.get('pre_url', '/'))
# response.set_cookie('username', username, expires=604800)
# response.set_cookie('seed', PyCrypt.md5_crypt(password), expires=604800)
# return response
@@ -269,7 +268,7 @@ def setting(request):
if '' in [username, port] and ('' in password or '' in private_key):
return HttpResponse('所填内容不能为空, 且密码和私钥填一个')
else:
- private_key_path = os.path.join(BASE_DIR, 'role_keys', 'default', 'default_private_key.pem')
+ private_key_path = os.path.join(BASE_DIR, 'keys/role_keys', 'default', 'default_private_key.pem')
if private_key:
with open(private_key_path, 'w') as f:
f.write(private_key)
diff --git a/juser/user_api.py b/juser/user_api.py
index 911c554ee..87e7b5cc5 100644
--- a/juser/user_api.py
+++ b/juser/user_api.py
@@ -123,21 +123,21 @@ def db_del_user(username):
def gen_ssh_key(username, password='',
key_dir=os.path.join(KEY_DIR, 'user'),
-
authorized_keys=True, home="/home", length=2048):
"""
generate a user ssh key in a property dir
生成一个用户ssh密钥对
"""
+ logger.debug('生成ssh key, 并设置authorized_keys')
private_key_file = os.path.join(key_dir, username)
- mkdir(private_key_file, username)
+ mkdir(key_dir)
if os.path.isfile(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))
if authorized_keys:
auth_key_dir = os.path.join(home, username, '.ssh')
- mkdir(auth_key_dir, username, mode=0700)
+ mkdir(auth_key_dir, mode=0700)
authorized_key_file = os.path.join(auth_key_dir, 'authorized_keys')
with open(private_key_file+'.pub') as pub_f:
with open(authorized_key_file, 'w') as auth_f:
diff --git a/keys/README.md b/keys/README.md
new file mode 100644
index 000000000..9e060e41d
--- /dev/null
+++ b/keys/README.md
@@ -0,0 +1,3 @@
+看山是山,看水是水
+看山不是山,看水不是水
+看山是山,看水是水
diff --git a/logs/README.md b/logs/README.md
new file mode 100644
index 000000000..309d1a147
--- /dev/null
+++ b/logs/README.md
@@ -0,0 +1 @@
+永远年轻,永远热泪盈眶
diff --git a/playbook/user_perm.yaml b/playbook/user_perm.yaml
deleted file mode 100644
index 4bcfd72e6..000000000
--- a/playbook/user_perm.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-- hosts: the_del_group
- tasks:
- - name: del user
- user: name={{ item }} state=absent remove=yes
- with_items: [ the_del_users ]
-
-- hosts: the_new_group
- tasks:
- - name: add user
- user: name={{ item }} state=present
- with_items: [ the_new_users ]
- - name: .ssh direcotory
- file: name=/home/{{ item }}/.ssh mode=700 owner={{ item }} group={{ item }} state=directory
- with_items: [ the_new_users ]
- - name: set authorizied_file
- copy: src=KEY_DIR/{{ item }}.pub dest=/home/{{ item }}/.ssh/authorizied_keys owner={{ item }} group={{ item }} mode=600
- with_items: [ the_new_users ]
diff --git a/templates/index.html b/templates/index.html
index af6966ef6..0d8baf9f9 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -14,7 +14,6 @@
-{#
{{ percent_user }}
#}
All user
@@ -27,7 +26,6 @@
-{#
{{ percent_host }}
#}
All host
@@ -37,7 +35,7 @@
Online
-
实时在线用户
+ 在线用户
-{#
{{ percent_online_host }}
#}
Connected host
@@ -169,7 +166,7 @@
-
一周Top10资产
+ 一周Top10资产
登录次数及最近一次登录记录.
@@ -309,14 +306,7 @@
-
-
-
-
-
-
-
-
+
{% endblock %}
diff --git a/templates/jasset/asset_detail.html b/templates/jasset/asset_detail.html
index 1f8d0d130..ef202bae9 100644
--- a/templates/jasset/asset_detail.html
+++ b/templates/jasset/asset_detail.html
@@ -31,11 +31,11 @@
IP
- {{ asset.ip }}
+ {{ asset.ip|default_if_none:"" }}
主机名
- {{ asset.hostname }}
+ {{ asset.hostname|default_if_none:"" }}
其他IP
@@ -53,11 +53,11 @@
远控IP
- {{ asset.remote_ip }}
+ {{ asset.remote_ip|default_if_none:"" }}
端口
- {{ asset.port }}
+ {{ asset.port|default_if_none:"" }}
@@ -66,7 +66,7 @@
{% for asset_group in asset.group.all %}
- {{ asset_group.name }}
+ {{ asset_group.name|default_if_none:"" }}
{% endfor %}
@@ -79,19 +79,19 @@
机房
- {{ asset.idc.name }}
+ {{ asset.idc.name|default_if_none:"" }}
硬件厂商型号
- {{ asset.brand }}
+ {{ asset.brand|default_if_none:"" }}
CPU
- {{ asset.cpu }}
+ {{ asset.cpu|default_if_none:"" }}
内存
- {{ asset.memory }}M
+ {{ asset.memory|default_if_none:"" }}{% if asset.memory %}M{% endif %}
硬盘
@@ -100,7 +100,7 @@
{% if asset.disk %}
{% for disk, value in asset.disk|str_to_dic %}
- {{ disk }}     {{ value }}
+ {{ disk|default_if_none:"" }}     {{ value|default_if_none:"" }}
{% endfor %}
{% endif %}
@@ -109,35 +109,35 @@
资产编号
- {{ asset.number }}
+ {{ asset.number|default_if_none:"" }}
SN
- {{ asset.sn }}
+ {{ asset.sn|default_if_none:"" }}
主机类型
- {{ asset.get_asset_type_display }}
+ {{ asset.get_asset_type_display|default_if_none:"" }}
系统版本
- {{ asset.system_type }} {{ asset.system_version }}
+ {{ asset.system_type|default_if_none:"" }} {{ asset.system_version|default_if_none:"" }}
运行环境
- {{ asset.get_env_display }}
+ {{ asset.get_env_display|default_if_none:"" }}
机器状态
- {{ asset.get_status_display }}
+ {{ asset.get_status_display|default_if_none:"" }}
机柜号
- {{ asset.cabinet }}
+ {{ asset.cabinet|default_if_none:"" }}
机柜位置
- {{ asset.position }}
+ {{ asset.position|default_if_none:"" }}
激活
@@ -149,7 +149,7 @@
备注
- {{ asset.comment }}
+ {{ asset.comment|default_if_none:"" }}
diff --git a/templates/jasset/asset_edit_batch.html b/templates/jasset/asset_edit_batch.html
index b41afcb7b..5422a75b1 100644
--- a/templates/jasset/asset_edit_batch.html
+++ b/templates/jasset/asset_edit_batch.html
@@ -54,17 +54,17 @@
@@ -140,8 +140,8 @@
$('#uuid').val(ids)
});
- $('#id_use_default_auth').click(function(){
- if ($(this).is(':checked')){
+ $('.auth').click(function(){
+ if ($(this).attr('id') == 'pass'){
$('#admin_account').css('display', 'block')
}
else {
diff --git a/templates/jasset/asset_excel_download.html b/templates/jasset/asset_excel_download.html
index d1b6738ee..113544c15 100644
--- a/templates/jasset/asset_excel_download.html
+++ b/templates/jasset/asset_excel_download.html
@@ -1,7 +1,6 @@
×
-
- Nice! excel文件已生成请点击
下载
+
Nice! excel文件已生成请点击
下载
\ No newline at end of file
diff --git a/templates/jasset/asset_list.html b/templates/jasset/asset_list.html
index 133e41eea..9e3ea2d2c 100644
--- a/templates/jasset/asset_list.html
+++ b/templates/jasset/asset_list.html
@@ -119,12 +119,12 @@
- {{ asset.ip }}
- {{ asset.hostname }}
- {{ asset.idc.name }}
+ {{ asset.ip|default_if_none:"" }}
+ {{ asset.hostname|default_if_none:"" }}
+ {{ asset.idc.name|default_if_none:"" }}
{{ asset.group.all|group_str2 }}
{# {{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }} #}
- {{ asset.system_type }}{{ asset.system_version }}
+ {{ asset.system_type|default_if_none:"" }}{{ asset.system_version|default_if_none:"" }}
{{ asset.use_default_auth|bool2str }}
详情
@@ -169,17 +169,17 @@
});
$(document).ready(function(){
- $('#editable').editableTableWidget({editor: $('