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
719bea68
Unverified
Commit
719bea68
authored
Oct 09, 2019
by
老广
Committed by
GitHub
Oct 09, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3313 from jumpserver/dev
Dev
parents
7502a372
dc5598f8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
93 additions
and
14 deletions
+93
-14
node.py
apps/assets/serializers/node.py
+6
-4
const.py
apps/assets/tasks/const.py
+4
-1
conf.py
apps/jumpserver/conf.py
+5
-1
settings.py
apps/jumpserver/settings.py
+8
-0
django.mo
apps/locale/zh/LC_MESSAGES/django.mo
+0
-0
django.po
apps/locale/zh/LC_MESSAGES/django.po
+0
-0
tasks.py
apps/ops/tasks.py
+0
-2
celery_task_log.html
apps/ops/templates/ops/celery_task_log.html
+11
-1
celery.py
apps/ops/views/celery.py
+5
-1
api.py
apps/settings/api.py
+4
-2
forms.py
apps/settings/forms.py
+4
-0
serializers.py
apps/settings/serializers.py
+1
-0
utils.py
apps/settings/utils.py
+3
-2
tasks.py
apps/users/tasks.py
+35
-0
config_example.yml
config_example.yml
+7
-0
jms
jms
+0
-0
No files found.
apps/assets/serializers/node.py
View file @
719bea68
...
@@ -25,10 +25,12 @@ class NodeSerializer(BulkOrgResourceModelSerializer):
...
@@ -25,10 +25,12 @@ class NodeSerializer(BulkOrgResourceModelSerializer):
read_only_fields
=
[
'key'
,
'org_id'
]
read_only_fields
=
[
'key'
,
'org_id'
]
def
validate_value
(
self
,
data
):
def
validate_value
(
self
,
data
):
if
not
self
.
instance
and
not
data
:
if
self
.
instance
:
return
data
instance
=
self
.
instance
instance
=
self
.
instance
siblings
=
instance
.
get_siblings
()
siblings
=
instance
.
get_siblings
()
else
:
instance
=
Node
.
org_root
()
siblings
=
instance
.
get_children
()
if
siblings
.
filter
(
value
=
data
):
if
siblings
.
filter
(
value
=
data
):
raise
serializers
.
ValidationError
(
raise
serializers
.
ValidationError
(
_
(
'The same level node name cannot be the same'
)
_
(
'The same level node name cannot be the same'
)
...
...
apps/assets/tasks/const.py
View file @
719bea68
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
import
os
import
os
from
django.conf
import
settings
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
PERIOD_TASK_ENABLED
=
os
.
environ
.
get
(
"PERIOD_TASK"
,
"on"
)
==
'on'
ENV_PERIOD_TASK
=
os
.
environ
.
get
(
"PERIOD_TASK"
,
"on"
)
==
'on'
PERIOD_TASK_ENABLED
=
settings
.
PERIOD_TASK_ENABLED
and
ENV_PERIOD_TASK
UPDATE_ASSETS_HARDWARE_TASKS
=
[
UPDATE_ASSETS_HARDWARE_TASKS
=
[
{
{
...
...
apps/jumpserver/conf.py
View file @
719bea68
...
@@ -374,6 +374,10 @@ defaults = {
...
@@ -374,6 +374,10 @@ defaults = {
'RADIUS_SERVER'
:
'localhost'
,
'RADIUS_SERVER'
:
'localhost'
,
'RADIUS_PORT'
:
1812
,
'RADIUS_PORT'
:
1812
,
'RADIUS_SECRET'
:
''
,
'RADIUS_SECRET'
:
''
,
'AUTH_LDAP_SEARCH_PAGED_SIZE'
:
1000
,
'AUTH_LDAP_SYNC_IS_PERIODIC'
:
False
,
'AUTH_LDAP_SYNC_INTERVAL'
:
None
,
'AUTH_LDAP_SYNC_CRONTAB'
:
None
,
'HTTP_BIND_HOST'
:
'0.0.0.0'
,
'HTTP_BIND_HOST'
:
'0.0.0.0'
,
'HTTP_LISTEN_PORT'
:
8080
,
'HTTP_LISTEN_PORT'
:
8080
,
'WS_LISTEN_PORT'
:
8070
,
'WS_LISTEN_PORT'
:
8070
,
...
@@ -386,8 +390,8 @@ defaults = {
...
@@ -386,8 +390,8 @@ defaults = {
'PERM_SINGLE_ASSET_TO_UNGROUP_NODE'
:
False
,
'PERM_SINGLE_ASSET_TO_UNGROUP_NODE'
:
False
,
'WINDOWS_SSH_DEFAULT_SHELL'
:
'cmd'
,
'WINDOWS_SSH_DEFAULT_SHELL'
:
'cmd'
,
'FLOWER_URL'
:
"127.0.0.1:5555"
,
'FLOWER_URL'
:
"127.0.0.1:5555"
,
'AUTH_LDAP_SEARCH_PAGED_SIZE'
:
1000
,
'DEFAULT_ORG_SHOW_ALL_USERS'
:
True
,
'DEFAULT_ORG_SHOW_ALL_USERS'
:
True
,
'PERIOD_TASK_ENABLED'
:
True
,
}
}
...
...
apps/jumpserver/settings.py
View file @
719bea68
...
@@ -357,6 +357,7 @@ EMAIL_PORT = 25
...
@@ -357,6 +357,7 @@ EMAIL_PORT = 25
EMAIL_HOST_USER
=
'noreply@jumpserver.org'
EMAIL_HOST_USER
=
'noreply@jumpserver.org'
EMAIL_HOST_PASSWORD
=
''
EMAIL_HOST_PASSWORD
=
''
EMAIL_FROM
=
''
EMAIL_FROM
=
''
EMAIL_RECIPIENT
=
''
EMAIL_USE_SSL
=
False
EMAIL_USE_SSL
=
False
EMAIL_USE_TLS
=
False
EMAIL_USE_TLS
=
False
EMAIL_SUBJECT_PREFIX
=
'[JMS] '
EMAIL_SUBJECT_PREFIX
=
'[JMS] '
...
@@ -425,6 +426,10 @@ OTP_VALID_WINDOW = CONFIG.OTP_VALID_WINDOW
...
@@ -425,6 +426,10 @@ OTP_VALID_WINDOW = CONFIG.OTP_VALID_WINDOW
# Auth LDAP settings
# Auth LDAP settings
AUTH_LDAP
=
False
AUTH_LDAP
=
False
AUTH_LDAP_SEARCH_PAGED_SIZE
=
CONFIG
.
AUTH_LDAP_SEARCH_PAGED_SIZE
AUTH_LDAP_SEARCH_PAGED_SIZE
=
CONFIG
.
AUTH_LDAP_SEARCH_PAGED_SIZE
AUTH_LDAP_SYNC_IS_PERIODIC
=
CONFIG
.
AUTH_LDAP_SYNC_IS_PERIODIC
AUTH_LDAP_SYNC_INTERVAL
=
CONFIG
.
AUTH_LDAP_SYNC_INTERVAL
AUTH_LDAP_SYNC_CRONTAB
=
CONFIG
.
AUTH_LDAP_SYNC_CRONTAB
AUTH_LDAP_SERVER_URI
=
'ldap://localhost:389'
AUTH_LDAP_SERVER_URI
=
'ldap://localhost:389'
AUTH_LDAP_BIND_DN
=
'cn=admin,dc=jumpserver,dc=org'
AUTH_LDAP_BIND_DN
=
'cn=admin,dc=jumpserver,dc=org'
AUTH_LDAP_BIND_PASSWORD
=
''
AUTH_LDAP_BIND_PASSWORD
=
''
...
@@ -645,3 +650,6 @@ CHANNEL_LAYERS = {
...
@@ -645,3 +650,6 @@ CHANNEL_LAYERS = {
},
},
},
},
}
}
# Enable internal period task
PERIOD_TASK_ENABLED
=
CONFIG
.
PERIOD_TASK_ENABLED
apps/locale/zh/LC_MESSAGES/django.mo
View file @
719bea68
No preview for this file type
apps/locale/zh/LC_MESSAGES/django.po
View file @
719bea68
This diff is collapsed.
Click to expand it.
apps/ops/tasks.py
View file @
719bea68
...
@@ -114,8 +114,6 @@ def hello(name, callback=None):
...
@@ -114,8 +114,6 @@ def hello(name, callback=None):
# @after_app_shutdown_clean_periodic
# @after_app_shutdown_clean_periodic
# @register_as_period_task(interval=30)
# @register_as_period_task(interval=30)
def
hello123
():
def
hello123
():
p
=
subprocess
.
Popen
(
'ls /tmp'
,
shell
=
True
)
print
(
"{} Hello world"
.
format
(
datetime
.
datetime
.
now
()
.
strftime
(
"
%
H:
%
M:
%
S"
)))
return
None
return
None
...
...
apps/ops/templates/ops/celery_task_log.html
View file @
719bea68
...
@@ -24,6 +24,8 @@
...
@@ -24,6 +24,8 @@
var
port
=
document
.
location
.
port
?
":"
+
document
.
location
.
port
:
""
;
var
port
=
document
.
location
.
port
?
":"
+
document
.
location
.
port
:
""
;
var
url
=
"/ws/ops/tasks/"
+
"{{ task_id }}"
+
"/log/"
;
var
url
=
"/ws/ops/tasks/"
+
"{{ task_id }}"
+
"/log/"
;
var
wsURL
=
scheme
+
"://"
+
document
.
location
.
hostname
+
port
+
url
;
var
wsURL
=
scheme
+
"://"
+
document
.
location
.
hostname
+
port
+
url
;
var
failOverPort
=
"{{ ws_port }}"
;
var
failOverWsURL
=
scheme
+
"://"
+
document
.
location
.
hostname
+
':'
+
failOverPort
+
url
;
var
term
;
var
term
;
var
ws
;
var
ws
;
...
@@ -38,13 +40,21 @@
...
@@ -38,13 +40,21 @@
});
});
term
.
open
(
document
.
getElementById
(
'term'
));
term
.
open
(
document
.
getElementById
(
'term'
));
term
.
resize
(
120
,
30
);
term
.
resize
(
120
,
30
);
ws
=
new
WebSocket
(
wsURL
);
ws
=
new
WebSocket
(
wsURL
);
ws
.
onmessage
=
function
(
e
)
{
ws
.
onmessage
=
function
(
e
)
{
var
data
=
JSON
.
parse
(
e
.
data
);
var
data
=
JSON
.
parse
(
e
.
data
);
term
.
write
(
data
.
message
);
term
.
write
(
data
.
message
);
};
};
ws
.
onerror
=
function
(
e
)
{
ws
.
onerror
=
function
(
e
)
{
term
.
write
(
"Connect websocket server error"
)
ws
=
new
WebSocket
(
failOverWsURL
);
ws
.
onmessage
=
function
(
e
)
{
var
data
=
JSON
.
parse
(
e
.
data
);
term
.
write
(
data
.
message
);
};
ws
.
onerror
=
function
(
e
)
{
term
.
write
(
"Connect websocket server error"
)
}
}
}
});
});
</script>
</script>
apps/ops/views/celery.py
View file @
719bea68
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
from
django.views.generic
import
TemplateView
from
django.views.generic
import
TemplateView
from
django.conf
import
settings
from
common.permissions
import
PermissionsMixin
,
IsOrgAdmin
,
IsOrgAuditor
from
common.permissions
import
PermissionsMixin
,
IsOrgAdmin
,
IsOrgAuditor
...
@@ -14,5 +15,8 @@ class CeleryTaskLogView(PermissionsMixin, TemplateView):
...
@@ -14,5 +15,8 @@ class CeleryTaskLogView(PermissionsMixin, TemplateView):
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
()
.
get_context_data
(
**
kwargs
)
context
=
super
()
.
get_context_data
(
**
kwargs
)
context
.
update
({
'task_id'
:
self
.
kwargs
.
get
(
'pk'
)})
context
.
update
({
'task_id'
:
self
.
kwargs
.
get
(
'pk'
),
'ws_port'
:
settings
.
CONFIG
.
WS_LISTEN_PORT
})
return
context
return
context
apps/settings/api.py
View file @
719bea68
...
@@ -30,6 +30,7 @@ class MailTestingAPI(APIView):
...
@@ -30,6 +30,7 @@ class MailTestingAPI(APIView):
serializer
=
self
.
serializer_class
(
data
=
request
.
data
)
serializer
=
self
.
serializer_class
(
data
=
request
.
data
)
if
serializer
.
is_valid
():
if
serializer
.
is_valid
():
email_from
=
serializer
.
validated_data
[
"EMAIL_FROM"
]
email_from
=
serializer
.
validated_data
[
"EMAIL_FROM"
]
email_recipient
=
serializer
.
validated_data
[
"EMAIL_RECIPIENT"
]
email_host_user
=
serializer
.
validated_data
[
"EMAIL_HOST_USER"
]
email_host_user
=
serializer
.
validated_data
[
"EMAIL_HOST_USER"
]
for
k
,
v
in
serializer
.
validated_data
.
items
():
for
k
,
v
in
serializer
.
validated_data
.
items
():
if
k
.
startswith
(
'EMAIL'
):
if
k
.
startswith
(
'EMAIL'
):
...
@@ -38,11 +39,12 @@ class MailTestingAPI(APIView):
...
@@ -38,11 +39,12 @@ class MailTestingAPI(APIView):
subject
=
"Test"
subject
=
"Test"
message
=
"Test smtp setting"
message
=
"Test smtp setting"
email_from
=
email_from
or
email_host_user
email_from
=
email_from
or
email_host_user
send_mail
(
subject
,
message
,
email_from
,
[
email_from
])
email_recipient
=
email_recipient
or
email_from
send_mail
(
subject
,
message
,
email_from
,
[
email_recipient
])
except
Exception
as
e
:
except
Exception
as
e
:
return
Response
({
"error"
:
str
(
e
)},
status
=
401
)
return
Response
({
"error"
:
str
(
e
)},
status
=
401
)
return
Response
({
"msg"
:
self
.
success_message
.
format
(
email_
host_user
)})
return
Response
({
"msg"
:
self
.
success_message
.
format
(
email_
recipient
)})
else
:
else
:
return
Response
({
"error"
:
str
(
serializer
.
errors
)},
status
=
401
)
return
Response
({
"error"
:
str
(
serializer
.
errors
)},
status
=
401
)
...
...
apps/settings/forms.py
View file @
719bea68
...
@@ -89,6 +89,10 @@ class EmailSettingForm(BaseForm):
...
@@ -89,6 +89,10 @@ class EmailSettingForm(BaseForm):
"Tips: Send mail account, default SMTP account as the send account"
"Tips: Send mail account, default SMTP account as the send account"
)
)
)
)
EMAIL_RECIPIENT
=
forms
.
CharField
(
max_length
=
128
,
label
=
_
(
"Test recipient"
),
initial
=
''
,
required
=
False
,
help_text
=
_
(
"Tips: Used only as a test mail recipient"
)
)
EMAIL_USE_SSL
=
forms
.
BooleanField
(
EMAIL_USE_SSL
=
forms
.
BooleanField
(
label
=
_
(
"Use SSL"
),
initial
=
False
,
required
=
False
,
label
=
_
(
"Use SSL"
),
initial
=
False
,
required
=
False
,
help_text
=
_
(
"If SMTP port is 465, may be select"
)
help_text
=
_
(
"If SMTP port is 465, may be select"
)
...
...
apps/settings/serializers.py
View file @
719bea68
...
@@ -7,6 +7,7 @@ class MailTestSerializer(serializers.Serializer):
...
@@ -7,6 +7,7 @@ class MailTestSerializer(serializers.Serializer):
EMAIL_HOST_USER
=
serializers
.
CharField
(
max_length
=
1024
)
EMAIL_HOST_USER
=
serializers
.
CharField
(
max_length
=
1024
)
EMAIL_HOST_PASSWORD
=
serializers
.
CharField
(
required
=
False
,
allow_blank
=
True
)
EMAIL_HOST_PASSWORD
=
serializers
.
CharField
(
required
=
False
,
allow_blank
=
True
)
EMAIL_FROM
=
serializers
.
CharField
(
required
=
False
,
allow_blank
=
True
)
EMAIL_FROM
=
serializers
.
CharField
(
required
=
False
,
allow_blank
=
True
)
EMAIL_RECIPIENT
=
serializers
.
CharField
(
required
=
False
,
allow_blank
=
True
)
EMAIL_USE_SSL
=
serializers
.
BooleanField
(
default
=
False
)
EMAIL_USE_SSL
=
serializers
.
BooleanField
(
default
=
False
)
EMAIL_USE_TLS
=
serializers
.
BooleanField
(
default
=
False
)
EMAIL_USE_TLS
=
serializers
.
BooleanField
(
default
=
False
)
...
...
apps/settings/utils.py
View file @
719bea68
...
@@ -170,7 +170,7 @@ class LDAPUtil:
...
@@ -170,7 +170,7 @@ class LDAPUtil:
email
=
construct_user_email
(
username
,
email
)
email
=
construct_user_email
(
username
,
email
)
return
email
return
email
def
create_or_update_users
(
self
,
user_items
,
force_update
=
True
):
def
create_or_update_users
(
self
,
user_items
):
succeed
=
failed
=
0
succeed
=
failed
=
0
for
user_item
in
user_items
:
for
user_item
in
user_items
:
exist
=
user_item
.
pop
(
'existing'
,
False
)
exist
=
user_item
.
pop
(
'existing'
,
False
)
...
@@ -180,13 +180,14 @@ class LDAPUtil:
...
@@ -180,13 +180,14 @@ class LDAPUtil:
else
:
else
:
ok
,
error
=
self
.
update_user
(
user_item
)
ok
,
error
=
self
.
update_user
(
user_item
)
if
not
ok
:
if
not
ok
:
logger
.
info
(
"Failed User: {}"
.
format
(
user_item
))
failed
+=
1
failed
+=
1
else
:
else
:
succeed
+=
1
succeed
+=
1
result
=
{
'total'
:
len
(
user_items
),
'succeed'
:
succeed
,
'failed'
:
failed
}
result
=
{
'total'
:
len
(
user_items
),
'succeed'
:
succeed
,
'failed'
:
failed
}
return
result
return
result
def
sync_users
(
self
,
username_list
):
def
sync_users
(
self
,
username_list
=
None
):
user_items
=
self
.
search_filter_user_items
(
username_list
)
user_items
=
self
.
search_filter_user_items
(
username_list
)
result
=
self
.
create_or_update_users
(
user_items
)
result
=
self
.
create_or_update_users
(
user_items
)
return
result
return
result
apps/users/tasks.py
View file @
719bea68
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
#
#
from
celery
import
shared_task
from
celery
import
shared_task
from
django.conf
import
settings
from
ops.celery.utils
import
create_or_update_celery_periodic_tasks
from
ops.celery.utils
import
create_or_update_celery_periodic_tasks
from
ops.celery.decorator
import
after_app_ready_start
from
ops.celery.decorator
import
after_app_ready_start
...
@@ -10,6 +11,7 @@ from .models import User
...
@@ -10,6 +11,7 @@ from .models import User
from
.utils
import
(
from
.utils
import
(
send_password_expiration_reminder_mail
,
send_user_expiration_reminder_mail
send_password_expiration_reminder_mail
,
send_user_expiration_reminder_mail
)
)
from
settings.utils
import
LDAPUtil
logger
=
get_logger
(
__file__
)
logger
=
get_logger
(
__file__
)
...
@@ -66,3 +68,36 @@ def check_user_expired_periodic():
...
@@ -66,3 +68,36 @@ def check_user_expired_periodic():
}
}
create_or_update_celery_periodic_tasks
(
tasks
)
create_or_update_celery_periodic_tasks
(
tasks
)
@shared_task
def
sync_ldap_user
():
logger
.
info
(
"Start sync ldap user periodic task"
)
util
=
LDAPUtil
()
result
=
util
.
sync_users
()
logger
.
info
(
"Result: {}"
.
format
(
result
))
@shared_task
@after_app_ready_start
def
sync_ldap_user_periodic
():
if
not
settings
.
AUTH_LDAP
:
return
if
not
settings
.
AUTH_LDAP_SYNC_IS_PERIODIC
:
return
interval
=
settings
.
AUTH_LDAP_SYNC_INTERVAL
if
isinstance
(
interval
,
int
):
interval
=
interval
*
3600
else
:
interval
=
None
crontab
=
settings
.
AUTH_LDAP_SYNC_CRONTAB
tasks
=
{
'sync_ldap_user_periodic'
:
{
'task'
:
sync_ldap_user
.
name
,
'interval'
:
interval
,
'crontab'
:
crontab
,
'enabled'
:
True
,
}
}
create_or_update_celery_periodic_tasks
(
tasks
)
config_example.yml
View file @
719bea68
...
@@ -72,6 +72,13 @@ REDIS_PORT: 6379
...
@@ -72,6 +72,13 @@ REDIS_PORT: 6379
# RADIUS_PORT: 1812
# RADIUS_PORT: 1812
# RADIUS_SECRET:
# RADIUS_SECRET:
# LDAP/AD 设置定时同步参数
# 启用/禁用
# AUTH_LDAP_SYNC_IS_PERIODIC: True
# 单位: 时
# AUTH_LDAP_SYNC_INTERVAL: 12
# Crontab 表达式
# AUTH_LDAP_SYNC_CRONTAB: * 6 * * *
# OTP settings
# OTP settings
# OTP/MFA 配置
# OTP/MFA 配置
...
...
jms
View file @
719bea68
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