From bcc57743658922ece6f22b2cd8689d1632de74f6 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Apr 2015 13:52:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=88=90=E5=8A=9F=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- connect.py | 14 +- jumpserver/api.py | 13 +- jumpserver/ssh.py | 396 ---------------------------------- jumpserver/views.py | 4 +- templates/login.html | 14 +- templates/paginator_new..html | 84 -------- templates/success.html | 39 ++++ 7 files changed, 57 insertions(+), 507 deletions(-) delete mode 100644 jumpserver/ssh.py delete mode 100644 templates/paginator_new..html create mode 100644 templates/success.html diff --git a/connect.py b/connect.py index a91507b14..64215601d 100755 --- a/connect.py +++ b/connect.py @@ -202,13 +202,13 @@ def verify_connect(username, part_ip): 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[32mG/g+gid\033[0m To Print The Server Group Hosts You Available. - 5) Type \033[32mE/e\033[0m To Execute Command On Several Servers. - 6) Type \033[32mQ/q\033[0m To Quit. - """ + 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[32mG/g(1-N)\033[0m To Print The Server Group Hosts You Available. + 5) Type \033[32mE/e\033[0m To Execute Command On Several Servers. + 6) Type \033[32mQ/q\033[0m To Quit. + """ print textwrap.dedent(msg) diff --git a/jumpserver/api.py b/jumpserver/api.py index db2b93e3b..5b75219f1 100644 --- a/jumpserver/api.py +++ b/jumpserver/api.py @@ -1,4 +1,5 @@ -#coding: utf-8 +# coding: utf-8 + from django.http import HttpResponseRedirect import json @@ -14,6 +15,7 @@ import datetime import subprocess from django.core.paginator import Paginator, EmptyPage, InvalidPage from django.http import HttpResponse, Http404 +from django.shortcuts import render_to_response from juser.models import User, UserGroup, DEPT from jasset.models import Asset, BisGroup, IDC from jlog.models import Log @@ -470,11 +472,6 @@ def verify(request, user_group=None, user=None, asset_group=None, asset=None, ed return True -def get_dept_asset(request): - dept_id = get_user_dept(request) - dept_asset = DEPT.objects.get(id=dept_id).asset_set.all() - - def bash(cmd): """执行bash命令""" return subprocess.call(cmd, shell=True) @@ -486,3 +483,7 @@ def is_dir(dir_name, username='root', mode=0755): bash("chown %s:%s '%s'" % (username, username, dir_name)) os.chmod(dir_name, mode) + +def success(request, msg): + return render_to_response('success.html', locals()) + diff --git a/jumpserver/ssh.py b/jumpserver/ssh.py deleted file mode 100644 index 917d0a436..000000000 --- a/jumpserver/ssh.py +++ /dev/null @@ -1,396 +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() - -CURRENT_DIR = os.path.abspath(os.path.dirname(__file__)) -BASE_DIR = os.path.dirname(CURRENT_DIR) -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() diff --git a/jumpserver/views.py b/jumpserver/views.py index a214f8d2c..eb9796bfa 100644 --- a/jumpserver/views.py +++ b/jumpserver/views.py @@ -240,9 +240,7 @@ def install(request): User(id=5000, username="admin", password=md5_crypt('admin'), name='admin', email='admin@jumpserver.org', role='SU', is_active=True, dept=dept).save() - User(id=5001, username="group_admin", password=md5_crypt('group_admin'), - name='group_admin', email='group_admin@jumpserver.org', role='DA', is_active=True, dept=dept2).save() - return HttpResponse('Ok') + return success(request, u'安装成功') def download(request): diff --git a/templates/login.html b/templates/login.html index 3eb83c4a3..00b070ddd 100644 --- a/templates/login.html +++ b/templates/login.html @@ -2,32 +2,24 @@ - - - JumpServer | Login + 登录 | JumpServer - - - -
-

-
{% if error %} -
{{ error }}
+
{{ error }}
{% endif %}

Welcome to JumpServer

@@ -39,7 +31,7 @@
- Forgot password? + Forgot password? Contact Administrator.

Copyright Jumpserver.org Organization © 2014-2015

diff --git a/templates/paginator_new..html b/templates/paginator_new..html deleted file mode 100644 index 12a4ba9c5..000000000 --- a/templates/paginator_new..html +++ /dev/null @@ -1,84 +0,0 @@ -
-
-
    - {% if keyword %} - {% if contacts.has_previous %} - - {% else %} - - {% endif %} - - {% set href="" %} - {% if gid %} - {% set href=href+"&gid="+gid %} - {% endif %} - {% if did %} - {% set href=href+"&did="+did %} - {% endif %} - {% if keyword %} - {% set href=href+"&keyword"+keyword %} - {% endif %} - - {% ifequal show_first 1 %} -
  • 1...
  • - {% endifequal %} - {% for page in page_range %} - {% ifequal current_page page %} -
  • {{ page }}
  • - {% else %} -
  • {{ page }}
  • - {% endifequal %} - {% endfor %} - {% ifequal show_end 1 %} -
  • ...{{ p.num_pages }}
  • - {% endifequal %} - {% if contacts.has_next %} - - {% else %} - - {% endif %} - - {% else %} - {% if contacts.has_previous %} - - {% else %} - - {% endif %} - {% ifequal show_first 1 %} -
  • 1...
  • - {% endifequal %} - {% for page in page_range %} - {% ifequal current_page page %} -
  • {{ page }}
  • - {% else %} -
  • {{ page }}
  • - {% endifequal %} - {% endfor %} - {% ifequal show_end 1 %} -
  • ...{{ p.num_pages }}
  • - {% endifequal %} - {% if contacts.has_next %} - - {% else %} - - {% endif %} - {% endif %} -
-
-
diff --git a/templates/success.html b/templates/success.html new file mode 100644 index 000000000..7280e29a1 --- /dev/null +++ b/templates/success.html @@ -0,0 +1,39 @@ + + + + + + + + + Jumpserver | Success + + + + + + + + + + + + +
+

成功

+

{{ msg }}

+ +
+ The server success response the request. Congratulations.
+ You can go back to main page:
仪表盘 +
+
+ + + + + + + + +