pull/34/head
yumaojun 2016-01-04 13:13:35 +08:00
commit 0821e7cf41
14 changed files with 108 additions and 54 deletions

View File

@ -36,9 +36,10 @@ Web批量执行命令
### 文档
* [访问wiki](https://github.com/ibuler/jumpserver/wiki)
* [快速安装](https://github.com/ibuler/jumpserver/wiki/快速安装)
* [名词解释](https://github.com/ibuler/jumpserver/wiki/名称解释)
* [快速开始](https://github.com/ibuler/jumpserver/wiki/快速开始)
* [快速安装](https://github.com/ibuler/jumpserver/wiki/Quickinstall)
* [名词解释](https://github.com/ibuler/jumpserver/wiki/Termexplain)
* [快速开始](https://github.com/ibuler/jumpserver/wiki/Quickstart)
* [FAQ](https://github.com/ibuler/jumpserver/wiki/FAQs)
### 特点

View File

@ -1,3 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
import sys
@ -290,7 +291,7 @@ class Tty(object):
# 发起ssh连接请求 Make a ssh connection
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
#ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
role_key = connect_info.get('role_key')
@ -527,7 +528,7 @@ class Nav(object):
user_asset_search = user_asset_all
self.search_result = dict(zip(range(len(user_asset_search)), user_asset_search))
color_print('[%-3s] %-12s %-15s %-5s %-10s %s' % ('ID', u'主机名', 'IP', u'端口', u'系统用户', u'备注'), 'title')
color_print('[%-3s] %-12s %-15s %-5s %-10s %s' % ('ID', '主机名', 'IP', '端口', '系统用户', '备注'), 'title')
for index, asset in self.search_result.items():
# 获取该资产信息
asset_info = get_asset_info(asset)
@ -684,7 +685,7 @@ class Nav(object):
res = gen_resource({'user': self.user, 'asset': assets}, perm=self.user_perm)
runner = MyRunner(res)
asset_name_str = ''
print "匹配用户:\n"
print "匹配主机:\n"
for inv in runner.inventory.get_hosts(pattern=pattern):
asset_name_str += '%s ' % inv.name
print ' %s' % inv.name
@ -734,7 +735,7 @@ def main():
主程序
"""
if not login_user: # 判断用户是否存在
color_print(u'没有该用户或许你是以root运行的 No that user.', exits=True)
color_print('没有该用户或许你是以root运行的 No that user.', exits=True)
gid_pattern = re.compile(r'^g\d+$')
nav = Nav(login_user)
@ -799,7 +800,9 @@ def main():
color_print('请输入正确ID', 'red')
except ServerError, e:
color_print(e, 'red')
except IndexError:
except Exception, e:
color_print(e)
time.sleep(5)
pass
if __name__ == '__main__':

View File

@ -109,7 +109,7 @@ class PreSetup(object):
def _test_db_conn(self):
try:
MySQLdb.connect(host=self.db_host, port=self.db_port,
MySQLdb.connect(host=self.db_host, port=int(self.db_port),
user=self.db_user, passwd=self.db_pass, db=self.db)
color_print('连接数据库成功', 'green')
return True
@ -127,8 +127,11 @@ class PreSetup(object):
smtp.quit()
return True
except (SMTPAuthenticationError, socket.timeout, socket.gaierror, SMTPSenderRefused, SMTPConnectError), e:
except Exception, e:
color_print(e, 'red')
skip = raw_input('是否跳过(y/n) [n]? : ')
if skip == 'y':
return True
return False
@staticmethod
@ -147,7 +150,7 @@ class PreSetup(object):
bash('pip install -r requirements.txt')
def _input_ip(self):
ip = raw_input('\n请输入您服务器的IP地址用户浏览器可以访问 [%s]: ' % get_ip_addr())
ip = raw_input('\n请输入您服务器的IP地址用户浏览器可以访问 [%s]: ' % get_ip_addr()).strip()
self.ip = ip if ip else get_ip_addr()
def _input_mysql(self):
@ -156,11 +159,11 @@ class PreSetup(object):
if mysql != 'n':
self._setup_mysql()
else:
db_host = raw_input('请输入数据库服务器IP [127.0.0.1]: ')
db_port = int(raw_input('请输入数据库服务器端口 [3306]: '))
db_user = raw_input('请输入数据库服务器用户 [root]: ')
db_pass = raw_input('请输入数据库服务器密码: ')
db = raw_input('请输入使用的数据库 [jumpserver]: ')
db_host = raw_input('请输入数据库服务器IP [127.0.0.1]: ').strip()
db_port = raw_input('请输入数据库服务器端口 [3306]: ').strip()
db_user = raw_input('请输入数据库服务器用户 [root]: ').strip()
db_pass = raw_input('请输入数据库服务器密码: ').strip()
db = raw_input('请输入使用的数据库 [jumpserver]: ').strip()
if db_host: self.db_host = db_host
if db_port: self.db_port = db_port

View File

@ -81,9 +81,9 @@ class Setup(object):
os.system('id %s &> /dev/null || useradd %s' % (self.admin_user, self.admin_user))
@staticmethod
def _cp_zzsh():
os.chdir(os.path.join(jms_dir, 'install'))
shutil.copy('zzjumpserver.sh', '/etc/profile.d/')
def _ensure_sh():
jshell = os.path.join(jms_dir, 'connect.py')
os.chmod(jshell, 0755)
@staticmethod
def _run_service():
@ -97,7 +97,7 @@ class Setup(object):
self._sync_db()
self._input_admin()
self._create_admin()
self._cp_zzsh()
self._ensure_sh()
self._run_service()

View File

@ -1,13 +0,0 @@
#!/bin/bash
if [ "$USER" == "admin" ] || [ "$USER" == "root" ] || [ "$USER" == "" ];then
echo ""
else
python /opt/jumpserver/connect.py
if [ $USER == 'guanghongwei' ];then
echo
else
exit 3
echo
fi
fi

View File

@ -545,7 +545,7 @@ def perm_role_push(request):
if not failed_asset:
msg = u'系统用户 %s 推送成功[ %s ]' % (role.name, ','.join(success_asset.keys()))
else:
error = u'系统用户 %s 推送失败 [ %s ], 推送成功 [ %s ]' % (role.name,
error = u'系统用户 %s 推送失败 [ %s ], 推送成功 [ %s ] 进入系统用户详情,查看失败原因' % (role.name,
','.join(failed_asset.keys()),
','.join(success_asset.keys()))
return my_render('jperm/perm_role_push.html', locals(), request)

View File

@ -352,6 +352,10 @@ def exec_cmd(request):
def web_terminal(request):
asset_id = request.GET.get('id')
role_name = request.GET.get('role')
asset = get_object(Asset, id=asset_id)
if asset:
print asset
hostname = asset.hostname
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())

View File

@ -151,7 +151,8 @@ def server_add_user(username, password, ssh_key_pwd='', ssh_key_login_need=True)
add a system user in jumpserver
在jumpserver服务器上添加一个用户
"""
bash("useradd '%s'; echo '%s'; echo '%s' | passwd --stdin '%s'" % (username, password, password, username))
bash("useradd -s %s/connect.py '%s'; echo '%s'; echo '%s' | passwd --stdin '%s'" %
(BASE_DIR, username, password, password, username))
if ssh_key_login_need:
gen_ssh_key(username, ssh_key_pwd)

View File

@ -230,15 +230,14 @@ class ExecHandler(tornado.websocket.WebSocketHandler):
def on_message(self, message):
data = json.loads(message)
pattern = data.get('pattern', '')
command = data.get('command', '')
asset_name_str = ''
if pattern and command:
self.command = data.get('command', '')
self.asset_name_str = ''
if pattern and self.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()
self.asset_name_str += '%s ' % inv.name
self.write_message('匹配主机: ' + self.asset_name_str)
self.write_message('<span style="color: yellow">Ansible> %s</span>\n\n' % self.command)
self.__class__.tasks.append(MyThread(target=self.run_cmd, args=(self.command, pattern)))
for t in self.__class__.tasks:
if t.is_alive():
@ -251,11 +250,12 @@ class ExecHandler(tornado.websocket.WebSocketHandler):
def run_cmd(self, command, pattern):
self.runner.run('shell', command, pattern=pattern)
ExecLog(host=self.asset_name_str, cmd=self.command, user=self.user.username,
remote_ip=self.remote_ip, result=self.runner.results).save()
newline_pattern = re.compile(r'\n')
for k, v in self.runner.results.items():
for host, output in v.items():
output = newline_pattern.sub('<br />', output)
logger.debug(output)
if k == 'ok':
header = "<span style='color: green'>[ %s => %s]</span>\n" % (host, 'Ok')
else:
@ -333,7 +333,13 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
data = json.loads(message)
if not data:
return
if data.get('data'):
if 'resize' in data.get('data'):
self.channel.resize_pty(
data.get('data').get('resize').get('cols', 80),
data.get('data').get('resize').get('rows', 24)
)
elif data.get('data'):
self.term.input_mode = True
if str(data['data']) in ['\r', '\n', '\r\n']:
if self.term.vim_flag:
@ -350,6 +356,8 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
self.term.data = ''
self.term.input_mode = False
self.channel.send(data['data'])
else:
pass
def on_close(self):
logger.debug('Websocket: Close request')

View File

@ -233,6 +233,7 @@
layer.alert('没有授权系统用户')
}
else if (dataArray.length == 1 && data != 'error' && navigator.platform == 'Win32'){
/*
var title = 'Jumpserver Web Terminal' + '<span class="text-info"> '+ hostname +'</span>';
layer.open({
type: 2,
@ -242,8 +243,10 @@
area: ['628px', '420px'],
content: new_url+data
});
*/
window.open(new_url+data, '', 'width=628px, height=420px')
} else if (dataArray.length == 1 && data != 'error'){
layer.open({
/*layer.open({
type: 2,
title: title,
maxmin: true,
@ -251,6 +254,9 @@
area: ['628px', '452px'],
content: new_url+data
});
*/
window.open(new_url+data, '', 'width=628px, height=440px')
}
else {
aUrl = '';
@ -276,6 +282,7 @@
var hostname = $(a).attr('value');
var title = 'Jumpserver Web Terminal - ' + '<span class="text-info"> '+ hostname +'</span>';
if (navigator.platform == 'Win32'){
/*
layer.open({
type: 2,
title: title,
@ -284,8 +291,11 @@
shade: false,
content: new_url
});
*/
window.open(new_url, '', 'height=628px, width=420px')
} else {
/*
layer.open({
type: 2,
title: title,
@ -294,6 +304,8 @@
shade: false,
content: new_url
});
*/
window.open(new_url, '', 'height=628px, width=452px')
}
return false
@ -310,7 +322,6 @@
shade: false,
content: new_url
});
console.log(new_url);
return false
}

View File

@ -2,7 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<title>Jumpserver web terminal</title>
<title>Jumpserver Web Terminal: {{ hostname }}</title>
<style>
body {
@ -37,6 +37,8 @@
<script type="application/javascript" src="/static/js/term.js">
</script>
<script type="application/javascript">
var rowHeight = 1;
var colWidth = 1;
function WSSHClient() {
}
@ -101,7 +103,22 @@
term.write(data);
}
}));
rowHeight = 0.0 + 1.00 * $('.terminal').height() / 24 ;
colWidth = 0.0 + 1.00 * $('.terminal').width() / 80;
return {'term': term, 'client': client};
}
function resize(){
$('.terminal').css('width', window.innerWidth-25);
console.log(window.innerWidth);
console.log(window.innerWidth-10);
var rows = Math.floor(window.innerHeight/rowHeight) - 1;
var cols = Math.floor(window.innerWidth/colWidth) - 1;
return {rows: rows, cols: cols};
}
</script>
<script type='application/javascript'>
@ -110,7 +127,17 @@
};
$('#ssh').show();
openTerminal(options);
var term_client = openTerminal(options);
console.log(rowHeight);
window.onresize = function(){
var geom = resize();
console.log(geom);
term_client.term.resize(geom.cols, geom.rows);
term_client.client.send({'resize': {'roles': geom.rows, 'cols': geom.cols}});
$('#ssh').show();
}
});
</script>
</body>

View File

@ -204,7 +204,7 @@
{% if info.success %}
<td class="text-center" style="color: #1ab394;" >{{ info.success | yesno:"成功,失败,未知" }} </td>
{% else %}
<td class="text-center" style="color: #ec4758;cursor: help" title="{{ info.result }}" >{{ info.success | yesno:"成功,失败,未知" }} </td>
<td class="text-center push_failed" style="color: #ec4758;cursor: help" title="{{ info.result }}">{{ info.success | yesno:"成功,失败,未知" }} </td>
{% endif %}
<td class="text-center" ><a class="fa fa-times del" href="{% url 'role_recycle' %}?role_id={{ role.id }}&asset_id={{ asset.id }}" style="color: #ec4758;"></a></td>
</tr>
@ -321,7 +321,16 @@
});
var url = '/jperm/role/push/?id={{ role.id }}&asset_id=' + check_array.join(',');
$(this).attr('href', url)
});
$('.push_failed').click(function() {
var fail_reason = $(this).attr('title');
layer.alert(fail_reason, {
skin: 'layui-layer-molv',
area: '500px'
})
});
})
</script>

View File

@ -67,7 +67,7 @@
<div class="col-sm-8">
<select name="asset" id="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset in assets %}
<option value="{{ asset.id }}"{% if asset in rule.asset.all %} selected {% endif %}>{{ asset.ip }}</option>
<option value="{{ asset.id }}"{% if asset in rule.asset.all %} selected {% endif %}>{{ asset.hostname }}</option>
{% endfor %}
</select>
<span class="help-block m-b-none">资产和资产组必选一个</span>

View File

@ -113,12 +113,12 @@ $('#userForm').validator({
$("document").ready(function() {
$("#regen_ssh_key").click(function () {
alert('申请已提交,请等待,请勿重复提交');
layer.alert('申请已提交,请等待,请勿重复提交');
$.get(
$(this).attr('value'),
{},
function(data){
alert(data)
layer.alert(data)
}
)
})