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'
|
||||
if django.get_version() != '1.6':
|
||||
django.setup()
|
||||
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir
|
||||
from jumpserver.api import logger, Log, TtyLog
|
||||
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir, get_asset_info, get_role
|
||||
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 jperm.ansible_api import Command
|
||||
|
||||
|
@ -73,15 +74,15 @@ class Tty(object):
|
|||
A virtual tty class
|
||||
一个虚拟终端类,实现连接ssh和记录日志,基类
|
||||
"""
|
||||
def __init__(self, username, asset_name):
|
||||
self.username = username
|
||||
self.asset_name = asset_name
|
||||
def __init__(self, user, asset, role):
|
||||
self.username = user.username
|
||||
self.asset_name = asset.hostname
|
||||
self.ip = None
|
||||
self.port = 22
|
||||
self.channel = None
|
||||
#self.asset = get_object(Asset, name=asset_name)
|
||||
#self.user = get_object(User, username=username)
|
||||
self.role = None
|
||||
self.asset = asset
|
||||
self.user = user
|
||||
self.role = role
|
||||
self.ssh = None
|
||||
self.connect_info = None
|
||||
self.login_type = 'ssh'
|
||||
|
@ -287,7 +288,10 @@ class Tty(object):
|
|||
# 2. get 映射用户
|
||||
# 3. get 映射用户的账号,密码或者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
|
||||
|
||||
def get_connection(self):
|
||||
|
@ -301,7 +305,7 @@ class Tty(object):
|
|||
ssh.load_system_host_keys()
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
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):
|
||||
try:
|
||||
ssh.connect(connect_info.get('ip'),
|
||||
|
@ -469,6 +473,7 @@ class Nav(object):
|
|||
def __init__(self, user):
|
||||
self.user = user
|
||||
self.search_result = {}
|
||||
self.user_perm = {}
|
||||
|
||||
@staticmethod
|
||||
def print_nav():
|
||||
|
@ -499,7 +504,9 @@ class Nav(object):
|
|||
|
||||
def search(self, str_r=''):
|
||||
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 = []
|
||||
if str_r:
|
||||
if gid_pattern.match(str_r):
|
||||
|
@ -512,13 +519,15 @@ class Nav(object):
|
|||
user_asset_search = user_asset_all
|
||||
|
||||
self.search_result = dict(zip(range(len(user_asset_search)), user_asset_search))
|
||||
|
||||
print '\033[32m[%-3s] %-15s %-15s %-5s %-5s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment')
|
||||
print '\033[32m[%-3s] %-15s %-15s %-5s %-10s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment')
|
||||
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:
|
||||
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:
|
||||
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
|
||||
|
||||
@staticmethod
|
||||
|
@ -542,13 +551,11 @@ class Nav(object):
|
|||
if pattern == 'q':
|
||||
break
|
||||
else:
|
||||
res = {
|
||||
"group1": {
|
||||
"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"}],
|
||||
"vars": {"var1": 'a', "var2": 'a'}
|
||||
}
|
||||
}
|
||||
if not self.user_perm:
|
||||
self.user_perm = get_group_user_perm(self.user)
|
||||
res = gen_resource(self.user, perm=self.user_perm)
|
||||
cmd = Command(res)
|
||||
logger.debug(res)
|
||||
for inv in cmd.inventory.get_hosts(pattern=pattern):
|
||||
print inv.name
|
||||
confirm_host = raw_input("\033[1;32mIs that [y/n]>:\033[0m ").strip()
|
||||
|
@ -617,7 +624,28 @@ def main():
|
|||
else:
|
||||
try:
|
||||
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()
|
||||
except (KeyError, ValueError):
|
||||
color_print('请输入正确ID', 'red')
|
||||
|
|
|
@ -404,7 +404,7 @@ class Tasks(Command):
|
|||
|
||||
result[key] = {
|
||||
"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_mac": setup.get("ansible_default_ipv4").get("macaddress"),
|
||||
"product_name": setup.get("ansible_product_name"),
|
||||
|
|
|
@ -132,37 +132,30 @@ def get_group_asset_perm(ob):
|
|||
return perm
|
||||
|
||||
|
||||
def gen_resource(ob):
|
||||
def gen_resource(ob, perm=None):
|
||||
"""
|
||||
ob为用户或资产列表或资产queryset
|
||||
生成MyInventory需要的 resource文件
|
||||
"""
|
||||
res = []
|
||||
if isinstance(ob, User):
|
||||
if not perm:
|
||||
perm = get_group_user_perm(ob)
|
||||
|
||||
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:
|
||||
role = sorted(list(asset_info.get('role')))[0]
|
||||
role = sorted(list(perm.get('asset').get(asset).get('role')))[0]
|
||||
except IndexError:
|
||||
continue
|
||||
info['username'] = role.name
|
||||
info['password'] = role.password
|
||||
info['key_path'] = role.key_path
|
||||
info['ssh_key'] = get_role_key(ob, role)
|
||||
res.append(info)
|
||||
elif isinstance(ob, (list, QuerySet)):
|
||||
default = get_object(Setting, name='default')
|
||||
for asset in ob:
|
||||
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'] = default.default_password
|
||||
info['ssh_key'] = default.default_pri_key_path
|
||||
else:
|
||||
info['port'] = asset.port
|
||||
info['username'] = asset.username
|
||||
info = get_asset_info(asset)
|
||||
res.append(info)
|
||||
return res
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ def gen_keys():
|
|||
private_key = os.path.join(key_path_dir, 'id_rsa')
|
||||
public_key = os.path.join(key_path_dir, 'id_rsa.pub')
|
||||
key.write_private_key_file(private_key)
|
||||
os.chmod(private_key, 0644)
|
||||
|
||||
with open(public_key, 'w') as content_file:
|
||||
for data in [key.get_name(),
|
||||
|
|
|
@ -9,19 +9,21 @@ import hashlib
|
|||
import datetime
|
||||
import random
|
||||
import subprocess
|
||||
from settings import *
|
||||
import json
|
||||
import logging
|
||||
|
||||
from settings import *
|
||||
from django.core.paginator import Paginator, EmptyPage, InvalidPage
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.template import RequestContext
|
||||
from juser.models import User, UserGroup
|
||||
from jlog.models import Log, TtyLog
|
||||
from jasset.models import Asset, AssetGroup
|
||||
from jperm.models import PermRule, PermRole
|
||||
from jumpserver.models import Setting
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render_to_response
|
||||
from django.core.mail import send_mail
|
||||
import json
|
||||
import logging
|
||||
|
||||
|
||||
def set_log(level):
|
||||
|
@ -45,11 +47,57 @@ def set_log(level):
|
|||
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:
|
||||
group = user
|
||||
uid = pwd.getpwnam(user).pwd_uid
|
||||
gid = pwd.getpwnam(group).gr_gid
|
||||
uid = pwd.getpwnam(user).pw_uid
|
||||
gid = pwd.getpwnam(group).pwd_gid
|
||||
os.chown(path, uid, gid)
|
||||
|
||||
|
||||
|
@ -170,8 +218,7 @@ class PyCrypt(object):
|
|||
try:
|
||||
plain_text = cryptor.decrypt(a2b_hex(text))
|
||||
except TypeError:
|
||||
# raise ServerError('Decrypt password error, TYpe error.')
|
||||
pass
|
||||
raise ServerError('Decrypt password error, TYpe error.')
|
||||
return plain_text.rstrip('\0')
|
||||
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ def gen_ssh_key(username, password='',
|
|||
"""
|
||||
logger.debug('生成ssh key, 并设置authorized_keys')
|
||||
private_key_file = os.path.join(key_dir, username)
|
||||
mkdir(key_dir)
|
||||
mkdir(key_dir, mode=777)
|
||||
if os.path.isfile(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))
|
||||
|
|
Loading…
Reference in New Issue