Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
coco
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
coco
Commits
2467b4e2
Commit
2467b4e2
authored
May 21, 2018
by
广宏伟
Browse files
Options
Browse Files
Download
Plain Diff
Merged in dev (pull request #57)
Dev
parents
4d2015df
01285f53
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
82 additions
and
34 deletions
+82
-34
app.py
coco/app.py
+10
-4
connection.py
coco/connection.py
+36
-11
httpd.py
coco/httpd.py
+3
-4
interactive.py
coco/interactive.py
+1
-1
models.py
coco/models.py
+9
-4
proxy.py
coco/proxy.py
+2
-2
sftp.py
coco/sftp.py
+18
-6
utils.py
coco/utils.py
+2
-1
requirements.txt
requirements/requirements.txt
+1
-1
No files found.
coco/app.py
View file @
2467b4e2
...
@@ -219,13 +219,19 @@ class Coco:
...
@@ -219,13 +219,19 @@ class Coco:
def
add_client
(
self
,
client
):
def
add_client
(
self
,
client
):
with
self
.
lock
:
with
self
.
lock
:
self
.
clients
.
append
(
client
)
self
.
clients
.
append
(
client
)
logger
.
info
(
"New client {} join, total {} now"
.
format
(
client
,
len
(
self
.
clients
)))
logger
.
info
(
"New client {} join, total {} now"
.
format
(
client
,
len
(
self
.
clients
)
)
)
def
remove_client
(
self
,
client
):
def
remove_client
(
self
,
client
):
with
self
.
lock
:
with
self
.
lock
:
try
:
try
:
self
.
clients
.
remove
(
client
)
self
.
clients
.
remove
(
client
)
logger
.
info
(
"Client {} leave, total {} now"
.
format
(
client
,
len
(
self
.
clients
)))
logger
.
info
(
"Client {} leave, total {} now"
.
format
(
client
,
len
(
self
.
clients
)
)
)
client
.
close
()
client
.
close
()
except
:
except
:
pass
pass
...
@@ -242,4 +248,5 @@ class Coco:
...
@@ -242,4 +248,5 @@ class Coco:
self
.
sessions
.
remove
(
session
)
self
.
sessions
.
remove
(
session
)
self
.
service
.
finish_session
(
session
.
to_json
())
self
.
service
.
finish_session
(
session
.
to_json
())
except
ValueError
:
except
ValueError
:
logger
.
warning
(
"Remove session: {} fail, maybe already removed"
.
format
(
session
))
msg
=
"Remove session: {} fail, maybe already removed"
\ No newline at end of file
logger
.
warning
(
msg
.
format
(
session
))
coco/connection.py
View file @
2467b4e2
...
@@ -34,7 +34,7 @@ class SSHConnection:
...
@@ -34,7 +34,7 @@ class SSHConnection:
self
.
get_system_user_auth
(
system_user
)
self
.
get_system_user_auth
(
system_user
)
if
asset
.
domain
:
if
asset
.
domain
:
sock
=
self
.
get_proxy_sock
(
asset
)
sock
=
self
.
get_proxy_sock
_v2
(
asset
)
try
:
try
:
ssh
.
connect
(
ssh
.
connect
(
...
@@ -64,29 +64,54 @@ class SSHConnection:
...
@@ -64,29 +64,54 @@ class SSHConnection:
return
None
,
str
(
e
)
return
None
,
str
(
e
)
except
(
socket
.
error
,
TimeoutError
)
as
e
:
except
(
socket
.
error
,
TimeoutError
)
as
e
:
return
None
,
str
(
e
)
return
None
,
str
(
e
)
return
ssh
,
None
return
ssh
,
sock
,
None
def
get_transport
(
self
,
asset
,
system_user
):
def
get_transport
(
self
,
asset
,
system_user
):
ssh
,
msg
=
self
.
get_ssh_client
(
asset
,
system_user
)
ssh
,
sock
,
msg
=
self
.
get_ssh_client
(
asset
,
system_user
)
if
ssh
:
if
ssh
:
return
ssh
.
get_transport
(),
None
return
ssh
.
get_transport
(),
sock
,
None
else
:
else
:
return
None
,
msg
return
None
,
None
,
msg
def
get_channel
(
self
,
asset
,
system_user
,
term
=
"xterm"
,
width
=
80
,
height
=
24
):
def
get_channel
(
self
,
asset
,
system_user
,
term
=
"xterm"
,
width
=
80
,
height
=
24
):
ssh
,
msg
=
self
.
get_ssh_client
(
asset
,
system_user
)
ssh
,
sock
,
msg
=
self
.
get_ssh_client
(
asset
,
system_user
)
if
ssh
:
if
ssh
:
chan
=
ssh
.
invoke_shell
(
term
,
width
=
width
,
height
=
height
)
chan
=
ssh
.
invoke_shell
(
term
,
width
=
width
,
height
=
height
)
return
chan
,
None
return
chan
,
sock
,
None
else
:
else
:
return
None
,
msg
return
None
,
sock
,
msg
def
get_sftp
(
self
,
asset
,
system_user
):
def
get_sftp
(
self
,
asset
,
system_user
):
ssh
,
msg
=
self
.
get_ssh_client
(
asset
,
system_user
)
ssh
,
sock
,
msg
=
self
.
get_ssh_client
(
asset
,
system_user
)
if
ssh
:
if
ssh
:
return
ssh
.
open_sftp
(),
None
return
ssh
.
open_sftp
(),
sock
,
None
else
:
else
:
return
None
,
msg
return
None
,
sock
,
msg
def
get_proxy_sock_v2
(
self
,
asset
):
sock
=
None
domain
=
app_service
.
get_domain_detail_with_gateway
(
asset
.
domain
)
if
not
domain
.
has_ssh_gateway
():
return
None
for
i
in
domain
.
gateways
:
gateway
=
domain
.
random_ssh_gateway
()
ssh
=
paramiko
.
SSHClient
()
ssh
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
())
try
:
ssh
.
connect
(
gateway
.
ip
,
username
=
gateway
.
username
,
password
=
gateway
.
password
,
pkey
=
gateway
.
private_key_obj
)
except
(
paramiko
.
AuthenticationException
,
paramiko
.
BadAuthenticationType
,
SSHException
):
continue
sock
=
ssh
.
get_transport
()
.
open_channel
(
'direct-tcpip'
,
(
asset
.
ip
,
asset
.
port
),
(
'127.0.0.1'
,
0
)
)
break
return
sock
def
get_proxy_sock
(
self
,
asset
):
def
get_proxy_sock
(
self
,
asset
):
sock
=
None
sock
=
None
...
...
coco/httpd.py
View file @
2467b4e2
...
@@ -212,8 +212,7 @@ class ProxyNamespace(BaseNamespace):
...
@@ -212,8 +212,7 @@ class ProxyNamespace(BaseNamespace):
def
on_disconnect
(
self
):
def
on_disconnect
(
self
):
logger
.
debug
(
"On disconnect event trigger"
)
logger
.
debug
(
"On disconnect event trigger"
)
room_id_list
=
list
(
self
.
connections
.
get
(
request
.
sid
,
{})
.
keys
())
for
room_id
in
self
.
connections
.
get
(
request
.
sid
,
{}):
for
room_id
in
room_id_list
:
try
:
try
:
self
.
on_logout
(
room_id
)
self
.
on_logout
(
room_id
)
except
Exception
as
e
:
except
Exception
as
e
:
...
@@ -250,14 +249,14 @@ class HttpServer:
...
@@ -250,14 +249,14 @@ class HttpServer:
self
.
flask_app
.
config
.
update
(
config
)
self
.
flask_app
.
config
.
update
(
config
)
self
.
socket_io
=
SocketIO
()
self
.
socket_io
=
SocketIO
()
self
.
register_routes
()
self
.
register_routes
()
self
.
register_error_handler
()
def
register_routes
(
self
):
def
register_routes
(
self
):
self
.
socket_io
.
on_namespace
(
ProxyNamespace
(
'/ssh'
))
self
.
socket_io
.
on_namespace
(
ProxyNamespace
(
'/ssh'
))
@staticmethod
@staticmethod
def
on_error_default
(
e
):
def
on_error_default
(
e
):
traceback
.
print_exc
()
logger
.
exception
(
e
)
logger
.
warn
(
e
)
def
register_error_handler
(
self
):
def
register_error_handler
(
self
):
self
.
socket_io
.
on_error_default
(
self
.
on_error_default
)
self
.
socket_io
.
on_error_default
(
self
.
on_error_default
)
...
...
coco/interactive.py
View file @
2467b4e2
...
@@ -263,7 +263,7 @@ class InteractiveServer:
...
@@ -263,7 +263,7 @@ class InteractiveServer:
self
.
display_banner
()
self
.
display_banner
()
while
True
:
while
True
:
try
:
try
:
opt
=
net_input
(
self
.
client
,
prompt
=
'Opt>'
,
before
=
1
)
opt
=
net_input
(
self
.
client
,
prompt
=
'Opt>
'
,
before
=
1
)
rv
=
self
.
dispatch
(
opt
)
rv
=
self
.
dispatch
(
opt
)
if
rv
is
self
.
_sentinel
:
if
rv
is
self
.
_sentinel
:
break
break
...
...
coco/models.py
View file @
2467b4e2
...
@@ -94,8 +94,9 @@ class Server:
...
@@ -94,8 +94,9 @@ class Server:
"""
"""
# Todo: Server name is not very suitable
# Todo: Server name is not very suitable
def
__init__
(
self
,
chan
,
asset
,
system_user
):
def
__init__
(
self
,
chan
,
sock
,
asset
,
system_user
):
self
.
chan
=
chan
self
.
chan
=
chan
self
.
sock
=
sock
self
.
asset
=
asset
self
.
asset
=
asset
self
.
system_user
=
system_user
self
.
system_user
=
system_user
self
.
send_bytes
=
0
self
.
send_bytes
=
0
...
@@ -168,6 +169,8 @@ class Server:
...
@@ -168,6 +169,8 @@ class Server:
self
.
stop_evt
.
set
()
self
.
stop_evt
.
set
()
self
.
chan
.
close
()
self
.
chan
.
close
()
self
.
chan
.
transport
.
close
()
self
.
chan
.
transport
.
close
()
if
self
.
sock
:
self
.
sock
.
transport
.
close
()
@staticmethod
@staticmethod
def
_have_enter_char
(
s
):
def
_have_enter_char
(
s
):
...
@@ -251,7 +254,6 @@ class WSProxy:
...
@@ -251,7 +254,6 @@ class WSProxy:
if
len
(
data
)
==
0
:
if
len
(
data
)
==
0
:
self
.
close
()
self
.
close
()
data
=
data
.
decode
(
errors
=
"ignore"
)
data
=
data
.
decode
(
errors
=
"ignore"
)
print
(
"Send data: {}"
.
format
(
data
))
self
.
ws
.
emit
(
"data"
,
{
'data'
:
data
,
'room'
:
self
.
room_id
},
self
.
ws
.
emit
(
"data"
,
{
'data'
:
data
,
'room'
:
self
.
room_id
},
room
=
self
.
room_id
)
room
=
self
.
room_id
)
if
len
(
data
)
==
BUF_SIZE
:
if
len
(
data
)
==
BUF_SIZE
:
...
@@ -264,8 +266,11 @@ class WSProxy:
...
@@ -264,8 +266,11 @@ class WSProxy:
def
close
(
self
):
def
close
(
self
):
self
.
stop_event
.
set
()
self
.
stop_event
.
set
()
self
.
child
.
shutdown
(
1
)
try
:
self
.
child
.
close
()
self
.
child
.
shutdown
(
1
)
self
.
child
.
close
()
except
(
OSError
,
EOFError
):
pass
logger
.
debug
(
"Proxy {} closed"
.
format
(
self
))
logger
.
debug
(
"Proxy {} closed"
.
format
(
self
))
...
...
coco/proxy.py
View file @
2467b4e2
...
@@ -90,14 +90,14 @@ class ProxyServer:
...
@@ -90,14 +90,14 @@ class ProxyServer:
width
=
request
.
meta
.
get
(
'width'
,
80
)
width
=
request
.
meta
.
get
(
'width'
,
80
)
height
=
request
.
meta
.
get
(
'height'
,
24
)
height
=
request
.
meta
.
get
(
'height'
,
24
)
ssh
=
SSHConnection
()
ssh
=
SSHConnection
()
chan
,
msg
=
ssh
.
get_channel
(
chan
,
sock
,
msg
=
ssh
.
get_channel
(
asset
,
system_user
,
term
=
term
,
width
=
width
,
height
=
height
asset
,
system_user
,
term
=
term
,
width
=
width
,
height
=
height
)
)
if
not
chan
:
if
not
chan
:
self
.
client
.
send
(
warning
(
wr
(
msg
,
before
=
1
,
after
=
0
)))
self
.
client
.
send
(
warning
(
wr
(
msg
,
before
=
1
,
after
=
0
)))
server
=
None
server
=
None
else
:
else
:
server
=
Server
(
chan
,
asset
,
system_user
)
server
=
Server
(
chan
,
sock
,
asset
,
system_user
)
self
.
connecting
=
False
self
.
connecting
=
False
self
.
client
.
send
(
b
'
\r\n
'
)
self
.
client
.
send
(
b
'
\r\n
'
)
return
server
return
server
...
...
coco/sftp.py
View file @
2467b4e2
...
@@ -2,6 +2,7 @@ import os
...
@@ -2,6 +2,7 @@ import os
import
tempfile
import
tempfile
import
paramiko
import
paramiko
import
time
import
time
from
.ctx
import
app_service
from
datetime
import
datetime
from
datetime
import
datetime
from
.connection
import
SSHConnection
from
.connection
import
SSHConnection
...
@@ -16,6 +17,17 @@ class SFTPServer(paramiko.SFTPServerInterface):
...
@@ -16,6 +17,17 @@ class SFTPServer(paramiko.SFTPServerInterface):
self
.
_sftp
=
{}
self
.
_sftp
=
{}
self
.
hosts
=
self
.
get_perm_hosts
()
self
.
hosts
=
self
.
get_perm_hosts
()
def
session_ended
(
self
):
super
()
.
session_ended
()
for
_
,
v
in
self
.
_sftp
.
items
():
sftp
=
v
[
'sftp'
]
sock
=
v
.
get
(
'sock'
)
sftp
.
close
()
if
sock
:
sock
.
close
()
sock
.
transport
.
close
()
self
.
_sftp
=
{}
def
get_host_sftp
(
self
,
host
,
su
):
def
get_host_sftp
(
self
,
host
,
su
):
asset
=
self
.
hosts
.
get
(
host
)
asset
=
self
.
hosts
.
get
(
host
)
system_user
=
None
system_user
=
None
...
@@ -28,18 +40,18 @@ class SFTPServer(paramiko.SFTPServerInterface):
...
@@ -28,18 +40,18 @@ class SFTPServer(paramiko.SFTPServerInterface):
raise
OSError
(
"No asset or system user explicit"
)
raise
OSError
(
"No asset or system user explicit"
)
if
host
not
in
self
.
_sftp
:
if
host
not
in
self
.
_sftp
:
ssh
=
SSHConnection
(
self
.
server
.
app
)
ssh
=
SSHConnection
()
sftp
,
msg
=
ssh
.
get_sftp
(
asset
,
system_user
)
sftp
,
sock
,
msg
=
ssh
.
get_sftp
(
asset
,
system_user
)
if
sftp
:
if
sftp
:
self
.
_sftp
[
host
]
=
sftp
self
.
_sftp
[
host
]
=
{
'sftp'
:
sftp
,
'sock'
:
sock
}
return
sftp
return
sftp
else
:
else
:
raise
OSError
(
"Can not connect asset sftp server: {}"
.
format
(
msg
))
raise
OSError
(
"Can not connect asset sftp server: {}"
.
format
(
msg
))
else
:
else
:
return
self
.
_sftp
[
host
]
return
self
.
_sftp
[
host
]
[
'sftp'
]
def
get_perm_hosts
(
self
):
def
get_perm_hosts
(
self
):
assets
=
self
.
server
.
app
.
service
.
get_user_assets
(
assets
=
app_
service
.
get_user_assets
(
self
.
server
.
request
.
user
self
.
server
.
request
.
user
)
)
return
{
asset
.
hostname
:
asset
for
asset
in
assets
}
return
{
asset
.
hostname
:
asset
for
asset
in
assets
}
...
@@ -89,7 +101,7 @@ class SFTPServer(paramiko.SFTPServerInterface):
...
@@ -89,7 +101,7 @@ class SFTPServer(paramiko.SFTPServerInterface):
"is_success"
:
is_success
,
"is_success"
:
is_success
,
}
}
for
i
in
range
(
1
,
4
):
for
i
in
range
(
1
,
4
):
ok
=
self
.
server
.
app
.
service
.
create_ftp_log
(
data
)
ok
=
app_
service
.
create_ftp_log
(
data
)
if
ok
:
if
ok
:
break
break
else
:
else
:
...
...
coco/utils.py
View file @
2467b4e2
...
@@ -396,7 +396,6 @@ def size_of_str_with_zh(s):
...
@@ -396,7 +396,6 @@ def size_of_str_with_zh(s):
try
:
try
:
chinese
=
find_chinese
(
s
)
chinese
=
find_chinese
(
s
)
except
TypeError
:
except
TypeError
:
print
(
type
(
s
))
raise
raise
return
len
(
s
)
+
len
(
chinese
)
return
len
(
s
)
+
len
(
chinese
)
...
@@ -406,6 +405,8 @@ def item_max_length(_iter, maxi=None, mini=None, key=None):
...
@@ -406,6 +405,8 @@ def item_max_length(_iter, maxi=None, mini=None, key=None):
_iter
=
[
key
(
i
)
for
i
in
_iter
]
_iter
=
[
key
(
i
)
for
i
in
_iter
]
length
=
[
size_of_str_with_zh
(
s
)
for
s
in
_iter
]
length
=
[
size_of_str_with_zh
(
s
)
for
s
in
_iter
]
if
not
length
:
return
1
if
maxi
:
if
maxi
:
length
.
append
(
maxi
)
length
.
append
(
maxi
)
length
=
max
(
length
)
length
=
max
(
length
)
...
...
requirements/requirements.txt
View file @
2467b4e2
...
@@ -20,7 +20,7 @@ Jinja2==2.10
...
@@ -20,7 +20,7 @@ Jinja2==2.10
jmespath==0.9.3
jmespath==0.9.3
jms-es-sdk==0.5.2
jms-es-sdk==0.5.2
jms-storage==0.0.12
jms-storage==0.0.12
jumpserver-python-sdk==0.0.4
1
jumpserver-python-sdk==0.0.4
2
MarkupSafe==1.0
MarkupSafe==1.0
oss2==2.4.0
oss2==2.4.0
paramiko==2.4.0
paramiko==2.4.0
...
...
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