定义Command前

pull/26/head
ibuler 2015-11-20 18:42:44 +08:00
parent 6b1b33481c
commit ab313aacd8
6 changed files with 126 additions and 334 deletions

View File

@ -22,7 +22,7 @@ if django.get_version() != '1.6':
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir
from jumpserver.api import logger, Log, TtyLog
from jumpserver.settings import LOG_DIR
from jperm.ansible_api import Command
login_user = get_object(User, username=getpass.getuser())
VIM_FLAG = False
@ -301,18 +301,24 @@ class Tty(object):
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
if connect_info.get('role_pass'):
ssh.connect(connect_info.get('ip'),
port=connect_info.get('port'),
username=connect_info.get('role_name'),
password=connect_info.get('role_pass'),
look_for_keys=False)
else:
ssh.connect(connect_info.get('ip'),
port=connect_info.get('port'),
username=connect_info.get('role_name'),
key_filename=connect_info.get('role_key'),
look_for_keys=False)
role_key = connect_info.get('role_key')
if role_key and os.path.isfile(role_key):
try:
ssh.connect(connect_info.get('ip'),
port=connect_info.get('port'),
username=connect_info.get('role_name'),
key_filename=role_key,
look_for_keys=False)
self.ssh = ssh
return ssh
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
pass
ssh.connect(connect_info.get('ip'),
port=connect_info.get('port'),
username=connect_info.get('role_name'),
password=connect_info.get('role_pass'),
look_for_keys=False)
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
raise ServerError('认证失败 Authentication Error.')
@ -458,23 +464,6 @@ class SshTty(Tty):
channel.close()
ssh.close()
def execute(self, cmd):
"""
execute cmd on the asset
执行命令
"""
pass
def print_user_asset_group_info(user):
asset_groups = AssetGroup.objects.all()
for asset_group in asset_groups:
if asset_group.comment:
print '[%-2s] %-10s %s' % (asset_group.id, asset_group.name, asset_group.comment)
else:
print '[%-2s] %-10s' % (asset_group.id, asset_group.name)
print
class Nav(object):
def __init__(self, user):
@ -544,6 +533,52 @@ class Nav(object):
print '[%-3s] %-15s' % (asset_group.id, asset_group.name)
print
def exec_cmd(self):
self.search()
while True:
print "请输入主机名、IP或ansile支持的pattern, q退出"
try:
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
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'}
}
}
cmd = Command(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()
if confirm_host == 'y':
while True:
print "请输入执行的命令, 按q退出"
command = raw_input("\033[1;32mCmds>:\033[0m ").strip()
if command == 'q':
break
result = cmd.run(module_name='shell', command=command, pattern=pattern)
for k, v in result.items():
if k == 'ok':
for host, output in v.items():
color_print("%s => %s" % (host, 'Ok'), 'green')
print output
print
else:
for host, output in v.items():
color_print("%s => %s" % (host, k), 'red')
color_print(output, 'red')
print
print "=" * 20
print
else:
continue
except EOFError:
print
break
def main():
"""
@ -575,8 +610,8 @@ def main():
nav.print_asset_group()
continue
elif option in ['E', 'e']:
# exec_cmd_servers(login_name)
pass
nav.exec_cmd()
continue
elif option in ['Q', 'q', 'exit']:
sys.exit()
else:

View File

@ -107,43 +107,72 @@ class MyInventory(object):
self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
class MyRunner(MyInventory):
"""
This is a General object for parallel execute modules.
"""
def __init__(self, *args, **kwargs):
super(MyRunner, self).__init__(*args, **kwargs)
self.results = {}
def run(self, module_name, module_args='', timeout=10, forks=10, pattern='',
sudo=False, sudo_user='root', sudo_pass=''):
"""
run module from andible ad-hoc.
module_name: ansible module_name
module_args: ansible module args
"""
hoc = Runner(module_name=module_name,
module_args=module_args,
timeout=timeout,
inventory=self.inventory,
pattern=pattern,
forks=forks,
become=sudo,
become_method='sudo',
become_user=sudo_user,
become_pass=sudo_pass
)
self.results = hoc.run()
return self.results
class Command(MyInventory):
"""
this is a command object for parallel execute command.
"""
def __init__(self, *args, **kwargs):
super(Command, self).__init__(*args, **kwargs)
self.results = ''
self.results = {}
def run(self, command, module_name="command", timeout=10, forks=10, group='default_group', pattern='*'):
def run(self, command, module_name="command", timeout=10, forks=10, pattern='*'):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串 比如
'uname -a'
"""
data = {}
if module_name not in ["raw", "command", "shell"]:
raise CommandValueError("module_name",
"module_name must be of the 'raw, command, shell'")
hoc = Runner(module_name=module_name,
module_args=command,
timeout=timeout,
inventory=self.inventory,
subset=group,
pattern=pattern,
forks=forks,
"module_name must be of the 'raw, command, shell'")
hoc = MyRunner(module_name=module_name,
module_args=command,
timeout=timeout,
inventory=self.inventory,
pattern=pattern,
forks=forks,
)
self.results = hoc.run()
if self.stdout:
return {"ok": self.stdout}
else:
msg = []
if self.stderr:
msg.append(self.stderr)
if self.dark:
msg.append(self.dark)
return {"failed": msg}
data['ok'] = self.stdout
if self.stderr:
data['err'] = self.stderr
if self.dark:
data['dark'] = self.dark
return data
@property
def raw_results(self):
@ -174,7 +203,7 @@ class Command(MyInventory):
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
result[key] = value.get("stdout")
result[key] = value.get("stdout")
return result
@property
@ -185,7 +214,8 @@ class Command(MyInventory):
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
result[key] = {
if value.get("stderr") or value.get("warnings"):
result[key] = {
"stderr": value.get("stderr"),
"warnings": value.get("warnings"),}
return result

View File

@ -5,20 +5,6 @@ from jasset.models import Asset, AssetGroup
from juser.models import User, UserGroup
class PermLog(models.Model):
datetime = models.DateTimeField(auto_now_add=True)
action = models.CharField(max_length=100, null=True, blank=True, default='')
results = models.CharField(max_length=1000, null=True, blank=True, default='')
is_success = models.BooleanField(default=False)
is_finish = models.BooleanField(default=False)
class SysUser(models.Model):
username = models.CharField(max_length=100)
password = models.CharField(max_length=100)
comment = models.CharField(max_length=100, null=True, blank=True, default='')
class PermRole(models.Model):
name = models.CharField(max_length=100, unique=True)
comment = models.CharField(max_length=100, null=True, blank=True, default='')

View File

@ -4,12 +4,10 @@
from jumpserver.api import *
import uuid
import re
from jumpserver.tasks import playbook_run
from jumpserver.models import Setting
from jperm.models import PermLog
from jperm.models import PermRole
from jperm.models import PermRule
def get_object_list(model, id_list):
@ -22,267 +20,6 @@ def get_object_list(model, id_list):
return object_list
def get_rand_file_path(base_dir=os.path.join(BASE_DIR, 'tmp')):
"""获取随机文件路径"""
filename = uuid.uuid1().hex
return os.path.join(base_dir, filename)
def get_inventory(host_group):
"""生成资产表库存清单"""
path = get_rand_file_path()
f = open(path, 'w')
for group, host_list in host_group.items():
f.write('[%s]\n' % group)
for ip in host_list:
asset = get_object(Asset, ip=ip)
if asset.use_default:
f.write('%s\n' % ip)
else:
f.write('%s ansible_ssh_port=%s ansible_ssh_user=%s ansible_ssh_pass=%s\n' %
(ip, asset.port, asset.username, CRYPTOR.decrypt(asset.password)))
f.close()
return path
def get_playbook(template, var):
"""根据playbook模板生成playbook"""
str_playbook = open(template).read()
for k, v in var.items():
str_playbook = re.sub(r'%s' % k, v, str_playbook) # 正则来替换传入的字符
path = get_rand_file_path()
f = open(path, 'w')
f.write(str_playbook)
return path
def perm_user_api(perm_info):
"""
用户授权api通过调用ansible API完成用户新建等,传入参数必须如下,列表中可以是对象也可以是用户名和ip
perm_info = {'del': {'users': [],
'assets': [],
},
'new': {'users': [],
'assets': []}}
"""
log = PermLog(action=perm_info.get('action', ''))
try:
new_users = perm_info.get('new', {}).get('users', [])
new_assets = perm_info.get('new', {}).get('assets', [])
del_users = perm_info.get('del', {}).get('users', [])
del_assets = perm_info.get('del', {}).get('assets', [])
print new_users, new_assets
except IndexError:
raise ServerError("Error: function perm_user_api传入参数错误")
try:
new_ip = [asset.ip for asset in new_assets if isinstance(asset, Asset)]
del_ip = [asset.ip for asset in del_assets if isinstance(asset, Asset)]
new_username = [user.username for user in new_users]
del_username = [user.username for user in del_users]
except IndexError:
raise ServerError("Error: function perm_user_api传入参数类型错误")
host_group = {'new': new_ip, 'del': del_ip}
inventory = get_inventory(host_group)
the_new_users = ','.join(new_username)
the_del_users = ','.join(del_username)
playbook = get_playbook(os.path.join(BASE_DIR, 'keys/../playbook', 'user_perm.yaml'),
{'the_new_group': 'new', 'the_del_group': 'del',
'the_new_users': the_new_users, 'the_del_users': the_del_users,
'KEY_DIR': os.path.join(SSH_KEY_DIR, 'sysuser')})
print playbook, inventory
settings = get_object(Setting, name='default')
results = playbook_run(inventory, playbook, settings)
if not results.get('failures', 1) and not results.get('unreachable', ''):
is_success = True
else:
is_success = False
log.results = results
log.is_finish = True
log.is_success = is_success
log.save()
return results
def user_group_permed(user_group):
assets = user_group.asset.all()
asset_groups = user_group.asset_group.all()
for asset_group in asset_groups:
assets.extend(asset_group.asset.all())
return {'assets': assets, 'asset_groups': asset_groups}
def user_permed(user):
asset_groups = []
assets = []
user_groups = user.group.all()
asset_groups.extend(user.asset_group.all())
assets.extend(user.asset.all())
for user_group in user_groups:
asset_groups.extend(user_group_permed(user_group).get('assets', []))
assets.extend((user_group_permed(user_group).get('asset_groups', [])))
return {'assets': assets, 'asset_groups': asset_groups}
def _public_perm_api(info):
"""
公用的用户用户组主机主机组编辑修改新建调用的api用来完成授权
info like that:
{
'type': 'new_user',
'user': 'a',
'group': ['A', 'B']
}
{
'type': 'edit_user',
'user': 'a',
'group': {'new': ['A'], 'del': []}
}
{
'type': 'del_user',
'user': ['a', 'b']
}
{
'type': 'edit_user_group',
'group': 'A',
'user': {'del': ['a', 'b'], 'new': ['c', 'd']}
}
{
'type': 'del_user_group',
'group': ['A']
}
{
'type': 'new_asset',
'asset': 'a',
'group': ['A', 'B']
}
{
'type': 'edit_asset',
'asset': 'a',
'group': {
'del': ['A', ['B'],
'new': ['C', ['D']]
}
}
{
'type': 'del_asset',
'asset': ['a', 'b']
}
{
'type': 'edit_asset_group',
'group': 'A',
'asset': {'new': ['a', 'b'], 'del': ['c', 'd']}
}
{
'type': 'del_asset_group',
'group': ['A', 'B']
}
"""
if info.get('type') == 'new_user':
new_assets = []
user = info.get('user')
user_groups = info.get('group')
for user_group in user_groups:
new_assets.extend(user_group_permed(user_group).get('assets', []))
perm_info = {
'action': 'new user: ' + user.name,
'new': {'users': [user], 'assets': new_assets}
}
elif info.get('type') == 'edit_user':
new_assets = []
del_assets = []
user = info.get('user')
new_group = info.get('group').get('new')
del_group = info.get('group').get('del')
for user_group in new_group:
new_assets.extend(user_group_permed(user_group).get('assets', []))
for user_group in del_group:
del_assets.extend((user_group_permed(user_group).get('assets', [])))
perm_info = {
'action': 'edit user: ' + user.name,
'del': {'users': [user], 'assets': del_assets},
'new': {'users': [user], 'assets': new_assets}
}
elif info.get('type') == 'del_user':
user = info.get('user')
del_assets = user_permed(user).get('assets', [])
perm_info = {
'action': 'del user: ' + user.name, 'del': {'users': [user], 'assets': del_assets},
}
elif info.get('type') == 'edit_user_group':
user_group = info.get('group')
new_users = info.get('user').get('new')
del_users = info.get('user').get('del')
assets = user_group_permed(user_group).get('assets', [])
perm_info = {
'action': 'edit user group: ' + user_group.name,
'new': {'users': new_users, 'assets': assets},
'del': {'users': del_users, 'assets': assets}
}
elif info.get('type') == 'del_user_group':
user_group = info.get('group', [])
del_users = user_group.user_set.all()
assets = user_group_permed(user_group).get('assets', [])
perm_info = {
'action': "del user group: " + user_group.name, 'del': {'users': del_users, 'assets': assets}
}
else:
return
try:
results = perm_user_api(perm_info) # 通过API授权或回收
except ServerError, e:
return e
else:
return results
def push_user(user, asset_groups_id):
assets = []
if not user:
return {'error': '没有该用户'}
for group_id in asset_groups_id:
asset_group = get_object(AssetGroup, id=group_id)
if asset_group:
assets.extend(asset_group.asset_set.all())
perm_info = {
'action': 'Push user:' + user.username,
'new': {'users': [user], 'assets': assets}
}
results = perm_user_api(perm_info)
return results
def get_role_info(role_id, type="all"):
"""
获取role对应的一些信息

View File

@ -14,7 +14,7 @@ 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
from jlog.models import Log, TtyLog
from jasset.models import Asset, AssetGroup
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
@ -28,11 +28,15 @@ def set_log(level):
return a log file object
根据提示设置log打印
"""
log_file = os.path.join(LOG_DIR, 'jumpserver.log')
if not os.path.isfile(log_file):
os.mknod(log_file)
os.chmod(log_file, 0777)
log_level_total = {'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARN, 'error': logging.ERROR,
'critical': logging.CRITICAL}
logger_f = logging.getLogger('jumpserver')
logger_f.setLevel(logging.DEBUG)
fh = logging.FileHandler(os.path.join(LOG_DIR, 'jumpserver.log'))
fh = logging.FileHandler(log_file)
fh.setLevel(log_level_total.get(level, logging.DEBUG))
formatter = logging.Formatter('%(asctime)s - %(filename)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)

View File

@ -29,11 +29,11 @@
<li id="jperm">
<a href="#"><i class="fa fa-edit"></i> <span class="nav-label">授权管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li class="dept_perm_list dept_perm_edit">
<li class="rule ">
<a href="/jperm/rule/">授权规则</a>
</li>
<li class="sudo_list sudo_edit sudo_add cmd_list cmd_edit cmd_add sudo_detail">
<li class="role">
<a href="/jperm/role/">系统角色</a>
</li>
<li class="apply_show online"><a href="/jperm/apply_show/online/">权限审批</a></li>