mirror of https://github.com/jumpserver/jumpserver
定义Command前
parent
6b1b33481c
commit
ab313aacd8
99
connect.py
99
connect.py
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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='')
|
||||
|
|
|
@ -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对应的一些信息
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue