修正导入select错误

pull/26/head
ibuler 2015-11-05 20:07:21 +08:00
parent 1bc15e57a6
commit 9a897e0cf4
8 changed files with 57 additions and 475 deletions

View File

@ -8,5 +8,5 @@ urlpatterns = patterns('',
url(r'^history/$', log_history), url(r'^history/$', log_history),
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),
) )

View File

@ -11,9 +11,6 @@ from models import Log
from jumpserver.settings import web_socket_host from jumpserver.settings import web_socket_host
web_socket_host = 'ws://j:8080/monitor'
@require_role('admin') @require_role('admin')
def log_list(request, offset): def log_list(request, offset):
""" 显示日志 """ """ 显示日志 """
@ -51,7 +48,7 @@ def log_list(request, offset):
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
web_socket_uri = web_socket_host web_monitor_uri = '%s/monitor' % web_socket_host
return render_to_response('jlog/log_%s.html' % offset, locals(), context_instance=RequestContext(request)) return render_to_response('jlog/log_%s.html' % offset, locals(), context_instance=RequestContext(request))
@ -106,5 +103,6 @@ def log_record(request):
def web_terminal(request): def web_terminal(request):
web_terminal_uri = '%s/terminal' % web_socket_host
return render_to_response('jlog/web_terminal.html', locals()) return render_to_response('jlog/web_terminal.html', locals())

View File

@ -23,7 +23,7 @@ root_pw = secret234
[websocket] [websocket]
web_socket_host = 192.168.40.140:3000 web_socket_host = ws://192.168.244.129:3000
[mail] [mail]

View File

@ -1,241 +0,0 @@
#!/usr/bin/env python
__author__ = 'liuzheng'
import sys
import os
import re
from tornado.options import options, define, parse_command_line
import tornado.wsgi
import tornado.web
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.ioloop
import tornado.websocket
import pty
import io
import struct
import string
import random
import fcntl
import termios
import tornado.process
import tornado.options
import signal
import utils
import getpass
from connect import Jtty
define('port', type=int, default=8000)
ioloop = tornado.ioloop.IOLoop.instance()
class Terminal(tornado.websocket.WebSocketHandler):
terminals = set()
def pty(self):
# Make a "unique" id in 4 bytes
self.uid = ''.join(
random.choice(
string.ascii_lowercase + string.ascii_uppercase +
string.digits)
for _ in range(4))
self.pid, self.fd = pty.fork()
# print "pid:",self.pid,"fd",self.fd,"uid",self.uid
if self.pid == 0:
# print "Login as", self.user
os.execv("/usr/bin/ssh", [self.user, "localhost"])
# self.callee = utils.User(name=self.user)
# self.determine_user()
self.shell()
else:
self.communicate()
def determine_user(self):
if self.callee is None:
# If callee is now known and we have unsecure connection
user = self.user
try:
self.callee = utils.User(name=user)
except Exception:
# self.log.debug("Can't switch to user %s" % user, exc_info=True)
self.callee = utils.User(name='nobody')
assert self.callee is not None
def shell(self):
try:
os.chdir(self.path or self.callee.dir)
except Exception:
pass
env = os.environ
# If local and local user is the same as login user
# We set the env of the user from the browser
# Usefull when running as root
if self.caller == self.callee:
env.update(self.socket.env)
env["TERM"] = "xterm-256color"
env["COLORTERM"] = "butterfly"
env["HOME"] = self.callee.dir
# print(self.callee.dir)
env["LOCATION"] = "http%s://%s:%d/" % (
"s" if not True else "",
"localhost", 8001)
env["PATH"] = '%s:%s' % (os.path.abspath(os.path.join(
os.path.dirname(__file__), 'bin')), env.get("PATH"))
try:
tty = os.ttyname(0).replace('/dev/', '')
except Exception:
tty = ''
if self.caller != self.callee:
try:
os.chown(os.ttyname(0), self.callee.uid, -1)
except Exception:
pass
utils.add_user_info(
self.uid,
tty, os.getpid(),
self.callee.name, self.request.headers['Host'])
if os.path.exists('/usr/bin/su'):
args = ['/usr/bin/su']
else:
args = ['/bin/su']
if sys.platform == 'linux':
args.append('-p')
if tornado.options.options.shell:
args.append('-s')
args.append(tornado.options.options.shell)
args.append(self.callee.name)
os.execvpe(args[0], args, env)
def communicate(self):
fcntl.fcntl(self.fd, fcntl.F_SETFL, os.O_NONBLOCK)
self.reader = io.open(
self.fd,
'rb',
buffering=0,
closefd=False
)
self.writer = io.open(
self.fd,
'wt',
encoding='utf-8',
closefd=False
)
ioloop.add_handler(
self.fd, self.shellHandle, ioloop.READ | ioloop.ERROR)
def allow_draft76(self):
# for iOS 5.0 Safari
return True
def check_origin(self, origin):
return True
def open(self):
print "term socket open"
self.fd = None
self.closed = False
self.socket = utils.Socket(self.ws_connection.stream.socket)
self.set_nodelay(True)
self.path = None
self.user = getpass.getuser()
self.caller = self.callee = None
# self.user = "liuzheng"
self.callee = None
Terminal.terminals.add(self)
self.pty()
print self.fd
def on_message(self, msg):
print "on_message ", msg
if not hasattr(self, 'writer'):
self.on_close()
self.close()
return
if msg[0] == 'C': # Change screen
c, r = map(int, msg[1:].split(','))
s = struct.pack("HHHH", r, c, 0, 0)
fcntl.ioctl(self.fd, termios.TIOCSWINSZ, s)
elif msg[0] == 'R': # Run shell
self.writer.write(msg[1:])
self.writer.flush()
def shellHandle(self, f, events):
if events & ioloop.READ:
try:
read = self.reader.read()
except IOError:
read = ''
if read and len(read) != 0 and self.ws_connection:
self.write_message(read.decode('utf-8', 'replace'))
else:
events = ioloop.ERROR
if events & ioloop.ERROR:
self.on_close()
self.close()
def on_close(self):
print "term close", self.uid
if self.closed:
return
self.closed = True
if getattr(self, 'pid', 0) == 0:
return
utils.rm_user_info(self.uid, self.pid)
try:
ioloop.remove_handler(self.fd)
except Exception:
pass
try:
os.close(self.fd)
except Exception:
pass
try:
os.kill(self.pid, signal.SIGKILL)
os.waitpid(self.pid, 0)
except Exception:
pass
Terminal.terminals.remove(self)
class Index(tornado.web.RequestHandler):
def get(self):
self.render('templates/terminal.html')
def main():
sys.path.append('./jumpserver') # path to your project if needed
parse_command_line()
tornado_app = tornado.web.Application(
[
('/ws/terminal', Terminal),
('/ws/Terminal', Index),
])
server = tornado.httpserver.HTTPServer(tornado_app)
server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == '__main__':
main()

View File

@ -16,32 +16,22 @@ import tornado.gen
from tornado.websocket import WebSocketClosedError 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 from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE, IN_MODIFY, AsyncNotifier
from gevent import monkey # from gevent import monkey
monkey.patch_all() # monkey.patch_all()
# import gevent
import gevent
from gevent.socket import wait_read, wait_write from gevent.socket import wait_read, wait_write
from gevent.select import select
from gevent.event import Event
import paramiko import paramiko
from paramiko import PasswordRequiredException
from paramiko.dsskey import DSSKey
from paramiko.rsakey import RSAKey
from paramiko.ssh_exception import SSHException
import socket
try: try:
import simplejson as json import simplejson as json
except ImportError: except ImportError:
import json import json
from StringIO import StringIO
define("port", default=8080, help="run on the given port", type=int) 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)
@ -80,7 +70,7 @@ def file_monitor(path='.', client=None):
print "You should monitor a file" print "You should monitor a file"
sys.exit(3) sys.exit(3)
else: else:
print "now starting monitor %s." %path print "now starting monitor %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]
@ -88,7 +78,6 @@ def file_monitor(path='.', client=None):
while True: while True:
try: try:
print "hello world"
notifier.process_events() notifier.process_events()
if notifier.check_events(): if notifier.check_events():
notifier.read_events() notifier.read_events()
@ -101,7 +90,6 @@ def file_monitor(path='.', client=None):
class Application(tornado.web.Application): class Application(tornado.web.Application):
def __init__(self): def __init__(self):
handlers = [ handlers = [
(r'/', MainHandler),
(r'/monitor', MonitorHandler), (r'/monitor', MonitorHandler),
(r'/terminal', WebTerminalHandler), (r'/terminal', WebTerminalHandler),
] ]
@ -164,11 +152,6 @@ class MonitorHandler(tornado.websocket.WebSocketHandler):
MonitorHandler.threads.remove(MonitorHandler.threads[client_index]) MonitorHandler.threads.remove(MonitorHandler.threads[client_index])
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render('log_watch.html')
class WebTerminalHandler(tornado.websocket.WebSocketHandler): class WebTerminalHandler(tornado.websocket.WebSocketHandler):
tasks = [] tasks = []

View File

@ -37,7 +37,7 @@ client.connect({
*/ */
function WSSHClient() { function WSSHClient() {
}; }
WSSHClient.prototype._generateEndpoint = function(options) { WSSHClient.prototype._generateEndpoint = function(options) {
console.log(options); console.log(options);

View File

@ -108,7 +108,7 @@
function init(obj){ function init(obj){
var file_path = obj.attr('file_path'); var file_path = obj.attr('file_path');
var wsUri = '{{ web_socket_uri }}'; var wsUri = '{{ web_monitor_uri }}';
var socket = new WebSocket(wsUri + '?file_path=' + file_path); var socket = new WebSocket(wsUri + '?file_path=' + file_path);
socket.onopen = function(evt){ socket.onopen = function(evt){
socket.send(file_path) socket.send(file_path)

View File

@ -2,12 +2,10 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>wssh</title> <title>Jumpserver web terminal</title>
<link href="/static/css/plugins/bootstrap.min.css" rel="stylesheet" />
<style> <style>
body { body {
padding-top: 60px;
padding-bottom: 40px; padding-bottom: 40px;
} }
@ -29,139 +27,56 @@
</head> </head>
<body> <body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="#">wssh</a>
</div>
</div>
</div>
<div class="container"> <div class="container">
<!-- Connection form -->
<form id="connect" class="form-horizontal">
<fieldset>
<legend>Connect to a remote SSH server</legend>
<div class="control-group">
<label class="control-label">
Destination
</label>
<div class="controls">
<input type="text" id="username"
class="input-small"
placeholder="root" />
<div class="input-prepend">
<span class="add-on">@</span><input
type="text"
id="hostname"
class="input-large"
placeholder="localhost" />
<span class="add-on">port</span><input
type="text"
id="portnumber"
class="input-small"
value=22 />
</div>
</div>
</div>
<div class="control-group">
<label class="control-label">
Authentication method
</label>
<div class="controls">
<label class="radio">
<input type="radio" name="authentication_method"
value="password" checked />
Password
</label>
<label class="radio">
<input type="radio" name="authentication_method"
value="private_key" />
Private Key
</label>
</div>
</div>
<div class="control-group" id="password_authentication">
<label class="control-label">
Password
</label>
<div class="controls">
<input type="password" id="password"
class="input-large" />
</div>
</div>
<div id="private_key_authentication">
<div class="control-group">
<label class="control-label">
Private Key
</label>
<div class="controls">
<textarea id="private_key" rows="6"
class="input-xxlarge"></textarea>
<p class="help-block">
Copy &amp; Paste your SSH private from
<code>~/.ssh/id_rsa</code> or
<code>~/.ssh/id_dsa</code>
</p>
</div>
</div>
<div class="control-group">
<label class="control-label">
Key Passphrase
</label>
<div class="controls">
<input type="password" id="key_passphrase"
class="input-large" />
<p class="help-block">
Enter your private key passphrase if it
is encrypted. Leave empty otherwise.
</p>
</div>
</div>
</div>
<div class="control-group">
<label class="control-label">
Command
</label>
<div class="controls">
<input type="text" id="command" class="input-large" />
<p class="help-block">
Enter command to be executed or
empty for interactive.
</p>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">
Connect
</button>
</div>
</fieldset>
</form>
<div id="term"> <div id="term">
</div> </div>
</div> </div>
<script type="application/javascript" src="/static/js/jquery-2.1.1.js"> <script type="application/javascript" src="/static/js/jquery-2.1.1.js">
</script> </script>
<script type="application/javascript" src="/static/js/term.js"> <script type="application/javascript" src="/static/js/term.js">
</script> </script>
<script type="application/javascript" src="/static/js/wssh.js">
</script>
<script type="application/javascript"> <script type="application/javascript">
function WSSHClient() {
}
WSSHClient.prototype.connect = function(options) {
var endpoint = '{{ web_terminal_uri }}';
if (window.WebSocket) {
this._connection = new WebSocket(endpoint);
}
else if (window.MozWebSocket) {
this._connection = MozWebSocket(endpoint);
}
else {
options.onError('WebSocket Not Supported');
return ;
}
this._connection.onopen = function() {
options.onConnect();
};
this._connection.onmessage = function (evt) {
var data = JSON.parse(evt.data.toString());
if (data.error !== undefined) {
options.onError(data.error);
}
else {
options.onData(data.data);
}
};
this._connection.onclose = function(evt) {
options.onClose();
};
};
WSSHClient.prototype.send = function(data) {
this._connection.send(JSON.stringify({'data': data}));
};
function openTerminal(options) { function openTerminal(options) {
var client = new WSSHClient(); var client = new WSSHClient();
var term = new Terminal(80, 24, function(key) { var term = new Terminal(80, 24, function(key) {
@ -191,84 +106,11 @@
<script type='application/javascript'> <script type='application/javascript'>
$(document).ready(function() { $(document).ready(function() {
$('#ssh').hide(); var options = {
$('#private_key_authentication', '#connect').hide(); };
$('input:radio[value=private_key]', '#connect').click( $('#ssh').show();
function() { openTerminal(options);
$('#password_authentication').hide();
$('#private_key_authentication').show();
}
);
$('input:radio[value=password]', '#connect').click(
function() {
$('#password_authentication').show();
$('#private_key_authentication').hide();
}
);
$('#connect').submit(function(ev) {
ev.preventDefault();
function validate(fields) {
var success = true;
fields.forEach(function(field) {
if (!field.val()) {
field.closest('.control-group')
.addClass('error');
success = false;
}
});
return success;
}
// Clear errors
$('.error').removeClass('error');
var username = $('input:text#username');
var hostname = $('input:text#hostname');
var portnumber = $('input:text#portnumber');
var command = $('input:text#command');
var authentication = $(
'input[name=authentication_method]:checked',
'#connect').val();
var options = {
username: username.val(),
hostname: hostname.val(),
command: command.val(),
authentication_method: authentication
};
var port = parseInt(portnumber.val())
if (port > 0 && port < 65535) {
$.extend(options, {port: port});
} else {
$.extend(options, {port: 22});
}
if (authentication == 'password') {
var password = $('input:password#password');
if (!validate([username, hostname, password]))
return false;
$.extend(options, {password: password.val()});
} else if (authentication == 'private_key') {
var private_key = $('textarea#private_key');
if (!validate([username, hostname, private_key]))
return false;
$.extend(options, {private_key: private_key.val()});
var key_passphrase = $('input:password#key_passphrase');
if (key_passphrase.val()) {
$.extend(options,
{key_passphrase: key_passphrase.val()});
}
}
$('#connect').hide();
$('#ssh').show();
openTerminal(options);
});
}); });
</script> </script>
</body> </body>