feat: publish

parent 754028bb
...@@ -8,5 +8,3 @@ logs/* ...@@ -8,5 +8,3 @@ logs/*
conf.py conf.py
host_rsa_key host_rsa_key
sessions/* sessions/*
Dockerfile
conf_docker.py
...@@ -20,6 +20,9 @@ logger = get_logger(__file__) ...@@ -20,6 +20,9 @@ logger = get_logger(__file__)
class BaseWebSocketHandler: class BaseWebSocketHandler:
clients = None
current_user = None
def app(self, app): def app(self, app):
self.app = app self.app = app
return self return self
...@@ -31,11 +34,13 @@ class BaseWebSocketHandler: ...@@ -31,11 +34,13 @@ class BaseWebSocketHandler:
remote_ip = x_forwarded_for[0] remote_ip = x_forwarded_for[0]
else: else:
remote_ip = request.remote_addr remote_ip = request.remote_addr
self.clients[request.sid]["request"] = Request((remote_ip, 0)) req = Request((remote_ip, 0))
self.clients[request.sid]["request"].user = self.current_user req.user = self.current_user
self.clients[request.sid]["request"].meta = {"width": self.clients[request.sid]["cols"], req.meta = {
"height": self.clients[request.sid]["rows"]} "width": self.clients[request.sid]["cols"],
# self.request.__dict__.update(request.__dict__) "height": self.clients[request.sid]["rows"]
}
self.clients[request.sid]["request"] = req
def check_origin(self, origin): def check_origin(self, origin):
return True return True
...@@ -45,7 +50,6 @@ class BaseWebSocketHandler: ...@@ -45,7 +50,6 @@ class BaseWebSocketHandler:
self.clients[request.sid]["client"].close() self.clients[request.sid]["client"].close()
except: except:
pass pass
pass
class SSHws(Namespace, BaseWebSocketHandler): class SSHws(Namespace, BaseWebSocketHandler):
...@@ -72,8 +76,10 @@ class SSHws(Namespace, BaseWebSocketHandler): ...@@ -72,8 +76,10 @@ class SSHws(Namespace, BaseWebSocketHandler):
"rw": [] "rw": []
} }
join_room(room) join_room(room)
self.current_user = self.app.service.check_user_cookie(session_id=request.cookies.get('sessionid', ''), self.current_user = self.app.service.check_user_cookie(
csrf_token=request.cookies.get('csrftoken', '')) session_id=request.cookies.get('sessionid', ''),
csrf_token=request.cookies.get('csrftoken', '')
)
self.prepare(request) self.prepare(request)
def on_data(self, message): def on_data(self, message):
...@@ -83,25 +89,31 @@ class SSHws(Namespace, BaseWebSocketHandler): ...@@ -83,25 +89,31 @@ class SSHws(Namespace, BaseWebSocketHandler):
def on_host(self, message): def on_host(self, message):
# 此处获取主机的信息 # 此处获取主机的信息
connection = str(uuid.uuid4()) connection = str(uuid.uuid4())
assetID = message.get('uuid', None) asset_id = message.get('uuid', None)
userid = message.get('userid', None) user_id = message.get('userid', None)
self.emit('room', {'room': connection, 'secret': message['secret']}) self.emit('room', {'room': connection, 'secret': message['secret']})
if assetID and userid: if asset_id and user_id:
asset = self.app.service.get_asset(assetID) asset = self.app.service.get_asset(asset_id)
system_user = self.app.service.get_system_user(userid) system_user = self.app.service.get_system_user(user_id)
if system_user:
if system_user:
child, parent = socket.socketpair() child, parent = socket.socketpair()
self.clients[request.sid]["client"][connection] = Client(parent, self.clients[request.sid]["request"]) self.clients[request.sid]["client"][connection] = Client(
self.clients[request.sid]["proxy"][connection] = WSProxy(self, child, self.clients[request.sid]["room"], parent, self.clients[request.sid]["request"]
connection) )
self.clients[request.sid]["proxy"][connection] = WSProxy(
self, child, self.clients[request.sid]["room"], connection
)
self.clients[request.sid]["forwarder"][
connection] = ProxyServer(
self.app, self.clients[request.sid]["client"][connection]
)
self.app.clients.append(self.clients[request.sid]["client"][connection]) self.app.clients.append(self.clients[request.sid]["client"][connection])
self.clients[request.sid]["forwarder"][connection] = ProxyServer(self.app, self.socketio.start_background_task(
self.clients[request.sid]["client"][connection]) self.clients[request.sid]["forwarder"][connection].proxy,
asset, system_user
self.socketio.start_background_task(self.clients[request.sid]["forwarder"][connection].proxy, asset, )
system_user)
# self.forwarder.proxy(self.asset, system_user) # self.forwarder.proxy(self.asset, system_user)
else: else:
self.on_disconnect() self.on_disconnect()
...@@ -135,19 +147,24 @@ class SSHws(Namespace, BaseWebSocketHandler): ...@@ -135,19 +147,24 @@ class SSHws(Namespace, BaseWebSocketHandler):
def on_disconnect(self): def on_disconnect(self):
self.on_leave(self.clients[request.sid]["room"]) self.on_leave(self.clients[request.sid]["room"])
try: try:
for connection in self.clients[request.sid]["client"]:
self.on_logout(connection)
del self.clients[request.sid] del self.clients[request.sid]
except: except:
pass pass
# self.ssh.close()
pass
def on_logout(self, connection): def on_logout(self, connection):
print("logout", connection)
if connection: if connection:
if connection in self.clients[request.sid]["proxy"].keys():
self.clients[request.sid]["proxy"][connection].close() self.clients[request.sid]["proxy"][connection].close()
def logout(self, connection):
if connection and (request.sid in self.clients.keys()):
if connection in self.clients[request.sid]["proxy"].keys():
del self.clients[request.sid]["proxy"][connection] del self.clients[request.sid]["proxy"][connection]
if connection in self.clients[request.sid]["forwarder"].keys():
del self.clients[request.sid]["forwarder"][connection] del self.clients[request.sid]["forwarder"][connection]
self.clients[request.sid]["client"][connection].close() if connection in self.clients[request.sid]["client"].keys():
del self.clients[request.sid]["client"][connection] del self.clients[request.sid]["client"][connection]
......
...@@ -212,7 +212,10 @@ class WSProxy: ...@@ -212,7 +212,10 @@ class WSProxy:
def forward(self): def forward(self):
while not self.stop_event.is_set(): while not self.stop_event.is_set():
try:
data = self.child.recv(BUF_SIZE) data = self.child.recv(BUF_SIZE)
except OSError:
continue
if len(data) == 0: if len(data) == 0:
self.close() self.close()
self.ws.emit("data", {'data': data.decode("utf-8"), 'room': self.connection}, room=self.room) self.ws.emit("data", {'data': data.decode("utf-8"), 'room': self.connection}, room=self.room)
...@@ -225,3 +228,5 @@ class WSProxy: ...@@ -225,3 +228,5 @@ class WSProxy:
def close(self): def close(self):
self.stop_event.set() self.stop_event.set()
self.child.close() self.child.close()
self.ws.logout(self.connection)
logger.debug("Proxy {} closed".format(self))
...@@ -9,6 +9,7 @@ import os ...@@ -9,6 +9,7 @@ import os
import gzip import gzip
import json import json
import shutil import shutil
import boto3 # AWS S3 sdk
from jms_es_sdk import ESStore from jms_es_sdk import ESStore
...@@ -238,6 +239,25 @@ class ESCommandRecorder(CommandRecorder, metaclass=Singleton): ...@@ -238,6 +239,25 @@ class ESCommandRecorder(CommandRecorder, metaclass=Singleton):
print("{} has been gc".format(self)) print("{} has been gc".format(self))
class S3ReplayRecorder(ServerReplayRecorder):
def __init__(self, app):
super().__init__(app)
self.bucket = app.config["REPLAY_STORAGE"].get("BUCKET", "jumpserver")
self.s3 = boto3.client('s3')
def push_to_server(self, session_id):
try:
self.s3.upload_file(
os.path.join(self.app.config['LOG_DIR'], session_id + '.replay.gz'),
self.bucket,
time.strftime('%Y-%m-%d', time.localtime(
self.starttime)) + '/' + session_id + '.replay.gz')
except:
return self.app.service.push_session_replay(
os.path.join(self.app.config['LOG_DIR'], session_id + '.replay.gz'),
session_id)
def get_command_recorder_class(config): def get_command_recorder_class(config):
command_storage = config["COMMAND_STORAGE"] command_storage = config["COMMAND_STORAGE"]
...@@ -248,8 +268,10 @@ def get_command_recorder_class(config): ...@@ -248,8 +268,10 @@ def get_command_recorder_class(config):
def get_replay_recorder_class(config): def get_replay_recorder_class(config):
replay_engine = config["REPLAY_RECORD_ENGINE"] replay_storage = config["REPLAY_STORAGE"]
if replay_engine == "server": if replay_storage['TYPE'] == "s3":
return S3ReplayRecorder
elif replay_storage['TYPE'] == "locale":
return ServerReplayRecorder return ServerReplayRecorder
else: else:
return ServerReplayRecorder return ServerReplayRecorder
...@@ -86,61 +86,6 @@ def ssh_key_gen(length=2048, type='rsa', password=None, ...@@ -86,61 +86,6 @@ def ssh_key_gen(length=2048, type='rsa', password=None,
raise IOError('These is error when generate ssh key.') raise IOError('These is error when generate ssh key.')
def content_md5(data):
"""计算data的MD5值,经过Base64编码并返回str类型。
返回值可以直接作为HTTP Content-Type头部的值
"""
if isinstance(data, str):
data = hashlib.md5(data.encode('utf-8'))
value = base64.b64encode(data.digest())
return value.decode('utf-8')
_STRPTIME_LOCK = threading.Lock()
_GMT_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"
_ISO8601_FORMAT = "%Y-%m-%dT%H:%M:%S.000Z"
def to_unixtime(time_string, format_string):
with _STRPTIME_LOCK:
return int(calendar.timegm(time.strptime(str(time_string), format_string)))
def http_date(timeval=None):
"""返回符合HTTP标准的GMT时间字符串,用strftime的格式表示就是"%a, %d %b %Y %H:%M:%S GMT"。
但不能使用strftime,因为strftime的结果是和locale相关的。
"""
return formatdate(timeval, usegmt=True)
def http_to_unixtime(time_string):
"""把HTTP Date格式的字符串转换为UNIX时间(自1970年1月1日UTC零点的秒数)。
HTTP Date形如 `Sat, 05 Dec 2015 11:10:29 GMT` 。
"""
return to_unixtime(time_string, _GMT_FORMAT)
def iso8601_to_unixtime(time_string):
"""把ISO8601时间字符串(形如,2012-02-24T06:07:48.000Z)转换为UNIX时间,精确到秒。"""
return to_unixtime(time_string, _ISO8601_FORMAT)
def make_signature(access_key_secret, date=None):
if isinstance(date, bytes):
date = bytes.decode(date)
if isinstance(date, int):
date_gmt = http_date(date)
elif date is None:
date_gmt = http_date(int(time.time()))
else:
date_gmt = date
data = str(access_key_secret) + "\n" + date_gmt
return content_md5(data)
class TtyIOParser(object): class TtyIOParser(object):
def __init__(self, width=80, height=24): def __init__(self, width=80, height=24):
self.screen = pyte.Screen(width, height) self.screen = pyte.Screen(width, height)
...@@ -287,10 +232,6 @@ def wrap_with_title(text): ...@@ -287,10 +232,6 @@ def wrap_with_title(text):
return wrap_with_color(text, color='black', background='green') return wrap_with_color(text, color='black', background='green')
def b64encode_as_string(data):
return base64.b64encode(data).decode("utf-8")
def split_string_int(s): def split_string_int(s):
"""Split string or int """Split string or int
...@@ -324,37 +265,6 @@ def sort_assets(assets, order_by='hostname'): ...@@ -324,37 +265,6 @@ def sort_assets(assets, order_by='hostname'):
return assets return assets
class PKey(object):
@classmethod
def from_string(cls, key_string):
try:
pkey = paramiko.RSAKey(file_obj=StringIO(key_string))
return pkey
except paramiko.SSHException:
try:
pkey = paramiko.DSSKey(file_obj=StringIO(key_string))
return pkey
except paramiko.SSHException:
return None
def timestamp_to_datetime_str(ts):
datetime_format = '%Y-%m-%dT%H:%M:%S.%fZ'
dt = datetime.datetime.fromtimestamp(ts, tz=pytz.timezone('UTC'))
return dt.strftime(datetime_format)
class MultiQueue(Queue):
def mget(self, size=1, block=True, timeout=5):
items = []
for i in range(size):
try:
items.append(self.get(block=block, timeout=timeout))
except Empty:
break
return items
def _gettext(): def _gettext():
gettext.bindtextdomain("coco", os.path.join(BASE_DIR, "locale")) gettext.bindtextdomain("coco", os.path.join(BASE_DIR, "locale"))
gettext.textdomain("coco") gettext.textdomain("coco")
......
asn1crypto==0.23.0 asn1crypto==0.23.0
bcrypt==3.1.4 bcrypt==3.1.4
boto3==1.5.18
botocore==1.8.32
certifi==2017.11.5 certifi==2017.11.5
cffi==1.11.2 cffi==1.11.2
chardet==3.0.4 chardet==3.0.4
...@@ -28,5 +30,5 @@ tornado==4.5.2 ...@@ -28,5 +30,5 @@ tornado==4.5.2
urllib3==1.22 urllib3==1.22
wcwidth==0.1.7 wcwidth==0.1.7
werkzeug==0.12.2 werkzeug==0.12.2
jumpserver-python-sdk==0.0.26 jumpserver-python-sdk==0.0.27
jms-es-sdk jms-es-sdk
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