Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
J
jumpserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
jumpserver
Commits
b8cb6f42
Commit
b8cb6f42
authored
Nov 22, 2015
by
wangyong
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' into cmdb
parents
d25e2362
a143797a
Hide whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
820 additions
and
720 deletions
+820
-720
.gitignore
.gitignore
+1
-0
connect.py
connect.py
+184
-59
requirements.txt
docs/requirements.txt
+7
-3
views.py
jasset/views.py
+1
-1
ansible_api.py
jperm/ansible_api.py
+63
-30
models.py
jperm/models.py
+2
-18
perm_api.py
jperm/perm_api.py
+159
-256
urls.py
jperm/urls.py
+0
-7
utils.py
jperm/utils.py
+4
-6
views.py
jperm/views.py
+146
-136
api.py
jumpserver/api.py
+75
-14
settings.py
jumpserver/settings.py
+2
-2
mytags.py
jumpserver/templatetags/mytags.py
+11
-0
views.py
jumpserver/views.py
+15
-15
user_api.py
juser/user_api.py
+4
-4
views.py
juser/views.py
+21
-20
README.md
keys/README.md
+3
-0
README.md
logs/README.md
+1
-0
user_perm.yaml
playbook/user_perm.yaml
+0
-17
index.html
templates/index.html
+3
-13
asset_add.html
templates/jasset/asset_add.html
+1
-0
asset_edit_batch.html
templates/jasset/asset_edit_batch.html
+27
-0
perm_role_edit.html
templates/jperm/perm_role_edit.html
+7
-0
perm_role_list.html
templates/jperm/perm_role_list.html
+8
-0
perm_role_push.html
templates/jperm/perm_role_push.html
+0
-10
perm_rule_add.html
templates/jperm/perm_rule_add.html
+38
-47
perm_rule_edit.html
templates/jperm/perm_rule_edit.html
+6
-46
perm_rule_list.html
templates/jperm/perm_rule_list.html
+15
-5
group_list.html
templates/juser/group_list.html
+2
-1
user_edit.html
templates/juser/user_edit.html
+1
-1
user_list.html
templates/juser/user_list.html
+7
-1
nav.html
templates/nav.html
+6
-6
version
version
+0
-2
No files found.
.gitignore
View file @
b8cb6f42
...
...
@@ -37,6 +37,7 @@ nosetests.xml
.mr.developer.cfg
.project
.pydevproject
*.log
logs/*
keys/*
jumpserver.conf
...
...
connect.py
View file @
b8cb6f42
...
...
@@ -19,10 +19,11 @@ 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
from
jumpserver.api
import
logger
,
mkdir
,
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
login_user
=
get_object
(
User
,
username
=
getpass
.
getuser
())
VIM_FLAG
=
False
...
...
@@ -68,23 +69,20 @@ def check_vim_status(command, ssh):
return
False
class
Tty
(
object
):
"""
A virtual tty class
一个虚拟终端类,实现连接ssh和记录日志,基类
"""
def
__init__
(
self
,
user
name
,
asset_nam
e
):
self
.
username
=
username
self
.
asset_name
=
asset
_
name
def
__init__
(
self
,
user
,
asset
,
rol
e
):
self
.
username
=
user
.
user
name
self
.
asset_name
=
asset
.
host
name
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
=
Non
e
self
.
asset
=
asset
self
.
user
=
user
self
.
role
=
rol
e
self
.
ssh
=
None
self
.
connect_info
=
None
self
.
login_type
=
'ssh'
...
...
@@ -252,6 +250,7 @@ class Tty(object):
log_file_path
=
os
.
path
.
join
(
today_connect_log_dir
,
'
%
s_
%
s_
%
s'
%
(
self
.
username
,
self
.
asset_name
,
time_start
))
try
:
mkdir
(
os
.
path
.
dirname
(
today_connect_log_dir
),
mode
=
0777
)
mkdir
(
today_connect_log_dir
,
mode
=
0777
)
except
OSError
:
logger
.
debug
(
'创建目录
%
s 失败,请修改
%
s目录权限'
%
(
today_connect_log_dir
,
tty_log_dir
))
...
...
@@ -289,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'
:
''
,
'role_key'
:
'/root/.ssh/id_rsa.bak'
}
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
):
...
...
@@ -303,18 +305,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
=
get_role_key
(
self
.
user
,
self
.
role
)
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.'
)
...
...
@@ -452,7 +460,7 @@ class SshTty(Tty):
#print 'ok'+tmp+'ok'
# SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip()
# SSH_TTY = ''
channel
.
send
(
'clear
\n
'
)
#
channel.send('clear\n')
# Make ssh interactive tunnel
self
.
posix_shell
()
...
...
@@ -460,28 +468,123 @@ class SshTty(Tty):
channel
.
close
()
ssh
.
close
()
def
execute
(
self
,
cmd
):
class
Nav
(
object
):
def
__init__
(
self
,
user
):
self
.
user
=
user
self
.
search_result
=
{}
self
.
user_perm
=
{}
@staticmethod
def
print_nav
():
"""
execute cmd on the asset
执行命令
Print prompt
打印提示导航
"""
msg
=
"""
\n\033
[1;32m### Welcome To Use JumpServer, A Open Source System . ###
\033
[0m
1) Type
\033
[32mID
\033
[0m To Login.
2) Type
\033
[32m/
\033
[0m +
\033
[32mIP, Host Name, Host Alias or Comments
\033
[0mTo Search.
3) Type
\033
[32mP/p
\033
[0m To Print The Servers You Available.
4) Type
\033
[32mG/g
\033
[0m To Print The Server Groups You Available.
5) Type
\033
[32mG/g
\033
[0m
\033
[0m +
\033
[32mGroup ID
\033
[0m To Print The Server Group You Available.
6) Type
\033
[32mE/e
\033
[0m To Execute Command On Several Servers.
7) Type
\033
[32mQ/q
\033
[0m To Quit.
"""
pass
msg
=
"""
\n\033
[1;32m### 欢迎使用Jumpserver开源跳板机 ###
\033
[0m
1) 输入
\033
[32mID
\033
[0m 直接登录.
2) 输入
\033
[32m/
\033
[0m +
\033
[32mIP, 主机名, 主机别名 or 备注
\033
[0m搜索.
3) 输入
\033
[32mP/p
\033
[0m 显示您有权限的主机.
4) 输入
\033
[32mG/g
\033
[0m 显示您有权限的主机组.
5) 输入
\033
[32mG/g
\033
[0m
\033
[0m +
\033
[32m组ID
\033
[0m 显示该组下主机.
6) 输入
\033
[32mE/e
\033
[0m 批量执行命令.
7) 输入
\033
[32mQ/q
\033
[0m 退出.
"""
print
textwrap
.
dedent
(
msg
)
def
search
(
self
,
str_r
=
''
):
gid_pattern
=
re
.
compile
(
r'^g\d+$'
)
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
):
user_asset_search
=
list
(
Asset
.
objects
.
all
())
else
:
for
asset
in
user_asset_all
:
if
str_r
in
asset
.
ip
or
str_r
in
str
(
asset
.
comment
):
user_asset_search
.
append
(
asset
)
else
:
user_asset_search
=
user_asset_all
self
.
search_result
=
dict
(
zip
(
range
(
len
(
user_asset_search
)),
user_asset_search
))
print
'
\033
[32m[
%-3
s]
%-15
s
%-15
s
%-5
s
%-10
s
%
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
'[
%-3
s]
%-15
s
%-15
s
%-5
s
%-10
s
%
s'
%
(
index
,
asset
.
hostname
,
asset
.
ip
,
asset_info
.
get
(
'port'
),
role
,
asset
.
comment
)
else
:
print
'[
%-3
s]
%-15
s
%-15
s
%-5
s
%-10
s'
%
(
index
,
asset
.
hostname
,
asset
.
ip
,
asset_info
.
get
(
'port'
),
role
)
print
def
print_prompt
():
"""
Print prompt
打印提示导航
"""
msg
=
"""
\033
[1;32m### Welcome Use JumpServer To Login. ###
\033
[0m
1) Type
\033
[32mIP or Part IP, Host Alias or Comments
\033
[0m To Login.
2) Type
\033
[32mP/p
\033
[0m To Print The Servers You Available.
3) Type
\033
[32mG/g
\033
[0m To Print The Server Groups You Available.
4) Type
\033
[32mG/g(1-N)
\033
[0m To Print The Server Group Hosts You Available.
5) Type
\033
[32mE/e
\033
[0m To Execute Command On Several Servers.
6) Type
\033
[32mQ/q
\033
[0m To Quit.
"""
print
textwrap
.
dedent
(
msg
)
@staticmethod
def
print_asset_group
():
user_asset_group_all
=
AssetGroup
.
objects
.
all
()
print
'
\033
[32m[
%-3
s]
%-15
s
%
s
\033
[0m'
%
(
'ID'
,
'GroupName'
,
'Comment'
)
for
asset_group
in
user_asset_group_all
:
if
asset_group
.
comment
:
print
'[
%-3
s]
%-15
s
%
s'
%
(
asset_group
.
id
,
asset_group
.
name
,
asset_group
.
comment
)
else
:
print
'[
%-3
s]
%-15
s'
%
(
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
:
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
()
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
():
...
...
@@ -492,38 +595,60 @@ def main():
if
not
login_user
:
# 判断用户是否存在
color_print
(
u'没有该用户,或许你是以root运行的 No that user.'
,
exits
=
True
)
print_prompt
()
gid_pattern
=
re
.
compile
(
r'^g\d+$'
)
nav
=
Nav
(
login_user
)
nav
.
print_nav
()
try
:
while
True
:
try
:
option
=
raw_input
(
"
\033
[1;32mOpt or I
P>:
\033
[0m "
)
option
=
raw_input
(
"
\033
[1;32mOpt or I
D>:
\033
[0m "
)
.
strip
(
)
except
EOFError
:
print_prompt
()
nav
.
print_nav
()
continue
except
KeyboardInterrupt
:
sys
.
exit
(
0
)
if
option
in
[
'P'
,
'p'
]:
login_user
.
get_asset_info
(
printable
=
True
)
if
option
in
[
'P'
,
'p'
,
'
\n
'
,
''
]:
nav
.
search
(
)
continue
if
option
.
startswith
(
'/'
)
or
gid_pattern
.
match
(
option
):
nav
.
search
(
option
.
lstrip
(
'/'
))
elif
option
in
[
'G'
,
'g'
]:
login_user
.
get_asset_group_info
(
printable
=
True
)
continue
elif
gid_pattern
.
match
(
option
):
gid
=
option
[
1
:]
.
strip
()
asset_group
=
get_object
(
AssetGroup
,
id
=
gid
)
if
asset_group
and
asset_group
.
is_permed
(
user
=
login_user
):
asset_group
.
get_asset_info
(
printable
=
True
)
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
:
try
:
verify_connect
(
login_user
,
option
)
asset
=
nav
.
search_result
[
int
(
option
)]
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'
)
except
ServerError
,
e
:
color_print
(
e
,
'red'
)
except
IndexError
:
...
...
docs/requirements.txt
View file @
b8cb6f42
sphinx-me==0.3
django==1.6
python-ldap==2.4.19
pycrypto==2.6.1
paramiko==1.15.2
ecdsa==0.13
...
...
@@ -9,4 +8,9 @@ django-uuidfield==0.5.0
psutil==2.2.1
xlsxwriter==0.7.7
xlrd==0.9.4
django-bootstrap-form
\ No newline at end of file
django-bootstrap-form
tornado
ansible
pyinotify
passlib
argparse
\ No newline at end of file
jasset/views.py
View file @
b8cb6f42
...
...
@@ -145,7 +145,7 @@ def asset_add(request):
asset_save
=
af_post
.
save
(
commit
=
False
)
if
not
use_default_auth
:
password
=
request
.
POST
.
get
(
'password'
,
''
)
password_encode
=
CRYPTOR
.
encrypt
(
password
)
password_encode
=
password
asset_save
.
password
=
password_encode
if
not
ip
:
asset_save
.
ip
=
hostname
...
...
jperm/ansible_api.py
View file @
b8cb6f42
...
...
@@ -15,11 +15,11 @@ from utils import get_rand_pass
import
os.path
API_DIR
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
ANSIBLE_DIR
=
os
.
path
.
join
(
API_DIR
,
'playbooks'
)
class
AnsibleError
(
StandardError
):
"""
the base AnsibleError which contains error(required),
...
...
@@ -61,7 +61,7 @@ class MyInventory(object):
[{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...]
"""
self
.
resource
=
resource
self
.
inventory
=
Inventory
()
self
.
inventory
=
Inventory
(
host_list
=
[]
)
self
.
gen_inventory
()
def
add_group
(
self
,
hosts
,
groupname
,
groupvars
=
None
):
...
...
@@ -79,14 +79,17 @@ class MyInventory(object):
for
host
in
hosts
:
# set connection variables
hostname
=
host
.
get
(
"hostname"
)
hostip
=
host
.
get
(
'ip'
,
hostname
)
hostport
=
host
.
get
(
"port"
)
username
=
host
.
get
(
"username"
)
password
=
host
.
get
(
"password"
)
ssh_key
=
host
.
get
(
"ssh_key"
)
my_host
=
Host
(
name
=
hostname
,
port
=
hostport
)
my_host
.
set_variable
(
'ansible_ssh_host'
,
host
name
)
my_host
.
set_variable
(
'ansible_ssh_host'
,
host
ip
)
my_host
.
set_variable
(
'ansible_ssh_port'
,
hostport
)
my_host
.
set_variable
(
'ansible_ssh_user'
,
username
)
my_host
.
set_variable
(
'ansible_ssh_pass'
,
password
)
my_host
.
set_variable
(
'ansible_ssh_private_key_file'
,
ssh_key
)
# set other variables
for
key
,
value
in
host
.
iteritems
():
if
key
not
in
[
"hostname"
,
"port"
,
"username"
,
"password"
]:
...
...
@@ -101,47 +104,78 @@ class MyInventory(object):
add hosts to inventory.
"""
if
isinstance
(
self
.
resource
,
list
):
self
.
add_group
(
self
.
resource
,
'
my
_group'
)
self
.
add_group
(
self
.
resource
,
'
default
_group'
)
elif
isinstance
(
self
.
resource
,
dict
):
for
groupname
,
hosts_and_vars
in
self
.
resource
.
iteritems
():
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
=
5
,
forks
=
10
,
group
=
'my_group
'
):
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'"
)
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
,
forks
=
forks
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
):
...
...
@@ -172,7 +206,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
...
...
@@ -183,7 +217,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
...
...
@@ -203,7 +238,7 @@ class Tasks(Command):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
Tasks
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
__run
(
self
,
module_args
,
module_name
=
"command"
,
timeout
=
5
,
forks
=
10
,
group
=
'
my_group
'
):
def
__run
(
self
,
module_args
,
module_name
=
"command"
,
timeout
=
5
,
forks
=
10
,
group
=
'
default_group'
,
pattern
=
'*
'
):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串, 比如
...
...
@@ -214,7 +249,8 @@ class Tasks(Command):
timeout
=
timeout
,
inventory
=
self
.
inventory
,
subset
=
group
,
forks
=
forks
pattern
=
pattern
,
forks
=
forks
,
)
self
.
results
=
hoc
.
run
()
...
...
@@ -368,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"
),
...
...
@@ -385,8 +421,6 @@ class Tasks(Command):
return
{
"status"
:
"failed"
,
"msg"
:
self
.
msg
}
if
self
.
msg
else
{
"status"
:
"ok"
,
"result"
:
result
}
class
CustomAggregateStats
(
callbacks
.
AggregateStats
):
"""
Holds stats about per-host activity during playbook runs.
...
...
@@ -405,7 +439,6 @@ class CustomAggregateStats(callbacks.AggregateStats):
self
.
results
.
append
(
runner_results
)
def
summarize
(
self
,
host
):
"""
Return information about a particular host
...
...
@@ -425,7 +458,6 @@ class MyPlaybook(MyInventory):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
MyPlaybook
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
run
(
self
,
playbook_relational_path
,
extra_vars
=
None
):
"""
run ansible playbook,
...
...
@@ -464,7 +496,6 @@ class App(MyPlaybook):
if
__name__
==
"__main__"
:
pass
# resource = {
# "group1": {
...
...
@@ -472,8 +503,10 @@ if __name__ == "__main__":
# "vars" : {"var1": "value1", "var2": "value2"},
# },
# }
# command = Command(resource)
# print command.run("who", group="group1")
resource
=
[{
"hostname"
:
"127.0.0.1"
,
"port"
:
"22"
,
"username"
:
"yumaojun"
,
"password"
:
"yusky0902"
}]
command
=
Command
(
resource
)
print
command
.
run
(
"who"
)
# resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}]
# task = Tasks(resource)
...
...
jperm/models.py
View file @
b8cb6f42
...
...
@@ -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
=
''
)
...
...
@@ -32,14 +18,13 @@ class PermRole(models.Model):
class
PermRule
(
models
.
Model
):
date_added
=
models
.
DateTimeField
(
auto_now
=
True
)
name
=
models
.
CharField
(
max_length
=
100
)
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
)
comment
=
models
.
CharField
(
max_length
=
100
)
asset
=
models
.
ManyToManyField
(
Asset
,
related_name
=
'perm_rule'
)
asset_group
=
models
.
ManyToManyField
(
AssetGroup
,
related_name
=
'perm_rule'
)
user
=
models
.
ManyToManyField
(
User
,
related_name
=
'perm_rule'
)
user_group
=
models
.
ManyToManyField
(
UserGroup
,
related_name
=
'perm_rule'
)
role
=
models
.
ManyToManyField
(
PermRole
,
related_name
=
'perm_rule'
)
ssh_type
=
models
.
BooleanField
()
def
__unicode__
(
self
):
return
self
.
name
\ No newline at end of file
return
self
.
name
jperm/perm_api.py
View file @
b8cb6f42
# coding: utf-8
from
django.db.models.query
import
QuerySet
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
):
"""根据id列表获取对象列表"""
object_list
=
[]
for
object_id
in
id_list
:
if
object_id
:
object_list
.
extend
(
model
.
objects
.
filter
(
id
=
int
(
object_id
)))
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
):
def
get_group_user_perm
(
ob
):
"""
用户授权api,通过调用ansible API完成用户新建等,传入参数必须如下,列表中可以是对象,也可以是用户名和ip
perm_info = {'del': {'users': [],
'assets': [],
},
'new': {'users': [],
'assets': []}}
ob为用户或用户组
获取用户、用户组授权的资产、资产组
return:
{’asset_group': {
asset_group1: {'asset': [], 'role': [role1, role2], 'rule': [rule1, rule2]},
asset_group2: {'asset: [], 'role': [role1, role2], 'rule': [rule1, rule2]},
}
'asset':{
asset1: {'role': [role1, role2], 'rule': [rule1, rule2]},
asset2: {'role': [role1, role2], 'rule': [rule1, rule2]},
}
]},
'rule':[rule1, rule2,]
}
"""
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
,
'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
perm
=
{}
if
isinstance
(
ob
,
User
):
rule_all
=
PermRule
.
objects
.
filter
(
user
=
ob
)
elif
isinstance
(
ob
,
UserGroup
):
rule_all
=
PermRule
.
objects
.
filter
(
user_group
=
ob
)
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'
,
[])))
rule_all
=
[]
perm
[
'rule'
]
=
rule_all
perm_asset_group
=
perm
[
'asset_group'
]
=
{}
perm_asset
=
perm
[
'asset'
]
=
{}
for
rule
in
rule_all
:
asset_groups
=
rule
.
asset_group
.
all
()
assets
=
rule
.
asset
.
all
()
# 获取一个规则用户授权的资产
for
asset
in
assets
:
if
perm_asset
.
get
(
asset
):
perm_asset
[
asset
]
.
get
(
'role'
,
set
())
.
update
(
set
(
rule
.
role
.
all
()))
perm_asset
[
asset
]
.
get
(
'rule'
,
set
())
.
add
(
rule
)
else
:
perm_asset
[
asset
]
=
{
'role'
:
set
(
rule
.
role
.
all
()),
'rule'
:
set
([
rule
])}
# 获取一个规则用户授权的资产组
for
asset_group
in
asset_groups
:
asset_group_assets
=
asset_group
.
asset_set
.
all
()
if
perm_asset_group
.
get
(
asset_group
):
perm_asset_group
[
asset_group
]
.
get
(
'role'
,
set
())
.
update
(
set
(
rule
.
role
.
all
()))
perm_asset_group
[
asset_group
]
.
get
(
'rule'
,
set
())
.
add
(
rule
)
else
:
perm_asset_group
[
asset_group
]
=
{
'role'
:
set
(
rule
.
role
.
all
()),
'rule'
:
set
([
rule
]),
'asset'
:
asset_group_assets
}
return
{
'assets'
:
assets
,
'asset_groups'
:
asset_groups
}
# 将资产组中的资产添加到资产授权中
for
asset
in
asset_group_assets
:
if
perm_asset
.
get
(
asset
):
perm_asset
[
asset
]
.
get
(
'role'
,
set
())
.
update
(
perm_asset_group
[
asset_group
]
.
get
(
'role'
,
set
()))
perm_asset
[
asset
]
.
get
(
'rule'
,
set
())
.
update
(
perm_asset_group
[
asset_group
]
.
get
(
'rule'
,
set
()))
else
:
perm_asset
[
asset
]
=
{
'role'
:
perm_asset_group
[
asset_group
]
.
get
(
'role'
,
set
()),
'rule'
:
perm_asset_group
[
asset_group
]
.
get
(
'rule'
,
set
())}
return
perm
def
_public_perm_api
(
info
):
def
get_group_asset_perm
(
ob
):
"""
公用的用户,用户组,主机,主机组编辑修改新建调用的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']
ob为资产或资产组
获取资产,资产组授权的用户,用户组
return:
{’user_group': {
user_group1: {'user': [], 'role': [role1, role2], 'rule': [rule1, rule2]},
user_group2: {'user: [], 'role': [role1, role2], 'rule': [rule1, rule2]},
}
'user':{
user1: {'role': [role1, role2], 'rule': [rule1, rule2]},
user2: {'role': [role1, role2], 'rule': [rule1, rule2]},
}
]},
'rule':[rule1, rule2,]
}
"""
perm
=
{}
if
isinstance
(
ob
,
Asset
):
rule_all
=
PermRule
.
objects
.
filter
(
asset
=
ob
)
elif
isinstance
(
ob
,
AssetGroup
):
rule_all
=
PermRule
.
objects
.
filter
(
asset_group
=
ob
)
else
:
rule_all
=
[]
perm
[
'rule'
]
=
rule_all
perm_user_group
=
perm
[
'user_group'
]
=
{}
perm_user
=
perm
[
'user'
]
=
{}
for
rule
in
rule_all
:
user_groups
=
rule
.
user_group
.
all
()
users
=
rule
.
user
.
all
()
# 获取一个规则资产的用户
for
user
in
users
:
if
perm_user
.
get
(
user
):
perm_user
[
user
]
.
get
(
'role'
,
set
())
.
update
(
set
(
rule
.
role
.
all
()))
perm_user
[
user
]
.
get
(
'rule'
,
set
())
.
add
(
rule
)
else
:
perm_user
[
user
]
=
{
'role'
:
set
(
rule
.
role
.
all
()),
'rule'
:
set
([
rule
])}
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
}
}
user_group_users
=
user_group
.
user_set
.
all
()
if
perm_user_group
.
get
(
user_group
):
perm_user_group
[
user_group
]
.
get
(
'role'
,
set
())
.
update
(
set
(
rule
.
role
.
all
()))
perm_user_group
[
user_group
]
.
get
(
'rule'
,
set
())
.
add
(
rule
)
else
:
perm_user_group
[
user_group
]
=
{
'role'
:
set
(
rule
.
role
.
all
()),
'rule'
:
set
([
rule
]),
'user'
:
user_group_users
}
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'
,
[])
# 将用户组中的资产添加到用户授权中
for
user
in
user_group_users
:
if
perm_user
.
get
(
user
):
perm_user
[
user
]
.
get
(
'role'
,
set
())
.
update
(
perm_user_group
[
user_group
]
.
get
(
'role'
,
set
()))
perm_user
[
user
]
.
get
(
'rule'
,
set
())
.
update
(
perm_user_group
[
user_group
]
.
get
(
'rule'
,
set
()))
else
:
perm_user
[
user
]
=
{
'role'
:
perm_user_group
[
user_group
]
.
get
(
'role'
,
set
()),
'rule'
:
perm_user_group
[
user_group
]
.
get
(
'rule'
,
set
())}
return
perm
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
gen_resource
(
ob
,
ex
=
''
,
perm
=
None
):
"""
ob为用户或资产列表或资产queryset, 如果同时输入用户和资产,则获取用户在这些资产上的信息
生成MyInventory需要的 resource文件
"""
res
=
[]
if
isinstance
(
ob
,
User
)
and
isinstance
(
ex
,
(
list
,
QuerySet
)):
if
not
perm
:
perm
=
get_group_user_perm
(
ob
)
for
asset
,
asset_info
in
perm
.
get
(
'asset'
)
.
items
():
if
asset
not
in
ex
:
continue
asset_info
=
get_asset_info
(
asset
)
info
=
{
'hostname'
:
asset
.
hostname
,
'ip'
:
asset
.
ip
,
'port'
:
asset_info
.
get
(
'port'
,
22
)}
try
:
role
=
sorted
(
list
(
perm
.
get
(
'asset'
)
.
get
(
asset
)
.
get
(
'role'
)))[
0
]
except
IndexError
:
continue
info
[
'username'
]
=
role
.
name
info
[
'password'
]
=
role
.
password
info
[
'ssh_key'
]
=
get_role_key
(
ob
,
role
)
res
.
append
(
info
)
elif
isinstance
(
ob
,
User
):
if
not
perm
:
perm
=
get_group_user_perm
(
ob
)
for
asset
,
asset_info
in
perm
.
get
(
'asset'
)
.
items
():
asset_info
=
get_asset_info
(
asset
)
info
=
{
'hostname'
:
asset
.
hostname
,
'ip'
:
asset
.
ip
,
'port'
:
asset_info
.
get
(
'port'
,
22
)}
try
:
role
=
sorted
(
list
(
perm
.
get
(
'asset'
)
.
get
(
asset
)
.
get
(
'role'
)))[
0
]
except
IndexError
:
continue
info
[
'username'
]
=
role
.
name
info
[
'password'
]
=
role
.
password
info
[
'ssh_key'
]
=
get_role_key
(
ob
,
role
)
res
.
append
(
info
)
elif
isinstance
(
ob
,
(
list
,
QuerySet
)):
for
asset
in
ob
:
info
=
get_asset_info
(
asset
)
res
.
append
(
info
)
return
res
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
}
}
def
get_object_list
(
model
,
id_list
):
"""根据id列表获取对象列表"""
object_list
=
[]
for
object_id
in
id_list
:
if
object_id
:
object_list
.
extend
(
model
.
objects
.
filter
(
id
=
int
(
object_id
)))
results
=
perm_user_api
(
perm_info
)
return
results
return
object_list
def
get_role_info
(
role_id
,
type
=
"all"
):
...
...
jperm/urls.py
View file @
b8cb6f42
...
...
@@ -13,11 +13,4 @@ urlpatterns = patterns('jperm.views',
(
r'^role/perm_role_detail/$'
,
perm_role_detail
),
(
r'^role/perm_role_edit/$'
,
perm_role_edit
),
(
r'^role/perm_role_push/$'
,
perm_role_push
),
(
r'^log/$'
,
log
),
(
r'^sys_user_add/$'
,
sys_user_add
),
(
r'^perm_user_list/$'
,
sys_user_list
),
(
r'^sys_user_del/$'
,
sys_user_del
),
(
r'^sys_user_edit/$'
,
sys_user_edit
),
)
jperm/utils.py
View file @
b8cb6f42
...
...
@@ -4,7 +4,7 @@ import random
import
os.path
from
paramiko.rsakey
import
RSAKey
from
os
import
chmod
,
mkdir
from
jumpserver.api
import
mkdir
from
uuid
import
uuid4
from
jumpserver.settings
import
KEY_DIR
...
...
@@ -45,13 +45,13 @@ def gen_keys():
:return: 返回目录名(uuid)
"""
key_basename
=
"key-"
+
uuid4
()
.
hex
key_path_dir
=
os
.
path
.
join
(
KEY_DIR
,
key_basename
)
mkdir
(
key_path_dir
,
0700
)
key_path_dir
=
os
.
path
.
join
(
KEY_DIR
,
'role_key'
,
key_basename
)
mkdir
(
key_path_dir
,
0755
)
key
=
RSAKey
.
generate
(
2048
)
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
(),
...
...
@@ -62,8 +62,6 @@ def gen_keys():
return
key_path_dir
if
__name__
==
"__main__"
:
print
gen_keys
()
...
...
jperm/views.py
View file @
b8cb6f42
# -*- coding: utf-8 -*-
from
django.db.models
import
Q
from
jperm.perm_api
import
*
from
jperm.models
import
PermLog
as
Log
from
jperm.models
import
SysUser
from
juser.user_api
import
gen_ssh_key
from
juser.models
import
User
,
UserGroup
from
jasset.models
import
Asset
,
AssetGroup
from
jperm.models
import
PermRole
,
PermRule
from
jumpserver.models
import
Setting
from
jperm.utils
import
updates_dict
,
gen_keys
,
get_rand_pass
from
jperm.ansible_api
import
Tasks
from
jperm.perm_api
import
get_role_info
from
jumpserver.api
import
my_render
,
get_object
from
jumpserver.api
import
my_render
,
get_object
,
CRYPTOR
@require_role
(
'admin'
)
...
...
@@ -62,7 +60,7 @@ def perm_rule_detail(request):
assets
=
asset_obj
return
my_render
(
'jperm/perm_rule_detail.html'
,
locals
(),
request
)
def
perm_rule_add
(
request
):
"""
...
...
@@ -89,7 +87,8 @@ def perm_rule_add(request):
asset_groups_select
=
request
.
POST
.
getlist
(
'assetgroup'
,
[])
roles_select
=
request
.
POST
.
getlist
(
'role'
,
[])
rule_name
=
request
.
POST
.
get
(
'rulename'
)
rule_comment
=
request
.
POST
.
get
(
'comment'
)
rule_comment
=
request
.
POST
.
get
(
'rule_comment'
)
rule_ssh_key
=
request
.
POST
.
get
(
"use_publicKey"
)
# 获取需要授权的主机列表
assets_obj
=
[
Asset
.
objects
.
get
(
ip
=
asset
)
for
asset
in
assets_select
]
...
...
@@ -115,7 +114,19 @@ def perm_rule_add(request):
rule
.
asset_group
=
asset_groups_obj
rule
.
role
=
roles_obj
rule
.
save
()
return
HttpResponse
(
u"添加授权规则:
%
s"
%
rule
.
name
)
msg
=
u"添加授权规则:
%
s"
%
rule
.
name
# 渲染数据
header_title
,
path1
,
path2
=
"授权规则"
,
"规则管理"
,
"查看规则"
rules_list
=
PermRule
.
objects
.
all
()
# TODO: 搜索和分页
keyword
=
request
.
GET
.
get
(
'search'
,
''
)
if
keyword
:
rules_list
=
rules_list
.
filter
(
Q
(
name
=
keyword
))
rules_list
,
p
,
rules
,
page_range
,
current_page
,
show_first
,
show_end
=
pages
(
rules_list
,
request
)
return
my_render
(
'jperm/perm_rule_list.html'
,
locals
(),
request
)
@require_role
(
'admin'
)
...
...
@@ -131,17 +142,69 @@ def perm_rule_edit(request):
rule
=
PermRule
.
objects
.
get
(
id
=
rule_id
)
if
request
.
method
==
'GET'
and
rule_id
:
# 渲染数据, 获取所有的rule对象
users
=
rule
.
user
.
all
()
user_groups
=
rule
.
user_group
.
all
()
assets
=
rule
.
asset
.
all
()
asset_groups
=
rule
.
asset_group
.
all
()
roles
=
rule
.
role
.
all
()
# 渲染数据, 获取所选的rule对象
rule_comment
=
rule
.
comment
users_select
=
rule
.
user
.
all
()
user_groups_select
=
rule
.
user_group
.
all
()
assets_select
=
rule
.
asset
.
all
()
asset_groups_select
=
rule
.
asset_group
.
all
()
roles_select
=
rule
.
role
.
all
()
users
=
User
.
objects
.
all
()
user_groups
=
UserGroup
.
objects
.
all
()
assets
=
Asset
.
objects
.
all
()
asset_groups
=
AssetGroup
.
objects
.
all
()
roles
=
PermRole
.
objects
.
all
()
return
my_render
(
'jperm/perm_rule_edit.html'
,
locals
(),
request
)
elif
request
.
method
==
'POST'
and
rule_id
:
return
HttpResponse
(
"uncompleted"
)
# 获取用户选择的 用户,用户组,资产,资产组,用户角色
rule_name
=
request
.
POST
.
get
(
'rule_name'
)
rule_comment
=
request
.
POST
.
get
(
"rule_comment"
)
users_select
=
request
.
POST
.
getlist
(
'user'
,
[])
user_groups_select
=
request
.
POST
.
getlist
(
'usergroup'
,
[])
assets_select
=
request
.
POST
.
getlist
(
'asset'
,
[])
asset_groups_select
=
request
.
POST
.
getlist
(
'assetgroup'
,
[])
roles_select
=
request
.
POST
.
getlist
(
'role'
,
[])
# 获取需要授权的主机列表
assets_obj
=
[
Asset
.
objects
.
get
(
ip
=
asset
)
for
asset
in
assets_select
]
asset_groups_obj
=
[
AssetGroup
.
objects
.
get
(
name
=
group
)
for
group
in
asset_groups_select
]
group_assets_obj
=
[
asset
for
asset
in
[
group
.
asset_set
.
all
()
for
group
in
asset_groups_obj
]]
calc_assets
=
set
(
group_assets_obj
)
|
set
(
assets_obj
)
# 获取需要授权的用户列表
users_obj
=
[
User
.
objects
.
get
(
name
=
user
)
for
user
in
users_select
]
user_groups_obj
=
[
UserGroup
.
objects
.
get
(
name
=
group
)
for
group
in
user_groups_select
]
group_users_obj
=
[
user
for
user
in
[
group
.
user_set
.
all
()
for
group
in
user_groups_obj
]]
calc_users
=
set
(
group_users_obj
)
|
set
(
users_obj
)
# 获取授予的角色列表
roles_obj
=
[
PermRole
.
objects
.
get
(
name
=
role
)
for
role
in
roles_select
]
# 仅授权成功的,写回数据库(授权规则,用户,用户组,资产,资产组,用户角色)
rule
.
user
=
users_obj
rule
.
usergroup
=
user_groups_obj
rule
.
asset
=
assets_obj
rule
.
asset_group
=
asset_groups_obj
rule
.
role
=
roles_obj
rule
.
name
=
rule_name
rule
.
comment
=
rule
.
comment
rule
.
save
()
msg
=
u"更新授权规则:
%
s"
%
rule
.
name
# 渲染数据
header_title
,
path1
,
path2
=
"授权规则"
,
"规则管理"
,
"查看规则"
rules_list
=
PermRule
.
objects
.
all
()
# TODO: 搜索和分页
keyword
=
request
.
GET
.
get
(
'search'
,
''
)
if
keyword
:
rules_list
=
rules_list
.
filter
(
Q
(
name
=
keyword
))
rules_list
,
p
,
rules
,
page_range
,
current_page
,
show_first
,
show_end
=
pages
(
rules_list
,
request
)
return
my_render
(
'jperm/perm_rule_list.html'
,
locals
(),
request
)
@require_role
(
'admin'
)
...
...
@@ -201,12 +264,24 @@ def perm_role_add(request):
name
=
request
.
POST
.
get
(
"role_name"
)
comment
=
request
.
POST
.
get
(
"role_comment"
)
password
=
request
.
POST
.
get
(
"role_password"
)
encrypt_pass
=
CRYPTOR
.
encrypt
(
password
)
# 生成随机密码,生成秘钥对
key_path
=
gen_keys
()
role
=
PermRole
(
name
=
name
,
comment
=
comment
,
password
=
password
,
key_path
=
key_path
)
role
=
PermRole
(
name
=
name
,
comment
=
comment
,
password
=
encrypt_pass
,
key_path
=
key_path
)
role
.
save
()
return
HttpResponse
(
u"添加角色:
%
s"
%
name
)
msg
=
u"添加角色:
%
s"
%
name
# 渲染 刷新数据
header_title
,
path1
,
path2
=
"系统角色"
,
"角色管理"
,
"查看角色"
roles_list
=
PermRole
.
objects
.
all
()
# TODO: 搜索和分页
keyword
=
request
.
GET
.
get
(
'search'
,
''
)
if
keyword
:
roles_list
=
roles_list
.
filter
(
Q
(
name
=
keyword
))
roles_list
,
p
,
roles
,
page_range
,
current_page
,
show_first
,
show_end
=
pages
(
roles_list
,
request
)
return
my_render
(
'jperm/perm_role_list.html'
,
locals
(),
request
)
else
:
return
HttpResponse
(
u"不支持该操作"
)
...
...
@@ -252,8 +327,12 @@ def perm_role_detail(request):
role_info
=
get_role_info
(
role_id
)
# 渲染数据
for
key
,
value
in
role_info
.
iteritems
():
key
=
value
rules
=
role_info
.
get
(
"rules"
)
assets
=
role_info
.
get
(
"assets"
)
asset_groups
=
role_info
.
get
(
"asset_groups"
)
users
=
role_info
.
get
(
"users"
)
user_groups
=
role_info
.
get
(
"user_groups"
)
return
my_render
(
'jperm/perm_role_detail.html'
,
locals
(),
request
)
...
...
@@ -265,15 +344,38 @@ def perm_role_edit(request):
# 渲染数据
header_title
,
path1
,
path2
=
"系统角色"
,
"角色管理"
,
"角色编辑"
# 渲染数据
role_id
=
request
.
GET
.
get
(
"id"
)
role
=
PermRole
.
objects
.
get
(
id
=
role_id
)
role_pass
=
CRYPTOR
.
decrypt
(
role
.
password
)
if
request
.
method
==
"GET"
:
role_id
=
request
.
GET
.
get
(
"id"
)
# 渲染数据
role
=
PermRole
.
objects
.
get
(
id
=
role_id
)
return
my_render
(
'jperm/perm_role_edit.html'
,
locals
(),
request
)
if
request
.
method
==
"POST"
:
return
HttpResponse
(
u"未实现"
)
# 获取 POST 数据
role_name
=
request
.
POST
.
get
(
"role_name"
)
role_password
=
request
.
POST
.
get
(
"role_password"
)
encrypt_role_pass
=
CRYPTOR
.
encrypt
(
role_password
)
role_comment
=
request
.
POST
.
get
(
"role_comment"
)
# 写入数据库
role
.
name
=
role_name
role
.
password
=
encrypt_role_pass
role
.
comment
=
role_comment
role
.
save
()
msg
=
u"更新系统角色:
%
s"
%
role
.
name
# 渲染 刷新数据
header_title
,
path1
,
path2
=
"系统角色"
,
"角色管理"
,
"查看角色"
roles_list
=
PermRole
.
objects
.
all
()
# TODO: 搜索和分页
keyword
=
request
.
GET
.
get
(
'search'
,
''
)
if
keyword
:
roles_list
=
roles_list
.
filter
(
Q
(
name
=
keyword
))
roles_list
,
p
,
roles
,
page_range
,
current_page
,
show_first
,
show_end
=
pages
(
roles_list
,
request
)
return
my_render
(
'jperm/perm_role_list.html'
,
locals
(),
request
)
@require_role
(
'admin'
)
...
...
@@ -307,10 +409,20 @@ def perm_role_push(request):
calc_assets
=
set
(
assets_obj
)
|
set
(
group_assets_obj
)
# 生成Inventory
push_resource
=
[{
"hostname"
:
asset
.
ip
,
"port"
:
asset
.
port
,
"username"
:
asset
.
username
,
"password"
:
asset
.
password
}
for
asset
in
calc_assets
]
push_resource
=
[]
for
asset
in
calc_assets
:
if
asset
.
use_default_auth
:
username
=
Setting
.
default_user
password
=
Setting
.
default_password
port
=
Setting
.
default_port
else
:
username
=
asset
.
username
password
=
asset
.
password
port
=
asset
.
port
push_resource
.
append
({
"hostname"
:
asset
.
ip
,
"port"
:
port
,
"username"
:
username
,
"password"
:
password
})
# 获取角色的推送方式,以及推送需要的信息
roles_obj
=
[
PermRole
.
objects
.
get
(
name
=
role_name
)
for
role_name
in
role_names
]
...
...
@@ -326,10 +438,13 @@ def perm_role_push(request):
task
=
Tasks
(
push_resource
)
ret
=
{}
ret_failed
=
[]
if
password_push
:
ret
[
"password_push"
]
=
task
.
add_multi_user
(
**
role_pass
)
if
ret
[
"password_push"
]
.
get
(
"status"
)
!=
"success"
:
ret_failed
.
append
(
1
)
# 因为要先建立用户,所以password 是必选项,
# 而push key是在 password也完成的情况下的 可选项
ret
[
"password_push"
]
=
task
.
add_multi_user
(
**
role_pass
)
if
ret
[
"password_push"
]
.
get
(
"status"
)
!=
"success"
:
ret_failed
.
append
(
1
)
if
key_push
:
ret
[
"key_push"
]
=
task
.
push_multi_key
(
**
role_key
)
if
ret
[
"key_push"
]
.
get
(
"status"
)
!=
"success"
:
...
...
@@ -341,108 +456,3 @@ def perm_role_push(request):
else
:
return
HttpResponse
(
u"推送系统角色:
%
s"
%
','
.
join
(
role_names
))
@require_role
(
'admin'
)
def
perm_group_list
(
request
):
header_title
,
path1
,
path2
=
'用户组授权'
,
'授权管理'
,
'用户组授权'
keyword
=
request
.
GET
.
get
(
'search'
,
''
)
user_groups_list
=
UserGroup
.
objects
.
all
()
if
keyword
:
request
=
user_groups_list
.
filter
(
Q
(
name
=
keyword
)
|
Q
(
comment
=
keyword
))
user_groups_list
,
p
,
user_groups
,
page_range
,
current_page
,
show_first
,
show_end
=
pages
(
user_groups_list
,
request
)
return
my_render
(
'jperm/perm_group_list.html'
,
locals
(),
request
)
@require_role
(
'admin'
)
def
perm_group_edit
(
request
):
header_title
,
path1
,
path2
=
'用户组授权'
,
'授权管理'
,
'授权更改'
user_group_id
=
request
.
GET
.
get
(
'id'
,
''
)
user_group
=
get_object
(
UserGroup
,
id
=
user_group_id
)
asset_all
=
Asset
.
objects
.
all
()
asset_group_all
=
AssetGroup
.
objects
.
all
()
asset_permed
=
user_group
.
asset
.
all
()
# 获取授权的资产对象列表
asset_group_permed
=
user_group
.
asset_group
.
all
()
# 获取授权的资产组对象列表
if
request
.
method
==
'GET'
and
user_group
:
assets
=
[
asset
for
asset
in
asset_all
if
asset
not
in
asset_permed
]
asset_groups
=
[
asset_group
for
asset_group
in
asset_group_all
if
asset_group
not
in
asset_group_permed
]
return
my_render
(
'jperm/perm_group_edit.html'
,
locals
(),
request
)
elif
request
.
method
==
'POST'
and
user_group
:
asset_id_select
=
request
.
POST
.
getlist
(
'asset_select'
,
[])
asset_group_id_select
=
request
.
POST
.
getlist
(
'asset_groups_select'
,
[])
asset_select
=
get_object_list
(
Asset
,
asset_id_select
)
asset_group_select
=
get_object_list
(
AssetGroup
,
asset_group_id_select
)
asset_new
=
list
(
set
(
asset_select
)
-
set
(
asset_permed
))
# 计算的得到新授权的资产对象列表
asset_del
=
list
(
set
(
asset_permed
)
-
set
(
asset_select
))
# 计算得到回收权限的资产对象列表
asset_group_new
=
list
(
set
(
asset_group_select
)
-
set
(
asset_group_permed
))
# 新授权的资产组对象列表
asset_group_del
=
list
(
set
(
asset_group_permed
)
-
set
(
asset_group_select
))
# 回收的资产组对象列表
users
=
user_group
.
user_set
.
all
()
perm_info
=
{
'action'
:
'perm group edit: '
+
user_group
.
name
,
'del'
:
{
'users'
:
users
,
'assets'
:
asset_del
},
'new'
:
{
'users'
:
users
,
'assets'
:
asset_new
}
}
results
=
perm_user_api
(
perm_info
)
unreachable_asset
=
[]
failures_asset
=
[]
for
ip
in
results
.
get
(
'unreachable'
):
unreachable_asset
.
extend
(
filter
(
lambda
x
:
x
,
Asset
.
objects
.
filter
(
ip
=
ip
)))
for
ip
in
results
.
get
(
'failures'
):
failures_asset
.
extend
(
filter
(
lambda
x
:
x
,
Asset
.
objects
.
filter
(
ip
=
ip
)))
failures_asset
.
extend
(
unreachable_asset
)
# 失败的授权要统计
for
asset
in
failures_asset
:
if
asset
in
asset_select
:
asset_select
.
remove
(
asset
)
else
:
asset_select
.
append
(
asset
)
user_group
.
asset
=
asset_select
user_group
.
asset_group
=
asset_group_select
user_group
.
save
()
# 保存到数据库
return
HttpResponse
(
json
.
dumps
(
results
,
sort_keys
=
True
,
indent
=
4
),
content_type
=
"application/json"
)
else
:
return
HttpResponse
(
'输入错误'
)
def
log
(
request
):
header_title
,
path1
,
path2
=
'授权记录'
,
'授权管理'
,
'授权记录'
log_all
=
Log
.
objects
.
all
()
.
order_by
(
'-datetime'
)
log_all
,
p
,
logs
,
page_range
,
current_page
,
show_first
,
show_end
=
pages
(
log_all
,
request
)
return
my_render
(
'jperm/perm_log.html'
,
locals
(),
request
)
def
sys_user_add
(
request
):
asset_group_all
=
AssetGroup
.
objects
.
all
()
if
request
.
method
==
'POST'
:
username
=
request
.
POST
.
get
(
'username'
,
''
)
password
=
request
.
POST
.
get
(
'password'
,
''
)
asset_groups_id
=
request
.
POST
.
getlist
(
'asset_groups_select'
,
[])
comment
=
request
.
POST
.
get
(
'comment'
)
sys_user
=
SysUser
(
username
=
username
,
password
=
password
,
comment
=
comment
)
sys_user
.
save
()
gen_ssh_key
(
username
,
key_dir
=
os
.
path
.
join
(
SSH_KEY_DIR
,
'sysuser'
),
authorized_keys
=
False
)
results
=
push_user
(
sys_user
,
asset_groups_id
)
return
HttpResponse
(
json
.
dumps
(
results
,
sort_keys
=
True
,
indent
=
4
),
content_type
=
"application/json"
)
return
my_render
(
'jperm/sys_user_add.html'
,
locals
(),
request
)
def
sys_user_list
(
request
):
users_list
=
SysUser
.
objects
.
all
()
users_list
,
p
,
users
,
page_range
,
current_page
,
show_first
,
show_end
=
pages
(
users_list
,
request
)
return
my_render
(
'jperm/sys_user_list.html'
,
locals
(),
request
)
def
sys_user_edit
(
request
):
pass
def
sys_user_del
(
request
):
pass
jumpserver/api.py
View file @
b8cb6f42
...
...
@@ -3,26 +3,27 @@
import
os
,
sys
,
time
,
re
from
Crypto.Cipher
import
AES
import
crypt
import
pwd
from
binascii
import
b2a_hex
,
a2b_hex
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
jasset.models
import
Asset
,
AssetGroup
# from jlog.models import Log
from
jlog.models
import
Log
,
TtyLog
from
django.core.exceptions
import
ObjectDoesNotExist
,
MultipleObjectsReturned
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
):
...
...
@@ -30,11 +31,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
)
...
...
@@ -42,6 +47,63 @@ def set_log(level):
return
logger_f
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
try
:
uid
=
pwd
.
getpwnam
(
user
)
.
pw_uid
gid
=
pwd
.
getpwnam
(
group
)
.
pw_gid
os
.
chown
(
path
,
uid
,
gid
)
except
KeyError
:
pass
def
page_list_return
(
total
,
current
=
1
):
"""
page
...
...
@@ -159,8 +221,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
'
)
...
...
@@ -197,9 +258,9 @@ def require_role(role='user'):
def
_deco
(
func
):
def
__deco
(
request
,
*
args
,
**
kwargs
):
request
.
session
[
'pre_url'
]
=
request
.
path
if
not
request
.
user
.
is_authenticated
():
return
HttpResponseRedirect
(
'/login/'
)
if
role
==
'admin'
:
# if request.session.get('role_id', 0) < 1:
if
request
.
user
.
role
==
'CU'
:
...
...
@@ -388,15 +449,16 @@ def bash(cmd):
return
subprocess
.
call
(
cmd
,
shell
=
True
)
def
mkdir
(
dir_name
,
username
=
'
root
'
,
mode
=
0755
):
def
mkdir
(
dir_name
,
username
=
''
,
mode
=
0755
):
"""
insure the dir exist and mode ok
目录存在,如果不存在就建立,并且权限正确
"""
if
not
os
.
path
.
isdir
(
dir_name
):
os
.
makedirs
(
dir_name
)
bash
(
"chown
%
s:
%
s '
%
s'"
%
(
username
,
username
,
dir_name
))
os
.
chmod
(
dir_name
,
mode
)
os
.
chmod
(
dir_name
,
mode
)
if
username
:
chown
(
dir_name
,
username
)
def
http_success
(
request
,
msg
):
...
...
@@ -414,4 +476,3 @@ def my_render(template, data, request):
CRYPTOR
=
PyCrypt
(
KEY
)
logger
=
set_log
(
LOG_LEVEL
)
KEY_DIR
=
os
.
path
.
join
(
BASE_DIR
,
'keys'
)
jumpserver/settings.py
View file @
b8cb6f42
...
...
@@ -17,8 +17,8 @@ config = ConfigParser.ConfigParser()
BASE_DIR
=
os
.
path
.
abspath
(
os
.
path
.
dirname
(
os
.
path
.
dirname
(
__file__
)))
config
.
read
(
os
.
path
.
join
(
BASE_DIR
,
'jumpserver.conf'
))
KEY_DIR
=
os
.
path
.
join
(
BASE_DIR
,
'keys'
)
KEY_DIR
=
os
.
path
.
join
(
BASE_DIR
,
'role_keys'
)
DB_HOST
=
config
.
get
(
'db'
,
'host'
)
DB_PORT
=
config
.
getint
(
'db'
,
'port'
)
...
...
@@ -37,7 +37,7 @@ EMAIL_TIMEOUT = 5
# ======== Log ==========
LOG_DIR
=
os
.
path
.
join
(
BASE_DIR
,
'logs'
)
SSH_KEY_DIR
=
os
.
path
.
join
(
BASE_DIR
,
'role_keys'
)
SSH_KEY_DIR
=
os
.
path
.
join
(
BASE_DIR
,
'
keys/
role_keys'
)
KEY
=
config
.
get
(
'base'
,
'key'
)
URL
=
config
.
get
(
'base'
,
'url'
)
LOG_LEVEL
=
config
.
get
(
'base'
,
'log'
)
...
...
jumpserver/templatetags/mytags.py
View file @
b8cb6f42
...
...
@@ -226,3 +226,14 @@ def ip_str_to_list(ip_str):
ip str to list
"""
return
ip_str
.
split
(
','
)
@register.filter
(
name
=
'key_exist'
)
def
key_exist
(
username
):
"""
ssh key is exist or not
"""
if
os
.
path
.
isfile
(
os
.
path
.
join
(
KEY_DIR
,
'user'
,
username
)):
return
True
else
:
return
False
jumpserver/views.py
View file @
b8cb6f42
...
...
@@ -15,7 +15,6 @@ from jumpserver.api import *
from
jumpserver.models
import
Setting
from
django.contrib.auth
import
authenticate
,
login
,
logout
from
django.contrib.auth.decorators
import
login_required
from
settings
import
BASE_DIR
from
jlog.models
import
Log
...
...
@@ -80,18 +79,19 @@ def index_cu(request):
# user = get_object(User, id=user_id)
login_types
=
{
'L'
:
'LDAP'
,
'M'
:
'MAP'
}
username
=
request
.
user
.
username
posts
=
Asset
.
object
.
all
()
host_count
=
len
(
posts
)
new_posts
=
[]
post_five
=
[]
for
post
in
posts
:
if
len
(
post_five
)
<
5
:
post_five
.
append
(
post
)
else
:
new_posts
.
append
(
post_five
)
post_five
=
[]
new_posts
.
append
(
post_five
)
# TODO: need fix,liuzheng need Asset help
# posts = Asset.object.all()
# host_count = len(posts)
#
# new_posts = []
# post_five = []
# for post in posts:
# if len(post_five) < 5:
# post_five.append(post)
# else:
# new_posts.append(post_five)
# post_five = []
# new_posts.append(post_five)
return
render_to_response
(
'index_cu.html'
,
locals
(),
context_instance
=
RequestContext
(
request
))
...
...
@@ -235,7 +235,7 @@ def Login(request):
request
.
session
[
'role_id'
]
=
1
else
:
request
.
session
[
'role_id'
]
=
0
return
HttpResponseRedirect
(
request
.
GET
.
get
(
'next'
,
'/'
),
)
return
HttpResponseRedirect
(
request
.
session
.
get
(
'pre_url'
,
'/'
)
)
# response.set_cookie('username', username, expires=604800)
# response.set_cookie('seed', PyCrypt.md5_crypt(password), expires=604800)
# return response
...
...
@@ -268,7 +268,7 @@ def setting(request):
if
''
in
[
username
,
port
]
and
(
''
in
password
or
''
in
private_key
):
return
HttpResponse
(
'所填内容不能为空, 且密码和私钥填一个'
)
else
:
private_key_path
=
os
.
path
.
join
(
BASE_DIR
,
'role_keys'
,
'default'
,
'default_private_key.pem'
)
private_key_path
=
os
.
path
.
join
(
BASE_DIR
,
'
keys/
role_keys'
,
'default'
,
'default_private_key.pem'
)
if
private_key
:
with
open
(
private_key_path
,
'w'
)
as
f
:
f
.
write
(
private_key
)
...
...
juser/user_api.py
View file @
b8cb6f42
...
...
@@ -123,27 +123,27 @@ def db_del_user(username):
def
gen_ssh_key
(
username
,
password
=
''
,
key_dir
=
os
.
path
.
join
(
KEY_DIR
,
'user'
),
authorized_keys
=
True
,
home
=
"/home"
,
length
=
2048
):
"""
generate a user ssh key in a property dir
生成一个用户ssh密钥对
"""
logger
.
debug
(
'生成ssh key, 并设置authorized_keys'
)
private_key_file
=
os
.
path
.
join
(
key_dir
,
username
)
mkdir
(
private_key_file
,
username
)
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
))
if
authorized_keys
:
auth_key_dir
=
os
.
path
.
join
(
home
,
username
,
'.ssh'
)
mkdir
(
auth_key_dir
,
username
,
mode
=
0700
)
mkdir
(
auth_key_dir
,
mode
=
0700
)
authorized_key_file
=
os
.
path
.
join
(
auth_key_dir
,
'authorized_keys'
)
with
open
(
private_key_file
+
'.pub'
)
as
pub_f
:
with
open
(
authorized_key_file
,
'w'
)
as
auth_f
:
auth_f
.
write
(
pub_f
.
read
())
os
.
chmod
(
authorized_key_file
,
0600
)
bash
(
'chown
%
s:
%
s
%
s'
%
(
username
,
username
,
authorized_key_file
)
)
chown
(
authorized_key_file
,
username
)
def
server_add_user
(
username
,
password
,
ssh_key_pwd
,
ssh_key_login_need
):
...
...
juser/views.py
View file @
b8cb6f42
...
...
@@ -96,36 +96,37 @@ def group_edit(request):
if
request
.
method
==
'GET'
:
group_id
=
request
.
GET
.
get
(
'id'
,
''
)
user_group
=
get_object
(
UserGroup
,
id
=
group_id
)
if
user_group
:
users_all
=
User
.
objects
.
all
(
)
users_selected
=
user_group
.
user_set
.
all
(
)
users_remain
=
[
user
for
user
in
users_all
if
user
not
in
users_selected
]
#
user_group = get_object(UserGroup, id=group_id)
user_group
=
UserGroup
.
objects
.
get
(
id
=
group_id
)
users_selected
=
User
.
objects
.
filter
(
group
=
user_group
)
users_remain
=
User
.
objects
.
filter
(
~
Q
(
group
=
user_group
)
)
users_all
=
User
.
objects
.
all
()
el
se
:
el
if
request
.
method
==
'POST'
:
group_id
=
request
.
POST
.
get
(
'group_id'
,
''
)
group_name
=
request
.
POST
.
get
(
'group_name'
,
''
)
comment
=
request
.
POST
.
get
(
'comment'
,
''
)
users_selected
=
request
.
POST
.
getlist
(
'users_selected'
)
users
=
[]
try
:
if
''
in
[
group_id
,
group_name
]:
raise
ServerError
(
'组名不能为空'
)
user_group
=
get_object
(
UserGroup
,
id
=
group_id
)
other_group
=
get_object
(
UserGroup
,
name
=
group_name
)
if
other_group
and
other_group
.
id
!=
int
(
group_id
):
if
len
(
UserGroup
.
objects
.
filter
(
name
=
group_name
))
>
1
:
raise
ServerError
(
u'
%
s 用户组已存在'
%
group_name
)
# add user group
for
user
in
User
.
objects
.
filter
(
id__in
=
users_selected
):
user
.
group
.
add
(
UserGroup
.
objects
.
get
(
id
=
group_id
))
# delete user group
user_group
=
UserGroup
.
objects
.
get
(
id
=
group_id
)
for
user
in
[
user
for
user
in
User
.
objects
.
filter
(
group
=
user_group
)
if
user
not
in
User
.
objects
.
filter
(
id__in
=
users_selected
)]:
user_group_all
=
user
.
group
.
all
()
user
.
group
.
clear
()
for
g
in
user_group_all
:
if
g
==
user_group
:
continue
user
.
group
.
add
(
g
)
for
user_id
in
users_selected
:
users
.
extend
(
User
.
objects
.
filter
(
id
=
user_id
))
if
user_group
:
user_group
.
update
(
name
=
group_name
,
comment
=
comment
)
user_group
.
user_set
.
clear
()
user_group
.
user_set
=
users
except
ServerError
,
e
:
error
=
e
...
...
@@ -133,8 +134,8 @@ def group_edit(request):
return
HttpResponseRedirect
(
'/juser/group_list/'
)
else
:
users_all
=
User
.
objects
.
all
()
users_selected
=
user_group
.
user_set
.
all
(
)
users_remain
=
[
user
for
user
in
users_all
if
user
not
in
users_selected
]
users_selected
=
User
.
objects
.
filter
(
group
=
user_group
)
users_remain
=
User
.
objects
.
filter
(
~
Q
(
group
=
user_group
))
return
my_render
(
'juser/group_edit.html'
,
locals
(),
request
)
...
...
keys/README.md
0 → 100644
View file @
b8cb6f42
看山是山,看水是水
看山不是山,看水不是水
看山是山,看水是水
logs/README.md
0 → 100644
View file @
b8cb6f42
永远年轻,永远热泪盈眶
playbook/user_perm.yaml
deleted
100644 → 0
View file @
d25e2362
-
hosts
:
the_del_group
tasks
:
-
name
:
del user
user
:
name={{ item }} state=absent remove=yes
with_items
:
[
the_del_users
]
-
hosts
:
the_new_group
tasks
:
-
name
:
add user
user
:
name={{ item }} state=present
with_items
:
[
the_new_users
]
-
name
:
.ssh direcotory
file
:
name=/home/{{ item }}/.ssh mode=700 owner={{ item }} group={{ item }} state=directory
with_items
:
[
the_new_users
]
-
name
:
set authorizied_file
copy
:
src=KEY_DIR/{{ item }}.pub dest=/home/{{ item }}/.ssh/authorizied_keys owner={{ item }} group={{ item }} mode=600
with_items
:
[
the_new_users
]
templates/index.html
View file @
b8cb6f42
...
...
@@ -14,7 +14,6 @@
</div>
<div
class=
"ibox-content"
>
<h1
class=
"no-margins"
><a
href=
"/juser/user_list/"
>
{{ users.count}}
</a></h1>
{#
<div
class=
"stat-percent font-bold text-success"
>
{{ percent_user }}
<i
class=
"fa fa-bolt"
></i></div>
#}
<small>
All user
</small>
</div>
</div>
...
...
@@ -27,7 +26,6 @@
</div>
<div
class=
"ibox-content"
>
<h1
class=
"no-margins"
><a
href=
"/jasset/host_list/"
>
{{ hosts.count }}
</a></h1>
{#
<div
class=
"stat-percent font-bold text-info"
>
{{ percent_host }}
<i
class=
"fa fa-level-up"
></i></div>
#}
<small>
All host
</small>
</div>
</div>
...
...
@@ -37,7 +35,7 @@
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<span
class=
"label label-primary pull-right"
>
Online
</span>
<h5>
实时
在线用户
</h5>
<h5>
在线用户
</h5>
</div>
<div
class=
"ibox-content"
>
<h1
class=
"no-margins"
><a
href=
"/jlog/log_list/online/"
>
<span
id=
"online_users"
>
{{ online_user | length }}
</span></a></h1>
...
...
@@ -55,7 +53,6 @@
</div>
<div
class=
"ibox-content"
>
<h1
class=
"no-margins"
><a
href=
"/jlog/log_list/online/"
>
<span
id=
"online_hosts"
>
{{ online_host | length }}
</span></a></h1>
{#
<div
class=
"stat-percent font-bold text-danger"
>
{{ percent_online_host }}
<i
class=
"fa fa-level-down"
></i></div>
#}
<small>
Connected host
</small>
</div>
</div>
...
...
@@ -169,7 +166,7 @@
</div>
</div>
<div
class=
"ibox-content ibox-heading"
>
<h3><i
class=
"fa fa-
user
"
></i>
一周Top10资产
</h3>
<h3><i
class=
"fa fa-
inbox
"
></i>
一周Top10资产
</h3>
<small><i
class=
"fa fa-map-marker"
></i>
登录次数及最近一次登录记录.
</small>
</div>
<div
class=
"ibox-content inspinia-timeline"
>
...
...
@@ -309,14 +306,7 @@
</div>
</div>
</div>
<!--</div>-->
<!--<div class="col-xm-6" id="top10" style="width:50%;height:400px;"></div>-->
<!--<div class="col-xm-6" id="usertop10" style="width:50%;height:400px;"></div>-->
<!--<div class="row">-->
<!--<div class="col-lg-6" id="hosttop10" style="width:50%;height:400px; margin-top: 20px"></div>-->
<!--</div>-->
</div>
</div>
</div>
{% endblock %}
...
...
templates/jasset/asset_add.html
View file @
b8cb6f42
...
...
@@ -48,6 +48,7 @@
{{ af.ip|bootstrap_horizontal }}
<p
class=
"col-sm-offset-2"
>
Tips: 如果IP地址不填写, IP默认会设置与主机名一致
</p>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"j_group"
class=
"col-sm-2 control-label"
>
管理账号
<span
class=
"red-fonts"
>
*
</span></label>
...
...
templates/jasset/asset_edit_batch.html
View file @
b8cb6f42
...
...
@@ -54,17 +54,29 @@
<div
class=
"col-sm-2"
>
<div
class=
"radio i-checks"
>
<label>
<
<<<<<<
HEAD
<
input
type=
"radio"
checked=
""
value=
"no_action"
id=
"no"
name=
"use_default_auth"
class=
"auth"
><span>
不修改
</span>
=======
<input
type=
"radio"
checked=
""
value=
""
id=
"no"
name=
"use_default_auth"
class=
"auth"
><span>
不修改
</span>
>>>>>>> cmdb
</label>
</div>
<div
class=
"radio i-checks"
>
<label>
<
<<<<<<
HEAD
<
input
type=
"radio"
id=
"default"
name=
"use_default_auth"
class=
"auth"
><span>
使用默认
</span>
=======
<input
type=
"radio"
id=
"default"
name=
"use_default_auth"
class=
"auth"
value=
"default"
><span>
使用默认
</span>
>>>>>>> cmdb
</label>
</div>
<div
class=
"radio i-checks"
>
<label>
<
<<<<<<
HEAD
<
input
type=
"radio"
id=
"pass"
name=
"use_default_auth"
class=
"auth"
><span>
用户名密码
</span>
=======
<input
type=
"radio"
id=
"pass"
name=
"use_default_auth"
class=
"auth"
value=
"user_passwd"
><span>
用户名密码
</span>
>>>>>>> cmdb
</label>
</div>
</div>
...
...
@@ -126,6 +138,21 @@
</div>
<script>
$
(
document
).
ready
(
function
()
{
<<<<<<<
HEAD
$
(
'#host_edit'
).
click
(
function
()
{
var
args
=
{};
var
match
=
null
;
var
uuid
=
decodeURIComponent
(
location
.
search
.
substring
(
1
));
var
reg
=
/
(?:([^
&
]
+
)
=
([^
&
]
+
))
/g
;
while
((
match
=
reg
.
exec
(
uuid
))
!==
null
){
args
[
match
[
1
]]
=
match
[
2
];
}
var
ids
=
args
[
'uuid'
];
$
(
'#uuid'
).
val
(
ids
)
});
=======
>>>>>>>
cmdb
$
(
'.auth'
).
click
(
function
(){
if
(
$
(
this
).
attr
(
'id'
)
==
'pass'
){
$
(
'#admin_account'
).
css
(
'display'
,
'block'
)
...
...
templates/jperm/perm_role_edit.html
View file @
b8cb6f42
...
...
@@ -40,6 +40,13 @@
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"role_password_label"
class=
"col-sm-2 control-label"
>
角色密码
<span
class=
"red-fonts"
>
*
</span></label>
<div
class=
"col-sm-8"
>
<input
id=
"role_password"
name=
"role_password"
type=
"password"
class=
"form-control"
value=
"{{ role_pass }}"
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"role_comment"
class=
"col-sm-2 control-label"
>
备注
</label>
<div
class=
"col-sm-8"
>
...
...
templates/jperm/perm_role_list.html
View file @
b8cb6f42
...
...
@@ -7,6 +7,14 @@
<div
class=
"row"
>
<div
class=
"col-lg-10"
>
<div
class=
"ibox float-e-margins"
>
<div>
{% if error %}
<div
class=
"alert alert-warning text-center"
>
{{ error }}
</div>
{% endif %}
{% if msg %}
<div
class=
"alert alert-success text-center"
>
{{ msg }}
</div>
{% endif %}
</div>
<div
class=
"ibox-title"
>
<h5>
所有系统角色
</h5>
<div
class=
"ibox-tools"
>
...
...
templates/jperm/perm_role_push.html
View file @
b8cb6f42
...
...
@@ -67,16 +67,6 @@
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"row"
>
<div
class=
"form-group"
>
<label
for=
"j_group"
class=
"col-sm-2 control-label"
>
使用密码
</label>
<div
class=
"col-sm-1"
>
<div
class=
"radio i-checks"
>
<label>
<input
type=
"checkbox"
value=
"1"
id=
"use_password"
name=
"use_password"
>
</label>
</div>
</div>
</div>
<div
class=
"form-group"
>
<label
for=
"j_group"
class=
"col-sm-2 control-label"
>
使用秘钥
</label>
<div
class=
"col-sm-1"
>
...
...
templates/jperm/perm_rule_add.html
View file @
b8cb6f42
...
...
@@ -26,7 +26,7 @@
</div>
</div>
<div
class=
"ibox-content"
>
<form
method=
"post"
id=
"
user
Form"
class=
"form-horizontal"
action=
""
>
<form
method=
"post"
id=
"
rule
Form"
class=
"form-horizontal"
action=
""
>
{% if error %}
<div
class=
"alert alert-warning text-center"
>
{{ error }}
</div>
{% endif %}
...
...
@@ -34,7 +34,7 @@
<div
class=
"alert alert-success text-center"
>
{{ msg }}
</div>
{% endif %}
<div
class=
"form-group"
>
<label
for=
"
user
name"
class=
"col-sm-2 control-label"
>
授权名称
<span
class=
"red-fonts"
>
*
</span></label>
<label
for=
"
rule
name"
class=
"col-sm-2 control-label"
>
授权名称
<span
class=
"red-fonts"
>
*
</span></label>
<div
class=
"col-sm-8"
>
<input
id=
"rulename"
name=
"rulename"
placeholder=
"Rule Name"
type=
"text"
class=
"form-control"
{%
if
error
%}
value=
"{{ username }}"
{%
endif
%}
>
</div>
...
...
@@ -48,11 +48,11 @@
<option
value=
"{{ user.name }}"
>
{{ user.name }}
</option>
{% endfor %}
</select>
<span
class=
"help-block m-b-none"
>
用户和用户组必选一个
</span>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"usergroup"
class=
"col-sm-2 control-label"
>
用户组
<
span
class=
"red-fonts"
>
*
</span><
/label>
<label
for=
"usergroup"
class=
"col-sm-2 control-label"
>
用户组
</label>
<div
class=
"col-sm-8"
>
<select
name=
"usergroup"
data-placeholder=
"请选择用户组"
class=
"chosen-select form-control m-b"
multiple
tabindex=
"2"
>
{% for user_group in user_groups %}
...
...
@@ -70,11 +70,11 @@
<option
value=
"{{ asset.ip }}"
>
{{ asset.ip }}
</option>
{% endfor %}
</select>
<span
class=
"help-block m-b-none"
>
资产和资产组必选一个
</span>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"assetgroup"
class=
"col-sm-2 control-label"
>
资产组
<
span
class=
"red-fonts"
>
*
</span><
/label>
<label
for=
"assetgroup"
class=
"col-sm-2 control-label"
>
资产组
</label>
<div
class=
"col-sm-8"
>
<select
name=
"assetgroup"
data-placeholder=
"请选择资产组"
class=
"chosen-select form-control m-b"
multiple
tabindex=
"2"
>
{% for asset_group in asset_groups %}
...
...
@@ -95,51 +95,11 @@
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"j_group"
class=
"col-sm-2 control-label"
>
使用密码
</label>
<div
class=
"col-sm-1"
>
<div
class=
"radio i-checks"
>
<label>
<input
type=
"checkbox"
value=
"0"
id=
"use_password"
name=
"use_password"
>
</label>
</div>
</div>
</div>
<div
class=
"form-group"
id=
"admin_account_password"
style=
"display: none"
>
<label
class=
"col-sm-1 control-label"
>
密码
<span
class=
"red-fonts"
>
*
</span>
</label>
<div
class=
"col-sm-4"
>
<input
type=
"password"
name=
"password"
class=
"form-control"
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"j_group"
class=
"col-sm-2 control-label"
>
使用秘钥
</label>
<div
class=
"col-sm-1"
>
<div
class=
"radio i-checks"
>
<label>
<input
type=
"checkbox"
value=
"1"
id=
"use_publicKey"
name=
"use_publicKey"
>
</label>
</div>
</div>
</div>
<div
class=
"form-group"
id=
"admin_account_publicKey"
style=
"display: none"
>
<label
class=
"col-sm-1 control-label"
>
秘钥
<span
class=
"red-fonts"
>
*
</span>
</label>
<div
class=
"col-sm-4"
>
<input
type=
"password"
name=
"password"
class=
"form-control"
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"comment"
class=
"col-sm-2 control-label"
>
备注
</label>
<div
class=
"col-sm-8"
>
<input
id=
"
comment"
name=
"
comment"
placeholder=
"Rule Comment"
type=
"text"
class=
"form-control"
{%
if
error
%}
value=
"{{ username }}"
{%
endif
%}
>
<input
id=
"
rule_comment"
name=
"rule_
comment"
placeholder=
"Rule Comment"
type=
"text"
class=
"form-control"
{%
if
error
%}
value=
"{{ username }}"
{%
endif
%}
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
...
...
@@ -158,6 +118,37 @@
{% endblock %}
{% block self_footer_js %}
<script>
$
(
'#ruleForm'
).
submit
(
function
()
{
var
result
=
{};
var
data
=
$
(
this
).
serializeArray
();
$
.
each
(
data
,
function
(
i
,
field
)
{
result
[
field
.
name
]
=
field
.
value
;
});
if
(
result
[
'user'
]
||
result
[
'usergroup'
]
||
result
[
'asset'
]
||
result
[
'assetgroup'
]
||
result
[
'rulename'
]
||
result
[
'role'
])
{
if
(
result
[
'rulename'
]
===
''
)
{
alert
(
"请添加授权名称"
);
return
false
}
if
(
!
result
[
'user'
]
&&
!
result
[
'usergroup'
])
{
alert
(
"用户和用户组必选1个"
);
return
false
}
if
(
!
result
[
'asset'
]
&&
!
result
[
'assetgroup'
])
{
alert
(
"资产和资产组必选1个"
);
return
false
}
if
(
!
result
[
'role'
])
{
alert
(
"请填写角色"
);
return
false
}
return
true
}
else
{
alert
(
"请填必选项"
);
return
false
;
}
});
$
(
document
).
ready
(
function
(){
$
(
"input.role"
).
click
(
function
(){
if
(
$
(
"input.role[value=GA]"
).
is
(
":checked"
)){
...
...
templates/jperm/perm_rule_edit.html
View file @
b8cb6f42
...
...
@@ -45,7 +45,7 @@
<div
class=
"col-sm-8"
>
<select
name=
"user"
data-placeholder=
"用户名"
class=
"chosen-select form-control m-b"
multiple
tabindex=
"2"
>
{% for user in users %}
<option
value=
"{{ user.name }}"
>
{{ user.name }}
</option>
<option
value=
"{{ user.name }}"
{%
if
user
in
users_select
%}
selected
{%
endif
%}
>
{{ user.name }}
</option>
{% endfor %}
</select>
</div>
...
...
@@ -56,7 +56,7 @@
<div
class=
"col-sm-8"
>
<select
name=
"usergroup"
data-placeholder=
"请选择用户组"
class=
"chosen-select form-control m-b"
multiple
tabindex=
"2"
>
{% for user_group in user_groups %}
<option
value=
"{{ user_group.name }}"
>
{{ user_group.name }}
</option>
<option
value=
"{{ user_group.name }}"
{%
if
user_group
in
users_groups_select
%}
selected
{%
endif
%}
>
{{ user_group.name }}
</option>
{% endfor %}
</select>
</div>
...
...
@@ -67,7 +67,7 @@
<div
class=
"col-sm-8"
>
<select
name=
"asset"
data-placeholder=
"请选择资产"
class=
"chosen-select form-control m-b"
multiple
tabindex=
"2"
>
{% for asset in assets %}
<option
value=
"{{ asset.ip }}"
>
{{ asset.ip }}
</option>
<option
value=
"{{ asset.ip }}"
{%
if
asset
in
assets_select
%}
selected
{%
endif
%}
>
{{ asset.ip }}
</option>
{% endfor %}
</select>
</div>
...
...
@@ -78,7 +78,7 @@
<div
class=
"col-sm-8"
>
<select
name=
"assetgroup"
data-placeholder=
"请选择资产组"
class=
"chosen-select form-control m-b"
multiple
tabindex=
"2"
>
{% for asset_group in asset_groups %}
<option
value=
"{{ asset_group.name }}"
>
{{ asset_group.name }}
</option>
<option
value=
"{{ asset_group.name }}"
{%
if
asset_group
in
asset_groups_select
%}
selected
{%
endif
%}
>
{{ asset_group.name }}
</option>
{% endfor %}
</select>
</div>
...
...
@@ -89,57 +89,17 @@
<div
class=
"col-sm-8"
>
<select
name=
"role"
data-placeholder=
"请选择角色"
class=
"chosen-select form-control m-b"
multiple
tabindex=
"2"
>
{% for role in roles %}
<option
value=
"{{ role.name }}"
>
{{ role.name }}
</option>
<option
value=
"{{ role.name }}"
{%
if
role
in
roles_select
%}
selected
{%
endif
%}
>
{{ role.name }}
</option>
{% endfor %}
</select>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"j_group"
class=
"col-sm-2 control-label"
>
使用密码
</label>
<div
class=
"col-sm-1"
>
<div
class=
"radio i-checks"
>
<label>
<input
type=
"checkbox"
value=
"0"
id=
"use_password"
name=
"use_password"
>
</label>
</div>
</div>
</div>
<div
class=
"form-group"
id=
"admin_account_password"
style=
"display: none"
>
<label
class=
"col-sm-1 control-label"
>
密码
<span
class=
"red-fonts"
>
*
</span>
</label>
<div
class=
"col-sm-4"
>
<input
type=
"password"
name=
"password"
class=
"form-control"
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"j_group"
class=
"col-sm-2 control-label"
>
使用秘钥
</label>
<div
class=
"col-sm-1"
>
<div
class=
"radio i-checks"
>
<label>
<input
type=
"checkbox"
value=
"1"
id=
"use_publicKey"
name=
"use_publicKey"
>
</label>
</div>
</div>
</div>
<div
class=
"form-group"
id=
"admin_account_publicKey"
style=
"display: none"
>
<label
class=
"col-sm-1 control-label"
>
秘钥
<span
class=
"red-fonts"
>
*
</span>
</label>
<div
class=
"col-sm-4"
>
<input
type=
"password"
name=
"password"
class=
"form-control"
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"comment"
class=
"col-sm-2 control-label"
>
备注
</label>
<div
class=
"col-sm-8"
>
<input
id=
"
comment"
name=
"comment"
placeholder=
"Comment"
type=
"text"
class=
"form-control"
{%
if
error
%}
value=
"{{ username }}"
{%
endif
%}
>
<input
id=
"
role_comment"
name=
"role_comment"
placeholder=
"Rule Comment"
type=
"text"
class=
"form-control"
value=
"{{ rule_comment }}"
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
...
...
templates/jperm/perm_rule_list.html
View file @
b8cb6f42
...
...
@@ -3,10 +3,20 @@
{% block content %}
{% include 'nav_cat_bar.html' %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-lg-10"
>
<div
class=
"ibox float-e-margins"
>
<div>
{% if error %}
<div
class=
"alert alert-warning text-center"
>
{{ error }}
</div>
{% endif %}
{% if msg %}
<div
class=
"alert alert-success text-center"
>
{{ msg }}
</div>
{% endif %}
</div>
<div
class=
"ibox-title"
>
<h5>
所有规则
</h5>
<div
class=
"ibox-tools"
>
...
...
@@ -55,19 +65,19 @@
<tr
class=
"gradeX"
id=
{{
rule
.
id
}}
>
<td
class=
"text-center"
>
{{ rule.name }}
</td>
<td
class=
"text-center"
>
<a
href=
"/jasset/asset_list/?gid={{ user.id }}"
>
{{ rule | rule_member_count:"user" }}
</a>
{{ rule | rule_member_count:"user" }}
</td>
<td
class=
"text-center"
>
<a
href=
"/jasset/group_list/?gid={{ user.id }}"
>
{{ rule | rule_member_count:"user_group" }}
</a>
{{ rule | rule_member_count:"user_group" }}
</td>
<td
class=
"text-center"
>
<a
href=
"/jasset/group_list/?gid={{ user.id }}"
>
{{ rule | rule_member_count:"asset" }}
</a>
{{ rule | rule_member_count:"asset" }}
</td>
<td
class=
"text-center"
>
<a
href=
"/jasset/group_list/?gid={{ user.id }}"
>
{{ rule | rule_member_count:"asset_group" }}
</a>
{{ rule | rule_member_count:"asset_group" }}
</td>
<td
class=
"text-center"
>
<a
href=
"/jasset/group_list/?gid={{ user.id }}"
>
{{ rule | rule_member_count:"role" }}
</a>
{{ rule | rule_member_count:"role" }}
</td>
<td
class=
"text-center"
>
<a
href=
"/jperm/perm_rule_detail/?id={{ rule.id }}"
class=
"btn btn-xs btn-primary"
>
详情
</a>
...
...
templates/juser/group_list.html
View file @
b8cb6f42
...
...
@@ -93,6 +93,7 @@ type="checkbox" name="selected" value="{{ group.id }}">
$
(
document
).
ready
(
function
(){
$
(
'.del'
).
click
(
function
(){
var
row
=
$
(
this
).
closest
(
'tr'
);
if
(
confirm
(
"确定删除"
))
{
$
.
get
(
$
(
this
).
attr
(
'value'
),
{},
...
...
@@ -101,7 +102,7 @@ type="checkbox" name="selected" value="{{ group.id }}">
alert
(
data
);
}
)
)
}
});
$
(
'#del_btn'
).
click
(
function
(){
...
...
templates/juser/user_edit.html
View file @
b8cb6f42
...
...
@@ -42,7 +42,7 @@
<div
class=
"col-sm-8"
>
<input
id=
"password"
name=
"password"
placeholder=
"Password"
type=
"password"
class=
"form-control"
>
<span
class=
"help-block m-b-none"
>
登陆web的密码
登陆web的密码
(如不修改请留空)
</span>
</div>
</div>
...
...
templates/juser/user_list.html
View file @
b8cb6f42
...
...
@@ -64,7 +64,13 @@
<td
class=
"text-center"
title=
"{% for user_group in user.group.all %} {{ user_group.name }} {% endfor %}"
>
{{ user.group.all | groups2str }}
</td>
<td
class=
"text-center"
>
{{ user.id | get_role }}
</td>
<td
class=
"text-center"
>
{{ user.is_active | bool2str }}
</td>
<td
class=
"text-center"
><a
href=
"/juser/down_key/?id={{ user.id }}"
>
下载
</a></td>
<td
class=
"text-center"
>
{% if user.username|key_exist %}
<a
href=
"/juser/down_key/?id={{ user.id }}"
>
下载
</a>
{% else %}
<span
style=
"color: #586b7d"
>
下载
</span>
{% endif %}
</td>
<td
class=
"text-center"
>
<a
href=
"../user_detail/?id={{ user.id }}"
class=
"btn btn-xs btn-primary"
>
详情
</a>
<a
href=
"../user_edit/?id={{ user.id }}"
class=
"btn btn-xs btn-info"
>
编辑
</a>
...
...
templates/nav.html
View file @
b8cb6f42
...
...
@@ -4,10 +4,10 @@
<ul
class=
"nav"
id=
"side-menu"
>
{% include 'nav_li_profile.html' %}
<li
id=
"index"
>
<a
href=
"/"
><i
class=
"fa fa-
th-large
"
></i>
<span
class=
"nav-label"
>
仪表盘
</span><span
class=
"label label-info pull-right"
></span></a>
<a
href=
"/"
><i
class=
"fa fa-
dashboard
"
></i>
<span
class=
"nav-label"
>
仪表盘
</span><span
class=
"label label-info pull-right"
></span></a>
</li>
<li
id=
"juser"
>
<a
href=
"#"
><i
class=
"fa fa-
rebel
"
></i>
<span
class=
"nav-label"
>
用户管理
</span><span
class=
"fa arrow"
></span></a>
<a
href=
"#"
><i
class=
"fa fa-
group
"
></i>
<span
class=
"nav-label"
>
用户管理
</span><span
class=
"fa arrow"
></span></a>
<ul
class=
"nav nav-second-level"
>
<li
class=
"group_list group_edit"
><a
href=
"/juser/group_list/"
>
查看用户组
</a></li>
<li
class=
"group_add"
><a
href=
"/juser/group_add/"
>
添加用户组
</a></li>
...
...
@@ -16,7 +16,7 @@
</ul>
</li>
<li
id=
"jasset"
>
<a><i
class=
"fa fa-
cube
"
></i>
<span
class=
"nav-label"
>
资产管理
</span><span
class=
"fa arrow"
></span></a>
<a><i
class=
"fa fa-
inbox
"
></i>
<span
class=
"nav-label"
>
资产管理
</span><span
class=
"fa arrow"
></span></a>
<ul
class=
"nav nav-second-level"
>
<li
class=
"group_add"
><a
href=
"/jasset/group_add/"
>
添加资产组
</a></li>
<li
class=
"group_list group_detail group_edit"
><a
href=
"/jasset/group_list/"
>
查看资产组
</a></li>
...
...
@@ -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>
...
...
@@ -44,7 +44,7 @@
<a
href=
"/jlog/log_list/online/"
><i
class=
"fa fa-files-o"
></i>
<span
class=
"nav-label"
>
日志审计
</span><span
class=
"label label-info pull-right"
></span></a>
</li>
<li
id=
"setting"
>
<a
href=
"/setting/"
><i
class=
"fa fa-
files-o
"
></i>
<span
class=
"nav-label"
>
设置
</span><span
class=
"label label-info pull-right"
></span></a>
<a
href=
"/setting/"
><i
class=
"fa fa-
gears
"
></i>
<span
class=
"nav-label"
>
设置
</span><span
class=
"label label-info pull-right"
></span></a>
</li>
<li
class=
"special_link"
>
<a
href=
"http://www.jumpserver.org"
target=
"_blank"
><i
class=
"fa fa-database"
></i>
<span
class=
"nav-label"
>
访问官网
</span></a>
...
...
version
deleted
100644 → 0
View file @
d25e2362
1.1
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment