mirror of https://github.com/jumpserver/jumpserver
修改变量命名
commit
f9c06c22ae
117
connect.py
117
connect.py
|
@ -13,16 +13,19 @@ import textwrap
|
|||
import getpass
|
||||
import readline
|
||||
import django
|
||||
from multiprocessing import Pool
|
||||
import paramiko
|
||||
import struct, fcntl, signal, socket, select, fnmatch
|
||||
import struct, fcntl, signal, socket, select
|
||||
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
||||
if django.get_version() != '1.6':
|
||||
django.setup()
|
||||
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object
|
||||
from jumpserver.api import logger, is_dir, Log, TtyLog
|
||||
from jumpserver.settings import log_dir
|
||||
from jumpserver.api import logger, mkdir, Log, TtyLog
|
||||
from jumpserver.settings import LOG_DIR
|
||||
|
||||
|
||||
login_user = get_object(User, username=getpass.getuser())
|
||||
|
||||
|
||||
try:
|
||||
import termios
|
||||
|
@ -32,11 +35,6 @@ except ImportError:
|
|||
time.sleep(3)
|
||||
sys.exit()
|
||||
|
||||
VIM_FLAG = False
|
||||
VIM_COMMAND = ''
|
||||
SSH_TTY = ''
|
||||
login_user = get_object(User, username=getpass.getuser())
|
||||
|
||||
|
||||
def color_print(msg, color='red', exits=False):
|
||||
"""
|
||||
|
@ -53,49 +51,6 @@ def color_print(msg, color='red', exits=False):
|
|||
sys.exit()
|
||||
|
||||
|
||||
def verify_connect(user, option):
|
||||
"""
|
||||
Check user was permed or not . Check ip is unique or not.
|
||||
鉴定用户是否有该主机权限 或 匹配到的ip是否唯一
|
||||
"""
|
||||
ip_matched = []
|
||||
try:
|
||||
assets_info = login_user.get_asset_info()
|
||||
except ServerError, e:
|
||||
color_print(e, 'red')
|
||||
return False
|
||||
|
||||
for ip, asset_info in assets_info.items():
|
||||
if option in asset_info[1:] and option:
|
||||
ip_matched = [asset_info[1]]
|
||||
break
|
||||
|
||||
for info in asset_info[1:]:
|
||||
if option in info:
|
||||
ip_matched.append(ip)
|
||||
|
||||
logger.debug('%s matched input %s: %s' % (login_user.username, option, ip_matched))
|
||||
ip_matched = list(set(ip_matched))
|
||||
|
||||
if len(ip_matched) > 1: # 如果匹配ip不唯一
|
||||
ip_comment = {}
|
||||
for ip in ip_matched:
|
||||
ip_comment[ip] = assets_info[ip][2]
|
||||
|
||||
for ip in sorted(ip_comment):
|
||||
if ip_comment[ip]:
|
||||
print '%-15s -- %s' % (ip, ip_comment[ip])
|
||||
else:
|
||||
print '%-15s' % ip
|
||||
print ''
|
||||
elif len(ip_matched) < 1: # 如果没匹配到
|
||||
color_print('没有该主机,或者您没有该主机的权限 No Permission or No host.', 'red')
|
||||
else: # 恰好是1个
|
||||
asset = get_object(Asset, ip=ip_matched[0])
|
||||
jtty = Jtty(user, asset)
|
||||
jtty.connect()
|
||||
|
||||
|
||||
def check_vim_status(command, ssh):
|
||||
global SSH_TTY
|
||||
print command
|
||||
|
@ -194,7 +149,7 @@ def deal_command(str_r, ssh):
|
|||
else :
|
||||
result_command += str_r[0]
|
||||
str_r = str_r[1:]
|
||||
|
||||
|
||||
if pattern_str !='':
|
||||
pattern_list.append(pattern_str)
|
||||
|
||||
|
@ -207,8 +162,7 @@ def deal_command(str_r, ssh):
|
|||
result_command = result_command[:-int(backspace)]
|
||||
result_command += pattern_list[0]
|
||||
pattern_list = pattern_list[1:]
|
||||
|
||||
|
||||
|
||||
control_char = re.compile(r"""
|
||||
\x1b[ #%()*+\-.\/]. |
|
||||
\r | #匹配 回车符(CR)
|
||||
|
@ -237,14 +191,6 @@ def deal_command(str_r, ssh):
|
|||
return ''
|
||||
|
||||
|
||||
def newline_code_in(strings):
|
||||
for i in ['\r', '\r\n', '\n']:
|
||||
if i in strings:
|
||||
#print "new line"
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class Tty(object):
|
||||
"""
|
||||
A virtual tty class
|
||||
|
@ -256,8 +202,8 @@ class Tty(object):
|
|||
self.ip = None
|
||||
self.port = 22
|
||||
self.channel = None
|
||||
self.user = None
|
||||
self.asset = None
|
||||
#self.asset = get_object(Asset, name=asset_name)
|
||||
#self.user = get_object(User, username=username)
|
||||
self.role = None
|
||||
self.ssh = None
|
||||
self.connect_info = None
|
||||
|
@ -292,44 +238,45 @@ class Tty(object):
|
|||
|
||||
return line_filtered
|
||||
|
||||
def get_log_file(self):
|
||||
def get_log(self):
|
||||
"""
|
||||
Logging user command and output.
|
||||
记录用户的日志
|
||||
"""
|
||||
tty_log_dir = os.path.join(log_dir, 'tty')
|
||||
timestamp_start = int(time.time())
|
||||
date_start = time.strftime('%Y%m%d', time.localtime(timestamp_start))
|
||||
time_start = time.strftime('%H%M%S', time.localtime(timestamp_start))
|
||||
tty_log_dir = os.path.join(LOG_DIR, 'tty')
|
||||
date_today = datetime.datetime.now()
|
||||
date_start = date_today.strftime('%Y%m%d')
|
||||
time_start = date_today.strftime('%H%M%S')
|
||||
today_connect_log_dir = os.path.join(tty_log_dir, date_start)
|
||||
log_file_path = os.path.join(today_connect_log_dir, '%s_%s_%s' % (self.username, self.asset_name, time_start))
|
||||
|
||||
try:
|
||||
is_dir(today_connect_log_dir, mode=0777)
|
||||
mkdir(today_connect_log_dir, mode=0777)
|
||||
except OSError:
|
||||
logger.debug('创建目录 %s 失败,请修改%s目录权限' % (today_connect_log_dir, tty_log_dir))
|
||||
raise ServerError('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, tty_log_dir))
|
||||
|
||||
try:
|
||||
log_file_f = open(log_file_path + '.log', 'a')
|
||||
log_time_f = open(log_file_path + '.time', 'a')
|
||||
except IOError:
|
||||
logger.debug('创建tty日志文件失败, 请修改目录%s权限' % today_connect_log_dir)
|
||||
raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir)
|
||||
|
||||
if self.login_type == 'ssh':
|
||||
if self.login_type == 'ssh': # 如果是ssh连接过来,记录connect.py的pid,web terminal记录为日志的id
|
||||
pid = os.getpid()
|
||||
remote_ip = os.popen("who -m | awk '{ print $5 }'").read().strip('()\n')
|
||||
remote_ip = os.popen("who -m | awk '{ print $5 }'").read().strip('()\n') # 获取远端IP
|
||||
log = Log(user=self.username, host=self.asset_name, remote_ip=remote_ip,
|
||||
log_path=log_file_path, start_time=datetime.datetime.now(), pid=pid)
|
||||
log_path=log_file_path, start_time=date_today, pid=pid)
|
||||
else:
|
||||
remote_ip = 'Web'
|
||||
log = Log(user=self.username, host=self.asset_name, remote_ip=remote_ip,
|
||||
log_path=log_file_path, start_time=datetime.datetime.now(), pid=0)
|
||||
log_path=log_file_path, start_time=date_today, pid=0)
|
||||
log.save()
|
||||
log.pid = log.id
|
||||
log.save()
|
||||
|
||||
log_file_f.write('Start at %s\n' % datetime.datetime.now())
|
||||
log.save()
|
||||
log_file_f.write('Start at %s\n' % datetime.datetime.now())
|
||||
return log_file_f, log_time_f, log
|
||||
|
||||
def get_connect_info(self):
|
||||
|
@ -413,10 +360,10 @@ class SshTty(Tty):
|
|||
Use paramiko channel connect server interactive.
|
||||
使用paramiko模块的channel,连接后端,进入交互式
|
||||
"""
|
||||
log_file_f, log_time_f, log = self.get_log_file()
|
||||
log_file_f, log_time_f, log = self.get_log()
|
||||
old_tty = termios.tcgetattr(sys.stdin)
|
||||
pre_timestamp = time.time()
|
||||
input_r = ''
|
||||
data = ''
|
||||
input_mode = False
|
||||
|
||||
try:
|
||||
|
@ -445,22 +392,20 @@ class SshTty(Tty):
|
|||
log_time_f.flush()
|
||||
|
||||
if input_mode and not self.is_output(x):
|
||||
input_r += x
|
||||
data += x
|
||||
|
||||
except socket.timeout:
|
||||
pass
|
||||
|
||||
if sys.stdin in r:
|
||||
x = os.read(sys.stdin.fileno(), 1)
|
||||
if not input_mode:
|
||||
input_mode = True
|
||||
input_mode = True
|
||||
|
||||
if str(x) in ['\r', '\n', '\r\n']:
|
||||
# input_r = deal_command(input_r,ssh)
|
||||
input_r = self.remove_control_char(input_r)
|
||||
data = self.remove_control_char(data)
|
||||
|
||||
TtyLog(log=log, datetime=datetime.datetime.now(), cmd=input_r).save()
|
||||
input_r = ''
|
||||
TtyLog(log=log, datetime=datetime.datetime.now(), cmd=data).save()
|
||||
data = ''
|
||||
input_mode = False
|
||||
|
||||
if len(x) == 0:
|
||||
|
|
|
@ -8,7 +8,7 @@ from django.http import HttpResponseNotFound
|
|||
from jlog.log_api import renderTemplate
|
||||
|
||||
from models import Log
|
||||
from jumpserver.settings import web_socket_host
|
||||
from jumpserver.settings import WEB_SOCKET_HOST
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
|
@ -48,8 +48,8 @@ def log_list(request, offset):
|
|||
|
||||
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
|
||||
|
||||
web_monitor_uri = 'ws://%s/monitor' % web_socket_host
|
||||
web_kill_uri = 'http://%s/kill' % web_socket_host
|
||||
web_monitor_uri = 'ws://%s/monitor' % WEB_SOCKET_HOST
|
||||
web_kill_uri = 'http://%s/kill' % WEB_SOCKET_HOST
|
||||
return render_to_response('jlog/log_%s.html' % offset, locals(), context_instance=RequestContext(request))
|
||||
|
||||
|
||||
|
@ -108,6 +108,6 @@ def web_terminal(request):
|
|||
token = request.COOKIES.get('sessionid')
|
||||
username = request.user.username
|
||||
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)
|
||||
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())
|
||||
|
||||
|
|
|
@ -14,14 +14,6 @@ password = mysql234
|
|||
database = jumpserver
|
||||
|
||||
|
||||
[ldap]
|
||||
ldap_enable = 1
|
||||
host_url = ldap://127.0.0.1:389
|
||||
base_dn = dc=jumpserver, dc=org
|
||||
root_dn = cn=admin,dc=jumpserver,dc=org
|
||||
root_pw = secret234
|
||||
|
||||
|
||||
[websocket]
|
||||
web_socket_host = 192.168.244.129:3000
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import json
|
|||
import logging
|
||||
|
||||
|
||||
|
||||
def set_log(level):
|
||||
"""
|
||||
return a log file object
|
||||
|
@ -35,7 +34,7 @@ def set_log(level):
|
|||
'critical': logging.CRITICAL}
|
||||
logger_f = logging.getLogger('jumpserver')
|
||||
logger_f.setLevel(logging.DEBUG)
|
||||
fh = logging.FileHandler(JLOG_FILE)
|
||||
fh = logging.FileHandler(os.path.join(LOG_DIR, 'jumpserver.log'))
|
||||
fh.setLevel(log_level_total.get(level, logging.DEBUG))
|
||||
formatter = logging.Formatter('%(asctime)s - %(filename)s - %(levelname)s - %(message)s')
|
||||
fh.setFormatter(formatter)
|
||||
|
@ -86,7 +85,6 @@ def pages(post_objects, request):
|
|||
return post_objects, paginator, page_objects, page_range, current_page, show_first, show_end
|
||||
|
||||
|
||||
|
||||
class PyCrypt(object):
|
||||
"""
|
||||
This class used to encrypt and decrypt password.
|
||||
|
@ -98,7 +96,7 @@ class PyCrypt(object):
|
|||
self.mode = AES.MODE_CBC
|
||||
|
||||
@staticmethod
|
||||
def random_pass(length, especial=False):
|
||||
def gen_rand_pass(length, especial=False):
|
||||
"""
|
||||
random password
|
||||
随机生成密码
|
||||
|
@ -139,7 +137,7 @@ class PyCrypt(object):
|
|||
对称加密之加密生成密码
|
||||
"""
|
||||
if not passwd:
|
||||
passwd = self.random_pass()
|
||||
passwd = self.gen_rand_pass()
|
||||
|
||||
cryptor = AES.new(self.key, self.mode, b'8122ca7d906ad5e1')
|
||||
try:
|
||||
|
@ -256,6 +254,7 @@ def get_session_user_info(request):
|
|||
# return [user.id, user.username, user]
|
||||
return [request.user.id, request.user.username, request.user]
|
||||
|
||||
|
||||
def get_user_dept(request):
|
||||
"""
|
||||
get the user dept id
|
||||
|
@ -389,7 +388,7 @@ def bash(cmd):
|
|||
return subprocess.call(cmd, shell=True)
|
||||
|
||||
|
||||
def is_dir(dir_name, username='root', mode=0755):
|
||||
def mkdir(dir_name, username='root', mode=0755):
|
||||
"""
|
||||
insure the dir exist and mode ok
|
||||
目录存在,如果不存在就建立,并且权限正确
|
||||
|
@ -414,5 +413,5 @@ def my_render(template, data, request):
|
|||
|
||||
|
||||
CRYPTOR = PyCrypt(KEY)
|
||||
logger = set_log(log_level)
|
||||
logger = set_log(LOG_LEVEL)
|
||||
|
||||
|
|
|
@ -34,18 +34,12 @@ EMAIL_USE_TLS = config.getboolean('mail', 'email_use_tls')
|
|||
EMAIL_TIMEOUT = 5
|
||||
|
||||
# ======== Log ==========
|
||||
LOG = False
|
||||
LOG_DIR = os.path.join(BASE_DIR, 'logs')
|
||||
JLOG_FILE = os.path.join(LOG_DIR, 'jumpserver.log')
|
||||
SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys')
|
||||
# SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server')
|
||||
KEY = config.get('base', 'key')
|
||||
LOGIN_NAME = getpass.getuser()
|
||||
# LDAP_ENABLE = CONF.getint('ldap', 'ldap_enable')
|
||||
URL = config.get('base', 'url')
|
||||
log_dir = os.path.join(BASE_DIR, 'logs')
|
||||
log_level = config.get('base', 'log')
|
||||
web_socket_host = config.get('websocket', 'web_socket_host')
|
||||
LOG_LEVEL = config.get('base', 'log')
|
||||
WEB_SOCKET_HOST = config.get('websocket', 'web_socket_host')
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
|
||||
|
|
|
@ -179,7 +179,7 @@ class WebTty(Tty):
|
|||
super(WebTty, self).__init__(*args, **kwargs)
|
||||
self.login_type = 'web'
|
||||
self.ws = None
|
||||
self.input_r = ''
|
||||
self.data = ''
|
||||
self.input_mode = False
|
||||
|
||||
|
||||
|
@ -197,12 +197,11 @@ class WebTerminalKillHandler(tornado.web.RequestHandler):
|
|||
|
||||
|
||||
class WebTerminalHandler(tornado.websocket.WebSocketHandler):
|
||||
tasks = []
|
||||
clients = []
|
||||
tasks = []
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.term = None
|
||||
self.channel = None
|
||||
self.log_file_f = None
|
||||
self.log_time_f = None
|
||||
self.log = None
|
||||
|
@ -220,7 +219,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
|
|||
print asset_name, username, token
|
||||
self.term = WebTty('a', 'b')
|
||||
self.term.get_connection()
|
||||
self.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.clients.append(self)
|
||||
|
||||
|
@ -237,10 +236,10 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
|
|||
if data.get('data'):
|
||||
self.term.input_mode = True
|
||||
if str(data['data']) in ['\r', '\n', '\r\n']:
|
||||
TtyLog(log=self.log, datetime=datetime.datetime.now(), cmd=self.term.remove_control_char(self.term.input_r)).save()
|
||||
self.term.input_r = ''
|
||||
TtyLog(log=self.log, datetime=datetime.datetime.now(), cmd=self.term.remove_control_char(self.term.data)).save()
|
||||
self.term.data = ''
|
||||
self.term.input_mode = False
|
||||
self.channel.send(data['data'])
|
||||
self.term.channel.send(data['data'])
|
||||
|
||||
def on_close(self):
|
||||
print 'On_close'
|
||||
|
@ -256,15 +255,15 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
|
|||
pass
|
||||
|
||||
def forward_outbound(self):
|
||||
self.log_file_f, self.log_time_f, self.log = self.term.get_log_file()
|
||||
self.log_file_f, self.log_time_f, self.log = self.term.get_log()
|
||||
self.id = self.log.id
|
||||
try:
|
||||
data = ''
|
||||
pre_timestamp = time.time()
|
||||
while True:
|
||||
r, w, e = select.select([self.channel, sys.stdin], [], [])
|
||||
if self.channel in r:
|
||||
recv = self.channel.recv(1024)
|
||||
r, w, e = select.select([self.term.channel, sys.stdin], [], [])
|
||||
if self.term.channel in r:
|
||||
recv = self.term.channel.recv(1024)
|
||||
if not len(recv):
|
||||
return
|
||||
data += recv
|
||||
|
@ -277,7 +276,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler):
|
|||
self.log_file_f.flush()
|
||||
self.log_time_f.flush()
|
||||
if self.term.input_mode and not self.term.is_output(data):
|
||||
self.term.input_r += data
|
||||
self.term.data += data
|
||||
data = ''
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue