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
b936d54a
Commit
b936d54a
authored
Jan 20, 2018
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Feature] 添加es支持
parent
ba5ab21b
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
259 additions
and
56 deletions
+259
-56
cluster.py
apps/assets/views/cluster.py
+0
-5
forms.py
apps/common/forms.py
+37
-6
models.py
apps/common/models.py
+12
-3
_add_terminal_command_storage_modal.html
...templates/common/_add_terminal_command_storage_modal.html
+21
-0
basic_setting.html
apps/common/templates/common/basic_setting.html
+1
-1
email_setting.html
apps/common/templates/common/email_setting.html
+1
-1
ldap_setting.html
apps/common/templates/common/ldap_setting.html
+1
-1
terminal_setting.html
apps/common/templates/common/terminal_setting.html
+33
-5
view_urls.py
apps/common/urls/view_urls.py
+1
-1
views.py
apps/common/views.py
+12
-8
settings.py
apps/jumpserver/settings.py
+17
-1
api.py
apps/terminal/api.py
+9
-2
__init__.py
apps/terminal/backends/__init__.py
+27
-3
base.py
apps/terminal/backends/command/base.py
+6
-0
db.py
apps/terminal/backends/command/db.py
+27
-7
models.py
apps/terminal/backends/command/models.py
+15
-0
forms.py
apps/terminal/forms.py
+1
-1
models.py
apps/terminal/models.py
+20
-0
serializers.py
apps/terminal/serializers.py
+2
-2
terminal_modal_accept.html
apps/terminal/templates/terminal/terminal_modal_accept.html
+1
-0
terminal_update.html
apps/terminal/templates/terminal/terminal_update.html
+1
-0
terminal_tags.py
apps/terminal/templatetags/terminal_tags.py
+6
-4
command.py
apps/terminal/views/command.py
+6
-3
session.py
apps/terminal/views/session.py
+2
-2
No files found.
apps/assets/views/cluster.py
View file @
b936d54a
...
@@ -60,11 +60,6 @@ class ClusterUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView)
...
@@ -60,11 +60,6 @@ class ClusterUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView)
success_url
=
reverse_lazy
(
'assets:cluster-list'
)
success_url
=
reverse_lazy
(
'assets:cluster-list'
)
success_message
=
update_success_msg
success_message
=
update_success_msg
def
form_valid
(
self
,
form
):
cluster
=
form
.
save
(
commit
=
False
)
cluster
.
save
()
return
super
()
.
form_valid
(
form
)
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
context
=
{
'app'
:
_
(
'assets'
),
'app'
:
_
(
'assets'
),
...
...
apps/common/forms.py
View file @
b936d54a
...
@@ -4,7 +4,9 @@ import json
...
@@ -4,7 +4,9 @@ import json
from
django
import
forms
from
django
import
forms
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.html
import
escape
from
django.db
import
transaction
from
django.db
import
transaction
from
django.conf
import
settings
from
.models
import
Setting
from
.models
import
Setting
from
.fields
import
DictField
from
.fields
import
DictField
...
@@ -30,28 +32,32 @@ def to_form_value(value):
...
@@ -30,28 +32,32 @@ def to_form_value(value):
class
BaseForm
(
forms
.
Form
):
class
BaseForm
(
forms
.
Form
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
super
()
.
__init__
(
*
args
,
**
kwargs
)
settings
=
Setting
.
objects
.
all
()
db_
settings
=
Setting
.
objects
.
all
()
for
name
,
field
in
self
.
fields
.
items
():
for
name
,
field
in
self
.
fields
.
items
():
db_value
=
getattr
(
settings
,
name
)
.
value
db_value
=
getattr
(
db_settings
,
name
)
.
value
if
db_value
:
django_value
=
getattr
(
settings
,
name
)
if
hasattr
(
settings
,
name
)
else
None
if
db_value
is
not
None
:
field
.
initial
=
to_form_value
(
db_value
)
field
.
initial
=
to_form_value
(
db_value
)
elif
django_value
is
not
None
:
field
.
initial
=
django_value
def
save
(
self
):
def
save
(
self
,
category
=
"default"
):
if
not
self
.
is_bound
:
if
not
self
.
is_bound
:
raise
ValueError
(
"Form is not bound"
)
raise
ValueError
(
"Form is not bound"
)
settings
=
Setting
.
objects
.
all
()
db_
settings
=
Setting
.
objects
.
all
()
if
self
.
is_valid
():
if
self
.
is_valid
():
with
transaction
.
atomic
():
with
transaction
.
atomic
():
for
name
,
value
in
self
.
cleaned_data
.
items
():
for
name
,
value
in
self
.
cleaned_data
.
items
():
field
=
self
.
fields
[
name
]
field
=
self
.
fields
[
name
]
if
isinstance
(
field
.
widget
,
forms
.
PasswordInput
)
and
not
value
:
if
isinstance
(
field
.
widget
,
forms
.
PasswordInput
)
and
not
value
:
continue
continue
if
value
==
to_form_value
(
getattr
(
settings
,
name
)
.
value
):
if
value
==
to_form_value
(
getattr
(
db_
settings
,
name
)
.
value
):
continue
continue
defaults
=
{
defaults
=
{
'name'
:
name
,
'name'
:
name
,
'category'
:
category
,
'value'
:
to_model_value
(
value
)
'value'
:
to_model_value
(
value
)
}
}
Setting
.
objects
.
update_or_create
(
defaults
=
defaults
,
name
=
name
)
Setting
.
objects
.
update_or_create
(
defaults
=
defaults
,
name
=
name
)
...
@@ -129,3 +135,28 @@ class LDAPSettingForm(BaseForm):
...
@@ -129,3 +135,28 @@ class LDAPSettingForm(BaseForm):
AUTH_LDAP_START_TLS
=
forms
.
BooleanField
(
AUTH_LDAP_START_TLS
=
forms
.
BooleanField
(
label
=
_
(
"Use SSL"
),
initial
=
False
,
required
=
False
label
=
_
(
"Use SSL"
),
initial
=
False
,
required
=
False
)
)
class
TerminalSettingForm
(
BaseForm
):
SORT_BY_CHOICES
=
(
(
'hostname'
,
_
(
'Hostname'
)),
(
'ip'
,
_
(
'IP'
)),
)
TERMINAL_ASSET_LIST_SORT_BY
=
forms
.
ChoiceField
(
choices
=
SORT_BY_CHOICES
,
initial
=
'hostname'
,
label
=
_
(
"List sort by"
)
)
TERMINAL_HEARTBEAT_INTERVAL
=
forms
.
IntegerField
(
initial
=
5
,
label
=
_
(
"Heartbeat interval"
),
help_text
=
_
(
"Units: seconds"
)
)
TERMINAL_PASSWORD_AUTH
=
forms
.
BooleanField
(
initial
=
True
,
required
=
False
,
label
=
_
(
"Password auth"
)
)
TERMINAL_PUBLIC_KEY_AUTH
=
forms
.
BooleanField
(
initial
=
True
,
required
=
False
,
label
=
_
(
"Public key auth"
)
)
TERMINAL_COMMAND_STORAGE
=
DictField
(
label
=
_
(
"Command storage"
),
help_text
=
_
(
"Set terminal storage setting, `default` is the using as default,"
"You can set other storage and some terminal using"
)
)
apps/common/models.py
View file @
b936d54a
...
@@ -24,6 +24,7 @@ class SettingManager(models.Manager):
...
@@ -24,6 +24,7 @@ class SettingManager(models.Manager):
class
Setting
(
models
.
Model
):
class
Setting
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
"Name"
))
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
"Name"
))
value
=
models
.
TextField
(
verbose_name
=
_
(
"Value"
))
value
=
models
.
TextField
(
verbose_name
=
_
(
"Value"
))
category
=
models
.
CharField
(
max_length
=
128
,
default
=
"default"
)
enabled
=
models
.
BooleanField
(
verbose_name
=
_
(
"Enabled"
),
default
=
True
)
enabled
=
models
.
BooleanField
(
verbose_name
=
_
(
"Enabled"
),
default
=
True
)
comment
=
models
.
TextField
(
verbose_name
=
_
(
"Comment"
))
comment
=
models
.
TextField
(
verbose_name
=
_
(
"Comment"
))
...
@@ -33,12 +34,20 @@ class Setting(models.Model):
...
@@ -33,12 +34,20 @@ class Setting(models.Model):
return
self
.
name
return
self
.
name
@property
@property
def
value_
(
self
):
def
cleaned_value
(
self
):
try
:
try
:
return
json
.
loads
(
self
.
value
)
return
json
.
loads
(
self
.
value
)
except
json
.
JSONDecodeError
:
except
json
.
JSONDecodeError
:
return
None
return
None
@cleaned_value.setter
def
cleaned_value
(
self
,
item
):
try
:
v
=
json
.
dumps
(
item
)
self
.
value
=
v
except
json
.
JSONDecodeError
as
e
:
raise
ValueError
(
"Json dump error: {}"
.
format
(
str
(
e
)))
@classmethod
@classmethod
def
refresh_all_settings
(
cls
):
def
refresh_all_settings
(
cls
):
settings_list
=
cls
.
objects
.
all
()
settings_list
=
cls
.
objects
.
all
()
...
@@ -53,9 +62,9 @@ class Setting(models.Model):
...
@@ -53,9 +62,9 @@ class Setting(models.Model):
setattr
(
settings
,
self
.
name
,
value
)
setattr
(
settings
,
self
.
name
,
value
)
if
self
.
name
==
"AUTH_LDAP"
:
if
self
.
name
==
"AUTH_LDAP"
:
if
self
.
value_
and
settings
.
AUTH_LDAP_BACKEND
not
in
settings
.
AUTHENTICATION_BACKENDS
:
if
self
.
cleaned_value
and
settings
.
AUTH_LDAP_BACKEND
not
in
settings
.
AUTHENTICATION_BACKENDS
:
settings
.
AUTHENTICATION_BACKENDS
.
insert
(
0
,
settings
.
AUTH_LDAP_BACKEND
)
settings
.
AUTHENTICATION_BACKENDS
.
insert
(
0
,
settings
.
AUTH_LDAP_BACKEND
)
elif
not
self
.
value_
and
settings
.
AUTH_LDAP_BACKEND
in
settings
.
AUTHENTICATION_BACKENDS
:
elif
not
self
.
cleaned_value
and
settings
.
AUTH_LDAP_BACKEND
in
settings
.
AUTHENTICATION_BACKENDS
:
settings
.
AUTHENTICATION_BACKENDS
.
remove
(
settings
.
AUTH_LDAP_BACKEND
)
settings
.
AUTHENTICATION_BACKENDS
.
remove
(
settings
.
AUTH_LDAP_BACKEND
)
if
self
.
name
==
"AUTH_LDAP_SEARCH_FILTER"
:
if
self
.
name
==
"AUTH_LDAP_SEARCH_FILTER"
:
...
...
apps/common/templates/common/_add_terminal_command_storage_modal.html
0 → 100644
View file @
b936d54a
{% extends '_modal.html' %}
{% load i18n %}
{% block modal_id %}add_command_storage_model{% endblock %}
{% block modal_title%}{% trans "Add command storage" %}{% endblock %}
{% block modal_body %}
<form
method=
"post"
action=
""
id=
"add_command_storage_form"
>
{% csrf_token %}
<div
class=
"form-group"
>
<label
class=
"control-label"
for=
"id_assets"
>
{% trans "Template" %}
</label>
<a
href=
"{% url 'assets:asset-export' %}"
style=
"display: block"
>
{% trans 'Download' %}
</a>
</div>
<div
class=
"form-group"
>
<label
class=
"control-label"
for=
"id_users"
>
{% trans "Asset csv file" %}
</label>
<input
id=
"id_assets"
type=
"file"
name=
"file"
/>
<span
class=
"help-block red-fonts"
>
{% trans 'If set id, will use this id update asset existed' %}
</span>
</div>
</form>
{% endblock %}
{% block modal_confirm_id %}btn_asset_import{% endblock %}
apps/common/templates/common/basic_setting.html
View file @
b936d54a
...
@@ -21,7 +21,7 @@
...
@@ -21,7 +21,7 @@
<a
href=
"{% url 'settings:ldap-setting' %}"
class=
"text-center"
><i
class=
"fa fa-archive"
></i>
{% trans 'LDAP setting' %}
</a>
<a
href=
"{% url 'settings:ldap-setting' %}"
class=
"text-center"
><i
class=
"fa fa-archive"
></i>
{% trans 'LDAP setting' %}
</a>
</li>
</li>
<li>
<li>
<a
href=
"{% url 'settings:
storage-setting' %}"
class=
"text-center"
><i
class=
"fa fa-hdd-o"
></i>
{% trans 'Storage
setting' %}
</a>
<a
href=
"{% url 'settings:
terminal-setting' %}"
class=
"text-center"
><i
class=
"fa fa-hdd-o"
></i>
{% trans 'Terminal
setting' %}
</a>
</li>
</li>
</ul>
</ul>
</div>
</div>
...
...
apps/common/templates/common/email_setting.html
View file @
b936d54a
...
@@ -21,7 +21,7 @@
...
@@ -21,7 +21,7 @@
<a
href=
"{% url 'settings:ldap-setting' %}"
class=
"text-center"
><i
class=
"fa fa-archive"
></i>
{% trans 'LDAP setting' %}
</a>
<a
href=
"{% url 'settings:ldap-setting' %}"
class=
"text-center"
><i
class=
"fa fa-archive"
></i>
{% trans 'LDAP setting' %}
</a>
</li>
</li>
<li>
<li>
<a
href=
"{% url 'settings:
storage-setting' %}"
class=
"text-center"
><i
class=
"fa fa-hdd-o"
></i>
{% trans 'Storage
setting' %}
</a>
<a
href=
"{% url 'settings:
terminal-setting' %}"
class=
"text-center"
><i
class=
"fa fa-hdd-o"
></i>
{% trans 'Terminal
setting' %}
</a>
</li>
</li>
</ul>
</ul>
</div>
</div>
...
...
apps/common/templates/common/ldap_setting.html
View file @
b936d54a
...
@@ -21,7 +21,7 @@
...
@@ -21,7 +21,7 @@
<a
href=
"{% url 'settings:ldap-setting' %}"
class=
"text-center"
><i
class=
"fa fa-archive"
></i>
{% trans 'LDAP setting' %}
</a>
<a
href=
"{% url 'settings:ldap-setting' %}"
class=
"text-center"
><i
class=
"fa fa-archive"
></i>
{% trans 'LDAP setting' %}
</a>
</li>
</li>
<li>
<li>
<a
href=
"{% url 'settings:
storage-setting' %}"
class=
"text-center"
><i
class=
"fa fa-hdd-o"
></i>
{% trans 'Storage
setting' %}
</a>
<a
href=
"{% url 'settings:
terminal-setting' %}"
class=
"text-center"
><i
class=
"fa fa-hdd-o"
></i>
{% trans 'Terminal
setting' %}
</a>
</li>
</li>
</ul>
</ul>
</div>
</div>
...
...
apps/common/templates/common/
storage
_setting.html
→
apps/common/templates/common/
terminal
_setting.html
View file @
b936d54a
...
@@ -21,7 +21,7 @@
...
@@ -21,7 +21,7 @@
<a
href=
"{% url 'settings:ldap-setting' %}"
class=
"text-center"
><i
class=
"fa fa-archive"
></i>
{% trans 'LDAP setting' %}
</a>
<a
href=
"{% url 'settings:ldap-setting' %}"
class=
"text-center"
><i
class=
"fa fa-archive"
></i>
{% trans 'LDAP setting' %}
</a>
</li>
</li>
<li
class=
"active"
>
<li
class=
"active"
>
<a
href=
"{% url 'settings:
storage-setting' %}"
class=
"text-center"
><i
class=
"fa fa-hdd-o"
></i>
{% trans 'Storage
setting' %}
</a>
<a
href=
"{% url 'settings:
terminal-setting' %}"
class=
"text-center"
><i
class=
"fa fa-hdd-o"
></i>
{% trans 'Terminal
setting' %}
</a>
</li>
</li>
</ul>
</ul>
</div>
</div>
...
@@ -35,26 +35,50 @@
...
@@ -35,26 +35,50 @@
</div>
</div>
{% endif %}
{% endif %}
{% csrf_token %}
{% csrf_token %}
<h3>
{% trans "Basic setting" %}
</h3>
{% for field in form %}
{% if not field.field|is_bool_field %}
{% bootstrap_field field layout="horizontal" %}
{% else %}
<div
class=
"form-group"
>
<label
for=
"{{ field.id_for_label }}"
class=
"col-sm-2 control-label"
>
{{ field.label }}
</label>
<div
class=
"col-sm-8"
>
<div
class=
"col-sm-1"
>
{{ field }}
</div>
<div
class=
"col-sm-9"
>
<span
class=
"help-block"
>
{{ field.help_text }}
</span>
</div>
</div>
</div>
{% endif %}
{% endfor %}
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans "Command storage" %}
</h3>
<h3>
{% trans "Command storage" %}
</h3>
<table
class=
"table table-hover "
id=
"task-history-list-table"
>
<table
class=
"table table-hover "
id=
"task-history-list-table"
>
<thead>
<thead>
<tr>
<tr>
<th>
{% trans 'Name' %}
</th>
<th>
{% trans 'Name' %}
</th>
<th>
{% trans 'Engine' %}
</th>
<th>
{% trans 'Type' %}
</th>
<th>
{% trans 'Action' %}
</th>
</tr>
</tr>
</thead>
</thead>
<tbody>
<tbody>
{% for name, setting in command_storage.items %}
<tr>
<td>
{{ name }}
</td>
<td>
{{ setting.TYPE }}
</td>
</tr>
{% endfor %}
</tbody>
</tbody>
</table>
</table>
{#
<button
class=
"btn btn-default btn-circle btn-add-command-storage"
data-toggle=
"modal"
data-target=
"#add_command_storage_model"
tabindex=
"0"
type=
"button"
><i
class=
"fa fa-plus"
></i></button>
#}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans "Replay storage" %}
</h3>
<h3>
{% trans "Replay storage" %}
</h3>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-default btn-test"
type=
"button"
>
{% trans 'Test connection' %}
</button>
<button
class=
"btn btn-default"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
class=
"btn btn-default"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
...
@@ -68,6 +92,7 @@
...
@@ -68,6 +92,7 @@
</div>
</div>
</div>
</div>
</div>
</div>
{% include 'common/_add_terminal_command_storage_modal.html' %}
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block custom_foot_js %}
<script>
<script>
...
@@ -97,6 +122,9 @@ $(document).ready(function () {
...
@@ -97,6 +122,9 @@ $(document).ready(function () {
success
:
success
,
success
:
success
,
error
:
error
error
:
error
});
});
})
.
on
(
'click'
,
''
,
function
()
{
})
})
</script>
</script>
{% endblock %}
{% endblock %}
apps/common/urls/view_urls.py
View file @
b936d54a
...
@@ -10,5 +10,5 @@ urlpatterns = [
...
@@ -10,5 +10,5 @@ urlpatterns = [
url
(
r'^$'
,
views
.
BasicSettingView
.
as_view
(),
name
=
'basic-setting'
),
url
(
r'^$'
,
views
.
BasicSettingView
.
as_view
(),
name
=
'basic-setting'
),
url
(
r'^email/$'
,
views
.
EmailSettingView
.
as_view
(),
name
=
'email-setting'
),
url
(
r'^email/$'
,
views
.
EmailSettingView
.
as_view
(),
name
=
'email-setting'
),
url
(
r'^ldap/$'
,
views
.
LDAPSettingView
.
as_view
(),
name
=
'ldap-setting'
),
url
(
r'^ldap/$'
,
views
.
LDAPSettingView
.
as_view
(),
name
=
'ldap-setting'
),
url
(
r'^
storage/$'
,
views
.
StorageSettingView
.
as_view
(),
name
=
'storage
-setting'
),
url
(
r'^
terminal/$'
,
views
.
TerminalSettingView
.
as_view
(),
name
=
'terminal
-setting'
),
]
]
apps/common/views.py
View file @
b936d54a
from
django.views.generic
import
View
,
TemplateView
from
django.views.generic
import
TemplateView
from
django.shortcuts
import
render
,
redirect
from
django.shortcuts
import
render
,
redirect
from
django.contrib
import
messages
from
django.contrib
import
messages
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
django.conf
import
settings
from
.forms
import
EmailSettingForm
,
LDAPSettingForm
,
BasicSettingForm
from
.forms
import
EmailSettingForm
,
LDAPSettingForm
,
BasicSettingForm
,
\
TerminalSettingForm
from
.models
import
Setting
from
.models
import
Setting
from
.mixins
import
AdminUserRequiredMixin
from
.mixins
import
AdminUserRequiredMixin
from
.signals
import
ldap_auth_enable
from
.signals
import
ldap_auth_enable
...
@@ -89,27 +91,29 @@ class LDAPSettingView(AdminUserRequiredMixin, TemplateView):
...
@@ -89,27 +91,29 @@ class LDAPSettingView(AdminUserRequiredMixin, TemplateView):
return
render
(
request
,
self
.
template_name
,
context
)
return
render
(
request
,
self
.
template_name
,
context
)
class
Storage
SettingView
(
AdminUserRequiredMixin
,
TemplateView
):
class
Terminal
SettingView
(
AdminUserRequiredMixin
,
TemplateView
):
form_class
=
LDAP
SettingForm
form_class
=
Terminal
SettingForm
template_name
=
"common/
storage
_setting.html"
template_name
=
"common/
terminal
_setting.html"
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
command_storage
=
settings
.
TERMINAL_COMMAND_STORAGE
context
=
{
context
=
{
'app'
:
_
(
'Settings'
),
'app'
:
_
(
'Settings'
),
'action'
:
_
(
'
Storage
setting'
),
'action'
:
_
(
'
Terminal
setting'
),
'form'
:
self
.
form_class
(),
'form'
:
self
.
form_class
(),
'command_storage'
:
Setting
.
objects
.
filter
(
name__endswith
=
"_COMMAND_STORAGE"
)
'command_storage'
:
command_storage
,
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
post
(
self
,
request
):
def
post
(
self
,
request
):
print
(
request
.
POST
)
form
=
self
.
form_class
(
request
.
POST
)
form
=
self
.
form_class
(
request
.
POST
)
if
form
.
is_valid
():
if
form
.
is_valid
():
form
.
save
()
form
.
save
()
msg
=
_
(
"Update setting successfully, please restart program"
)
msg
=
_
(
"Update setting successfully, please restart program"
)
messages
.
success
(
request
,
msg
)
messages
.
success
(
request
,
msg
)
return
redirect
(
'settings:
storage
-setting'
)
return
redirect
(
'settings:
terminal
-setting'
)
else
:
else
:
context
=
self
.
get_context_data
()
context
=
self
.
get_context_data
()
context
.
update
({
"form"
:
form
})
context
.
update
({
"form"
:
form
})
...
...
apps/jumpserver/settings.py
View file @
b936d54a
...
@@ -373,7 +373,23 @@ CAPTCHA_FOREGROUND_COLOR = '#001100'
...
@@ -373,7 +373,23 @@ CAPTCHA_FOREGROUND_COLOR = '#001100'
CAPTCHA_NOISE_FUNCTIONS
=
(
'captcha.helpers.noise_dots'
,)
CAPTCHA_NOISE_FUNCTIONS
=
(
'captcha.helpers.noise_dots'
,)
CAPTCHA_TEST_MODE
=
CONFIG
.
CAPTCHA_TEST_MODE
CAPTCHA_TEST_MODE
=
CONFIG
.
CAPTCHA_TEST_MODE
COMMAND_STORAGE_BACKEND
=
'terminal.backends.command.db'
COMMAND_STORAGE
=
{
'ENGINE'
:
'terminal.backends.command.db'
,
}
TERMINAL_COMMAND_STORAGE
=
{
'default'
:
{
'TYPE'
:
'server'
,
},
# 'ali-es': {
# 'TYPE': 'elasticsearch',
# 'HOSTS': ['http://elastic:changeme@localhost:9200'],
# },
# 'ali-hz-es': {
# 'TYPE': 'elasticsearch',
# 'HOSTS': ['http://elastic:changeme@localhost:9200'],
# }
}
# Django bootstrap3 setting, more see http://django-bootstrap3.readthedocs.io/en/latest/settings.html
# Django bootstrap3 setting, more see http://django-bootstrap3.readthedocs.io/en/latest/settings.html
BOOTSTRAP3
=
{
BOOTSTRAP3
=
{
...
...
apps/terminal/api.py
View file @
b936d54a
...
@@ -21,7 +21,7 @@ from .serializers import TerminalSerializer, StatusSerializer, \
...
@@ -21,7 +21,7 @@ from .serializers import TerminalSerializer, StatusSerializer, \
SessionSerializer
,
TaskSerializer
,
ReplaySerializer
SessionSerializer
,
TaskSerializer
,
ReplaySerializer
from
.hands
import
IsSuperUserOrAppUser
,
IsAppUser
,
\
from
.hands
import
IsSuperUserOrAppUser
,
IsAppUser
,
\
IsSuperUserOrAppUserOrUserReadonly
IsSuperUserOrAppUserOrUserReadonly
from
.backends
import
get_command_store
,
SessionCommandSerializer
from
.backends
import
get_
terminal_
command_store
,
SessionCommandSerializer
logger
=
logging
.
getLogger
(
__file__
)
logger
=
logging
.
getLogger
(
__file__
)
...
@@ -196,7 +196,7 @@ class CommandViewSet(viewsets.ViewSet):
...
@@ -196,7 +196,7 @@ class CommandViewSet(viewsets.ViewSet):
}
}
"""
"""
command_store
=
get_command_store
()
command_store
=
get_
terminal_
command_store
()
serializer_class
=
SessionCommandSerializer
serializer_class
=
SessionCommandSerializer
permission_classes
=
(
IsSuperUserOrAppUser
,)
permission_classes
=
(
IsSuperUserOrAppUser
,)
...
@@ -260,3 +260,10 @@ class SessionReplayViewSet(viewsets.ViewSet):
...
@@ -260,3 +260,10 @@ class SessionReplayViewSet(viewsets.ViewSet):
return
redirect
(
url
)
return
redirect
(
url
)
else
:
else
:
return
HttpResponseNotFound
()
return
HttpResponseNotFound
()
class
LoadConfig
(
APIView
):
permission_classes
=
(
IsAppUser
,)
def
get
(
self
,
request
):
pass
apps/terminal/backends/__init__.py
View file @
b936d54a
...
@@ -2,9 +2,33 @@ from importlib import import_module
...
@@ -2,9 +2,33 @@ from importlib import import_module
from
django.conf
import
settings
from
django.conf
import
settings
from
.command.serializers
import
SessionCommandSerializer
from
.command.serializers
import
SessionCommandSerializer
TYPE_ENGINE_MAPPING
=
{
'elasticsearch'
:
'terminal.backends.command.db'
,
}
def
get_command_store
():
def
get_command_store
():
command_engine
=
import_module
(
settings
.
COMMAND_STORAGE_BACKEND
)
params
=
settings
.
COMMAND_STORAGE
command_store
=
command_engine
.
CommandStore
()
engine_class
=
import_module
(
params
[
'ENGINE'
])
return
command_store
storage
=
engine_class
.
CommandStore
(
params
)
return
storage
def
get_terminal_command_store
():
storage_list
=
{}
for
name
,
params
in
settings
.
TERMINAL_COMMAND_STORAGE
.
items
():
tp
=
params
[
'TYPE'
]
if
tp
==
'server'
:
storage
=
get_command_store
()
else
:
if
not
TYPE_ENGINE_MAPPING
.
get
(
tp
):
raise
AssertionError
(
"Command storage type should in {}"
.
format
(
', '
.
join
(
TYPE_ENGINE_MAPPING
.
keys
()))
)
engine_class
=
import_module
(
TYPE_ENGINE_MAPPING
[
tp
])
storage
=
engine_class
.
CommandStore
(
params
)
storage_list
[
name
]
=
storage
return
storage_list
apps/terminal/backends/command/base.py
View file @
b936d54a
...
@@ -19,3 +19,9 @@ class CommandBase(object):
...
@@ -19,3 +19,9 @@ class CommandBase(object):
input
=
None
,
session
=
None
):
input
=
None
,
session
=
None
):
pass
pass
@abc.abstractmethod
def
count
(
self
,
date_from
=
None
,
date_to
=
None
,
user
=
None
,
asset
=
None
,
system_user
=
None
,
input
=
None
,
session
=
None
):
pass
apps/terminal/backends/command/db.py
View file @
b936d54a
...
@@ -8,7 +8,7 @@ from .base import CommandBase
...
@@ -8,7 +8,7 @@ from .base import CommandBase
class
CommandStore
(
CommandBase
):
class
CommandStore
(
CommandBase
):
def
__init__
(
self
):
def
__init__
(
self
,
params
):
from
terminal.models
import
Command
from
terminal.models
import
Command
self
.
model
=
Command
self
.
model
=
Command
...
@@ -37,9 +37,11 @@ class CommandStore(CommandBase):
...
@@ -37,9 +37,11 @@ class CommandStore(CommandBase):
))
))
return
self
.
model
.
objects
.
bulk_create
(
_commands
)
return
self
.
model
.
objects
.
bulk_create
(
_commands
)
def
filter
(
self
,
date_from
=
None
,
date_to
=
None
,
@staticmethod
user
=
None
,
asset
=
None
,
system_user
=
None
,
def
make_filter_kwargs
(
input
=
None
,
session
=
None
):
date_from
=
None
,
date_to
=
None
,
user
=
None
,
asset
=
None
,
system_user
=
None
,
input
=
None
,
session
=
None
):
filter_kwargs
=
{}
filter_kwargs
=
{}
date_from_default
=
timezone
.
now
()
-
datetime
.
timedelta
(
days
=
7
)
date_from_default
=
timezone
.
now
()
-
datetime
.
timedelta
(
days
=
7
)
date_to_default
=
timezone
.
now
()
date_to_default
=
timezone
.
now
()
...
@@ -60,10 +62,28 @@ class CommandStore(CommandBase):
...
@@ -60,10 +62,28 @@ class CommandStore(CommandBase):
if
session
:
if
session
:
filter_kwargs
[
'session'
]
=
session
filter_kwargs
[
'session'
]
=
session
return
filter_kwargs
def
filter
(
self
,
date_from
=
None
,
date_to
=
None
,
user
=
None
,
asset
=
None
,
system_user
=
None
,
input
=
None
,
session
=
None
):
filter_kwargs
=
self
.
make_filter_kwargs
(
date_from
=
date_from
,
date_to
=
date_to
,
user
=
user
,
asset
=
asset
,
system_user
=
system_user
,
input
=
input
,
session
=
session
,
)
queryset
=
self
.
model
.
objects
.
filter
(
**
filter_kwargs
)
queryset
=
self
.
model
.
objects
.
filter
(
**
filter_kwargs
)
return
queryset
return
queryset
def
all
(
self
):
def
count
(
self
,
date_from
=
None
,
date_to
=
None
,
"""返回所有数据"""
user
=
None
,
asset
=
None
,
system_user
=
None
,
return
self
.
model
.
objects
.
iterator
()
input
=
None
,
session
=
None
):
filter_kwargs
=
self
.
make_filter_kwargs
(
date_from
=
date_from
,
date_to
=
date_to
,
user
=
user
,
asset
=
asset
,
system_user
=
system_user
,
input
=
input
,
session
=
session
,
)
count
=
self
.
model
.
objects
.
filter
(
**
filter_kwargs
)
.
count
()
return
count
apps/terminal/backends/command/models.py
View file @
b936d54a
...
@@ -18,5 +18,20 @@ class AbstractSessionCommand(models.Model):
...
@@ -18,5 +18,20 @@ class AbstractSessionCommand(models.Model):
class
Meta
:
class
Meta
:
abstract
=
True
abstract
=
True
@classmethod
def
from_dict
(
cls
,
d
):
self
=
cls
()
for
k
,
v
in
d
.
items
():
setattr
(
self
,
k
,
v
)
return
self
@classmethod
def
from_multi_dict
(
cls
,
l
):
commands
=
[]
for
d
in
l
:
command
=
cls
.
from_dict
(
d
)
commands
.
append
(
command
)
return
commands
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
input
return
self
.
input
apps/terminal/forms.py
View file @
b936d54a
...
@@ -10,7 +10,7 @@ from .models import Terminal
...
@@ -10,7 +10,7 @@ from .models import Terminal
class
TerminalForm
(
forms
.
ModelForm
):
class
TerminalForm
(
forms
.
ModelForm
):
class
Meta
:
class
Meta
:
model
=
Terminal
model
=
Terminal
fields
=
[
'name'
,
'remote_addr'
,
'ssh_port'
,
'http_port'
,
'comment'
]
fields
=
[
'name'
,
'remote_addr'
,
'ssh_port'
,
'http_port'
,
'comment'
,
'command_storage'
]
help_texts
=
{
help_texts
=
{
'ssh_port'
:
_
(
"Coco ssh listen port"
),
'ssh_port'
:
_
(
"Coco ssh listen port"
),
'http_port'
:
_
(
"Coco http/ws listen port"
),
'http_port'
:
_
(
"Coco http/ws listen port"
),
...
...
apps/terminal/models.py
View file @
b936d54a
...
@@ -4,17 +4,27 @@ import uuid
...
@@ -4,17 +4,27 @@ import uuid
from
django.db
import
models
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.conf
import
settings
from
users.models
import
User
from
users.models
import
User
from
.backends.command.models
import
AbstractSessionCommand
from
.backends.command.models
import
AbstractSessionCommand
def
get_all_command_storage
():
storage_choices
=
[]
for
k
,
v
in
settings
.
TERMINAL_COMMAND_STORAGE
.
items
():
storage_choices
.
append
((
k
,
k
))
return
storage_choices
class
Terminal
(
models
.
Model
):
class
Terminal
(
models
.
Model
):
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
name
=
models
.
CharField
(
max_length
=
32
,
verbose_name
=
_
(
'Name'
))
name
=
models
.
CharField
(
max_length
=
32
,
verbose_name
=
_
(
'Name'
))
remote_addr
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
'Remote Address'
))
remote_addr
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
'Remote Address'
))
ssh_port
=
models
.
IntegerField
(
verbose_name
=
_
(
'SSH Port'
),
default
=
2222
)
ssh_port
=
models
.
IntegerField
(
verbose_name
=
_
(
'SSH Port'
),
default
=
2222
)
http_port
=
models
.
IntegerField
(
verbose_name
=
_
(
'HTTP Port'
),
default
=
5000
)
http_port
=
models
.
IntegerField
(
verbose_name
=
_
(
'HTTP Port'
),
default
=
5000
)
command_storage
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"Command storage"
),
default
=
'default'
,
choices
=
get_all_command_storage
())
replay_storage
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"Replay storage"
),
default
=
'default'
)
user
=
models
.
OneToOneField
(
User
,
related_name
=
'terminal'
,
verbose_name
=
'Application User'
,
null
=
True
,
on_delete
=
models
.
CASCADE
)
user
=
models
.
OneToOneField
(
User
,
related_name
=
'terminal'
,
verbose_name
=
'Application User'
,
null
=
True
,
on_delete
=
models
.
CASCADE
)
is_accepted
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
'Is Accepted'
)
is_accepted
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
'Is Accepted'
)
is_deleted
=
models
.
BooleanField
(
default
=
False
)
is_deleted
=
models
.
BooleanField
(
default
=
False
)
...
@@ -33,6 +43,16 @@ class Terminal(models.Model):
...
@@ -33,6 +43,16 @@ class Terminal(models.Model):
self
.
user
.
is_active
=
active
self
.
user
.
is_active
=
active
self
.
user
.
save
()
self
.
user
.
save
()
def
get_common_storage
(
self
):
pass
def
get_replay_storage
(
self
):
pass
@property
def
config
(
self
):
return
def
create_app_user
(
self
):
def
create_app_user
(
self
):
random
=
uuid
.
uuid4
()
.
hex
[:
6
]
random
=
uuid
.
uuid4
()
.
hex
[:
6
]
user
,
access_key
=
User
.
create_app_user
(
name
=
"{}-{}"
.
format
(
self
.
name
,
random
),
comment
=
self
.
comment
)
user
,
access_key
=
User
.
create_app_user
(
name
=
"{}-{}"
.
format
(
self
.
name
,
random
),
comment
=
self
.
comment
)
...
...
apps/terminal/serializers.py
View file @
b936d54a
...
@@ -5,7 +5,7 @@ from django.utils import timezone
...
@@ -5,7 +5,7 @@ from django.utils import timezone
from
rest_framework
import
serializers
from
rest_framework
import
serializers
from
.models
import
Terminal
,
Status
,
Session
,
Task
from
.models
import
Terminal
,
Status
,
Session
,
Task
from
.backends
import
get_command_store
from
.backends
import
get_
terminal_
command_store
class
TerminalSerializer
(
serializers
.
ModelSerializer
):
class
TerminalSerializer
(
serializers
.
ModelSerializer
):
...
@@ -43,7 +43,7 @@ class TerminalSerializer(serializers.ModelSerializer):
...
@@ -43,7 +43,7 @@ class TerminalSerializer(serializers.ModelSerializer):
class
SessionSerializer
(
serializers
.
ModelSerializer
):
class
SessionSerializer
(
serializers
.
ModelSerializer
):
command_amount
=
serializers
.
SerializerMethodField
()
command_amount
=
serializers
.
SerializerMethodField
()
command_store
=
get_command_store
()
command_store
=
get_
terminal_
command_store
()
class
Meta
:
class
Meta
:
model
=
Session
model
=
Session
...
...
apps/terminal/templates/terminal/terminal_modal_accept.html
View file @
b936d54a
...
@@ -12,6 +12,7 @@
...
@@ -12,6 +12,7 @@
{% bootstrap_field form.remote_addr layout="horizontal" %}
{% bootstrap_field form.remote_addr layout="horizontal" %}
{% bootstrap_field form.ssh_port layout="horizontal" %}
{% bootstrap_field form.ssh_port layout="horizontal" %}
{% bootstrap_field form.http_port layout="horizontal" %}
{% bootstrap_field form.http_port layout="horizontal" %}
{% bootstrap_field form.command_storage layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %}
</form>
</form>
...
...
apps/terminal/templates/terminal/terminal_update.html
View file @
b936d54a
...
@@ -35,6 +35,7 @@
...
@@ -35,6 +35,7 @@
{% bootstrap_field form.remote_addr layout="horizontal" %}
{% bootstrap_field form.remote_addr layout="horizontal" %}
{% bootstrap_field form.ssh_port layout="horizontal" %}
{% bootstrap_field form.ssh_port layout="horizontal" %}
{% bootstrap_field form.http_port layout="horizontal" %}
{% bootstrap_field form.http_port layout="horizontal" %}
{% bootstrap_field form.command_storage layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Other' %}
</h3>
<h3>
{% trans 'Other' %}
</h3>
...
...
apps/terminal/templatetags/terminal_tags.py
View file @
b936d54a
# ~*~ coding: utf-8 ~*~
# ~*~ coding: utf-8 ~*~
from
django
import
template
from
django
import
template
from
..backends
import
get_command_store
from
..backends
import
get_
terminal_
command_store
register
=
template
.
Library
()
register
=
template
.
Library
()
command_store
=
get
_command_store
()
command_store
_dict
=
get_terminal
_command_store
()
@register.filter
@register.filter
def
get_session_command_amount
(
session_id
):
def
get_session_command_amount
(
session_id
):
return
len
(
command_store
.
filter
(
session
=
str
(
session_id
)))
amount
=
0
for
name
,
store
in
command_store_dict
.
items
():
amount
+=
store
.
count
(
session
=
str
(
session_id
))
return
amount
apps/terminal/views/command.py
View file @
b936d54a
...
@@ -9,10 +9,10 @@ from django.utils.translation import ugettext as _
...
@@ -9,10 +9,10 @@ from django.utils.translation import ugettext as _
from
common.mixins
import
DatetimeSearchMixin
from
common.mixins
import
DatetimeSearchMixin
from
..models
import
Command
from
..models
import
Command
from
..
import
utils
from
..
import
utils
from
..backends
import
get_command_store
from
..backends
import
get_
terminal_
command_store
__all__
=
[
'CommandListView'
]
__all__
=
[
'CommandListView'
]
command_store
=
get
_command_store
()
command_store
_list
=
get_terminal
_command_store
()
class
CommandListView
(
DatetimeSearchMixin
,
ListView
):
class
CommandListView
(
DatetimeSearchMixin
,
ListView
):
...
@@ -39,7 +39,10 @@ class CommandListView(DatetimeSearchMixin, ListView):
...
@@ -39,7 +39,10 @@ class CommandListView(DatetimeSearchMixin, ListView):
filter_kwargs
[
'system_user'
]
=
self
.
system_user
filter_kwargs
[
'system_user'
]
=
self
.
system_user
if
self
.
command
:
if
self
.
command
:
filter_kwargs
[
'input'
]
=
self
.
command
filter_kwargs
[
'input'
]
=
self
.
command
queryset
=
command_store
.
filter
(
**
filter_kwargs
)
queryset
=
[]
for
store
in
command_store_list
:
queryset
.
extend
(
store
.
filter
(
**
filter_kwargs
))
queryset
=
sorted
(
queryset
,
key
=
lambda
c
:
c
.
timestamp
,
reverse
=
True
)
return
queryset
return
queryset
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
...
...
apps/terminal/views/session.py
View file @
b936d54a
...
@@ -10,7 +10,7 @@ from django.conf import settings
...
@@ -10,7 +10,7 @@ from django.conf import settings
from
users.utils
import
AdminUserRequiredMixin
from
users.utils
import
AdminUserRequiredMixin
from
common.mixins
import
DatetimeSearchMixin
from
common.mixins
import
DatetimeSearchMixin
from
..models
import
Session
,
Command
,
Terminal
from
..models
import
Session
,
Command
,
Terminal
from
..backends
import
get_command_store
from
..backends
import
get_
terminal_
command_store
from
..
import
utils
from
..
import
utils
...
@@ -19,7 +19,7 @@ __all__ = [
...
@@ -19,7 +19,7 @@ __all__ = [
'SessionDetailView'
,
'SessionDetailView'
,
]
]
command_store
=
get_command_store
()
command_store
=
get_
terminal_
command_store
()
class
SessionListView
(
AdminUserRequiredMixin
,
DatetimeSearchMixin
,
ListView
):
class
SessionListView
(
AdminUserRequiredMixin
,
DatetimeSearchMixin
,
ListView
):
...
...
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