Commit ef9e03c7 authored by ibuler's avatar ibuler

Merge remote-tracking branch 'github/dev' into dev

parents eb95a0a9 442d4e72
......@@ -16,7 +16,7 @@ class AssetCreateForm(forms.ModelForm):
fields = [
'hostname', 'ip', 'public_ip', 'port', 'comment',
'nodes', 'is_active', 'admin_user', 'labels', 'platform',
'domain',
'domain', 'protocol',
]
widgets = {
......@@ -56,7 +56,7 @@ class AssetUpdateForm(forms.ModelForm):
fields = [
'hostname', 'ip', 'port', 'nodes', 'is_active', 'platform',
'public_ip', 'number', 'comment', 'admin_user', 'labels',
'domain',
'domain', 'protocol',
]
widgets = {
'nodes': forms.SelectMultiple(attrs={
......
......@@ -93,14 +93,21 @@ class SystemUserForm(PasswordAndKeyAuthForm):
# Because we define custom field, so we need rewrite :method: `save`
system_user = super().save()
password = self.cleaned_data.get('password', '') or None
login_mode = self.cleaned_data.get('login_mode', '') or None
protocol = self.cleaned_data.get('protocol') or None
auto_generate_key = self.cleaned_data.get('auto_generate_key', False)
private_key, public_key = super().gen_keys()
if login_mode == SystemUser.MANUAL_LOGIN or protocol == SystemUser.TELNET_PROTOCOL:
system_user.auto_push = 0
system_user.save()
if auto_generate_key:
logger.info('Auto generate key and set system user auth')
system_user.auto_gen_auth()
else:
system_user.set_auth(password=password, private_key=private_key, public_key=public_key)
return system_user
def clean(self):
......@@ -109,12 +116,24 @@ class SystemUserForm(PasswordAndKeyAuthForm):
if not self.instance and not auto_generate:
super().validate_password_key()
def is_valid(self):
validated = super().is_valid()
username = self.cleaned_data.get('username')
login_mode = self.cleaned_data.get('login_mode')
if login_mode == SystemUser.AUTO_LOGIN and not username:
self.add_error(
"username", _('* Automatic login mode,'
' must fill in the username.')
)
return False
return validated
class Meta:
model = SystemUser
fields = [
'name', 'username', 'protocol', 'auto_generate_key',
'password', 'private_key_file', 'auto_push', 'sudo',
'comment', 'shell', 'priority',
'comment', 'shell', 'priority', 'login_mode',
]
widgets = {
'name': forms.TextInput(attrs={'placeholder': _('Name')}),
......@@ -124,5 +143,8 @@ class SystemUserForm(PasswordAndKeyAuthForm):
'name': '* required',
'username': '* required',
'auto_push': _('Auto push system user to asset'),
'priority': _('High level will be using login asset as default, if user was granted more than 2 system user'),
'priority': _('High level will be using login asset as default, '
'if user was granted more than 2 system user'),
'login_mode': _('If you choose manual login mode, you do not '
'need to fill in the username and password.')
}
......@@ -57,13 +57,27 @@ class Asset(models.Model):
('MacOS', 'MacOS'),
('BSD', 'BSD'),
('Windows', 'Windows'),
('Windows2016', 'Windows(2016)'),
('Other', 'Other'),
)
SSH_PROTOCOL = 'ssh'
RDP_PROTOCOL = 'rdp'
TELNET_PROTOCOL = 'telnet'
PROTOCOL_CHOICES = (
(SSH_PROTOCOL, 'ssh'),
(RDP_PROTOCOL, 'rdp'),
(TELNET_PROTOCOL, 'telnet (beta)'),
)
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'),
db_index=True)
hostname = models.CharField(max_length=128, unique=True,
verbose_name=_('Hostname'))
protocol = models.CharField(max_length=128, default=SSH_PROTOCOL,
choices=PROTOCOL_CHOICES,
verbose_name=_('Protocol'))
port = models.IntegerField(default=22, verbose_name=_('Port'))
platform = models.CharField(max_length=128, choices=PLATFORM_CHOICES,
default='Linux', verbose_name=_('Platform'))
......
......@@ -19,7 +19,7 @@ signer = get_signer()
class AssetUser(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
username = models.CharField(max_length=32, verbose_name=_('Username'), validators=[alphanumeric])
username = models.CharField(max_length=32, blank=True, verbose_name=_('Username'), validators=[alphanumeric])
_password = models.CharField(max_length=256, blank=True, null=True, verbose_name=_('Password'))
_private_key = models.TextField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'), validators=[private_key_validator, ])
_public_key = models.TextField(max_length=4096, blank=True, verbose_name=_('SSH public key'))
......
......@@ -95,9 +95,18 @@ class AdminUser(AssetUser):
class SystemUser(AssetUser):
SSH_PROTOCOL = 'ssh'
RDP_PROTOCOL = 'rdp'
TELNET_PROTOCOL = 'telnet'
PROTOCOL_CHOICES = (
(SSH_PROTOCOL, 'ssh'),
(RDP_PROTOCOL, 'rdp'),
(TELNET_PROTOCOL, 'telnet (beta)'),
)
AUTO_LOGIN = 'auto'
MANUAL_LOGIN = 'manual'
LOGIN_MODE_CHOICES = (
(AUTO_LOGIN, _('Automatic login')),
(MANUAL_LOGIN, _('Manually login'))
)
nodes = models.ManyToManyField('assets.Node', blank=True, verbose_name=_("Nodes"))
......@@ -107,6 +116,7 @@ class SystemUser(AssetUser):
auto_push = models.BooleanField(default=True, verbose_name=_('Auto push'))
sudo = models.TextField(default='/bin/whoami', verbose_name=_('Sudo'))
shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell'))
login_mode = models.CharField(choices=LOGIN_MODE_CHOICES, default=AUTO_LOGIN, max_length=10, verbose_name=_('Login mode'))
def __str__(self):
return '{0.name}({0.username})'.format(self)
......
......@@ -43,7 +43,7 @@ class AssetGrantedSerializer(serializers.ModelSerializer):
fields = (
"id", "hostname", "ip", "port", "system_users_granted",
"is_active", "system_users_join", "os", 'domain',
"platform", "comment"
"platform", "comment", "protocol",
)
@staticmethod
......
......@@ -18,6 +18,13 @@ class SystemUserSerializer(serializers.ModelSerializer):
model = SystemUser
exclude = ('_password', '_private_key', '_public_key')
def get_field_names(self, declared_fields, info):
fields = super(SystemUserSerializer, self).get_field_names(declared_fields, info)
fields.extend([
'get_login_mode_display',
])
return fields
@staticmethod
def get_unreachable_assets(obj):
return obj.unreachable_assets
......@@ -56,7 +63,10 @@ class AssetSystemUserSerializer(serializers.ModelSerializer):
"""
class Meta:
model = SystemUser
fields = ('id', 'name', 'username', 'priority', 'protocol', 'comment',)
fields = (
'id', 'name', 'username', 'priority',
'protocol', 'comment', 'login_mode'
)
class SystemUserSimpleSerializer(serializers.ModelSerializer):
......
......@@ -36,12 +36,13 @@
{% endif %}
<h3>{% trans 'Basic' %}</h3>
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.login_mode layout="horizontal" %}
{% bootstrap_field form.username layout="horizontal" %}
{% bootstrap_field form.priority layout="horizontal" %}
{% bootstrap_field form.protocol layout="horizontal" %}
<h3 id="auth_title_id">{% trans 'Auth' %}</h3>
{% block auth %}
<h3>{% trans 'Auth' %}</h3>
<div class="auto-generate">
<div class="form-group">
<label for="{{ form.auto_generate_key.id_for_label }}" class="col-sm-2 control-label">{% trans 'Auto generate key' %}</label>
......@@ -80,15 +81,22 @@
{% endblock %}
{% block custom_foot_js %}
<script>
var auto_generate_key = '#'+'{{ form.auto_generate_key.id_for_label }}';
var protocol_id = '#' + '{{ form.protocol.id_for_label }}';
var login_mode_id = '#' + '{{ form.login_mode.id_for_label }}';
var auto_generate_key = '#'+'{{ form.auto_generate_key.id_for_label }}';
var password_id = '#' + '{{ form.password.id_for_label }}';
var private_key_id = '#' + '{{ form.private_key_file.id_for_label }}';
var auto_push_id = '#' + '{{ form.auto_push.id_for_label }}';
var sudo_id = '#' + '{{ form.sudo.id_for_label }}';
var shell_id = '#' + '{{ form.shell.id_for_label }}';
var need_change_field = [
auto_generate_key, private_key_id, auto_push_id, sudo_id, shell_id
];
var need_change_field_login_mode = [
auto_generate_key, private_key_id, auto_push_id, password_id
];
function protocolChange() {
if ($(protocol_id + " option:selected").text() === 'rdp') {
......@@ -96,7 +104,19 @@ function protocolChange() {
$.each(need_change_field, function (index, value) {
$(value).closest('.form-group').addClass('hidden')
});
} else {
}
else if ($(protocol_id + " option:selected").text() === 'telnet (beta)') {
$('.auth-fields').removeClass('hidden');
$.each(need_change_field, function (index, value) {
$(value).closest('.form-group').addClass('hidden')
});
}
else {
if($(login_mode_id).val() === 'manual'){
$(sudo_id).closest('.form-group').removeClass('hidden');
$(shell_id).closest('.form-group').removeClass('hidden');
return
}
authFieldsDisplay();
$.each(need_change_field, function (index, value) {
$(value).closest('.form-group').removeClass('hidden')
......@@ -111,18 +131,35 @@ function authFieldsDisplay() {
$('.auth-fields').removeClass('hidden');
}
}
function loginModeChange(){
if ($(login_mode_id).val() === 'manual'){
$('#auth_title_id').addClass('hidden');
$.each(need_change_field_login_mode, function(index, value){
$(value).closest('.form-group').addClass('hidden')
})
}
else if($(login_mode_id).val() === 'auto'){
$('#auth_title_id').removeClass('hidden');
$(password_id).closest('.form-group').removeClass('hidden')
protocolChange();
}
}
$(document).ready(function () {
$('.select2').select2();
authFieldsDisplay();
protocolChange();
loginModeChange();
})
.on('change', protocol_id, function(){
protocolChange();
})
.on('change', auto_generate_key, function(){
authFieldsDisplay();
});
})
.on('change', login_mode_id, function(){
loginModeChange();
})
</script>
{% endblock %}
\ No newline at end of file
......@@ -17,6 +17,7 @@
{% bootstrap_field form.hostname layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.protocol layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %}
{% bootstrap_field form.domain layout="horizontal" %}
......@@ -85,14 +86,14 @@ $(document).ready(function () {
allowClear: true,
templateSelection: format
});
$("#id_platform").change(function (){
var platform = $("#id_platform option:selected").text();
$("#id_protocol").change(function (){
var protocol = $("#id_protocol option:selected").text();
var port = 22;
if(platform === 'Windows'){
if(protocol === 'rdp'){
port = 3389;
}
if(platform === 'Other'){
port = null;
if(protocol === 'telnet (beta)'){
port = 23;
}
$("#id_port").val(port);
});
......
......@@ -21,6 +21,7 @@
<h3>{% trans 'Basic' %}</h3>
{% bootstrap_field form.hostname layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.protocol layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %}
......
......@@ -62,6 +62,10 @@
<td>{% trans 'Username' %}:</td>
<td><b>{{ system_user.username }}</b></td>
</tr>
<tr>
<td>{% trans 'Login mode' %}:</td>
<td><b>{{ system_user.get_login_mode_display }}</b></td>
</tr>
<tr>
<td>{% trans 'Protocol' %}:</td>
<td><b id="id_protocol_type">{{ system_user.protocol }}</b></td>
......
......@@ -26,6 +26,7 @@
<th class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'Username' %}</th>
<th class="text-center">{% trans 'Protocol' %}</th>
<th class="text-center">{% trans 'Login mode' %}</th>
<th class="text-center">{% trans 'Asset' %}</th>
<th class="text-center">{% trans 'Reachable' %}</th>
<th class="text-center">{% trans 'Unreachable' %}</th>
......@@ -48,7 +49,7 @@ function initTable() {
var detail_btn = '<a href="{% url "assets:system-user-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
}},
{targets: 5, createdCell: function (td, cellData) {
{targets: 6, createdCell: function (td, cellData) {
var innerHtml = "";
if (cellData !== 0) {
innerHtml = "<span class='text-navy'>" + cellData + "</span>";
......@@ -57,7 +58,7 @@ function initTable() {
}
$(td).html('<span href="javascript:void(0);" data-toggle="tooltip" title="' + cellData +'">' + innerHtml + '</span>');
}},
{targets: 6, createdCell: function (td, cellData) {
{targets: 7, createdCell: function (td, cellData) {
var innerHtml = "";
if (cellData !== 0) {
innerHtml = "<span class='text-danger'>" + cellData + "</span>";
......@@ -66,7 +67,7 @@ function initTable() {
}
$(td).html('<span href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</span>');
}},
{targets: 7, createdCell: function (td, cellData, rowData) {
{targets: 8, createdCell: function (td, cellData, rowData) {
var val = 0;
var innerHtml = "";
var total = rowData.assets_amount;
......@@ -84,14 +85,14 @@ function initTable() {
$(td).html('<span href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</span>');
}},
{targets: 9, createdCell: function (td, cellData, rowData) {
{targets: 10, createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "assets:system-user-update" pk=DEFAULT_PK %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_admin_user_delete" data-uid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
$(td).html(update_btn + del_btn)
}}],
ajax_url: '{% url "api-assets:system-user-list" %}',
columns: [
{data: "id" }, {data: "name" }, {data: "username" }, {data: "protocol"}, {data: "assets_amount" },
{data: "id" }, {data: "name" }, {data: "username" }, {data: "protocol"}, {data: "get_login_mode_display"}, {data: "assets_amount" },
{data: "reachable_amount"}, {data: "unreachable_amount"}, {data: "id"}, {data: "comment" }, {data: "id" }
],
op_html: $('#actions').html()
......
......@@ -4,7 +4,6 @@
{% load bootstrap3 %}
{% block auth %}
<h3>{% trans 'Auth' %}</h3>
{% bootstrap_field form.password layout="horizontal" %}
{% bootstrap_field form.private_key_file layout="horizontal" %}
<div class="form-group">
......
This diff is collapsed.
......@@ -343,10 +343,11 @@ if AUTH_LDAP:
AUTHENTICATION_BACKENDS.insert(0, AUTH_LDAP_BACKEND)
# Celery using redis as broker
CELERY_BROKER_URL = 'redis://:%(password)s@%(host)s:%(port)s/3' % {
CELERY_BROKER_URL = 'redis://:%(password)s@%(host)s:%(port)s/%(db)s' % {
'password': CONFIG.REDIS_PASSWORD if CONFIG.REDIS_PASSWORD else '',
'host': CONFIG.REDIS_HOST or '127.0.0.1',
'port': CONFIG.REDIS_PORT or 6379,
'db':CONFIG.REDIS_DB_CELERY_BROKER or 3,
}
CELERY_TASK_SERIALIZER = 'pickle'
CELERY_RESULT_SERIALIZER = 'pickle'
......@@ -367,10 +368,11 @@ CELERY_WORKER_HIJACK_ROOT_LOGGER = False
CACHES = {
'default': {
'BACKEND': 'redis_cache.RedisCache',
'LOCATION': 'redis://:%(password)s@%(host)s:%(port)s/4' % {
'LOCATION': 'redis://:%(password)s@%(host)s:%(port)s/%(db)s' % {
'password': CONFIG.REDIS_PASSWORD if CONFIG.REDIS_PASSWORD else '',
'host': CONFIG.REDIS_HOST or '127.0.0.1',
'port': CONFIG.REDIS_PORT or 6379,
'db':CONFIG.REDIS_DB_CACHE or 4,
}
}
}
......
......@@ -73,9 +73,9 @@ class UserGrantedAssetsApi(ListAPIView):
util = AssetPermissionUtil(user)
for k, v in util.get_assets().items():
if k.is_unixlike():
system_users_granted = [s for s in v if s.protocol == 'ssh']
system_users_granted = [s for s in v if s.protocol in ['ssh', 'telnet']]
else:
system_users_granted = [s for s in v if s.protocol == 'rdp']
system_users_granted = [s for s in v if s.protocol in ['rdp', 'telnet']]
k.system_users_granted = system_users_granted
queryset.append(k)
return queryset
......@@ -124,9 +124,9 @@ class UserGrantedNodesWithAssetsApi(ListAPIView):
assets = _assets.keys()
for k, v in _assets.items():
if k.is_unixlike():
system_users_granted = [s for s in v if s.protocol == 'ssh']
system_users_granted = [s for s in v if s.protocol in ['ssh', 'telnet']]
else:
system_users_granted = [s for s in v if s.protocol == 'rdp']
system_users_granted = [s for s in v if s.protocol in ['rdp', 'telnet']]
k.system_users_granted = system_users_granted
node.assets_granted = assets
queryset.append(node)
......
......@@ -21,10 +21,10 @@ class Config:
ALLOWED_HOSTS = ['*']
# Development env open this, when error occur display the full process track, Production disable it
DEBUG = True
DEBUG = os.environ.get("DEBUG") or True
# DEBUG, INFO, WARNING, ERROR, CRITICAL can set. See https://docs.djangoproject.com/en/1.10/topics/logging/
LOG_LEVEL = 'DEBUG'
LOG_LEVEL = os.environ.get("LOG_LEVEL") or 'DEBUG'
LOG_DIR = os.path.join(BASE_DIR, 'logs')
# Database setting, Support sqlite3, mysql, postgres ....
......@@ -35,12 +35,12 @@ class Config:
DB_NAME = os.path.join(BASE_DIR, 'data', 'db.sqlite3')
# MySQL or postgres setting like:
# DB_ENGINE = 'mysql'
# DB_HOST = '127.0.0.1'
# DB_PORT = 3306
# DB_USER = 'root'
# DB_PASSWORD = ''
# DB_NAME = 'jumpserver'
# DB_ENGINE = os.environ.get("DB_ENGINE") or 'mysql'
# DB_HOST = os.environ.get("DB_HOST") or '127.0.0.1'
# DB_PORT = os.environ.get("DB_PORT") or 3306
# DB_USER = os.environ.get("DB_USER") or 'jumpserver'
# DB_PASSWORD = os.environ.get("DB_PASSWORD") or 'weakPassword'
# DB_NAME = os.environ.get("DB_NAME") or 'jumpserver'
# When Django start it will bind this host and port
# ./manage.py runserver 127.0.0.1:8080
......@@ -48,9 +48,11 @@ class Config:
HTTP_LISTEN_PORT = 8080
# Use Redis as broker for celery and web socket
REDIS_HOST = '127.0.0.1'
REDIS_PORT = 6379
REDIS_PASSWORD = ''
REDIS_HOST = os.environ.get("REDIS_HOST") or '127.0.0.1'
REDIS_PORT = os.environ.get("REDIS_PORT") or 6379
REDIS_PASSWORD = os.environ.get("REDIS_PASSWORD") or ''
REDIS_DB_CELERY = os.environ.get('REDIS_DB') or 3
REDIS_DB_CACHE = os.environ.get('REDIS_DB') or 4
def __init__(self):
pass
......
libtiff5-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk python-dev openssl libssl-dev libldap2-dev libsasl2-dev sqlite gcc automake
libtiff5-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk python-dev openssl libssl-dev libldap2-dev libsasl2-dev sqlite gcc automake libkrb5-dev
......@@ -4,3 +4,5 @@
python3 ../apps/manage.py makemigrations
python3 ../apps/manage.py migrate
python3 ../apps/manage.py makemigrations –merge
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment