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
9 years ago
by
wangyong
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' into cmdb
parents
d25e2362
a143797a
master
auditor_jym
audits
dev
dev_beta
dev_beta_db
gengmei
lagacy-0.4.0
node_service
password
rbac
restrict_access
test
v52
wph
1.5.2
1.5.1
1.5.0
1.4.10
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.1
1.1.0
1.0.0
0.3.3
0.3.2
0.3.2-rc2
0.3.1
0.3.0-beta
v1.4.10
v1.4.7
v1.4.4
No related merge requests found
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
...
...
This diff is collapsed.
Click to expand it.
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
:
...
...
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
...
...
This diff is collapsed.
Click to expand it.
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)
...
...
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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"
):
...
...
This diff is collapsed.
Click to expand it.
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
),
)
This diff is collapsed.
Click to expand it.
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
()
...
...
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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'
)
This diff is collapsed.
Click to expand it.
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'
)
...
...
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
)
...
...
This diff is collapsed.
Click to expand it.
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
):
...
...
This diff is collapsed.
Click to expand it.
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
)
...
...
This diff is collapsed.
Click to expand it.
keys/README.md
0 → 100644
View file @
b8cb6f42
看山是山,看水是水
看山不是山,看水不是水
看山是山,看水是水
This diff is collapsed.
Click to expand it.
logs/README.md
0 → 100644
View file @
b8cb6f42
永远年轻,永远热泪盈眶
This diff is collapsed.
Click to expand it.
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
]
This diff is collapsed.
Click to expand it.
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 %}
...
...
This diff is collapsed.
Click to expand it.
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>
...
...
This diff is collapsed.
Click to expand it.
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'
)
...
...
This diff is collapsed.
Click to expand it.
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"
>
...
...
This diff is collapsed.
Click to expand it.
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"
>
...
...
This diff is collapsed.
Click to expand it.
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"
>
...
...
This diff is collapsed.
Click to expand it.
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"
)){
...
...
This diff is collapsed.
Click to expand it.
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>
...
...
This diff is collapsed.
Click to expand it.
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>
...
...
This diff is collapsed.
Click to expand it.
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
(){
...
...
This diff is collapsed.
Click to expand it.
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>
...
...
This diff is collapsed.
Click to expand it.
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>
...
...
This diff is collapsed.
Click to expand it.
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>
...
...
This diff is collapsed.
Click to expand it.
version
deleted
100644 → 0
View file @
d25e2362
1.1
\ No newline at end of file
This diff is collapsed.
Click to expand it.
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