Merge branch 'ssh_key'

Conflicts:
	connect.py
pull/6/head
root 2014-12-30 23:59:27 +08:00
commit b1e0a24184
3 changed files with 115 additions and 46 deletions

View File

@ -38,6 +38,8 @@ CURRENT_DIR = os.path.abspath('.')
CONF = ConfigParser() CONF = ConfigParser()
CONF.read(os.path.join(CURRENT_DIR, 'jumpserver.conf')) CONF.read(os.path.join(CURRENT_DIR, 'jumpserver.conf'))
LOG_DIR = os.path.join(CURRENT_DIR, 'logs') LOG_DIR = os.path.join(CURRENT_DIR, 'logs')
SSH_KEY_DIR = os.path.join(CURRENT_DIR, 'keys')
SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server')
KEY = CONF.get('web', 'key') KEY = CONF.get('web', 'key')
LOGIN_NAME = getpass.getuser() LOGIN_NAME = getpass.getuser()
#LOGIN_NAME = os.getlogin() #LOGIN_NAME = os.getlogin()
@ -61,6 +63,16 @@ def alert_print(string):
sys.exit() sys.exit()
class ServerError(Exception):
def __init__(self, error):
self.error = error
def __str__(self):
return self.error
__repr__ = __str__
class PyCrypt(object): class PyCrypt(object):
"""It's used to encrypt and decrypt password.""" """It's used to encrypt and decrypt password."""
@ -119,21 +131,25 @@ def posix_shell(chan, username, host):
today_connect_log_dir = os.path.join(connect_log_dir, today) today_connect_log_dir = os.path.join(connect_log_dir, today)
log_filename = '%s_%s_%s.log' % (username, host, date_now) log_filename = '%s_%s_%s.log' % (username, host, date_now)
log_file_path = os.path.join(today_connect_log_dir, log_filename) log_file_path = os.path.join(today_connect_log_dir, log_filename)
user = User.objects.get(username=username)
asset = Asset.objects.get(ip=host)
pid = os.getpid()
try:
user = User.objects.get(username=username)
asset = Asset.objects.get(ip=host)
except ObjectDoesNotExist:
raise ServerError('user %s or asset %s does not exist.' % (username, host))
pid = os.getpid()
if not os.path.isdir(today_connect_log_dir): if not os.path.isdir(today_connect_log_dir):
try: try:
os.makedirs(today_connect_log_dir) os.makedirs(today_connect_log_dir)
os.chmod(today_connect_log_dir, 0777) os.chmod(today_connect_log_dir, 0777)
except OSError: except OSError:
alert_print('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, connect_log_dir)) raise ServerError('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, connect_log_dir))
try: try:
log_file = open(log_file_path, 'a') log_file = open(log_file_path, 'a')
except IOError: except IOError:
alert_print('Create logfile failed, Please modify %s permission.' % today_connect_log_dir) raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir)
log = Log(user=user, asset=asset, log_path=log_file_path, start_time=timestamp_start, pid=pid) log = Log(user=user, asset=asset, log_path=log_file_path, start_time=timestamp_start, pid=pid)
log.save() log.save()
@ -182,7 +198,7 @@ def get_user_host(username):
try: try:
user = User.objects.get(username=username) user = User.objects.get(username=username)
except ObjectDoesNotExist: except ObjectDoesNotExist:
return {'Error': ['0', "Username \033[1;31m%s\033[0m doesn't exist on Jumpserver." % username]}, ['Error'] raise ServerError("Username \033[1;31m%s\033[0m doesn't exist on Jumpserver." % username)
else: else:
perm_all = user.permission_set.all() perm_all = user.permission_set.all()
for perm in perm_all: for perm in perm_all:
@ -199,27 +215,64 @@ def get_connect_item(username, ip):
asset = Asset.objects.get(ip=ip) asset = Asset.objects.get(ip=ip)
port = asset.port port = asset.port
except ObjectDoesNotExist: except ObjectDoesNotExist:
red_print("Host %s isn't exist." % ip) raise ServerError("Host %s does not exist." % ip)
return
if asset.ldap_enable: if not asset.is_active:
raise ServerError('Host %s is not active.' % ip)
try:
user = User.objects.get(username=username) user = User.objects.get(username=username)
ldap_pwd = cryptor.decrypt(user.ldap_pwd) except ObjectDoesNotExist:
return username, ldap_pwd, ip, port raise ServerError('User %s does not exist.' % username)
else:
perms = asset.permission_set.all() if not user.is_active:
perm = perms[0] raise ServerError('User %s is not active.' % username)
if asset.login_type == 'L':
try:
ldap_pwd = cryptor.decrypt(user.ldap_pwd)
except TypeError:
raise ServerError('Decrypt %s ldap password error.' % username)
return 'L', username, ldap_pwd, ip, port
elif asset.login_type == 'S':
try:
ssh_key_pwd = cryptor.decrypt(user.ssh_key_pwd2)
except TypeError:
raise ServerError('Decrypt %s ssh key password error.' % username)
return 'S', username, ssh_key_pwd, ip, port
elif asset.login_type == 'P':
try:
ssh_pwd = cryptor.decrypt(user.ssh_pwd)
except TypeError:
raise ServerError('Decrypt %s ssh password error.' % username)
return 'P', username, ssh_pwd, ip, port
elif asset.login_type == 'M':
perms = asset.permission_set.filter(user=user)
try:
perm = perms[0]
except IndexError:
raise ServerError('Permission %s to %s does not exist.' % (username, ip))
if perm.role == 'SU': if perm.role == 'SU':
username_super = asset.username_super
try: try:
return asset.username_super, cryptor.decrypt(asset.password_super), ip, port password_super = cryptor.decrypt(asset.password_super)
except TypeError: except TypeError:
red_print('User %s password error to decrypt.' % username) raise ServerError('Decrypt %s map to %s password in %s error.' % (username, username_super, ip))
return 'M', username_super, password_super, ip, port
elif perm.role == 'CU':
username_common = asset.username_common
try:
password_common = asset.password_common
except TypeError:
raise ServerError('Decrypt %s map to %s password in %s error.' % (username, username_common, ip))
return 'CU', username_common, password_common, ip, port
else: else:
try: raise ServerError('Perm in %s for %s map role is not in ["SU", "CU"].' % (ip, username))
return asset.username_common, cryptor.decrypt(asset.password_common), ip, port else:
except TypeError: raise ServerError('Login type is not in ["L", "S", "P", "M"]')
red_print('User %s password error to decrypt.' % username)
def verify_connect(username, part_ip): def verify_connect(username, part_ip):
@ -235,12 +288,8 @@ def verify_connect(username, part_ip):
elif len(ip_matched) < 1: elif len(ip_matched) < 1:
red_print('No Permission or No host.') red_print('No Permission or No host.')
else: else:
try: login_type, username, password, host, port = get_connect_item(username, ip_matched[0])
username, password, host, port = get_connect_item(username, ip_matched[0]) connect(username, password, host, port, LOGIN_NAME, login_type=login_type)
except (ObjectDoesNotExist, IndexError):
red_print('Get get_connect_item Error.')
else:
connect(username, password, host, port, LOGIN_NAME)
def print_prompt(): def print_prompt():
@ -259,30 +308,38 @@ def print_user_host(username):
print '[%s] %s -- %s' % (hosts_attr[ip][0], ip, hosts_attr[ip][1]) print '[%s] %s -- %s' % (hosts_attr[ip][0], ip, hosts_attr[ip][1])
def connect(username, password, host, port, login_name): def connect(username, password, host, port, login_name, login_type='L'):
""" """
Connect server. Connect server.
""" """
ps1 = "PS1='[\u@%s \W]\$ '\n" % host ps1 = "PS1='[\u@%s \W]\$ '\n" % host
login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % host login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % host
user_key_file = os.path.join(SERVER_KEY_DIR, username)
if os.path.isfile(user_key_file):
key_filename = user_key_file
else:
key_filename = None
# Make a ssh connection # Make a ssh connection
ssh = paramiko.SSHClient() ssh = paramiko.SSHClient()
ssh.load_system_host_keys() ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try: try:
print port, username, password if login_type == 'L':
ssh.connect(host, port=port, username=username, password=password, compress=True) ssh.connect(host, port=port, username=username, password=password, key_filename=key_filename, compress=True)
except paramiko.ssh_exception.AuthenticationException: else:
alert_print('Host Password Error, Please Correct it.') 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: except socket.error:
alert_print('Connect SSH Socket Port Error, Please Correct it.') raise ServerError('Connect SSH Socket Port Error, Please Correct it.')
# Make a channel and set windows size # Make a channel and set windows size
global channel global channel
channel = ssh.invoke_shell()
win_size = get_win_size() win_size = get_win_size()
channel.resize_pty(height=win_size[0], width=win_size[1]) channel = ssh.invoke_shell(height=win_size[0], width=win_size[1])
#channel.resize_pty(height=win_size[0], width=win_size[1])
try: try:
signal.signal(signal.SIGWINCH, set_win_size) signal.signal(signal.SIGWINCH, set_win_size)
except: except:
@ -379,6 +436,9 @@ if __name__ == '__main__':
elif option in ['Q', 'q']: elif option in ['Q', 'q']:
sys.exit() sys.exit()
else: else:
verify_connect(LOGIN_NAME, option) try:
verify_connect(LOGIN_NAME, option)
except ServerError, e:
red_print(e)
except IndexError: except IndexError:
pass pass

View File

@ -3,24 +3,31 @@ from juser.models import Group, User
class IDC(models.Model): class IDC(models.Model):
name = models.CharField(max_length=80, unique=True) name = models.CharField(max_length=40, unique=True)
comment = models.CharField(max_length=100, blank=True, null=True) comment = models.CharField(max_length=80, blank=True, null=True)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Asset(models.Model): class Asset(models.Model):
LOGIN_TYPE_CHOICES = (
('L', 'LDAP'),
('S', 'SSH_KEY'),
('P', 'PASSWORD'),
('M', 'MAP'),
)
ip = models.IPAddressField(unique=True) ip = models.IPAddressField(unique=True)
port = models.SmallIntegerField(max_length=40) port = models.SmallIntegerField(max_length=5)
idc = models.ForeignKey(IDC) idc = models.ForeignKey(IDC)
group = models.ManyToManyField(Group) group = models.ManyToManyField(Group)
ldap_enable = models.BooleanField(default=True) login_type = models.CharField(max_length=1, choices=LOGIN_TYPE_CHOICES, default='L')
username_common = models.CharField(max_length=80, blank=True, null=True) username_common = models.CharField(max_length=20, blank=True, null=True)
password_common = models.CharField(max_length=160, blank=True, null=True) password_common = models.CharField(max_length=80, blank=True, null=True)
username_super = models.CharField(max_length=80, blank=True, null=True) username_super = models.CharField(max_length=20, blank=True, null=True)
password_super = models.CharField(max_length=160, blank=True, null=True) password_super = models.CharField(max_length=80, blank=True, null=True)
date_added = models.IntegerField(max_length=80) date_added = models.IntegerField(max_length=12)
is_active = models.BooleanField(default=True)
comment = models.CharField(max_length=100, blank=True, null=True) comment = models.CharField(max_length=100, blank=True, null=True)
def __unicode__(self): def __unicode__(self):

View File

@ -22,7 +22,9 @@ class User(models.Model):
role = models.CharField(max_length=2, choices=USER_ROLE_CHOICES, default='CU') role = models.CharField(max_length=2, choices=USER_ROLE_CHOICES, default='CU')
group = models.ManyToManyField(Group) group = models.ManyToManyField(Group)
ldap_pwd = models.CharField(max_length=100) ldap_pwd = models.CharField(max_length=100)
ssh_key_pwd = models.CharField(max_length=100) ssh_key_pwd1 = models.CharField(max_length=100)
ssh_key_pwd2 = models.CharField(max_length=100)
ssh_pwd = models.CharField(max_length=100)
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
last_login = models.IntegerField(default=0) last_login = models.IntegerField(default=0)
date_joined = models.IntegerField() date_joined = models.IntegerField()