mirror of https://github.com/jumpserver/jumpserver
完成登陆,批量执行命令流
parent
877383679c
commit
93481a98db
72
connect.py
72
connect.py
|
@ -19,8 +19,9 @@ import struct, fcntl, signal, socket, select
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
||||||
if django.get_version() != '1.6':
|
if django.get_version() != '1.6':
|
||||||
django.setup()
|
django.setup()
|
||||||
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir
|
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir, get_asset_info, get_role
|
||||||
from jumpserver.api import logger, Log, TtyLog
|
from jumpserver.api import logger, Log, TtyLog, get_role_key
|
||||||
|
from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm
|
||||||
from jumpserver.settings import LOG_DIR
|
from jumpserver.settings import LOG_DIR
|
||||||
from jperm.ansible_api import Command
|
from jperm.ansible_api import Command
|
||||||
|
|
||||||
|
@ -73,15 +74,15 @@ class Tty(object):
|
||||||
A virtual tty class
|
A virtual tty class
|
||||||
一个虚拟终端类,实现连接ssh和记录日志,基类
|
一个虚拟终端类,实现连接ssh和记录日志,基类
|
||||||
"""
|
"""
|
||||||
def __init__(self, username, asset_name):
|
def __init__(self, user, asset, role):
|
||||||
self.username = username
|
self.username = user.username
|
||||||
self.asset_name = asset_name
|
self.asset_name = asset.hostname
|
||||||
self.ip = None
|
self.ip = None
|
||||||
self.port = 22
|
self.port = 22
|
||||||
self.channel = None
|
self.channel = None
|
||||||
#self.asset = get_object(Asset, name=asset_name)
|
self.asset = asset
|
||||||
#self.user = get_object(User, username=username)
|
self.user = user
|
||||||
self.role = None
|
self.role = role
|
||||||
self.ssh = None
|
self.ssh = None
|
||||||
self.connect_info = None
|
self.connect_info = None
|
||||||
self.login_type = 'ssh'
|
self.login_type = 'ssh'
|
||||||
|
@ -287,7 +288,10 @@ class Tty(object):
|
||||||
# 2. get 映射用户
|
# 2. get 映射用户
|
||||||
# 3. get 映射用户的账号,密码或者key
|
# 3. get 映射用户的账号,密码或者key
|
||||||
# self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_key': ''}
|
# self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_key': ''}
|
||||||
self.connect_info = {'user': 'a', 'asset': 'b', 'ip': '127.0.0.1', 'port': 22, 'role_name': 'root', 'role_pass': 'redhat', 'role_key': ''}
|
asset_info = get_asset_info(self.asset)
|
||||||
|
self.connect_info = {'user': self.user, 'asset': self.asset, 'ip': asset_info.get('ip'),
|
||||||
|
'port': int(asset_info.get('port')), 'role_name': self.role.name,
|
||||||
|
'role_pass': self.role.password, 'role_key': self.role.key_path}
|
||||||
return self.connect_info
|
return self.connect_info
|
||||||
|
|
||||||
def get_connection(self):
|
def get_connection(self):
|
||||||
|
@ -301,7 +305,7 @@ class Tty(object):
|
||||||
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:
|
||||||
role_key = connect_info.get('role_key')
|
role_key = get_role_key(self.user, self.role)
|
||||||
if role_key and os.path.isfile(role_key):
|
if role_key and os.path.isfile(role_key):
|
||||||
try:
|
try:
|
||||||
ssh.connect(connect_info.get('ip'),
|
ssh.connect(connect_info.get('ip'),
|
||||||
|
@ -469,6 +473,7 @@ class Nav(object):
|
||||||
def __init__(self, user):
|
def __init__(self, user):
|
||||||
self.user = user
|
self.user = user
|
||||||
self.search_result = {}
|
self.search_result = {}
|
||||||
|
self.user_perm = {}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def print_nav():
|
def print_nav():
|
||||||
|
@ -499,7 +504,9 @@ class Nav(object):
|
||||||
|
|
||||||
def search(self, str_r=''):
|
def search(self, str_r=''):
|
||||||
gid_pattern = re.compile(r'^g\d+$')
|
gid_pattern = re.compile(r'^g\d+$')
|
||||||
user_asset_all = list(Asset.objects.all())
|
if not self.user_perm:
|
||||||
|
self.user_perm = get_group_user_perm(self.user)
|
||||||
|
user_asset_all = self.user_perm.get('asset').keys()
|
||||||
user_asset_search = []
|
user_asset_search = []
|
||||||
if str_r:
|
if str_r:
|
||||||
if gid_pattern.match(str_r):
|
if gid_pattern.match(str_r):
|
||||||
|
@ -512,13 +519,15 @@ class Nav(object):
|
||||||
user_asset_search = user_asset_all
|
user_asset_search = user_asset_all
|
||||||
|
|
||||||
self.search_result = dict(zip(range(len(user_asset_search)), user_asset_search))
|
self.search_result = dict(zip(range(len(user_asset_search)), user_asset_search))
|
||||||
|
print '\033[32m[%-3s] %-15s %-15s %-5s %-10s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment')
|
||||||
print '\033[32m[%-3s] %-15s %-15s %-5s %-5s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment')
|
|
||||||
for index, asset in self.search_result.items():
|
for index, asset in self.search_result.items():
|
||||||
|
asset_info = get_asset_info(asset)
|
||||||
|
role = [str(role.name) for role in self.user_perm.get('asset').get(asset).get('role')]
|
||||||
if asset.comment:
|
if asset.comment:
|
||||||
print '[%-3s] %-15s %-15s %-5s %-5s %s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role', asset.comment)
|
print '[%-3s] %-15s %-15s %-5s %-10s %s' % (index, asset.hostname, asset.ip, asset_info.get('port'),
|
||||||
|
role, asset.comment)
|
||||||
else:
|
else:
|
||||||
print '[%-3s] %-15s %-15s %-5s %-5s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role')
|
print '[%-3s] %-15s %-15s %-5s %-10s' % (index, asset.hostname, asset.ip, asset_info.get('port'), role)
|
||||||
print
|
print
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -542,13 +551,11 @@ class Nav(object):
|
||||||
if pattern == 'q':
|
if pattern == 'q':
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
res = {
|
if not self.user_perm:
|
||||||
"group1": {
|
self.user_perm = get_group_user_perm(self.user)
|
||||||
"hosts": [{"hostname": "127.0.0.1", "port": "22", "username": "lastimac", "password": "redhat"}, {"hostname": "192.168.244.129", "port": "22", "username": "root", "password": "redhat"}, {"hostname": "j", "port": "22", "username": "root", "password": "redhat"}],
|
res = gen_resource(self.user, perm=self.user_perm)
|
||||||
"vars": {"var1": 'a', "var2": 'a'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cmd = Command(res)
|
cmd = Command(res)
|
||||||
|
logger.debug(res)
|
||||||
for inv in cmd.inventory.get_hosts(pattern=pattern):
|
for inv in cmd.inventory.get_hosts(pattern=pattern):
|
||||||
print inv.name
|
print inv.name
|
||||||
confirm_host = raw_input("\033[1;32mIs that [y/n]>:\033[0m ").strip()
|
confirm_host = raw_input("\033[1;32mIs that [y/n]>:\033[0m ").strip()
|
||||||
|
@ -617,7 +624,28 @@ def main():
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
asset = nav.search_result[int(option)]
|
asset = nav.search_result[int(option)]
|
||||||
ssh_tty = SshTty('a', 'b')
|
roles = get_role(login_user, asset)
|
||||||
|
if len(roles) > 1:
|
||||||
|
role_check = dict(zip(range(len(roles)), roles))
|
||||||
|
print role_check
|
||||||
|
for index, role in role_check.items():
|
||||||
|
print "[%s] %s" % (index, role.name)
|
||||||
|
print "输入角色ID, q退出"
|
||||||
|
try:
|
||||||
|
role_index = raw_input("\033[1;32mID>:\033[0m ").strip()
|
||||||
|
if role_index == 'q':
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
role = role_check[int(role_index)]
|
||||||
|
except IndexError:
|
||||||
|
color_print('请输入正确ID', 'red')
|
||||||
|
continue
|
||||||
|
elif len(roles) == 1:
|
||||||
|
role = roles[0]
|
||||||
|
else:
|
||||||
|
color_print('没有映射用户', 'red')
|
||||||
|
continue
|
||||||
|
ssh_tty = SshTty(login_user, asset, role)
|
||||||
ssh_tty.connect()
|
ssh_tty.connect()
|
||||||
except (KeyError, ValueError):
|
except (KeyError, ValueError):
|
||||||
color_print('请输入正确ID', 'red')
|
color_print('请输入正确ID', 'red')
|
||||||
|
|
|
@ -404,7 +404,7 @@ class Tasks(Command):
|
||||||
|
|
||||||
result[key] = {
|
result[key] = {
|
||||||
"all_ip": setup.get("ansible_all_ipv4_addresses"),
|
"all_ip": setup.get("ansible_all_ipv4_addresses"),
|
||||||
"hostname" : setup.get("ansible_hostname" ),
|
"hostname" : setup.get("ansible_hostname"),
|
||||||
"default_ip": setup.get("ansible_default_ipv4").get("address"),
|
"default_ip": setup.get("ansible_default_ipv4").get("address"),
|
||||||
"default_mac": setup.get("ansible_default_ipv4").get("macaddress"),
|
"default_mac": setup.get("ansible_default_ipv4").get("macaddress"),
|
||||||
"product_name": setup.get("ansible_product_name"),
|
"product_name": setup.get("ansible_product_name"),
|
||||||
|
|
|
@ -132,37 +132,30 @@ def get_group_asset_perm(ob):
|
||||||
return perm
|
return perm
|
||||||
|
|
||||||
|
|
||||||
def gen_resource(ob):
|
def gen_resource(ob, perm=None):
|
||||||
"""
|
"""
|
||||||
ob为用户或资产列表或资产queryset
|
ob为用户或资产列表或资产queryset
|
||||||
生成MyInventory需要的 resource文件
|
生成MyInventory需要的 resource文件
|
||||||
"""
|
"""
|
||||||
res = []
|
res = []
|
||||||
if isinstance(ob, User):
|
if isinstance(ob, User):
|
||||||
perm = get_group_user_perm(ob)
|
if not perm:
|
||||||
|
perm = get_group_user_perm(ob)
|
||||||
|
|
||||||
for asset, asset_info in perm.get('asset').items():
|
for asset, asset_info in perm.get('asset').items():
|
||||||
info = {'hostname': asset.hostname, 'ip': asset.ip, 'port': asset.port}
|
asset_info = get_asset_info(asset)
|
||||||
|
info = {'hostname': asset.hostname, 'ip': asset.ip, 'port': asset_info.get('port', 22)}
|
||||||
try:
|
try:
|
||||||
role = sorted(list(asset_info.get('role')))[0]
|
role = sorted(list(perm.get('asset').get(asset).get('role')))[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
continue
|
continue
|
||||||
info['username'] = role.name
|
info['username'] = role.name
|
||||||
info['password'] = role.password
|
info['password'] = role.password
|
||||||
info['key_path'] = role.key_path
|
info['ssh_key'] = get_role_key(ob, role)
|
||||||
res.append(info)
|
res.append(info)
|
||||||
elif isinstance(ob, (list, QuerySet)):
|
elif isinstance(ob, (list, QuerySet)):
|
||||||
default = get_object(Setting, name='default')
|
|
||||||
for asset in ob:
|
for asset in ob:
|
||||||
info = {'hostname': asset.hostname, 'ip': asset.ip}
|
info = get_asset_info(asset)
|
||||||
if asset.use_default_auth:
|
|
||||||
if default:
|
|
||||||
info['port'] = default.default_port
|
|
||||||
info['username'] = default.default_user
|
|
||||||
info['password'] = default.default_password
|
|
||||||
info['ssh_key'] = default.default_pri_key_path
|
|
||||||
else:
|
|
||||||
info['port'] = asset.port
|
|
||||||
info['username'] = asset.username
|
|
||||||
res.append(info)
|
res.append(info)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ def gen_keys():
|
||||||
private_key = os.path.join(key_path_dir, 'id_rsa')
|
private_key = os.path.join(key_path_dir, 'id_rsa')
|
||||||
public_key = os.path.join(key_path_dir, 'id_rsa.pub')
|
public_key = os.path.join(key_path_dir, 'id_rsa.pub')
|
||||||
key.write_private_key_file(private_key)
|
key.write_private_key_file(private_key)
|
||||||
|
os.chmod(private_key, 0644)
|
||||||
|
|
||||||
with open(public_key, 'w') as content_file:
|
with open(public_key, 'w') as content_file:
|
||||||
for data in [key.get_name(),
|
for data in [key.get_name(),
|
||||||
|
|
|
@ -9,19 +9,21 @@ import hashlib
|
||||||
import datetime
|
import datetime
|
||||||
import random
|
import random
|
||||||
import subprocess
|
import subprocess
|
||||||
from settings import *
|
import json
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from settings import *
|
||||||
from django.core.paginator import Paginator, EmptyPage, InvalidPage
|
from django.core.paginator import Paginator, EmptyPage, InvalidPage
|
||||||
from django.http import HttpResponse, Http404
|
from django.http import HttpResponse, Http404
|
||||||
from django.template import RequestContext
|
from django.template import RequestContext
|
||||||
from juser.models import User, UserGroup
|
from juser.models import User, UserGroup
|
||||||
from jlog.models import Log, TtyLog
|
from jlog.models import Log, TtyLog
|
||||||
from jasset.models import Asset, AssetGroup
|
from jasset.models import Asset, AssetGroup
|
||||||
|
from jperm.models import PermRule, PermRole
|
||||||
|
from jumpserver.models import Setting
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
|
|
||||||
|
|
||||||
def set_log(level):
|
def set_log(level):
|
||||||
|
@ -45,11 +47,57 @@ def set_log(level):
|
||||||
return logger_f
|
return logger_f
|
||||||
|
|
||||||
|
|
||||||
def chown(path, user, group='', ):
|
def get_asset_info(asset):
|
||||||
|
default = get_object(Setting, name='default')
|
||||||
|
info = {'hostname': asset.hostname, 'ip': asset.ip}
|
||||||
|
if asset.use_default_auth:
|
||||||
|
if default:
|
||||||
|
info['port'] = default.default_port
|
||||||
|
info['username'] = default.default_user
|
||||||
|
info['password'] = CRYPTOR.decrypt(default.default_password)
|
||||||
|
info['ssh_key'] = default.default_pri_key_path
|
||||||
|
else:
|
||||||
|
info['port'] = asset.port
|
||||||
|
info['username'] = asset.username
|
||||||
|
info['password'] = asset.password
|
||||||
|
|
||||||
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
def get_role(user, asset):
|
||||||
|
roles = []
|
||||||
|
rules = PermRule.objects.filter(user=user, asset=asset)
|
||||||
|
for rule in rules:
|
||||||
|
roles.extend(list(rule.role.all()))
|
||||||
|
return roles
|
||||||
|
|
||||||
|
|
||||||
|
def get_role_key(user, role):
|
||||||
|
"""
|
||||||
|
由于role的key的权限是所有人可以读的, ansible要求为600,所以拷贝一份到特殊目录
|
||||||
|
:param user:
|
||||||
|
:param role:
|
||||||
|
:return: self key path
|
||||||
|
"""
|
||||||
|
user_role_key_dir = os.path.join(KEY_DIR, 'user')
|
||||||
|
user_role_key_path = os.path.join(user_role_key_dir, '%s_%s.pem' % (user.username, role.name))
|
||||||
|
mkdir(user_role_key_dir, mode=777)
|
||||||
|
if not os.path.isfile(user_role_key_path):
|
||||||
|
with open(os.path.join(role.key_path, 'id_rsa')) as fk:
|
||||||
|
with open(user_role_key_path, 'w') as fu:
|
||||||
|
fu.write(fk.read())
|
||||||
|
|
||||||
|
print user_role_key_path, user.username
|
||||||
|
chown(user_role_key_path, user.username)
|
||||||
|
os.chmod(user_role_key_path, 0600)
|
||||||
|
return user_role_key_path
|
||||||
|
|
||||||
|
|
||||||
|
def chown(path, user, group=''):
|
||||||
if not group:
|
if not group:
|
||||||
group = user
|
group = user
|
||||||
uid = pwd.getpwnam(user).pwd_uid
|
uid = pwd.getpwnam(user).pw_uid
|
||||||
gid = pwd.getpwnam(group).gr_gid
|
gid = pwd.getpwnam(group).pwd_gid
|
||||||
os.chown(path, uid, gid)
|
os.chown(path, uid, gid)
|
||||||
|
|
||||||
|
|
||||||
|
@ -170,8 +218,7 @@ class PyCrypt(object):
|
||||||
try:
|
try:
|
||||||
plain_text = cryptor.decrypt(a2b_hex(text))
|
plain_text = cryptor.decrypt(a2b_hex(text))
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# raise ServerError('Decrypt password error, TYpe error.')
|
raise ServerError('Decrypt password error, TYpe error.')
|
||||||
pass
|
|
||||||
return plain_text.rstrip('\0')
|
return plain_text.rstrip('\0')
|
||||||
|
|
||||||
|
|
||||||
|
@ -406,7 +453,7 @@ def mkdir(dir_name, username='', mode=0755):
|
||||||
"""
|
"""
|
||||||
if not os.path.isdir(dir_name):
|
if not os.path.isdir(dir_name):
|
||||||
os.makedirs(dir_name)
|
os.makedirs(dir_name)
|
||||||
os.chmod(dir_name, mode)
|
os.chmod(dir_name, mode)
|
||||||
if username:
|
if username:
|
||||||
chown(dir_name, username)
|
chown(dir_name, username)
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ def gen_ssh_key(username, password='',
|
||||||
"""
|
"""
|
||||||
logger.debug('生成ssh key, 并设置authorized_keys')
|
logger.debug('生成ssh key, 并设置authorized_keys')
|
||||||
private_key_file = os.path.join(key_dir, username)
|
private_key_file = os.path.join(key_dir, username)
|
||||||
mkdir(key_dir)
|
mkdir(key_dir, mode=777)
|
||||||
if os.path.isfile(private_key_file):
|
if os.path.isfile(private_key_file):
|
||||||
os.unlink(private_key_file)
|
os.unlink(private_key_file)
|
||||||
ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password))
|
ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password))
|
||||||
|
|
Loading…
Reference in New Issue