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
49821062
Commit
49821062
authored
Nov 24, 2015
by
wangyong
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' of
https://git.coding.net/jumpserver/jumpserver
into dev
parents
99439be0
17ccac92
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
222 additions
and
110 deletions
+222
-110
connect.py
connect.py
+30
-37
urls.py
jlog/urls.py
+2
-0
views.py
jlog/views.py
+15
-5
perm_api.py
jperm/perm_api.py
+9
-0
api.py
jumpserver/api.py
+1
-1
context_processors.py
jumpserver/context_processors.py
+2
-6
mytags.py
jumpserver/templatetags/mytags.py
+9
-0
run_websocket.py
run_websocket.py
+97
-34
asset_list.html
templates/jasset/asset_list.html
+41
-1
log_online.html
templates/jlog/log_online.html
+6
-14
nav.html
templates/nav.html
+0
-2
setting.html
templates/setting.html
+10
-10
No files found.
connect.py
View file @
49821062
...
@@ -19,9 +19,10 @@ import struct, fcntl, signal, socket, select
...
@@ -19,9 +19,10 @@ import struct, fcntl, signal, socket, select
os
.
environ
[
'DJANGO_SETTINGS_MODULE'
]
=
'jumpserver.settings'
os
.
environ
[
'DJANGO_SETTINGS_MODULE'
]
=
'jumpserver.settings'
if
django
.
get_version
()
!=
'1.6'
:
if
django
.
get_version
()
!=
'1.6'
:
django
.
setup
()
django
.
setup
()
from
jumpserver.api
import
ServerError
,
User
,
Asset
,
AssetGroup
,
get_object
,
mkdir
,
get_asset_info
,
get_role
from
django.contrib.sessions.models
import
Session
from
jumpserver.api
import
ServerError
,
User
,
Asset
,
PermRole
,
AssetGroup
,
get_object
,
mkdir
,
get_asset_info
,
get_role
from
jumpserver.api
import
logger
,
Log
,
TtyLog
,
get_role_key
from
jumpserver.api
import
logger
,
Log
,
TtyLog
,
get_role_key
from
jperm.perm_api
import
gen_resource
,
get_group_asset_perm
,
get_group_user_perm
from
jperm.perm_api
import
gen_resource
,
get_group_asset_perm
,
get_group_user_perm
,
user_have_perm
from
jumpserver.settings
import
LOG_DIR
from
jumpserver.settings
import
LOG_DIR
from
jperm.ansible_api
import
Command
from
jperm.ansible_api
import
Command
...
@@ -69,6 +70,8 @@ class Tty(object):
...
@@ -69,6 +70,8 @@ class Tty(object):
self
.
connect_info
=
None
self
.
connect_info
=
None
self
.
login_type
=
'ssh'
self
.
login_type
=
'ssh'
self
.
vim_flag
=
False
self
.
vim_flag
=
False
self
.
ps1_pattern
=
re
.
compile
(
'
\
[.*@.*
\
][
\
$#]'
)
self
.
vim_data
=
''
@staticmethod
@staticmethod
def
is_output
(
strings
):
def
is_output
(
strings
):
...
@@ -155,33 +158,12 @@ class Tty(object):
...
@@ -155,33 +158,12 @@ class Tty(object):
"""
,
re
.
X
)
"""
,
re
.
X
)
result_command
=
control_char
.
sub
(
''
,
result_command
.
strip
())
result_command
=
control_char
.
sub
(
''
,
result_command
.
strip
())
if
not
self
.
vim_flag
:
if
not
self
.
vim_flag
:
if
result_command
.
startswith
(
'vi'
):
if
result_command
.
startswith
(
'vi'
)
or
result_command
.
startswith
(
'fg'
)
:
self
.
vim_flag
=
True
self
.
vim_flag
=
True
return
result_command
.
decode
(
'utf8'
,
"ignore"
)
return
result_command
.
decode
(
'utf8'
,
"ignore"
)
else
:
else
:
return
''
return
''
@staticmethod
def
remove_control_char
(
str_r
):
"""
处理日志特殊字符
"""
control_char
=
re
.
compile
(
r"""
\x1b[ #
%
()*+\-.\/]. |
\r | #匹配 回车符(CR)
(?:\x1b\[|\x9b) [ -?]* [@-~] | #匹配 控制顺序描述符(CSI)... Cmd
(?:\x1b\]|\x9d) .*? (?:\x1b\\|[\a\x9c]) | \x07 | #匹配 操作系统指令(OSC)...终止符或振铃符(ST|BEL)
(?:\x1b[P^_]|[\x90\x9e\x9f]) .*? (?:\x1b\\|\x9c) | #匹配 设备控制串或私讯或应用程序命令(DCS|PM|APC)...终止符(ST)
\x1b. #匹配 转义过后的字符
[\x80-\x9f] #匹配 所有控制字符
"""
,
re
.
X
)
backspace
=
re
.
compile
(
r"[^\b][\b]"
)
line_filtered
=
control_char
.
sub
(
''
,
str_r
.
rstrip
())
while
backspace
.
search
(
line_filtered
):
line_filtered
=
backspace
.
sub
(
''
,
line_filtered
)
return
line_filtered
def
get_log
(
self
):
def
get_log
(
self
):
"""
"""
Logging user command and output.
Logging user command and output.
...
@@ -312,9 +294,7 @@ class SshTty(Tty):
...
@@ -312,9 +294,7 @@ class SshTty(Tty):
log_file_f
,
log_time_f
,
log
=
self
.
get_log
()
log_file_f
,
log_time_f
,
log
=
self
.
get_log
()
old_tty
=
termios
.
tcgetattr
(
sys
.
stdin
)
old_tty
=
termios
.
tcgetattr
(
sys
.
stdin
)
pre_timestamp
=
time
.
time
()
pre_timestamp
=
time
.
time
()
pattern
=
re
.
compile
(
'
\
[.*@.*
\
][
\
$#]'
)
data
=
''
data
=
''
chan_str
=
''
input_mode
=
False
input_mode
=
False
try
:
try
:
tty
.
setraw
(
sys
.
stdin
.
fileno
())
tty
.
setraw
(
sys
.
stdin
.
fileno
())
...
@@ -333,7 +313,7 @@ class SshTty(Tty):
...
@@ -333,7 +313,7 @@ class SshTty(Tty):
if
len
(
x
)
==
0
:
if
len
(
x
)
==
0
:
break
break
if
self
.
vim_flag
:
if
self
.
vim_flag
:
chan_str
+=
x
self
.
vim_data
+=
x
sys
.
stdout
.
write
(
x
)
sys
.
stdout
.
write
(
x
)
sys
.
stdout
.
flush
()
sys
.
stdout
.
flush
()
now_timestamp
=
time
.
time
()
now_timestamp
=
time
.
time
()
...
@@ -352,21 +332,20 @@ class SshTty(Tty):
...
@@ -352,21 +332,20 @@ class SshTty(Tty):
if
sys
.
stdin
in
r
:
if
sys
.
stdin
in
r
:
x
=
os
.
read
(
sys
.
stdin
.
fileno
(),
1
)
x
=
os
.
read
(
sys
.
stdin
.
fileno
(),
1
)
input_mode
=
True
input_mode
=
True
if
str
(
x
)
in
[
'
\r
'
,
'
\n
'
,
'
\r\n
'
]:
if
str
(
x
)
in
[
'
\r
'
,
'
\n
'
,
'
\r\n
'
]:
if
self
.
vim_flag
:
if
self
.
vim_flag
:
match
=
pattern
.
search
(
chan_str
)
match
=
self
.
ps1_pattern
.
search
(
self
.
vim_data
)
if
match
:
if
match
:
self
.
vim_flag
=
False
self
.
vim_flag
=
False
data
=
self
.
deal_command
(
data
)
data
=
self
.
deal_command
(
data
)
[
0
:
200
]
if
len
(
data
)
>
0
:
if
len
(
data
)
>
0
:
TtyLog
(
log
=
log
,
datetime
=
datetime
.
datetime
.
now
(),
cmd
=
data
)
.
save
()
TtyLog
(
log
=
log
,
datetime
=
datetime
.
datetime
.
now
(),
cmd
=
data
)
.
save
()
else
:
else
:
data
=
self
.
deal_command
(
data
)
data
=
self
.
deal_command
(
data
)
[
0
:
200
]
if
len
(
data
)
>
0
:
if
len
(
data
)
>
0
:
TtyLog
(
log
=
log
,
datetime
=
datetime
.
datetime
.
now
(),
cmd
=
data
)
.
save
()
TtyLog
(
log
=
log
,
datetime
=
datetime
.
datetime
.
now
(),
cmd
=
data
)
.
save
()
data
=
''
data
=
''
chan_str
=
''
self
.
vim_data
=
''
input_mode
=
False
input_mode
=
False
if
len
(
x
)
==
0
:
if
len
(
x
)
==
0
:
...
@@ -456,24 +435,33 @@ class Nav(object):
...
@@ -456,24 +435,33 @@ class Nav(object):
def
search
(
self
,
str_r
=
''
):
def
search
(
self
,
str_r
=
''
):
gid_pattern
=
re
.
compile
(
r'^g\d+$'
)
gid_pattern
=
re
.
compile
(
r'^g\d+$'
)
# 获取用户授权的所有主机信息
if
not
self
.
user_perm
:
if
not
self
.
user_perm
:
self
.
user_perm
=
get_group_user_perm
(
self
.
user
)
self
.
user_perm
=
get_group_user_perm
(
self
.
user
)
user_asset_all
=
self
.
user_perm
.
get
(
'asset'
)
.
keys
()
user_asset_all
=
self
.
user_perm
.
get
(
'asset'
)
.
keys
()
# 搜索结果保存
user_asset_search
=
[]
user_asset_search
=
[]
if
str_r
:
if
str_r
:
# 资产组组id匹配
if
gid_pattern
.
match
(
str_r
):
if
gid_pattern
.
match
(
str_r
):
user_asset_search
=
list
(
Asset
.
objects
.
all
())
gid
=
int
(
str_r
.
lstrip
(
'g'
))
# 获取资产组包含的资产
user_asset_search
=
get_object
(
AssetGroup
,
id
=
gid
)
.
asset_set
.
all
()
else
:
else
:
# 匹配 ip, hostname, 备注
for
asset
in
user_asset_all
:
for
asset
in
user_asset_all
:
if
str_r
in
asset
.
ip
or
str_r
in
str
(
asset
.
comment
):
if
str_r
in
asset
.
ip
or
str_r
in
str
(
asset
.
hostname
)
or
str_r
in
str
(
asset
.
comment
):
user_asset_search
.
append
(
asset
)
user_asset_search
.
append
(
asset
)
else
:
else
:
# 如果没有输入就展现所有
user_asset_search
=
user_asset_all
user_asset_search
=
user_asset_all
self
.
search_result
=
dict
(
zip
(
range
(
len
(
user_asset_search
)),
user_asset_search
))
self
.
search_result
=
dict
(
zip
(
range
(
len
(
user_asset_search
)),
user_asset_search
))
print
'
\033
[32m[
%-3
s]
%-15
s
%-15
s
%-5
s
%-10
s
%
s
\033
[0m'
%
(
'ID'
,
'AssetName'
,
'IP'
,
'Port'
,
'Role'
,
'Comment'
)
print
'
\033
[32m[
%-3
s]
%-15
s
%-15
s
%-5
s
%-10
s
%
s
\033
[0m'
%
(
'ID'
,
'AssetName'
,
'IP'
,
'Port'
,
'Role'
,
'Comment'
)
for
index
,
asset
in
self
.
search_result
.
items
():
for
index
,
asset
in
self
.
search_result
.
items
():
# 获取该资产信息
asset_info
=
get_asset_info
(
asset
)
asset_info
=
get_asset_info
(
asset
)
# 获取该资产包含的角色
role
=
[
str
(
role
.
name
)
for
role
in
self
.
user_perm
.
get
(
'asset'
)
.
get
(
asset
)
.
get
(
'role'
)]
role
=
[
str
(
role
.
name
)
for
role
in
self
.
user_perm
.
get
(
'asset'
)
.
get
(
asset
)
.
get
(
'role'
)]
if
asset
.
comment
:
if
asset
.
comment
:
print
'[
%-3
s]
%-15
s
%-15
s
%-5
s
%-10
s
%
s'
%
(
index
,
asset
.
hostname
,
asset
.
ip
,
asset_info
.
get
(
'port'
),
print
'[
%-3
s]
%-15
s
%-15
s
%-5
s
%-10
s
%
s'
%
(
index
,
asset
.
hostname
,
asset
.
ip
,
asset_info
.
get
(
'port'
),
...
@@ -482,9 +470,11 @@ class Nav(object):
...
@@ -482,9 +470,11 @@ class Nav(object):
print
'[
%-3
s]
%-15
s
%-15
s
%-5
s
%-10
s'
%
(
index
,
asset
.
hostname
,
asset
.
ip
,
asset_info
.
get
(
'port'
),
role
)
print
'[
%-3
s]
%-15
s
%-15
s
%-5
s
%-10
s'
%
(
index
,
asset
.
hostname
,
asset
.
ip
,
asset_info
.
get
(
'port'
),
role
)
print
print
@staticmethod
def
print_asset_group
(
self
):
def
print_asset_group
():
"""
user_asset_group_all
=
AssetGroup
.
objects
.
all
()
打印用户授权的资产组
"""
user_asset_group_all
=
get_group_user_perm
(
self
.
user
)
.
get
(
'asset_group'
,
[])
print
'
\033
[32m[
%-3
s]
%-15
s
%
s
\033
[0m'
%
(
'ID'
,
'GroupName'
,
'Comment'
)
print
'
\033
[32m[
%-3
s]
%-15
s
%
s
\033
[0m'
%
(
'ID'
,
'GroupName'
,
'Comment'
)
for
asset_group
in
user_asset_group_all
:
for
asset_group
in
user_asset_group_all
:
...
@@ -495,6 +485,9 @@ class Nav(object):
...
@@ -495,6 +485,9 @@ class Nav(object):
print
print
def
exec_cmd
(
self
):
def
exec_cmd
(
self
):
"""
批量执行命令
"""
self
.
search
()
self
.
search
()
while
True
:
while
True
:
print
"请输入主机名、IP或ansile支持的pattern, q退出"
print
"请输入主机名、IP或ansile支持的pattern, q退出"
...
...
jlog/urls.py
View file @
49821062
...
@@ -9,4 +9,5 @@ urlpatterns = patterns('',
...
@@ -9,4 +9,5 @@ urlpatterns = patterns('',
url
(
r'^log_kill/'
,
log_kill
),
url
(
r'^log_kill/'
,
log_kill
),
url
(
r'^record/$'
,
log_record
),
url
(
r'^record/$'
,
log_record
),
url
(
r'^web_terminal/$'
,
web_terminal
),
url
(
r'^web_terminal/$'
,
web_terminal
),
url
(
r'^get_role_name/$'
,
get_role_name
),
)
)
\ No newline at end of file
jlog/views.py
View file @
49821062
...
@@ -4,6 +4,7 @@ from django.template import RequestContext
...
@@ -4,6 +4,7 @@ from django.template import RequestContext
from
django.shortcuts
import
render_to_response
from
django.shortcuts
import
render_to_response
from
jumpserver.api
import
*
from
jumpserver.api
import
*
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
...
@@ -103,11 +104,20 @@ def log_record(request):
...
@@ -103,11 +104,20 @@ 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'
)
def
web_terminal
(
request
):
def
web_terminal
(
request
):
#username = get_session.get('username', '')
asset_id
=
request
.
GET
.
get
(
'id'
)
token
=
request
.
COOKIES
.
get
(
'sessionid'
)
role_name
=
request
.
GET
.
get
(
'role'
)
username
=
request
.
user
.
username
web_terminal_uri
=
'ws://
%
s/terminal?id=
%
s&role=
%
s'
%
(
WEB_SOCKET_HOST
,
asset_id
,
role_name
)
asset_name
=
'127.0.0.1'
web_terminal_uri
=
'ws://
%
s/terminal?username=
%
s&asset_name=
%
s&token=
%
s'
%
(
WEB_SOCKET_HOST
,
username
,
asset_name
,
token
)
return
render_to_response
(
'jlog/web_terminal.html'
,
locals
())
return
render_to_response
(
'jlog/web_terminal.html'
,
locals
())
jperm/perm_api.py
View file @
49821062
...
@@ -132,6 +132,15 @@ def get_group_asset_perm(ob):
...
@@ -132,6 +132,15 @@ def get_group_asset_perm(ob):
return
perm
return
perm
def
user_have_perm
(
user
,
asset
):
user_perm_all
=
get_group_user_perm
(
user
)
user_assets
=
user_perm_all
.
get
(
'asset'
)
.
keys
()
if
asset
in
user_assets
:
return
user_perm_all
.
get
(
'asset'
)
.
get
(
asset
)
.
get
(
'role'
)
else
:
return
False
def
gen_resource
(
ob
,
ex
=
''
,
perm
=
None
):
def
gen_resource
(
ob
,
ex
=
''
,
perm
=
None
):
"""
"""
ob为用户或资产列表或资产queryset, 如果同时输入用户和资产,则获取用户在这些资产上的信息
ob为用户或资产列表或资产queryset, 如果同时输入用户和资产,则获取用户在这些资产上的信息
...
...
jumpserver/api.py
View file @
49821062
...
@@ -59,7 +59,7 @@ def get_asset_info(asset):
...
@@ -59,7 +59,7 @@ def get_asset_info(asset):
else
:
else
:
info
[
'port'
]
=
asset
.
port
info
[
'port'
]
=
asset
.
port
info
[
'username'
]
=
asset
.
username
info
[
'username'
]
=
asset
.
username
info
[
'password'
]
=
asset
.
password
info
[
'password'
]
=
CRYPTOR
.
decrypt
(
asset
.
password
)
return
info
return
info
...
...
jumpserver/context_processors.py
View file @
49821062
...
@@ -5,16 +5,12 @@ from jumpserver.api import *
...
@@ -5,16 +5,12 @@ from jumpserver.api import *
def
name_proc
(
request
):
def
name_proc
(
request
):
user_id
=
request
.
user
.
id
user_id
=
request
.
user
.
id
# role_id = request.session.get('role_id')
role_id
=
{
'SU'
:
2
,
'GA'
:
1
,
'CU'
:
0
}
.
get
(
request
.
user
.
role
,
0
)
role_id
=
{
'SU'
:
2
,
'GA'
:
1
,
'CU'
:
0
}
.
get
(
request
.
user
.
role
,
0
)
# role_id = 'SU'
# if role_id == 2:
user_total_num
=
User
.
objects
.
all
()
.
count
()
user_total_num
=
User
.
objects
.
all
()
.
count
()
user_active_num
=
User
.
objects
.
filter
()
.
count
()
user_active_num
=
User
.
objects
.
filter
()
.
count
()
host_total_num
=
Asset
.
objects
.
all
()
.
count
()
host_total_num
=
Asset
.
objects
.
all
()
.
count
()
host_active_num
=
Asset
.
objects
.
filter
(
is_active
=
True
)
.
count
()
host_active_num
=
Asset
.
objects
.
filter
(
is_active
=
True
)
.
count
()
# else:
# pass
request
.
session
.
set_expiry
(
3600
)
request
.
session
.
set_expiry
(
3600
)
info_dic
=
{
'session_user_id'
:
user_id
,
info_dic
=
{
'session_user_id'
:
user_id
,
...
...
jumpserver/templatetags/mytags.py
View file @
49821062
...
@@ -237,3 +237,12 @@ def key_exist(username):
...
@@ -237,3 +237,12 @@ def key_exist(username):
return
True
return
True
else
:
else
:
return
False
return
False
@register.filter
(
name
=
'check_role'
)
def
check_role
(
asset_id
,
user
):
"""
ssh key is exist or not
"""
return
user
run_websocket.py
View file @
49821062
...
@@ -7,6 +7,7 @@ import os
...
@@ -7,6 +7,7 @@ import os
import
sys
import
sys
import
os.path
import
os.path
import
threading
import
threading
import
datetime
import
urllib
import
urllib
import
tornado.ioloop
import
tornado.ioloop
...
@@ -20,16 +21,10 @@ from tornado.websocket import WebSocketClosedError
...
@@ -20,16 +21,10 @@ from tornado.websocket import WebSocketClosedError
from
tornado.options
import
define
,
options
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
# from gevent import monkey
from
connect
import
Tty
,
User
,
Asset
,
PermRole
,
logger
,
get_object
# monkey.patch_all()
from
connect
import
TtyLog
,
Log
,
Session
,
user_have_perm
# import gevent
# from gevent.socket import wait_read, wait_write
import
struct
,
fcntl
,
signal
,
socket
,
select
,
fnmatch
import
paramiko
from
connect
import
Tty
from
connect
import
TtyLog
,
Log
try
:
try
:
import
simplejson
as
json
import
simplejson
as
json
...
@@ -41,17 +36,49 @@ define("port", default=3000, help="run on the given port", type=int)
...
@@ -41,17 +36,49 @@ define("port", default=3000, help="run on the given port", type=int)
define
(
"host"
,
default
=
'0.0.0.0'
,
help
=
"run port on"
,
type
=
str
)
define
(
"host"
,
default
=
'0.0.0.0'
,
help
=
"run port on"
,
type
=
str
)
def
require_auth
(
func
):
def
require_auth
(
role
=
'user'
):
def
_deco
(
request
,
*
args
,
**
kwargs
):
def
_deco
(
func
):
username
=
request
.
get_argument
(
'username'
,
''
)
def
_deco
(
request
,
*
args
,
**
kwargs
):
asset_name
=
request
.
get_argument
(
'asset_name'
,
''
)
if
request
.
get_cookie
(
'sessionid'
):
token
=
request
.
get_argument
(
'token'
,
''
)
session_key
=
request
.
get_cookie
(
'sessionid'
)
print
username
,
asset_name
,
token
else
:
client
=
tornado
.
httpclient
.
HTTPClient
()
session_key
=
request
.
get_secure_cookie
(
'sessionid'
)
# response = client.fetch('http://some/url') + urllib.urlencode({'username': username,
# 'asset_name': asset_name, 'token': token})
logger
.
debug
(
'Websocket: session_key: '
+
session_key
)
# return request.close()
return
func
(
request
,
*
args
,
**
kwargs
)
if
session_key
:
session
=
get_object
(
Session
,
session_key
=
session_key
)
if
session
and
datetime
.
datetime
.
now
()
>
session
.
expire_date
:
user_id
=
session
.
get_decoded
()
.
get
(
'_auth_user_id'
)
user
=
get_object
(
User
,
id
=
user_id
)
if
user
:
logger
.
debug
(
'Websocket: user [
%
s ] request websocket'
%
user
.
username
)
request
.
user
=
user
if
role
==
'admin'
:
if
user
.
role
in
[
'SU'
,
'GA'
]:
return
func
(
request
,
*
args
,
**
kwargs
)
logger
.
debug
(
'Websocket: user [
%
s ] is not admin.'
%
user
.
username
)
else
:
return
func
(
request
,
*
args
,
**
kwargs
)
request
.
close
()
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
_deco
return
_deco
return
_deco
...
@@ -87,10 +114,10 @@ def file_monitor(path='.', client=None):
...
@@ -87,10 +114,10 @@ def file_monitor(path='.', client=None):
notifier
=
AsyncNotifier
(
wm
,
EventHandler
(
client
))
notifier
=
AsyncNotifier
(
wm
,
EventHandler
(
client
))
wm
.
add_watch
(
path
,
mask
,
auto_add
=
True
,
rec
=
True
)
wm
.
add_watch
(
path
,
mask
,
auto_add
=
True
,
rec
=
True
)
if
not
os
.
path
.
isfile
(
path
):
if
not
os
.
path
.
isfile
(
path
):
print
"You should monitor a file"
logger
.
debug
(
"File
%
s does not exist."
%
path
)
sys
.
exit
(
3
)
sys
.
exit
(
3
)
else
:
else
:
print
"now starting monitor
%
s."
%
path
logger
.
debug
(
"Now starting monitor file
%
s."
%
path
)
global
f
global
f
f
=
open
(
path
,
'r'
)
f
=
open
(
path
,
'r'
)
st_size
=
os
.
stat
(
path
)[
6
]
st_size
=
os
.
stat
(
path
)[
6
]
...
@@ -136,7 +163,7 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
...
@@ -136,7 +163,7 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
def
check_origin
(
self
,
origin
):
def
check_origin
(
self
,
origin
):
return
True
return
True
@require_auth
@require_auth
(
'admin'
)
def
open
(
self
):
def
open
(
self
):
# 获取监控的path
# 获取监控的path
self
.
file_path
=
self
.
get_argument
(
'file_path'
,
''
)
self
.
file_path
=
self
.
get_argument
(
'file_path'
,
''
)
...
@@ -158,7 +185,8 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
...
@@ -158,7 +185,8 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
MonitorHandler
.
clients
.
remove
(
self
)
MonitorHandler
.
clients
.
remove
(
self
)
MonitorHandler
.
threads
.
remove
(
MonitorHandler
.
threads
[
client_index
])
MonitorHandler
.
threads
.
remove
(
MonitorHandler
.
threads
[
client_index
])
print
len
(
MonitorHandler
.
threads
),
len
(
MonitorHandler
.
clients
)
logger
.
debug
(
"Websocket: Monitor client num:
%
s, thread num:
%
s"
%
(
len
(
MonitorHandler
.
clients
),
len
(
MonitorHandler
.
threads
)))
def
on_message
(
self
,
message
):
def
on_message
(
self
,
message
):
# 监控日志,发生变动发向客户端
# 监控日志,发生变动发向客户端
...
@@ -168,10 +196,13 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
...
@@ -168,10 +196,13 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
# 客户端主动关闭
# 客户端主动关闭
# self.close()
# self.close()
print
"Close websocket."
logger
.
debug
(
"Websocket: Monitor client close request"
)
client_index
=
MonitorHandler
.
clients
.
index
(
self
)
try
:
MonitorHandler
.
clients
.
remove
(
self
)
client_index
=
MonitorHandler
.
clients
.
index
(
self
)
MonitorHandler
.
threads
.
remove
(
MonitorHandler
.
threads
[
client_index
])
MonitorHandler
.
clients
.
remove
(
self
)
MonitorHandler
.
threads
.
remove
(
MonitorHandler
.
threads
[
client_index
])
except
ValueError
:
pass
class
WebTty
(
Tty
):
class
WebTty
(
Tty
):
...
@@ -184,6 +215,7 @@ class WebTty(Tty):
...
@@ -184,6 +215,7 @@ class WebTty(Tty):
class
WebTerminalKillHandler
(
tornado
.
web
.
RequestHandler
):
class
WebTerminalKillHandler
(
tornado
.
web
.
RequestHandler
):
@require_auth
(
'admin'
)
def
get
(
self
):
def
get
(
self
):
ws_id
=
self
.
get_argument
(
'id'
)
ws_id
=
self
.
get_argument
(
'id'
)
Log
.
objects
.
filter
(
id
=
ws_id
)
.
update
(
is_finished
=
True
)
Log
.
objects
.
filter
(
id
=
ws_id
)
.
update
(
is_finished
=
True
)
...
@@ -206,6 +238,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
...
@@ -206,6 +238,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
self
.
log_time_f
=
None
self
.
log_time_f
=
None
self
.
log
=
None
self
.
log
=
None
self
.
id
=
0
self
.
id
=
0
self
.
user
=
None
super
(
WebTerminalHandler
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
WebTerminalHandler
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
check_origin
(
self
,
origin
):
def
check_origin
(
self
,
origin
):
...
@@ -213,11 +246,28 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
...
@@ -213,11 +246,28 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
@require_auth
@require_auth
def
open
(
self
):
def
open
(
self
):
asset_name
=
self
.
get_argument
(
'asset_name'
,
''
)
role_name
=
self
.
get_argument
(
'role'
,
'sb'
)
username
=
self
.
get_argument
(
'username'
,
''
)
asset_id
=
self
.
get_argument
(
'id'
,
9999
)
token
=
self
.
get_argument
(
'token'
,
''
)
asset
=
get_object
(
Asset
,
id
=
asset_id
)
print
asset_name
,
username
,
token
if
asset
:
self
.
term
=
WebTty
(
'a'
,
'b'
)
roles
=
user_have_perm
(
self
.
user
,
asset
)
login_role
=
''
for
role
in
roles
:
if
role
.
name
==
role_name
:
login_role
=
role
break
if
not
login_role
:
logger
.
warning
(
'Websocket: Not that Role
%
s for Host:
%
s User:
%
s '
%
(
role_name
,
asset
.
hostname
,
self
.
user
.
username
))
self
.
close
()
return
else
:
logger
.
warning
(
'Websocket: No that Host:
%
s User:
%
s '
%
(
asset_id
,
self
.
user
.
username
))
self
.
close
()
return
logger
.
debug
(
'Websocket: request web terminal Host:
%
s User:
%
s Role:
%
s'
%
(
asset
.
hostname
,
self
.
user
.
username
,
login_role
.
name
))
self
.
term
=
WebTty
(
self
.
user
,
self
.
asset
,
login_role
)
self
.
term
.
get_connection
()
self
.
term
.
get_connection
()
self
.
term
.
channel
=
self
.
term
.
ssh
.
invoke_shell
(
term
=
'xterm'
)
self
.
term
.
channel
=
self
.
term
.
ssh
.
invoke_shell
(
term
=
'xterm'
)
WebTerminalHandler
.
tasks
.
append
(
MyThread
(
target
=
self
.
forward_outbound
))
WebTerminalHandler
.
tasks
.
append
(
MyThread
(
target
=
self
.
forward_outbound
))
...
@@ -236,7 +286,17 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
...
@@ -236,7 +286,17 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
if
data
.
get
(
'data'
):
if
data
.
get
(
'data'
):
self
.
term
.
input_mode
=
True
self
.
term
.
input_mode
=
True
if
str
(
data
[
'data'
])
in
[
'
\r
'
,
'
\n
'
,
'
\r\n
'
]:
if
str
(
data
[
'data'
])
in
[
'
\r
'
,
'
\n
'
,
'
\r\n
'
]:
TtyLog
(
log
=
self
.
log
,
datetime
=
datetime
.
datetime
.
now
(),
cmd
=
self
.
term
.
deal_command
(
self
.
term
.
data
,
self
.
term
.
ssh
))
.
save
()
if
self
.
term
.
vim_flag
:
match
=
self
.
term
.
ps1_pattern
.
search
(
self
.
term
.
vim_data
)
if
match
:
self
.
term
.
vim_flag
=
False
vim_data
=
self
.
term
.
deal_command
(
self
.
term
.
vim_data
)[
0
:
200
]
if
len
(
data
)
>
0
:
TtyLog
(
log
=
self
.
log
,
datetime
=
datetime
.
datetime
.
now
(),
cmd
=
vim_data
)
.
save
()
TtyLog
(
log
=
self
.
log
,
datetime
=
datetime
.
datetime
.
now
(),
cmd
=
self
.
term
.
deal_command
(
self
.
term
.
data
)[
0
:
200
])
.
save
()
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
.
term
.
channel
.
send
(
data
[
'data'
])
...
@@ -267,6 +327,8 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
...
@@ -267,6 +327,8 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
if
not
len
(
recv
):
if
not
len
(
recv
):
return
return
data
+=
recv
data
+=
recv
if
self
.
term
.
vim_flag
:
self
.
term
.
vim_data
+=
recv
try
:
try
:
self
.
write_message
(
json
.
dumps
({
'data'
:
data
}))
self
.
write_message
(
json
.
dumps
({
'data'
:
data
}))
now_timestamp
=
time
.
time
()
now_timestamp
=
time
.
time
()
...
@@ -290,4 +352,5 @@ if __name__ == '__main__':
...
@@ -290,4 +352,5 @@ if __name__ == '__main__':
server
.
bind
(
options
.
port
,
options
.
host
)
server
.
bind
(
options
.
port
,
options
.
host
)
# server.listen(options.port)
# server.listen(options.port)
server
.
start
(
num_processes
=
1
)
server
.
start
(
num_processes
=
1
)
print
"Run server on
%
s:
%
s"
%
(
options
.
host
,
options
.
port
)
tornado
.
ioloop
.
IOLoop
.
instance
()
.
start
()
tornado
.
ioloop
.
IOLoop
.
instance
()
.
start
()
templates/jasset/asset_list.html
View file @
49821062
...
@@ -130,6 +130,7 @@
...
@@ -130,6 +130,7 @@
<a
href=
"/jasset/asset_detail/?id={{ asset.id }}"
class=
"btn btn-xs btn-primary"
>
详情
</a>
<a
href=
"/jasset/asset_detail/?id={{ asset.id }}"
class=
"btn btn-xs btn-primary"
>
详情
</a>
{% ifnotequal session_role_id 0 %}
{% ifnotequal session_role_id 0 %}
<a
href=
"/jasset/asset_edit/?id={{ asset.id }}"
class=
"btn btn-xs btn-info"
>
编辑
</a>
<a
href=
"/jasset/asset_edit/?id={{ asset.id }}"
class=
"btn btn-xs btn-info"
>
编辑
</a>
<a
value=
"{{ asset.id }}"
class=
"conn btn btn-xs btn-warning"
>
连接
</a>
<a
value=
"/jasset/asset_del/?id={{ asset.id }}"
class=
"btn btn-xs btn-danger asset_del"
>
删除
</a>
<a
value=
"/jasset/asset_del/?id={{ asset.id }}"
class=
"btn btn-xs btn-danger asset_del"
>
删除
</a>
{% endifnotequal %}
{% endifnotequal %}
</td>
</td>
...
@@ -168,9 +169,46 @@
...
@@ -168,9 +169,46 @@
}
}
)
)
}
}
})
});
$
(
'.conn'
).
click
(
function
(){
var
url
=
'/jlog/get_role_name/?id='
+
$
(
this
).
attr
(
'value'
);
var
href
=
$
(
this
).
attr
(
'href'
);
var
new_url
=
'/jlog/web_terminal/?id='
+
$
(
this
).
attr
(
'value'
)
+
'&role='
;
$
.
ajax
({
type
:
'GET'
,
url
:
url
,
data
:
{},
success
:
function
(
data
){
var
dataArray
=
data
.
split
(
','
);
if
(
dataArray
.
length
==
1
&&
data
!=
'error'
){
console
.
log
(
'one'
);
window
.
open
(
new_url
+
data
,
''
,
'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'
);
}
else
if
(
dataArray
.
length
==
'1'
&&
data
==
'error'
){
layer
.
alert
(
'没有授权角色'
)
}
else
{
aUrl
=
''
;
$
.
each
(
dataArray
,
function
(
index
,
value
){
aUrl
+=
'<a onclick="windowOpen(this); return false" class="btn btn-xs btn-primary newa" href='
+
new_url
+
value
+
'>'
+
value
+
'</a> '
});
layer
.
alert
(
aUrl
,
{
skin
:
'layui-layer-molv'
,
title
:
'多个角色,请选择一个连接'
,
closeBtn
:
0
})
}
}
});
return
false
});
});
});
function
windowOpen
(
aTab
){
var
new_url
=
aTab
.
href
;
window
.
open
(
new_url
,
''
,
'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'
);
return
false
}
$
(
".iframe"
).
on
(
'click'
,
function
(){
$
(
".iframe"
).
on
(
'click'
,
function
(){
var
asset_id_all
=
getIDall
();
var
asset_id_all
=
getIDall
();
if
(
asset_id_all
==
''
){
if
(
asset_id_all
==
''
){
...
@@ -207,6 +245,8 @@
...
@@ -207,6 +245,8 @@
});
});
});
});
$
(
'#asset_del'
).
click
(
function
()
{
$
(
'#asset_del'
).
click
(
function
()
{
var
asset_id_all
=
getIDall
();
var
asset_id_all
=
getIDall
();
if
(
asset_id_all
==
''
){
if
(
asset_id_all
==
''
){
...
...
templates/jlog/log_online.html
View file @
49821062
...
@@ -79,11 +79,9 @@
...
@@ -79,11 +79,9 @@
<th
class=
"text-center"
>
用户名
</th>
<th
class=
"text-center"
>
用户名
</th>
<th
class=
"text-center"
>
登录主机
</th>
<th
class=
"text-center"
>
登录主机
</th>
<th
class=
"text-center"
>
来源IP
</th>
<th
class=
"text-center"
>
来源IP
</th>
{% ifnotequal session_role_id 0 %}
<th
class=
"text-center"
>
统计命令
</th>
<th
class=
"text-center"
>
统计命令
</th>
<th
class=
"text-center"
>
实时监控
</th>
<th
class=
"text-center"
>
实时监控
</th>
<th
class=
"text-center"
>
阻断
</th>
<th
class=
"text-center"
>
阻断
</th>
{% endifnotequal %}
<th
class=
"text-center"
>
登录时间
</th>
<th
class=
"text-center"
>
登录时间
</th>
</tr>
</tr>
...
@@ -94,11 +92,9 @@
...
@@ -94,11 +92,9 @@
<td
id=
"username"
class=
"text-center"
>
{{ post.user }}
</td>
<td
id=
"username"
class=
"text-center"
>
{{ post.user }}
</td>
<td
id=
"ip"
class=
"text-center"
>
{{ post.host }}
</td>
<td
id=
"ip"
class=
"text-center"
>
{{ post.host }}
</td>
<td
id=
"remote_ip"
class=
"text-center"
>
{{ post.remote_ip }}
</td>
<td
id=
"remote_ip"
class=
"text-center"
>
{{ post.remote_ip }}
</td>
{% ifnotequal session_role_id 0 %}
<td
class=
"text-center"
><a
href=
"/jlog/history/?id={{ post.id }}"
class=
"log_command"
>
命令统计
</a></td>
<td
class=
"text-center"
><a
href=
"/jlog/history/?id={{ post.id }}"
class=
"log_command"
>
命令统计
</a></td>
<td
class=
"text-center"
><a
class=
"monitor"
file_path=
"{{ post.log_path }}"
>
监控
</a></td>
<td
class=
"text-center"
><a
class=
"monitor"
file_path=
"{{ post.log_path }}"
>
监控
</a></td>
<td
class=
"text-center"
><input
type=
"button"
id=
"cut"
class=
"btn btn-danger btn-xs"
name=
"cut"
value=
"阻断"
onclick=
'cut("{{ post.pid }}", "{{ post.remote_ip }}")'
/></td>
<td
class=
"text-center"
><input
type=
"button"
id=
"cut"
class=
"btn btn-danger btn-xs"
name=
"cut"
value=
"阻断"
onclick=
'cut("{{ post.pid }}", "{{ post.remote_ip }}")'
/></td>
{% endifnotequal %}
<td
class=
"text-center"
id=
"start_time"
>
{{ post.start_time|date:"Y-m-d H:i:s" }}
</td>
<td
class=
"text-center"
id=
"start_time"
>
{{ post.start_time|date:"Y-m-d H:i:s" }}
</td>
</tr>
</tr>
{% endfor %}
{% endfor %}
...
@@ -188,10 +184,6 @@
...
@@ -188,10 +184,6 @@
}});
}});
return
false
;
return
false
;
});
});
$
(
'#test_connect'
).
click
(
function
(){
window
.
open
(
'/jlog/web_terminal/?asset_name="hello'
,
'播放'
,
'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'
);
});
});
});
{
#
function
log_search
(){
#
}
{
#
function
log_search
(){
#
}
...
...
templates/nav.html
View file @
49821062
...
@@ -36,8 +36,6 @@
...
@@ -36,8 +36,6 @@
<li
class=
"role"
>
<li
class=
"role"
>
<a
href=
"/jperm/role/"
>
系统角色
</a>
<a
href=
"/jperm/role/"
>
系统角色
</a>
</li>
</li>
<li
class=
"apply_show online"
><a
href=
"/jperm/apply_show/online/"
>
权限审批
</a></li>
<li
class=
"apply_show online"
><a
href=
"/jperm/log/"
>
授权记录
</a></li>
</ul>
</ul>
</li>
</li>
<li
id=
"jlog"
>
<li
id=
"jlog"
>
...
...
templates/setting.html
View file @
49821062
...
@@ -29,7 +29,7 @@
...
@@ -29,7 +29,7 @@
<div
class=
"panel-options"
>
<div
class=
"panel-options"
>
<ul
class=
"nav nav-tabs"
>
<ul
class=
"nav nav-tabs"
>
<li
id=
"tab1"
class=
"active"
><a
data-toggle=
"tab"
href=
"#tab-default"
aria-expanded=
"true"
>
默认设置
</a></li>
<li
id=
"tab1"
class=
"active"
><a
data-toggle=
"tab"
href=
"#tab-default"
aria-expanded=
"true"
>
默认设置
</a></li>
<li
id=
"tab2"
class=
""
><a
data-toggle=
"tab"
href=
"#tab-email"
aria-expanded=
"true"
>
邮箱设置
</a></li>
{#
<li
id=
"tab2"
class=
""
><a
data-toggle=
"tab"
href=
"#tab-email"
aria-expanded=
"true"
>
邮箱设置
</a></li>
#}
</ul>
</ul>
</div>
</div>
</div>
</div>
...
@@ -82,15 +82,15 @@
...
@@ -82,15 +82,15 @@
</form>
</form>
</div>
</div>
<div
id=
"tab-email"
class=
"tab-pane"
>
{#
<div
id=
"tab-email"
class=
"tab-pane"
>
#}
<table
class=
"table table-striped table-bordered table-hover "
id=
"editable"
>
{#
<table
class=
"table table-striped table-bordered table-hover "
id=
"editable"
>
#}
<thead>
{#
<thead>
#}
<tr>
{#
<tr>
#}
<th
class=
"text-center"
>
组名
</th>
{#
<th
class=
"text-center"
>
组名
</th>
#}
</tr>
{#
</tr>
#}
</thead>
{#
</thead>
#}
</table>
{#
</table>
#}
</div>
{#
</div>
#}
</div>
</div>
</div>
</div>
</div>
</div>
...
...
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