完成登陆,批量执行命令流

pull/26/head
ibuler 2015-11-21 19:20:11 +08:00
parent 877383679c
commit 93481a98db
6 changed files with 118 additions and 49 deletions

View File

@ -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')

View File

@ -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"),

View File

@ -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

View File

@ -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(),

View File

@ -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)

View File

@ -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))