mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-06-03 04:09:37 +00:00
resolve confilict
This commit is contained in:
parent
09d3763a02
commit
e2ac212fc3
@ -24,11 +24,7 @@ from multiprocessing import Pool
|
|||||||
|
|
||||||
|
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
||||||
<<<<<<< HEAD
|
|
||||||
django.setup()
|
|
||||||
=======
|
|
||||||
#django.setup()
|
#django.setup()
|
||||||
>>>>>>> beta
|
|
||||||
from juser.models import User
|
from juser.models import User
|
||||||
|
|
||||||
from jlog.models import Log
|
from jlog.models import Log
|
||||||
|
@ -7,11 +7,7 @@ import datetime
|
|||||||
|
|
||||||
sys.path.append('../')
|
sys.path.append('../')
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
||||||
<<<<<<< HEAD
|
|
||||||
django.setup()
|
|
||||||
=======
|
|
||||||
#django.setup()
|
#django.setup()
|
||||||
>>>>>>> beta
|
|
||||||
|
|
||||||
|
|
||||||
from juser.views import db_add_user, md5_crypt, CRYPTOR, db_add_group
|
from juser.views import db_add_user, md5_crypt, CRYPTOR, db_add_group
|
||||||
@ -103,11 +99,7 @@ def test_add_asset():
|
|||||||
bis_group_all = BisGroup.objects.all()
|
bis_group_all = BisGroup.objects.all()
|
||||||
dept_all = DEPT.objects.all()
|
dept_all = DEPT.objects.all()
|
||||||
for i in range(1, 500):
|
for i in range(1, 500):
|
||||||
<<<<<<< HEAD
|
|
||||||
ip = '192.168.1.' + str(i)
|
|
||||||
=======
|
|
||||||
ip = '192.168.5.' + str(i)
|
ip = '192.168.5.' + str(i)
|
||||||
>>>>>>> beta
|
|
||||||
asset = Asset(ip=ip, port=22, login_type='L', idc=test_idc, is_active=True, comment='test')
|
asset = Asset(ip=ip, port=22, login_type='L', idc=test_idc, is_active=True, comment='test')
|
||||||
asset.save()
|
asset.save()
|
||||||
asset.bis_group = [random.choice(bis_group_all) for i in range(2)]
|
asset.bis_group = [random.choice(bis_group_all) for i in range(2)]
|
||||||
@ -136,15 +128,6 @@ def test_add_log():
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
#install()
|
#install()
|
||||||
<<<<<<< HEAD
|
|
||||||
test_add_dept()
|
|
||||||
test_add_group()
|
|
||||||
test_add_user()
|
|
||||||
test_add_idc()
|
|
||||||
test_add_asset_group()
|
|
||||||
test_add_asset()
|
|
||||||
test_add_log()
|
|
||||||
=======
|
|
||||||
#test_add_dept()
|
#test_add_dept()
|
||||||
#test_add_group()
|
#test_add_group()
|
||||||
#test_add_user()
|
#test_add_user()
|
||||||
@ -152,7 +135,6 @@ if __name__ == '__main__':
|
|||||||
#test_add_asset_group()
|
#test_add_asset_group()
|
||||||
test_add_asset()
|
test_add_asset()
|
||||||
#test_add_log()
|
#test_add_log()
|
||||||
>>>>>>> beta
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,11 +7,7 @@ import datetime
|
|||||||
|
|
||||||
sys.path.append('../')
|
sys.path.append('../')
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
||||||
<<<<<<< HEAD
|
|
||||||
django.setup()
|
|
||||||
=======
|
|
||||||
#django.setup()
|
#django.setup()
|
||||||
>>>>>>> beta
|
|
||||||
|
|
||||||
|
|
||||||
from juser.views import db_add_user, md5_crypt, CRYPTOR, db_add_group
|
from juser.views import db_add_user, md5_crypt, CRYPTOR, db_add_group
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
pexpect==3.3
|
|
||||||
sphinx-me==0.3
|
|
||||||
django==1.6
|
|
||||||
python-ldap==2.4.18
|
|
||||||
paramiko==1.15.1
|
|
||||||
pycrypto==2.6.1
|
|
||||||
ecdsa>=0.11
|
|
||||||
MySQL-python==1.2.5
|
|
||||||
readline
|
|
||||||
django-uuidfield
|
|
@ -66,11 +66,7 @@ MIDDLEWARE_CLASSES = (
|
|||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
#'django.middleware.csrf.CsrfViewMiddleware',
|
#'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
<<<<<<< HEAD
|
|
||||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
|
||||||
=======
|
|
||||||
#'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
#'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||||
>>>>>>> beta
|
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
)
|
)
|
||||||
|
@ -10,11 +10,7 @@ from datetime import datetime
|
|||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
||||||
|
|
||||||
import django
|
import django
|
||||||
<<<<<<< HEAD
|
|
||||||
django.setup()
|
|
||||||
=======
|
|
||||||
#django.setup()
|
#django.setup()
|
||||||
>>>>>>> beta
|
|
||||||
from jlog.models import Log
|
from jlog.models import Log
|
||||||
|
|
||||||
|
|
||||||
|
395
ssh
395
ssh
@ -1,395 +0,0 @@
|
|||||||
#!/usr/local/bin/python
|
|
||||||
|
|
||||||
import socket
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import ast
|
|
||||||
import select
|
|
||||||
import time
|
|
||||||
from datetime import datetime
|
|
||||||
import paramiko
|
|
||||||
import struct
|
|
||||||
import fcntl
|
|
||||||
import signal
|
|
||||||
import textwrap
|
|
||||||
import django
|
|
||||||
import getpass
|
|
||||||
import fnmatch
|
|
||||||
import optparse
|
|
||||||
import readline
|
|
||||||
from multiprocessing import Pool
|
|
||||||
from ConfigParser import ConfigParser
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
|
||||||
|
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
|
||||||
django.setup()
|
|
||||||
from juser.models import User
|
|
||||||
from jasset.models import Asset
|
|
||||||
from jlog.models import Log
|
|
||||||
from jumpserver.views import PyCrypt
|
|
||||||
from jumpserver.api import user_perm_asset_api, user_perm_group_api
|
|
||||||
|
|
||||||
try:
|
|
||||||
import termios
|
|
||||||
import tty
|
|
||||||
except ImportError:
|
|
||||||
print '\033[1;31mOnly postfix supported.\033[0m'
|
|
||||||
time.sleep(3)
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
|
||||||
CONF = ConfigParser()
|
|
||||||
CONF.read(os.path.join(BASE_DIR, 'jumpserver.conf'))
|
|
||||||
LOG_DIR = os.path.join(BASE_DIR, 'logs')
|
|
||||||
SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys')
|
|
||||||
SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server')
|
|
||||||
KEY = CONF.get('web', 'key')
|
|
||||||
LOGIN_NAME = getpass.getuser()
|
|
||||||
|
|
||||||
|
|
||||||
def color_print(msg, color='blue'):
|
|
||||||
"""Print colorful string."""
|
|
||||||
color_msg = {'blue': '\033[1;36m%s\033[0m',
|
|
||||||
'green': '\033[1;32m%s\033[0m',
|
|
||||||
'red': '\033[1;31m%s\033[0m'}
|
|
||||||
|
|
||||||
print color_msg.get(color, 'blue') % msg
|
|
||||||
|
|
||||||
|
|
||||||
def color_print_exit(msg, color='red'):
|
|
||||||
"""Print colorful string and exit."""
|
|
||||||
color_print(msg, color=color)
|
|
||||||
time.sleep(2)
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
|
|
||||||
class ServerError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def get_win_size():
|
|
||||||
"""This function use to get the size of the windows!"""
|
|
||||||
if 'TIOCGWINSZ' in dir(termios):
|
|
||||||
TIOCGWINSZ = termios.TIOCGWINSZ
|
|
||||||
else:
|
|
||||||
TIOCGWINSZ = 1074295912L # Assume
|
|
||||||
s = struct.pack('HHHH', 0, 0, 0, 0)
|
|
||||||
x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s)
|
|
||||||
return struct.unpack('HHHH', x)[0:2]
|
|
||||||
|
|
||||||
|
|
||||||
def set_win_size(sig, data):
|
|
||||||
"""This function use to set the window size of the terminal!"""
|
|
||||||
try:
|
|
||||||
win_size = get_win_size()
|
|
||||||
channel.resize_pty(height=win_size[0], width=win_size[1])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def get_object(model, **kwargs):
|
|
||||||
try:
|
|
||||||
the_object = model.objects.get(**kwargs)
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
raise ServerError('Object get %s failed.' % str(kwargs.values()))
|
|
||||||
return the_object
|
|
||||||
|
|
||||||
|
|
||||||
def log_record(username, host):
|
|
||||||
"""Logging user command and output."""
|
|
||||||
connect_log_dir = os.path.join(LOG_DIR, 'connect')
|
|
||||||
timestamp_start = int(time.time())
|
|
||||||
today = time.strftime('%Y%m%d', time.localtime(timestamp_start))
|
|
||||||
time_now = time.strftime('%H%M%S', time.localtime(timestamp_start))
|
|
||||||
today_connect_log_dir = os.path.join(connect_log_dir, today)
|
|
||||||
log_filename = '%s_%s_%s.log' % (username, host, time_now)
|
|
||||||
log_file_path = os.path.join(today_connect_log_dir, log_filename)
|
|
||||||
pid = os.getpid()
|
|
||||||
ip_list = []
|
|
||||||
remote_ip = os.popen("who |grep `ps aux |gawk '{if ($2==%s) print $1}'` |gawk '{print $5}'|tr -d '()'" % pid).readlines()
|
|
||||||
for ip in remote_ip:
|
|
||||||
ip_list.append(ip.strip('\n'))
|
|
||||||
ip_list = ','.join(list(set(ip_list)))
|
|
||||||
|
|
||||||
if not os.path.isdir(today_connect_log_dir):
|
|
||||||
try:
|
|
||||||
os.makedirs(today_connect_log_dir)
|
|
||||||
os.chmod(today_connect_log_dir, 0777)
|
|
||||||
except OSError:
|
|
||||||
raise ServerError('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, connect_log_dir))
|
|
||||||
|
|
||||||
try:
|
|
||||||
log_file = open(log_file_path, 'a')
|
|
||||||
except IOError:
|
|
||||||
raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir)
|
|
||||||
|
|
||||||
log = Log(user=username, host=host, remote_ip=ip_list, log_path=log_file_path, start_time=datetime.now(), pid=pid)
|
|
||||||
log_file.write('Starttime is %s\n' % datetime.now())
|
|
||||||
log.save()
|
|
||||||
return log_file, log
|
|
||||||
|
|
||||||
|
|
||||||
def posix_shell(chan, username, host):
|
|
||||||
"""
|
|
||||||
Use paramiko channel connect server interactive.
|
|
||||||
"""
|
|
||||||
log_file, log = log_record(username, host)
|
|
||||||
old_tty = termios.tcgetattr(sys.stdin)
|
|
||||||
try:
|
|
||||||
tty.setraw(sys.stdin.fileno())
|
|
||||||
tty.setcbreak(sys.stdin.fileno())
|
|
||||||
chan.settimeout(0.0)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
r, w, e = select.select([chan, sys.stdin], [], [])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if chan in r:
|
|
||||||
try:
|
|
||||||
x = chan.recv(1024)
|
|
||||||
if len(x) == 0:
|
|
||||||
break
|
|
||||||
sys.stdout.write(x)
|
|
||||||
sys.stdout.flush()
|
|
||||||
log_file.write(x)
|
|
||||||
log_file.flush()
|
|
||||||
except socket.timeout:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if sys.stdin in r:
|
|
||||||
x = os.read(sys.stdin.fileno(), 1)
|
|
||||||
if len(x) == 0:
|
|
||||||
break
|
|
||||||
chan.send(x)
|
|
||||||
|
|
||||||
finally:
|
|
||||||
timestamp_end = time.time()
|
|
||||||
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
|
|
||||||
log_file.write('Endtime is %s' % datetime.now())
|
|
||||||
log_file.close()
|
|
||||||
log.is_finished = True
|
|
||||||
log.log_finished = False
|
|
||||||
log.end_time = datetime.now()
|
|
||||||
log.save()
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_host(username):
|
|
||||||
"""Get the hosts of under the user control."""
|
|
||||||
hosts_attr = {}
|
|
||||||
asset_all = user_perm_asset_api(username)
|
|
||||||
for asset in asset_all:
|
|
||||||
hosts_attr[asset.ip] = [asset.id, asset.comment]
|
|
||||||
return hosts_attr
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_hostgroup(username):
|
|
||||||
"""Get the hostgroups of under the user control."""
|
|
||||||
groups_attr = {}
|
|
||||||
group_all = user_perm_group_api(username)
|
|
||||||
for group in group_all:
|
|
||||||
groups_attr[group.name] = [group.id, group.comment]
|
|
||||||
return groups_attr
|
|
||||||
|
|
||||||
|
|
||||||
def get_connect_item(username, ip):
|
|
||||||
cryptor = PyCrypt(KEY)
|
|
||||||
|
|
||||||
asset = get_object(Asset, ip=ip)
|
|
||||||
port = asset.port
|
|
||||||
|
|
||||||
if not asset.is_active:
|
|
||||||
raise ServerError('Host %s is not active.' % ip)
|
|
||||||
|
|
||||||
user = get_object(User, username=username)
|
|
||||||
|
|
||||||
if not user.is_active:
|
|
||||||
raise ServerError('User %s is not active.' % username)
|
|
||||||
|
|
||||||
login_type_dict = {
|
|
||||||
'L': user.ldap_pwd,
|
|
||||||
}
|
|
||||||
|
|
||||||
if asset.login_type in login_type_dict:
|
|
||||||
password = cryptor.decrypt(login_type_dict[asset.login_type])
|
|
||||||
return username, password, ip, port
|
|
||||||
|
|
||||||
elif asset.login_type == 'M':
|
|
||||||
username = asset.username
|
|
||||||
password = cryptor.decrypt(asset.password)
|
|
||||||
return username, password, ip, port
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise ServerError('Login type is not in ["L", "M"]')
|
|
||||||
|
|
||||||
|
|
||||||
def verify_connect(username, part_ip):
|
|
||||||
hosts_attr = get_user_host(username)
|
|
||||||
hosts = hosts_attr.keys()
|
|
||||||
ip_matched = [ip for ip in hosts if part_ip in ip]
|
|
||||||
|
|
||||||
if len(ip_matched) > 1:
|
|
||||||
for ip in ip_matched:
|
|
||||||
print '%s -- %s' % (ip, hosts_attr[ip][1])
|
|
||||||
elif len(ip_matched) < 1:
|
|
||||||
color_print('No Permission or No host.', 'red')
|
|
||||||
else:
|
|
||||||
username, password, host, port = get_connect_item(username, ip_matched[0])
|
|
||||||
print username, password, host, port
|
|
||||||
connect(username, password, host, port, LOGIN_NAME)
|
|
||||||
|
|
||||||
|
|
||||||
def print_prompt():
|
|
||||||
msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m
|
|
||||||
1) Type \033[32mIP ADDRESS\033[0m To Login.
|
|
||||||
2) Type \033[32mP/p\033[0m To Print The Servers You Available.
|
|
||||||
3) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
|
|
||||||
4) Type \033[32mE/e\033[0m To Execute Command On Several Servers.
|
|
||||||
5) Type \033[32mQ/q\033[0m To Quit.
|
|
||||||
"""
|
|
||||||
print textwrap.dedent(msg)
|
|
||||||
|
|
||||||
|
|
||||||
def print_user_host(username):
|
|
||||||
hosts_attr = get_user_host(username)
|
|
||||||
hosts = hosts_attr.keys()
|
|
||||||
hosts.sort()
|
|
||||||
for ip in hosts:
|
|
||||||
print '%s -- %s' % (ip, hosts_attr[ip][1])
|
|
||||||
|
|
||||||
|
|
||||||
def print_user_hostgroup(username):
|
|
||||||
group_attr = get_user_hostgroup(username)
|
|
||||||
groups = group_attr.keys()
|
|
||||||
for g in groups:
|
|
||||||
print '%s -- %s' % (g, group_attr[g][1])
|
|
||||||
|
|
||||||
|
|
||||||
def connect(username, password, host, port, login_name):
|
|
||||||
"""
|
|
||||||
Connect server.
|
|
||||||
"""
|
|
||||||
ps1 = "PS1='[\u@%s \W]\$ '\n" % host
|
|
||||||
login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % host
|
|
||||||
|
|
||||||
# Make a ssh connection
|
|
||||||
ssh = paramiko.SSHClient()
|
|
||||||
ssh.load_system_host_keys()
|
|
||||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
||||||
try:
|
|
||||||
ssh.connect(host, port=port, username=username, password=password, compress=True)
|
|
||||||
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
|
|
||||||
raise ServerError('Authentication Error.')
|
|
||||||
except socket.error:
|
|
||||||
raise ServerError('Connect SSH Socket Port Error, Please Correct it.')
|
|
||||||
|
|
||||||
# Make a channel and set windows size
|
|
||||||
global channel
|
|
||||||
win_size = get_win_size()
|
|
||||||
channel = ssh.invoke_shell(height=win_size[0], width=win_size[1])
|
|
||||||
#channel.resize_pty(height=win_size[0], width=win_size[1])
|
|
||||||
try:
|
|
||||||
signal.signal(signal.SIGWINCH, set_win_size)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Set PS1 and msg it
|
|
||||||
channel.send(ps1)
|
|
||||||
channel.send(login_msg)
|
|
||||||
|
|
||||||
# Make ssh interactive tunnel
|
|
||||||
posix_shell(channel, login_name, host)
|
|
||||||
|
|
||||||
# Shutdown channel socket
|
|
||||||
channel.close()
|
|
||||||
ssh.close()
|
|
||||||
|
|
||||||
|
|
||||||
def remote_exec_cmd(ip, port, username, password, cmd):
|
|
||||||
try:
|
|
||||||
time.sleep(5)
|
|
||||||
ssh = paramiko.SSHClient()
|
|
||||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
||||||
ssh.connect(ip, port, username, password, timeout=5)
|
|
||||||
stdin, stdout, stderr = ssh.exec_command("bash -l -c '%s'" % cmd)
|
|
||||||
out = stdout.readlines()
|
|
||||||
err = stderr.readlines()
|
|
||||||
color_print('%s:' %ip, 'blue')
|
|
||||||
for i in out:
|
|
||||||
color_print(" " * 4 + i.strip(), 'green')
|
|
||||||
for j in err:
|
|
||||||
color_print(" " * 4 + j.strip(), 'red')
|
|
||||||
ssh.close()
|
|
||||||
except Exception as e:
|
|
||||||
color_print(ip + ':', 'blue')
|
|
||||||
color_print(str(e), 'red')
|
|
||||||
|
|
||||||
|
|
||||||
def multi_remote_exec_cmd(hosts, username, cmd):
|
|
||||||
pool = Pool(processes=5)
|
|
||||||
for host in hosts:
|
|
||||||
username, password, ip, port = get_connect_item(username, host)
|
|
||||||
pool.apply_async(remote_exec_cmd, (ip, port, username, password, cmd))
|
|
||||||
pool.close()
|
|
||||||
pool.join()
|
|
||||||
|
|
||||||
|
|
||||||
def exec_cmd_servers(username):
|
|
||||||
hosts = []
|
|
||||||
color_print("Input the Host IP(s),Separated by Commas, q/Q to Quit.\n \
|
|
||||||
You can choose in the following IP(s), Use Linux / Unix glob.", 'green')
|
|
||||||
print_user_host(LOGIN_NAME)
|
|
||||||
while True:
|
|
||||||
inputs = raw_input('\033[1;32mip(s)>: \033[0m')
|
|
||||||
if inputs in ['q', 'Q']:
|
|
||||||
break
|
|
||||||
get_hosts = get_user_host(username).keys()
|
|
||||||
for host in get_hosts:
|
|
||||||
if fnmatch.fnmatch(host, inputs):
|
|
||||||
hosts.append(host.strip())
|
|
||||||
if len(hosts) == 0:
|
|
||||||
color_print("Check again, Not matched any ip!", 'red')
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
print "You matched ip: %s" % hosts
|
|
||||||
color_print("Input the Command , The command will be Execute on servers, q/Q to quit.", 'green')
|
|
||||||
while True:
|
|
||||||
cmd = raw_input('\033[1;32mCmd(s): \033[0m')
|
|
||||||
if cmd in ['q', 'Q']:
|
|
||||||
break
|
|
||||||
exec_log_dir = os.path.join(LOG_DIR, 'exec_cmds')
|
|
||||||
if not os.path.isdir(exec_log_dir):
|
|
||||||
os.mkdir(exec_log_dir)
|
|
||||||
os.chmod(exec_log_dir, 0777)
|
|
||||||
filename = "%s/%s.log" % (exec_log_dir, time.strftime('%Y%m%d'))
|
|
||||||
f = open(filename, 'a')
|
|
||||||
f.write("DateTime: %s User: %s Host: %s Cmds: %s\n" %
|
|
||||||
(time.strftime('%Y/%m/%d %H:%M:%S'), username, hosts, cmd))
|
|
||||||
multi_remote_exec_cmd(hosts, username, cmd)
|
|
||||||
|
|
||||||
|
|
||||||
def help():
|
|
||||||
global p, options, arguments
|
|
||||||
usage = "usage: %prog '' [options] arg1 [options] arg2"
|
|
||||||
p = optparse.OptionParser(usage=usage)
|
|
||||||
p.add_option('-p', '--host', help = "Print The Servers You Available.")
|
|
||||||
p.add_option('-g', '--group', help = "Print The Server Groups You Available.")
|
|
||||||
options, arguments = p.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
help()
|
|
||||||
if options.host:
|
|
||||||
pass
|
|
||||||
elif options.group:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
verify_connect(LOGIN_NAME, sys.argv[1])
|
|
||||||
except ServerError, e:
|
|
||||||
color_print(e, 'red')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
395
ssh.py
395
ssh.py
@ -1,395 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import socket
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import ast
|
|
||||||
import select
|
|
||||||
import time
|
|
||||||
from datetime import datetime
|
|
||||||
import paramiko
|
|
||||||
import struct
|
|
||||||
import fcntl
|
|
||||||
import signal
|
|
||||||
import textwrap
|
|
||||||
import django
|
|
||||||
import getpass
|
|
||||||
import fnmatch
|
|
||||||
import optparse
|
|
||||||
import readline
|
|
||||||
from multiprocessing import Pool
|
|
||||||
from ConfigParser import ConfigParser
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
|
||||||
|
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
|
||||||
django.setup()
|
|
||||||
from juser.models import User
|
|
||||||
from jasset.models import Asset
|
|
||||||
from jlog.models import Log
|
|
||||||
from jumpserver.views import PyCrypt
|
|
||||||
from jumpserver.api import user_perm_asset_api, user_perm_group_api
|
|
||||||
|
|
||||||
try:
|
|
||||||
import termios
|
|
||||||
import tty
|
|
||||||
except ImportError:
|
|
||||||
print '\033[1;31mOnly postfix supported.\033[0m'
|
|
||||||
time.sleep(3)
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
|
||||||
CONF = ConfigParser()
|
|
||||||
CONF.read(os.path.join(BASE_DIR, 'jumpserver.conf'))
|
|
||||||
LOG_DIR = os.path.join(BASE_DIR, 'logs')
|
|
||||||
SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys')
|
|
||||||
SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server')
|
|
||||||
KEY = CONF.get('web', 'key')
|
|
||||||
LOGIN_NAME = getpass.getuser()
|
|
||||||
|
|
||||||
|
|
||||||
def color_print(msg, color='blue'):
|
|
||||||
"""Print colorful string."""
|
|
||||||
color_msg = {'blue': '\033[1;36m%s\033[0m',
|
|
||||||
'green': '\033[1;32m%s\033[0m',
|
|
||||||
'red': '\033[1;31m%s\033[0m'}
|
|
||||||
|
|
||||||
print color_msg.get(color, 'blue') % msg
|
|
||||||
|
|
||||||
|
|
||||||
def color_print_exit(msg, color='red'):
|
|
||||||
"""Print colorful string and exit."""
|
|
||||||
color_print(msg, color=color)
|
|
||||||
time.sleep(2)
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
|
|
||||||
class ServerError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def get_win_size():
|
|
||||||
"""This function use to get the size of the windows!"""
|
|
||||||
if 'TIOCGWINSZ' in dir(termios):
|
|
||||||
TIOCGWINSZ = termios.TIOCGWINSZ
|
|
||||||
else:
|
|
||||||
TIOCGWINSZ = 1074295912L # Assume
|
|
||||||
s = struct.pack('HHHH', 0, 0, 0, 0)
|
|
||||||
x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s)
|
|
||||||
return struct.unpack('HHHH', x)[0:2]
|
|
||||||
|
|
||||||
|
|
||||||
def set_win_size(sig, data):
|
|
||||||
"""This function use to set the window size of the terminal!"""
|
|
||||||
try:
|
|
||||||
win_size = get_win_size()
|
|
||||||
channel.resize_pty(height=win_size[0], width=win_size[1])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def get_object(model, **kwargs):
|
|
||||||
try:
|
|
||||||
the_object = model.objects.get(**kwargs)
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
raise ServerError('Object get %s failed.' % str(kwargs.values()))
|
|
||||||
return the_object
|
|
||||||
|
|
||||||
|
|
||||||
def log_record(username, host):
|
|
||||||
"""Logging user command and output."""
|
|
||||||
connect_log_dir = os.path.join(LOG_DIR, 'connect')
|
|
||||||
timestamp_start = int(time.time())
|
|
||||||
today = time.strftime('%Y%m%d', time.localtime(timestamp_start))
|
|
||||||
time_now = time.strftime('%H%M%S', time.localtime(timestamp_start))
|
|
||||||
today_connect_log_dir = os.path.join(connect_log_dir, today)
|
|
||||||
log_filename = '%s_%s_%s.log' % (username, host, time_now)
|
|
||||||
log_file_path = os.path.join(today_connect_log_dir, log_filename)
|
|
||||||
pid = os.getpid()
|
|
||||||
ip_list = []
|
|
||||||
remote_ip = os.popen("who |grep `ps aux |gawk '{if ($2==%s) print $1}'` |gawk '{print $5}'|tr -d '()'" % pid).readlines()
|
|
||||||
for ip in remote_ip:
|
|
||||||
ip_list.append(ip.strip('\n'))
|
|
||||||
ip_list = ','.join(list(set(ip_list)))
|
|
||||||
|
|
||||||
if not os.path.isdir(today_connect_log_dir):
|
|
||||||
try:
|
|
||||||
os.makedirs(today_connect_log_dir)
|
|
||||||
os.chmod(today_connect_log_dir, 0777)
|
|
||||||
except OSError:
|
|
||||||
raise ServerError('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, connect_log_dir))
|
|
||||||
|
|
||||||
try:
|
|
||||||
log_file = open(log_file_path, 'a')
|
|
||||||
except IOError:
|
|
||||||
raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir)
|
|
||||||
|
|
||||||
log = Log(user=username, host=host, remote_ip=ip_list, log_path=log_file_path, start_time=datetime.now(), pid=pid)
|
|
||||||
log_file.write('Starttime is %s\n' % datetime.now())
|
|
||||||
log.save()
|
|
||||||
return log_file, log
|
|
||||||
|
|
||||||
|
|
||||||
def posix_shell(chan, username, host):
|
|
||||||
"""
|
|
||||||
Use paramiko channel connect server interactive.
|
|
||||||
"""
|
|
||||||
log_file, log = log_record(username, host)
|
|
||||||
old_tty = termios.tcgetattr(sys.stdin)
|
|
||||||
try:
|
|
||||||
tty.setraw(sys.stdin.fileno())
|
|
||||||
tty.setcbreak(sys.stdin.fileno())
|
|
||||||
chan.settimeout(0.0)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
r, w, e = select.select([chan, sys.stdin], [], [])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if chan in r:
|
|
||||||
try:
|
|
||||||
x = chan.recv(1024)
|
|
||||||
if len(x) == 0:
|
|
||||||
break
|
|
||||||
sys.stdout.write(x)
|
|
||||||
sys.stdout.flush()
|
|
||||||
log_file.write(x)
|
|
||||||
log_file.flush()
|
|
||||||
except socket.timeout:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if sys.stdin in r:
|
|
||||||
x = os.read(sys.stdin.fileno(), 1)
|
|
||||||
if len(x) == 0:
|
|
||||||
break
|
|
||||||
chan.send(x)
|
|
||||||
|
|
||||||
finally:
|
|
||||||
timestamp_end = time.time()
|
|
||||||
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
|
|
||||||
log_file.write('Endtime is %s' % datetime.now())
|
|
||||||
log_file.close()
|
|
||||||
log.is_finished = True
|
|
||||||
log.log_finished = False
|
|
||||||
log.end_time = datetime.now()
|
|
||||||
log.save()
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_host(username):
|
|
||||||
"""Get the hosts of under the user control."""
|
|
||||||
hosts_attr = {}
|
|
||||||
asset_all = user_perm_asset_api(username)
|
|
||||||
for asset in asset_all:
|
|
||||||
hosts_attr[asset.ip] = [asset.id, asset.comment]
|
|
||||||
return hosts_attr
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_hostgroup(username):
|
|
||||||
"""Get the hostgroups of under the user control."""
|
|
||||||
groups_attr = {}
|
|
||||||
group_all = user_perm_group_api(username)
|
|
||||||
for group in group_all:
|
|
||||||
groups_attr[group.name] = [group.id, group.comment]
|
|
||||||
return groups_attr
|
|
||||||
|
|
||||||
|
|
||||||
def get_connect_item(username, ip):
|
|
||||||
cryptor = PyCrypt(KEY)
|
|
||||||
|
|
||||||
asset = get_object(Asset, ip=ip)
|
|
||||||
port = asset.port
|
|
||||||
|
|
||||||
if not asset.is_active:
|
|
||||||
raise ServerError('Host %s is not active.' % ip)
|
|
||||||
|
|
||||||
user = get_object(User, username=username)
|
|
||||||
|
|
||||||
if not user.is_active:
|
|
||||||
raise ServerError('User %s is not active.' % username)
|
|
||||||
|
|
||||||
login_type_dict = {
|
|
||||||
'L': user.ldap_pwd,
|
|
||||||
}
|
|
||||||
|
|
||||||
if asset.login_type in login_type_dict:
|
|
||||||
password = cryptor.decrypt(login_type_dict[asset.login_type])
|
|
||||||
return username, password, ip, port
|
|
||||||
|
|
||||||
elif asset.login_type == 'M':
|
|
||||||
username = asset.username
|
|
||||||
password = cryptor.decrypt(asset.password)
|
|
||||||
return username, password, ip, port
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise ServerError('Login type is not in ["L", "M"]')
|
|
||||||
|
|
||||||
|
|
||||||
def verify_connect(username, part_ip):
|
|
||||||
hosts_attr = get_user_host(username)
|
|
||||||
hosts = hosts_attr.keys()
|
|
||||||
ip_matched = [ip for ip in hosts if part_ip in ip]
|
|
||||||
|
|
||||||
if len(ip_matched) > 1:
|
|
||||||
for ip in ip_matched:
|
|
||||||
print '%s -- %s' % (ip, hosts_attr[ip][1])
|
|
||||||
elif len(ip_matched) < 1:
|
|
||||||
color_print('No Permission or No host.', 'red')
|
|
||||||
else:
|
|
||||||
username, password, host, port = get_connect_item(username, ip_matched[0])
|
|
||||||
print username, password, host, port
|
|
||||||
connect(username, password, host, port, LOGIN_NAME)
|
|
||||||
|
|
||||||
|
|
||||||
def print_prompt():
|
|
||||||
msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m
|
|
||||||
1) Type \033[32mIP ADDRESS\033[0m To Login.
|
|
||||||
2) Type \033[32mP/p\033[0m To Print The Servers You Available.
|
|
||||||
3) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
|
|
||||||
4) Type \033[32mE/e\033[0m To Execute Command On Several Servers.
|
|
||||||
5) Type \033[32mQ/q\033[0m To Quit.
|
|
||||||
"""
|
|
||||||
print textwrap.dedent(msg)
|
|
||||||
|
|
||||||
|
|
||||||
def print_user_host(username):
|
|
||||||
hosts_attr = get_user_host(username)
|
|
||||||
hosts = hosts_attr.keys()
|
|
||||||
hosts.sort()
|
|
||||||
for ip in hosts:
|
|
||||||
print '%s -- %s' % (ip, hosts_attr[ip][1])
|
|
||||||
|
|
||||||
|
|
||||||
def print_user_hostgroup(username):
|
|
||||||
group_attr = get_user_hostgroup(username)
|
|
||||||
groups = group_attr.keys()
|
|
||||||
for g in groups:
|
|
||||||
print '%s -- %s' % (g, group_attr[g][1])
|
|
||||||
|
|
||||||
|
|
||||||
def connect(username, password, host, port, login_name):
|
|
||||||
"""
|
|
||||||
Connect server.
|
|
||||||
"""
|
|
||||||
ps1 = "PS1='[\u@%s \W]\$ '\n" % host
|
|
||||||
login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % host
|
|
||||||
|
|
||||||
# Make a ssh connection
|
|
||||||
ssh = paramiko.SSHClient()
|
|
||||||
ssh.load_system_host_keys()
|
|
||||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
||||||
try:
|
|
||||||
ssh.connect(host, port=port, username=username, password=password, compress=True)
|
|
||||||
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
|
|
||||||
raise ServerError('Authentication Error.')
|
|
||||||
except socket.error:
|
|
||||||
raise ServerError('Connect SSH Socket Port Error, Please Correct it.')
|
|
||||||
|
|
||||||
# Make a channel and set windows size
|
|
||||||
global channel
|
|
||||||
win_size = get_win_size()
|
|
||||||
channel = ssh.invoke_shell(height=win_size[0], width=win_size[1])
|
|
||||||
#channel.resize_pty(height=win_size[0], width=win_size[1])
|
|
||||||
try:
|
|
||||||
signal.signal(signal.SIGWINCH, set_win_size)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Set PS1 and msg it
|
|
||||||
channel.send(ps1)
|
|
||||||
channel.send(login_msg)
|
|
||||||
|
|
||||||
# Make ssh interactive tunnel
|
|
||||||
posix_shell(channel, login_name, host)
|
|
||||||
|
|
||||||
# Shutdown channel socket
|
|
||||||
channel.close()
|
|
||||||
ssh.close()
|
|
||||||
|
|
||||||
|
|
||||||
def remote_exec_cmd(ip, port, username, password, cmd):
|
|
||||||
try:
|
|
||||||
time.sleep(5)
|
|
||||||
ssh = paramiko.SSHClient()
|
|
||||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
||||||
ssh.connect(ip, port, username, password, timeout=5)
|
|
||||||
stdin, stdout, stderr = ssh.exec_command("bash -l -c '%s'" % cmd)
|
|
||||||
out = stdout.readlines()
|
|
||||||
err = stderr.readlines()
|
|
||||||
color_print('%s:' %ip, 'blue')
|
|
||||||
for i in out:
|
|
||||||
color_print(" " * 4 + i.strip(), 'green')
|
|
||||||
for j in err:
|
|
||||||
color_print(" " * 4 + j.strip(), 'red')
|
|
||||||
ssh.close()
|
|
||||||
except Exception as e:
|
|
||||||
color_print(ip + ':', 'blue')
|
|
||||||
color_print(str(e), 'red')
|
|
||||||
|
|
||||||
|
|
||||||
def multi_remote_exec_cmd(hosts, username, cmd):
|
|
||||||
pool = Pool(processes=5)
|
|
||||||
for host in hosts:
|
|
||||||
username, password, ip, port = get_connect_item(username, host)
|
|
||||||
pool.apply_async(remote_exec_cmd, (ip, port, username, password, cmd))
|
|
||||||
pool.close()
|
|
||||||
pool.join()
|
|
||||||
|
|
||||||
|
|
||||||
def exec_cmd_servers(username):
|
|
||||||
hosts = []
|
|
||||||
color_print("Input the Host IP(s),Separated by Commas, q/Q to Quit.\n \
|
|
||||||
You can choose in the following IP(s), Use Linux / Unix glob.", 'green')
|
|
||||||
print_user_host(LOGIN_NAME)
|
|
||||||
while True:
|
|
||||||
inputs = raw_input('\033[1;32mip(s)>: \033[0m')
|
|
||||||
if inputs in ['q', 'Q']:
|
|
||||||
break
|
|
||||||
get_hosts = get_user_host(username).keys()
|
|
||||||
for host in get_hosts:
|
|
||||||
if fnmatch.fnmatch(host, inputs):
|
|
||||||
hosts.append(host.strip())
|
|
||||||
if len(hosts) == 0:
|
|
||||||
color_print("Check again, Not matched any ip!", 'red')
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
print "You matched ip: %s" % hosts
|
|
||||||
color_print("Input the Command , The command will be Execute on servers, q/Q to quit.", 'green')
|
|
||||||
while True:
|
|
||||||
cmd = raw_input('\033[1;32mCmd(s): \033[0m')
|
|
||||||
if cmd in ['q', 'Q']:
|
|
||||||
break
|
|
||||||
exec_log_dir = os.path.join(LOG_DIR, 'exec_cmds')
|
|
||||||
if not os.path.isdir(exec_log_dir):
|
|
||||||
os.mkdir(exec_log_dir)
|
|
||||||
os.chmod(exec_log_dir, 0777)
|
|
||||||
filename = "%s/%s.log" % (exec_log_dir, time.strftime('%Y%m%d'))
|
|
||||||
f = open(filename, 'a')
|
|
||||||
f.write("DateTime: %s User: %s Host: %s Cmds: %s\n" %
|
|
||||||
(time.strftime('%Y/%m/%d %H:%M:%S'), username, hosts, cmd))
|
|
||||||
multi_remote_exec_cmd(hosts, username, cmd)
|
|
||||||
|
|
||||||
|
|
||||||
def help():
|
|
||||||
global p, options, arguments
|
|
||||||
usage = "usage: %prog '' [options] arg1 [options] arg2"
|
|
||||||
p = optparse.OptionParser(usage=usage)
|
|
||||||
p.add_option('-p', '--host', help = "Print The Servers You Available.")
|
|
||||||
p.add_option('-g', '--group', help = "Print The Server Groups You Available.")
|
|
||||||
options, arguments = p.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
help()
|
|
||||||
if options.host:
|
|
||||||
pass
|
|
||||||
elif options.group:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
verify_connect(LOGIN_NAME, sys.argv[1])
|
|
||||||
except ServerError, e:
|
|
||||||
color_print(e, 'red')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
File diff suppressed because one or more lines are too long
18
static/js/layer/layer.min.js
vendored
18
static/js/layer/layer.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,4 +1,3 @@
|
|||||||
<<<<<<< HEAD
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
@Name: layer's style
|
@Name: layer's style
|
||||||
@ -82,88 +81,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
=======
|
|
||||||
/**
|
|
||||||
|
|
||||||
@Name: layer's style
|
|
||||||
@Date: 2012.09.15
|
|
||||||
@Author: 贤心
|
|
||||||
@blog: sentsin.com
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
*html{background-image:url(about:blank); background-attachment:fixed;}
|
|
||||||
|
|
||||||
/** common **/
|
|
||||||
.xubox_shade, .xubox_layer{position:fixed; _position:absolute;}
|
|
||||||
.xubox_shade{top:0; left:0; width:100%; height:100%; _height:expression(document.body.offsetHeight+"px");}
|
|
||||||
.xubox_layer{top:150px; left:50%; height:auto; width:310px; margin-left:-155px;}
|
|
||||||
.xubox_border, .xubox_title, .xubox_title i, .xubox_page, .xubox_iframe, .xubox_title em, .xubox_close, .xubox_msgico, .xubox_moves{position:absolute;}
|
|
||||||
.xubox_border{border-radius: 5px;}
|
|
||||||
.xubox_title{left:0; top:0;}
|
|
||||||
.xubox_main{position:relative; height:100%; _float:left;}
|
|
||||||
.xubox_page{top:0; left:0;}
|
|
||||||
.xubox_load{background:url(default/xubox_loading0.gif) #fff center center no-repeat;}
|
|
||||||
.xubox_loading{display:block; float:left; text-decoration:none; color:#FFF; _float:none; }
|
|
||||||
.xulayer_png32{background:url(default/xubox_ico0.png) no-repeat;}
|
|
||||||
.xubox_moves{border:3px solid #666; cursor:move; background-color:rgba(255,255,255,.3); background-color:#fff\9; filter:alpha(opacity=50);}
|
|
||||||
|
|
||||||
.xubox_msgico{width:32px; height:32px; top:52px; left:15px; background:url(default/xubox_ico0.png) no-repeat;}
|
|
||||||
.xubox_text{ padding-left:55px; float:left; line-height:25px; word-break:break-all; padding-right:20px; overflow:hidden; font-size:14px;}
|
|
||||||
.xubox_msgtype0{background-position:-91px -38px;}
|
|
||||||
.xubox_msgtype1{background-position:-128px -38px }
|
|
||||||
.xubox_msgtype2{background-position:-163px -38px;}
|
|
||||||
.xubox_msgtype3{background-position:-91px -75px;}
|
|
||||||
.xubox_msgtype4{background-position:-163px -75px;}
|
|
||||||
.xubox_msgtype5{background-position:-163px -112px;}
|
|
||||||
.xubox_msgtype6{background-position:-163px -148px;}
|
|
||||||
.xubox_msgtype7{background-position:-128px -75px;}
|
|
||||||
.xubox_msgtype8{background-position:-91px -6px;}
|
|
||||||
.xubox_msgtype9{background-position:-129px -6px;}
|
|
||||||
.xubox_msgtype10{background-position:-163px -6px;}
|
|
||||||
.xubox_msgtype11{background-position:-206px -6px;}
|
|
||||||
.xubox_msgtype12{background-position:-206px -44px;}
|
|
||||||
.xubox_msgtype13{background-position:-206px -81px;}
|
|
||||||
.xubox_msgtype14{background-position:-206px -122px;}
|
|
||||||
.xubox_msgtype15{background-position:-206px -157px;}
|
|
||||||
.xubox_loading_0{width:60px; height:24px; background:url(default/xubox_loading0.gif) no-repeat;}
|
|
||||||
.xubox_loading_1{width:37px; height:37px; background:url(default/xubox_loading1.gif) no-repeat;}
|
|
||||||
.xubox_loading_2, .xubox_msgtype16{width:32px; height:32px; background:url(default/xubox_loading2.gif) no-repeat;}
|
|
||||||
.xubox_loading_3{width:126px; height:22px; background:url(default/xubox_loading3.gif) no-repeat;}
|
|
||||||
|
|
||||||
.xubox_setwin{position:absolute; right:10px; *right:0; top:10px; font-size:0;}
|
|
||||||
.xubox_setwin a{position:relative; display:inline-block; *display:inline; *zoom:1; vertical-align:top; width: 14px; height:14px; margin-left:10px; font-size:12px; _overflow:hidden;}
|
|
||||||
.xubox_setwin .xubox_min cite{position:absolute; width:14px; height:2px; left:0; top:50%; margin-top:-1px; background-color:#919191; cursor:pointer; _overflow:hidden;}
|
|
||||||
.xubox_setwin .xubox_min:hover cite{background-color:#2D93CA; }
|
|
||||||
.xubox_setwin .xubox_max{background-position:-6px -189px;}
|
|
||||||
.xubox_setwin .xubox_max:hover{background-position:-6px -206px;}
|
|
||||||
.xubox_setwin .xubox_maxmin{background-position:-29px -189px;}
|
|
||||||
.xubox_setwin .xubox_maxmin:hover{background-position:-29px -206px;}
|
|
||||||
.xubox_setwin .xubox_close0{ width:14px; height:14px; background-position: -31px -7px; cursor:pointer;}
|
|
||||||
.xubox_setwin .xubox_close0:hover{background-position:-51px -7px;}
|
|
||||||
.xubox_setwin .xubox_close1{position:absolute; right:-28px; top:-28px; width:30px; height:30px; margin-left:0; background-position:-60px -195px; *right:-18px; _right:-15px; _top:-23px; _width:14px; _height:14px; _background-position:-31px -7px;}
|
|
||||||
.xubox_setwin .xubox_close1:hover{ background-position:-91px -195px; _background-position:-51px -7px;}
|
|
||||||
|
|
||||||
.xubox_title{width:100%; height:35px; line-height:35px; border-bottom:1px solid #D5D5D5; background:url(default/xubox_title0.png) #EBEBEB repeat-x; font-size:14px; color:#333;}
|
|
||||||
.xubox_title em{height:20px; line-height:20px; width:60%; top:7px; left:10px; font-style:normal; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;}
|
|
||||||
|
|
||||||
.xubox_botton a{position:absolute; bottom:10px; left:50%; background:url(default/xubox_ico0.png) repeat; text-decoration:none; color:#FFF; font-size:14px; text-align:center; font-weight:bold; overflow:hidden; }
|
|
||||||
.xubox_botton a:hover{text-decoration:none; color:#FFF; }
|
|
||||||
.xubox_botton .xubox_botton1{ width:79px; height:32px; line-height:32px; margin-left:-39px; background-position:-6px -34px;}
|
|
||||||
.xubox_botton1:hover{background-position:-6px -72px;}
|
|
||||||
.xubox_botton .xubox_botton2{margin-left:-76px; width:71px; height:29px; line-height:29px; background-position:-5px -114px;}
|
|
||||||
.xubox_botton2:hover{ background-position:-5px -146px;}
|
|
||||||
.xubox_botton .xubox_botton3{width:71px; height:29px; line-height:29px; margin-left:10px; background-position:-81px -114px;}
|
|
||||||
.xubox_botton3:hover{background-position:-81px -146px;}
|
|
||||||
.xubox_tips{position:relative; line-height:20px; min-width: 12px; padding:3px 30px 3px 10px; font-size:12px; _float:left; border-radius:3px; box-shadow: 1px 1px 3px rgba(0,0,0,.3);}
|
|
||||||
.xubox_tips i.layerTipsG{ position:absolute; width:0; height:0; border-width:8px; border-color:transparent; border-style:dashed; *overflow:hidden;}
|
|
||||||
.xubox_tips i.layerTipsT, .xubox_tips i.layerTipsB{left:5px; border-right-style:solid;}
|
|
||||||
.xubox_tips i.layerTipsT{bottom:-8px;}
|
|
||||||
.xubox_tips i.layerTipsB{top:-8px;}
|
|
||||||
.xubox_tips i.layerTipsR, .xubox_tips i.layerTipsL{top:1px; border-bottom-style:solid;}
|
|
||||||
.xubox_tips i.layerTipsR{left:-8px;}
|
|
||||||
.xubox_tips i.layerTipsL{right:-8px;}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
>>>>>>> beta
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
<<<<<<< HEAD
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
@Name: layer拓展样式
|
@Name: layer拓展样式
|
||||||
@ -44,50 +43,3 @@
|
|||||||
.xubox_imgtit em{padding-left:10px;}
|
.xubox_imgtit em{padding-left:10px;}
|
||||||
|
|
||||||
|
|
||||||
=======
|
|
||||||
/**
|
|
||||||
|
|
||||||
@Name: layer拓展样式
|
|
||||||
@Date: 2012.12.13
|
|
||||||
@Author: 贤心
|
|
||||||
@blog: sentsin.com
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
.xubox_iconext{background:url(default/icon_ext.png) no-repeat;}
|
|
||||||
|
|
||||||
/* prompt模式 */
|
|
||||||
.xubox_layer .xubox_form{width:240px; height:30px; line-height:30px; padding: 0 5px; border: 1px solid #ccc; background: url(default/textbg.png) #fff repeat-x; color:#333;}
|
|
||||||
.xubox_layer .xubox_formArea{width:300px; height:100px; line-height:20px;}
|
|
||||||
|
|
||||||
/* tab模式 */
|
|
||||||
.xubox_layer .xubox_tab{position:relative; background-color:#fff; box-shadow:1px 1px 50px rgba(0,0,0,.4)}
|
|
||||||
.xubox_layer .xubox_tabmove{position:absolute; width:600px; height:30px; top:0; left:0;}
|
|
||||||
.xubox_layer .xubox_tabtit{ display:block; height:34px; border-bottom:1px solid #ccc; background-color:#eee;}
|
|
||||||
.xubox_layer .xubox_tabtit span{position:relative; float:left; width:120px; height:34px; line-height:34px; text-align:center; cursor:default;}
|
|
||||||
.xubox_layer .xubox_tabtit span.xubox_tabnow{left:-1px; _top:1px; height:35px; border-left:1px solid #ccc; border-right:1px solid #ccc; background-color:#fff; z-index:10;}
|
|
||||||
.xubox_layer .xubox_tab_main{line-height:24px; clear:both;}
|
|
||||||
.xubox_layer .xubox_tab_main .xubox_tabli{display:none;}
|
|
||||||
.xubox_layer .xubox_tab_main .xubox_tabli.xubox_tab_layer{display:block;}
|
|
||||||
.xubox_layer .xubox_tabclose{position:absolute; right:10px; top:5px; cursor:pointer;}
|
|
||||||
|
|
||||||
/* photo模式 */
|
|
||||||
.xubox_bigimg, .xubox_intro{height:300px}
|
|
||||||
.xubox_bigimg{position:relative; display:block; width:600px; text-align:center; background:url(default/xubox_loading1.gif) center center no-repeat #000; overflow:hidden; }
|
|
||||||
.xubox_bigimg img{position:relative; display:inline-block; visibility: hidden;}
|
|
||||||
.xubox_intro{position:absolute; right:-315px; top:0; width:300px; background-color:#fff; overflow-x:hidden; overflow-y:auto;}
|
|
||||||
.xubox_imgsee{display:none;}
|
|
||||||
.xubox_prev, .xubox_next{position:absolute; top:50%; width:27px; _width:44px; height:44px; margin-top:-22px; outline:none;blr:expression(this.onFocus=this.blur());}
|
|
||||||
.xubox_prev{left:10px; background-position:-5px -5px; _background-position:-70px -5px;}
|
|
||||||
.xubox_prev:hover{background-position:-33px -5px; _background-position:-120px -5px;}
|
|
||||||
.xubox_next{right:10px; _right:8px; background-position:-5px -50px; _background-position:-70px -50px;}
|
|
||||||
.xubox_next:hover{background-position:-33px -50px; _background-position:-120px -50px;}
|
|
||||||
.xubox_imgbar{position:absolute; left:0; bottom:0; width:100%; height:32px; line-height:32px; background-color:rgba(0,0,0,.8); background-color:#000\9; filter:Alpha(opacity=80); color:#fff; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; font-size:0;}
|
|
||||||
.xubox_imgtit{/*position:absolute; left:20px;*/}
|
|
||||||
.xubox_imgtit *{display:inline-block; *display:inline; *zoom:1; vertical-align:top; font-size:12px;}
|
|
||||||
.xubox_imgtit a{max-width:65%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; color:#fff;}
|
|
||||||
.xubox_imgtit a:hover{color:#fff; text-decoration:underline;}
|
|
||||||
.xubox_imgtit em{padding-left:10px;}
|
|
||||||
|
|
||||||
|
|
||||||
>>>>>>> beta
|
|
||||||
|
@ -128,17 +128,6 @@
|
|||||||
var div_username = ' 用户名: '+'<span class="text-info">'+username+'' + '</span>';
|
var div_username = ' 用户名: '+'<span class="text-info">'+username+'' + '</span>';
|
||||||
var div_ip = ' 主机: '+'<span class="text-info">' + ip + '</span>';
|
var div_ip = ' 主机: '+'<span class="text-info">' + ip + '</span>';
|
||||||
var div_time = ' 开始时间: ' + '<span class="text-info">'+start_time +'</span>' + ' 结束时间: ' +'<span class="text-info">' + end_time + '</span'
|
var div_time = ' 开始时间: ' + '<span class="text-info">'+start_time +'</span>' + ' 结束时间: ' +'<span class="text-info">' + end_time + '</span'
|
||||||
<<<<<<< HEAD
|
|
||||||
var title = 'JumpServer命令统计 '+ div_username + div_ip + div_time
|
|
||||||
$.ajax({url:url,success:function(data){
|
|
||||||
BootstrapDialog.show({title: title, message:data});
|
|
||||||
}});
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
globalConfig = {
|
|
||||||
SOCKET_HOST: "{{ web_socket_host }}"
|
|
||||||
}
|
|
||||||
=======
|
|
||||||
var title = 'JumpServer命令统计 '+ div_username + div_ip + div_time;
|
var title = 'JumpServer命令统计 '+ div_username + div_ip + div_time;
|
||||||
$.ajax({url:url,success:function(data){
|
$.ajax({url:url,success:function(data){
|
||||||
var tag = $('<div style="height: 500px;overflow: auto;background-color: rgba(0, 0, 0, 0);"></div>').html(data.replace(/\n/g,"<br />"));
|
var tag = $('<div style="height: 500px;overflow: auto;background-color: rgba(0, 0, 0, 0);"></div>').html(data.replace(/\n/g,"<br />"));
|
||||||
@ -149,7 +138,6 @@
|
|||||||
globalConfig = {
|
globalConfig = {
|
||||||
SOCKET_HOST: "{{ web_socket_host }}"
|
SOCKET_HOST: "{{ web_socket_host }}"
|
||||||
};
|
};
|
||||||
>>>>>>> beta
|
|
||||||
|
|
||||||
function log_search(){
|
function log_search(){
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
@ -136,19 +136,11 @@
|
|||||||
BootstrapDialog.show({message:function(){
|
BootstrapDialog.show({message:function(){
|
||||||
var option, exsit_message;
|
var option, exsit_message;
|
||||||
var escapeString = function (html){
|
var escapeString = function (html){
|
||||||
<<<<<<< HEAD
|
|
||||||
var elem = document.createElement('div')
|
|
||||||
var txt = document.createTextNode(html)
|
|
||||||
elem.appendChild(txt)
|
|
||||||
return elem.innerHTML;
|
|
||||||
}
|
|
||||||
=======
|
|
||||||
var elem = document.createElement('div');
|
var elem = document.createElement('div');
|
||||||
var txt = document.createTextNode(html);
|
var txt = document.createTextNode(html);
|
||||||
elem.appendChild(txt);
|
elem.appendChild(txt);
|
||||||
return elem.innerHTML;
|
return elem.innerHTML;
|
||||||
};
|
};
|
||||||
>>>>>>> beta
|
|
||||||
var tag = $('<div id="log" style="height: 500px;overflow: auto;background-color: rgba(0, 0, 0, 0);"></div>');
|
var tag = $('<div id="log" style="height: 500px;overflow: auto;background-color: rgba(0, 0, 0, 0);"></div>');
|
||||||
//告诉服务器端有用户登录
|
//告诉服务器端有用户登录
|
||||||
socket.emit('login', {userid:message.id, filename:message.filename});
|
socket.emit('login', {userid:message.id, filename:message.filename});
|
||||||
|
Loading…
Reference in New Issue
Block a user