Commit c8b6f615 authored by ibuler's avatar ibuler

Merge branch 'dev' of github.com:jumpserver/coco into dev

parents eb62a381 15cfc4e7
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import io
import socket import os
import json import paramiko
import logging import logging
import socket
import tornado.web from flask_socketio import SocketIO, Namespace, emit
import tornado.websocket from flask import Flask, send_from_directory, render_template, request, jsonify
import tornado.httpclient from urllib.parse import urlparse
import tornado.ioloop
import tornado.gen
# Todo: Remove for future # Todo: Remove for future
from jms.models import User from jms.models import User
from .models import Request, Client, WSProxy from .models import Request, Client, WSProxy
from .interactive import InteractiveServer from .forward import ProxyServer
import http.client
__version__ = '0.4.0'
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
logger = logging.getLogger(__file__) logger = logging.getLogger(__file__)
class BaseWebSocketHandler: class BaseWebSocketHandler:
def prepare(self): def app(self, app):
self.app = self.settings["app"] self.app = app
return self
def prepare(self, request):
# self.app = self.settings["app"]
child, parent = socket.socketpair() child, parent = socket.socketpair()
request = Request((self.request.remote_ip, 0)) if request.headers.getlist("X-Forwarded-For"):
request.user = self.current_user remote_ip = request.headers.getlist("X-Forwarded-For")[0]
self.request.__dict__.update(request.__dict__) else:
remote_ip = request.remote_addr
self.request = Request((remote_ip, 0))
self.request.user = self.get_current_user()
self.request.meta = {"width": self.cols, "height": self.rows}
# self.request.__dict__.update(request.__dict__)
self.client = Client(parent, self.request) self.client = Client(parent, self.request)
self.proxy = WSProxy(self, child) self.proxy = WSProxy(self, child)
self.app.clients.append(self.client) self.app.clients.append(self.client)
def get_current_user(self): def get_current_user(self):
return User(id=1, username="guanghongwei", name="广宏伟") return User(id='61c39c1f5b5742688180b6dda235aadd', username="admin", name="admin")
def check_origin(self, origin): def check_origin(self, origin):
return True return True
def close(self):
try:
self.ssh.close()
except:
pass
pass
class InteractiveWebSocketHandler(BaseWebSocketHandler, tornado.websocket.WebSocketHandler):
@tornado.web.authenticated
def open(self):
InteractiveServer(self.app, self.client).interact_async()
def on_message(self, message): class SSHws(Namespace, BaseWebSocketHandler):
try: def ssh_with_password(self):
message = json.loads(message) self.ssh = paramiko.SSHClient()
except json.JSONDecodeError:
logger.info("Loads websocket json message failed")
return
if message.get('event'): self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.evt_handle(message) self.ssh.connect("127.0.0.1", 22, "liuzheng", "liuzheng")
elif message.get('data'): self.chan = self.ssh.invoke_shell(term='xterm', width=self.cols, height=self.rows)
self.proxy.send(message) self.socketio.start_background_task(self.send_data)
def on_close(self): def send_data(self):
self.proxy.close() while True:
data = self.chan.recv(2048).decode('utf-8', 'replace')
self.emit('data', data)
def evt_handle(self, data): def on_connect(self):
if data['event'] == 'change_size': self.cols = int(request.cookies.get('cols', 80))
try: self.rows = int(request.cookies.get('rows', 24))
self.request.meta['width'] = data['meta']['width'] self.prepare(request)
self.request.meta['height'] = data['meta']['height'] self.forwarder = ProxyServer(self.app, self.client)
self.request.change_size_event.set()
except KeyError:
pass
def on_data(self, message):
self.proxy.send({"data": message})
class ProxyWebSocketHandler(BaseWebSocketHandler): def on_host(self, message):
pass # 此处获取主机的信息
print(message)
uuid = message.get('uuid', None)
userid = message.get('userid', None)
if uuid and userid:
self.asset = self.app.service.get_asset(uuid)
system_user = self.app.service.get_system_user(userid)
print(system_user)
if system_user:
self.socketio.start_background_task(self.forwarder.proxy, self.asset, system_user)
# self.forwarder.proxy(self.asset, system_user)
else:
self.close()
else:
self.close()
def on_resize(self, message):
self.request.meta['width'] = message.get('cols', 80)
self.request.meta['height'] = message.get('rows', 24)
self.request.change_size_event.set()
class MonitorWebSocketHandler(BaseWebSocketHandler): def on_disconnect(self):
pass self.proxy.close()
# self.ssh.close()
pass
class HttpServer: class HttpServer:
routers = [
(r'/ws/interactive/', InteractiveWebSocketHandler),
(r'/ws/proxy/(?P<asset_id>[0-9]+)/(?P<system_user_id>[0-9]+)/', ProxyWebSocketHandler),
(r'/ws/session/(?P<session_id>[0-9]+)/monitor/', MonitorWebSocketHandler),
]
# prepare may be rewrite it # prepare may be rewrite it
settings = { settings = {
'cookie_secret': '', 'cookie_secret': '',
...@@ -92,19 +117,174 @@ class HttpServer: ...@@ -92,19 +117,174 @@ class HttpServer:
def __init__(self, app): def __init__(self, app):
self.app = app self.app = app
self._prepare() # self.settings['cookie_secret'] = self.app.config['SECRET_KEY']
# self.settings['app'] = self.app
def _prepare(self): self.flask = Flask(__name__, template_folder='dist')
self.settings['cookie_secret'] = self.app.config['SECRET_KEY'] self.flask.config['SECRET_KEY'] = self.app.config['SECRET_KEY']
self.settings['app'] = self.app self.socketio = SocketIO()
def run(self): def run(self):
host = self.app.config["BIND_HOST"] host = self.app.config["BIND_HOST"]
port = self.app.config["HTTPD_PORT"] port = self.app.config["HTTPD_PORT"]
print('Starting websocket server at {}:{}'.format(host, port)) print('Starting websocket server at {}:{}'.format(host, port))
ws = tornado.web.Application(self.routers, **self.settings) self.socketio.on_namespace(SSHws('/ssh').app(self.app))
ws.listen(port=port, address=host) self.socketio.init_app(self.flask)
tornado.ioloop.IOLoop.current().start() self.socketio.run(self.flask, port=port, host=host)
def shutdown(self): def shutdown(self):
pass pass
if __name__ == "__main__":
app = Flask(__name__, template_folder='/Users/liuzheng/gitproject/Jumpserver/webterminal/dist')
@app.route('/luna/<path:path>')
def send_js(path):
return send_from_directory('/Users/liuzheng/gitproject/Jumpserver/webterminal/dist', path)
@app.route('/')
@app.route('/luna/')
def index():
return render_template('index.html')
@app.route('/api/perms/v1/user/my/asset-groups-assets/')
def asset_groups_assets():
assets = [
{
"id": 0,
"name": "ungrouped",
"assets": []
},
{
"id": 1,
"name": "Default",
"comment": "Default asset group",
"assets": [
{
"id": 2,
"hostname": "192.168.1.6",
"ip": "192.168.2.6",
"port": 22,
"system": "windows",
"uuid": "xxxxxx",
"system_users": [
{
"id": 1,
"name": "web",
"username": "web",
"protocol": "ssh",
"auth_method": "P",
"auto_push": True
}
]
},
{
"id": 4,
"hostname": "testserver123",
"ip": "123.57.183.135",
"port": 8022,
"system": "linux",
"uuid": "linux-xxlkjadf",
"system_users": [
{
"id": 1,
"name": "web",
"username": "web",
"protocol": "ssh",
"auth_method": "P",
"auto_push": True
}
]
}
]
},
{
"id": 4,
"name": "java",
"comment": "",
"assets": [
{
"id": 2,
"hostname": "192.168.1.6",
"ip": "192.168.2.6",
"uuid": "sadcascas",
"system": "linux",
"port": 22,
"system_users": [
{
"id": 1,
"name": "web",
"username": "web",
"protocol": "ssh",
"auth_method": "P",
"auto_push": True
}
]
}
]
},
{
"id": 3,
"name": "数据库",
"comment": "",
"assets": [
{
"id": 2,
"hostname": "192.168.1.6",
"ip": "192.168.2.6",
"port": 22,
"uuid": "sadcascascasdcas",
"system": "linux",
"system_users": [
{
"id": 1,
"name": "web",
"username": "web",
"protocol": "ssh",
"auth_method": "P",
"auto_push": True
}
]
}
]
},
{
"id": 2,
"name": "运维组",
"comment": "",
"assets": [
{
"id": 2,
"hostname": "192.168.1.6",
"ip": "192.168.2.6",
"port": 22,
"uuid": "zxcasd",
"system": "linux",
"system_users": [
{
"id": 1,
"name": "web",
"username": "web",
"protocol": "ssh",
"auth_method": "P",
"auto_push": True
}
]
}
]
}
]
return jsonify(assets)
print('socketio')
socketio = SocketIO()
socketio.init_app(app)
socketio.on_namespace(SSHws('/ssh'))
socketio.run(app)
...@@ -71,6 +71,7 @@ class Server: ...@@ -71,6 +71,7 @@ class Server:
Because we don't want to using python dynamic feature, such asset Because we don't want to using python dynamic feature, such asset
have the chan and system_user attr. have the chan and system_user attr.
""" """
# 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, asset, system_user):
self.chan = chan self.chan = chan
...@@ -219,7 +220,7 @@ class WSProxy: ...@@ -219,7 +220,7 @@ class WSProxy:
data = self.child.recv(BUF_SIZE) data = self.child.recv(BUF_SIZE)
if len(data) == 0: if len(data) == 0:
self.close() self.close()
self.ws.write_message(json.dumps({"data": data.decode("utf-8")})) self.ws.emit("data", data.decode("utf-8"))
def auto_forward(self): def auto_forward(self):
thread = threading.Thread(target=self.forward, args=()) thread = threading.Thread(target=self.forward, args=())
......
...@@ -73,18 +73,33 @@ class CommandRecorder(metaclass=abc.ABCMeta): ...@@ -73,18 +73,33 @@ class CommandRecorder(metaclass=abc.ABCMeta):
class ServerReplayRecorder(ReplayRecorder): class ServerReplayRecorder(ReplayRecorder):
filelist = dict()
def record_replay(self, data_set): def record_replay(self, data_set):
""" """
:param data_set: :param data_set:
[{
"session": session.id,
"data": data,
"timestamp": time.time()
},...]
:return: :return:
""" """
# Todo: <liuzheng712@gmail.com> # Todo: <liuzheng712@gmail.com>
super().record_replay(data_set) super().record_replay(data_set)
for data in data_set:
try:
ServerReplayRecorder.filelist[data["session"]].write(str(data) + '\n')
except KeyError:
logger.error("session ({})file does not exist!".format(data["session"]))
def session_start(self, session_id): def session_start(self, session_id):
ServerReplayRecorder.filelist[session_id] = open('logs/' + session_id + '.log', 'a')
print("When session {} start exec".format(session_id)) print("When session {} start exec".format(session_id))
def session_end(self, session_id): def session_end(self, session_id):
ServerReplayRecorder.filelist[session_id].close()
# Todo: upload the file
print("When session {} end start".format(session_id)) print("When session {} end start".format(session_id))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment