Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
J
jumpserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
jumpserver
Commits
0821e7cf
Commit
0821e7cf
authored
Jan 04, 2016
by
yumaojun
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' of
https://git.coding.net/jumpserver/jumpserver
into dev
parents
38f72a85
ccc2bcf0
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
108 additions
and
54 deletions
+108
-54
README.md
README.md
+4
-3
connect.py
connect.py
+8
-5
install.py
install/install.py
+11
-8
next.py
install/next.py
+4
-4
zzjumpserver.sh
install/zzjumpserver.sh
+0
-13
views.py
jperm/views.py
+1
-1
views.py
jumpserver/views.py
+4
-0
user_api.py
juser/user_api.py
+2
-1
run_websocket.py
run_websocket.py
+18
-10
asset_list.html
templates/jasset/asset_list.html
+13
-2
web_terminal.html
templates/jlog/web_terminal.html
+29
-2
perm_role_detail.html
templates/jperm/perm_role_detail.html
+11
-2
perm_rule_edit.html
templates/jperm/perm_rule_edit.html
+1
-1
change_info.html
templates/juser/change_info.html
+2
-2
No files found.
README.md
View file @
0821e7cf
...
...
@@ -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
)
### 特点
...
...
connect.py
View file @
0821e7cf
#!/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
(
'[
%-3
s]
%-12
s
%-15
s
%-5
s
%-10
s
%
s'
%
(
'ID'
,
u'主机名'
,
'IP'
,
u'端口'
,
u'系统用户'
,
u
'备注'
),
'title'
)
color_print
(
'[
%-3
s]
%-12
s
%-15
s
%-5
s
%-10
s
%
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__'
:
...
...
install/install.py
View file @
0821e7cf
...
...
@@ -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
...
...
install/next.py
View file @
0821e7cf
...
...
@@ -81,9 +81,9 @@ class Setup(object):
os
.
system
(
'id
%
s &> /dev/null || useradd
%
s'
%
(
self
.
admin_user
,
self
.
admin_user
))
@staticmethod
def
_
cp_zz
sh
():
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_zz
sh
()
self
.
_
ensure_
sh
()
self
.
_run_service
()
...
...
install/zzjumpserver.sh
deleted
100755 → 0
View file @
38f72a85
#!/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
jperm/views.py
View file @
0821e7cf
...
...
@@ -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
)
...
...
jumpserver/views.py
View file @
0821e7cf
...
...
@@ -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
())
...
...
juser/user_api.py
View file @
0821e7cf
...
...
@@ -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
)
...
...
run_websocket.py
View file @
0821e7cf
...
...
@@ -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'
)
...
...
templates/jasset/asset_list.html
View file @
0821e7cf
...
...
@@ -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
}
...
...
templates/jlog/web_terminal.html
View file @
0821e7cf
...
...
@@ -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>
...
...
templates/jperm/perm_role_detail.html
View file @
0821e7cf
...
...
@@ -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>
...
...
templates/jperm/perm_rule_edit.html
View file @
0821e7cf
...
...
@@ -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>
...
...
templates/juser/change_info.html
View file @
0821e7cf
...
...
@@ -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
)
}
)
})
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment