diff --git a/apps/common/api.py b/apps/common/api.py index cf3855b60..269d493d0 100644 --- a/apps/common/api.py +++ b/apps/common/api.py @@ -1,197 +1,17 @@ # -*- coding: utf-8 -*- # - import os -import json -import jms_storage import uuid -from rest_framework.views import Response, APIView -from rest_framework import generics -from ldap3 import Server, Connection -from django.core.mail import send_mail +from rest_framework.views import Response +from rest_framework import generics, serializers from django.core.cache import cache -from django.utils.translation import ugettext_lazy as _ -from django.conf import settings - -from .permissions import IsOrgAdmin, IsSuperUser -from .serializers import ( - MailTestSerializer, LDAPTestSerializer, OutputSerializer -) -from .models import Setting -class MailTestingAPI(APIView): - permission_classes = (IsOrgAdmin,) - serializer_class = MailTestSerializer - success_message = _("Test mail sent to {}, please check") - - def post(self, request): - serializer = self.serializer_class(data=request.data) - if serializer.is_valid(): - email_host_user = serializer.validated_data["EMAIL_HOST_USER"] - for k, v in serializer.validated_data.items(): - if k.startswith('EMAIL'): - setattr(settings, k, v) - try: - subject = "Test" - message = "Test smtp setting" - send_mail(subject, message, email_host_user, [email_host_user]) - except Exception as e: - return Response({"error": str(e)}, status=401) - - return Response({"msg": self.success_message.format(email_host_user)}) - else: - return Response({"error": str(serializer.errors)}, status=401) - - -class LDAPTestingAPI(APIView): - permission_classes = (IsOrgAdmin,) - serializer_class = LDAPTestSerializer - success_message = _("Test ldap success") - - def post(self, request): - serializer = self.serializer_class(data=request.data) - if serializer.is_valid(): - host = serializer.validated_data["AUTH_LDAP_SERVER_URI"] - bind_dn = serializer.validated_data["AUTH_LDAP_BIND_DN"] - password = serializer.validated_data["AUTH_LDAP_BIND_PASSWORD"] - use_ssl = serializer.validated_data.get("AUTH_LDAP_START_TLS", False) - search_ougroup = serializer.validated_data["AUTH_LDAP_SEARCH_OU"] - search_filter = serializer.validated_data["AUTH_LDAP_SEARCH_FILTER"] - attr_map = serializer.validated_data["AUTH_LDAP_USER_ATTR_MAP"] - - try: - attr_map = json.loads(attr_map) - except json.JSONDecodeError: - return Response({"error": "AUTH_LDAP_USER_ATTR_MAP not valid"}, status=401) - - server = Server(host, use_ssl=use_ssl) - conn = Connection(server, bind_dn, password) - try: - conn.bind() - except Exception as e: - return Response({"error": str(e)}, status=401) - - users = [] - for search_ou in str(search_ougroup).split("|"): - ok = conn.search(search_ou, search_filter % ({"user": "*"}), - attributes=list(attr_map.values())) - if not ok: - return Response({"error": _("Search no entry matched in ou {}").format(search_ou)}, status=401) - - for entry in conn.entries: - user = {} - for attr, mapping in attr_map.items(): - if hasattr(entry, mapping): - user[attr] = getattr(entry, mapping) - users.append(user) - if len(users) > 0: - return Response({"msg": _("Match {} s users").format(len(users))}) - else: - return Response({"error": "Have user but attr mapping error"}, status=401) - else: - return Response({"error": str(serializer.errors)}, status=401) - - -class ReplayStorageCreateAPI(APIView): - permission_classes = (IsSuperUser,) - - def post(self, request): - storage_data = request.data - - if storage_data.get('TYPE') == 'ceph': - port = storage_data.get('PORT') - if port.isdigit(): - storage_data['PORT'] = int(storage_data.get('PORT')) - - storage_name = storage_data.pop('NAME') - data = {storage_name: storage_data} - - if not self.is_valid(storage_data): - return Response({ - "error": _("Error: Account invalid (Please make sure the " - "information such as Access key or Secret key is correct)")}, - status=401 - ) - - Setting.save_storage('TERMINAL_REPLAY_STORAGE', data) - return Response({"msg": _('Create succeed')}, status=200) - - @staticmethod - def is_valid(storage_data): - if storage_data.get('TYPE') == 'server': - return True - storage = jms_storage.get_object_storage(storage_data) - target = 'tests.py' - src = os.path.join(settings.BASE_DIR, 'common', target) - return storage.is_valid(src, target) - - -class ReplayStorageDeleteAPI(APIView): - permission_classes = (IsSuperUser,) - - def post(self, request): - storage_name = str(request.data.get('name')) - Setting.delete_storage('TERMINAL_REPLAY_STORAGE', storage_name) - return Response({"msg": _('Delete succeed')}, status=200) - - -class CommandStorageCreateAPI(APIView): - permission_classes = (IsSuperUser,) - - def post(self, request): - storage_data = request.data - storage_name = storage_data.pop('NAME') - data = {storage_name: storage_data} - if not self.is_valid(storage_data): - return Response( - {"error": _("Error: Account invalid (Please make sure the " - "information such as Access key or Secret key is correct)")}, - status=401 - ) - - Setting.save_storage('TERMINAL_COMMAND_STORAGE', data) - return Response({"msg": _('Create succeed')}, status=200) - - @staticmethod - def is_valid(storage_data): - if storage_data.get('TYPE') == 'server': - return True - try: - storage = jms_storage.get_log_storage(storage_data) - except Exception: - return False - - return storage.ping() - - -class CommandStorageDeleteAPI(APIView): - permission_classes = (IsSuperUser,) - - def post(self, request): - storage_name = str(request.data.get('name')) - Setting.delete_storage('TERMINAL_COMMAND_STORAGE', storage_name) - return Response({"msg": _('Delete succeed')}, status=200) - - -class DjangoSettingsAPI(APIView): - def get(self, request): - if not settings.DEBUG: - return Response("Not in debug mode") - - data = {} - for i in [settings, getattr(settings, '_wrapped')]: - if not i: - continue - for k, v in i.__dict__.items(): - if k and k.isupper(): - try: - json.dumps(v) - data[k] = v - except (json.JSONDecodeError, TypeError): - data[k] = str(v) - return Response(data) +class OutputSerializer(serializers.Serializer): + output = serializers.CharField() + is_end = serializers.BooleanField() + mark = serializers.CharField() class LogTailApi(generics.RetrieveAPIView): diff --git a/apps/common/apps.py b/apps/common/apps.py index bc6db2151..ea797805d 100644 --- a/apps/common/apps.py +++ b/apps/common/apps.py @@ -1,13 +1,17 @@ from __future__ import unicode_literals +import sys from django.apps import AppConfig +from django.dispatch import receiver +from django.db.backends.signals import connection_created + + +@receiver(connection_created, dispatch_uid="my_unique_identifier") +def on_db_connection_ready(sender, **kwargs): + from .signals import django_ready + if 'migrate' not in sys.argv: + django_ready.send(CommonConfig) class CommonConfig(AppConfig): name = 'common' - - def ready(self): - from . import signals_handler - from .signals import django_ready - django_ready.send(self.__class__) - return super().ready() diff --git a/apps/common/migrations/0002_auto_20180111_1407.py b/apps/common/migrations/0002_auto_20180111_1407.py deleted file mode 100644 index 7c74b9d2b..000000000 --- a/apps/common/migrations/0002_auto_20180111_1407.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-11 06:07 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('common', '0001_initial'), - ] - - operations = [ - migrations.RenameModel( - old_name='Settings', - new_name='Setting', - ), - migrations.AlterModelManagers( - name='setting', - managers=[ - ], - ), - migrations.AlterModelTable( - name='setting', - table='settings', - ), - ] diff --git a/apps/common/migrations/0003_setting_category.py b/apps/common/migrations/0003_setting_category.py deleted file mode 100644 index 234518287..000000000 --- a/apps/common/migrations/0003_setting_category.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-22 03:54 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('common', '0002_auto_20180111_1407'), - ] - - operations = [ - migrations.AddField( - model_name='setting', - name='category', - field=models.CharField(default='default', max_length=128), - ), - ] diff --git a/apps/common/migrations/0004_setting_encrypted.py b/apps/common/migrations/0004_setting_encrypted.py deleted file mode 100644 index d6862643f..000000000 --- a/apps/common/migrations/0004_setting_encrypted.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1 on 2018-09-03 03:32 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('common', '0003_setting_category'), - ] - - operations = [ - migrations.AddField( - model_name='setting', - name='encrypted', - field=models.BooleanField(default=False), - ), - ] diff --git a/apps/common/migrations/0005_auto_20190221_1902.py b/apps/common/migrations/0005_auto_20190221_1902.py deleted file mode 100644 index 997ca7a13..000000000 --- a/apps/common/migrations/0005_auto_20190221_1902.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-21 11:02 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('common', '0004_setting_encrypted'), - ] - - operations = [ - migrations.AlterModelOptions( - name='setting', - options={'verbose_name': 'Setting'}, - ), - ] diff --git a/apps/common/tasks.py b/apps/common/tasks.py index 5aefd28ee..dec738921 100644 --- a/apps/common/tasks.py +++ b/apps/common/tasks.py @@ -2,7 +2,6 @@ from django.core.mail import send_mail from django.conf import settings from celery import shared_task from .utils import get_logger -from .models import Setting logger = get_logger(__file__) diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py index 43bc3cc1a..22e660bb1 100644 --- a/apps/jumpserver/settings.py +++ b/apps/jumpserver/settings.py @@ -59,6 +59,7 @@ INSTALLED_APPS = [ 'assets.apps.AssetsConfig', 'perms.apps.PermsConfig', 'ops.apps.OpsConfig', + 'settings.apps.SettingsConfig', 'common.apps.CommonConfig', 'terminal.apps.TerminalConfig', 'audits.apps.AuditsConfig', diff --git a/apps/jumpserver/urls.py b/apps/jumpserver/urls.py index 8ddf5cae4..bdae17a44 100644 --- a/apps/jumpserver/urls.py +++ b/apps/jumpserver/urls.py @@ -20,7 +20,7 @@ api_v1_patterns = [ path('ops/v1/', include('ops.urls.api_urls', namespace='api-ops')), path('audits/v1/', include('audits.urls.api_urls', namespace='api-audits')), path('orgs/v1/', include('orgs.urls.api_urls', namespace='api-orgs')), - path('common/v1/', include('common.urls.api_urls', namespace='api-common')), + path('settings/v1/', include('settings.urls.api_urls', namespace='api-settings')), ])) ] @@ -56,8 +56,7 @@ urlpatterns = [ path('', include(api_v1_patterns)), path('luna/', LunaView.as_view(), name='luna-error'), path('i18n//', I18NView.as_view(), name='i18n-switch'), - path('settings/', include('common.urls.view_urls', namespace='settings')), - path('common/', include('common.urls.view_urls', namespace='common')), + path('settings/', include('settings.urls.view_urls', namespace='settings')), # path('api/v2/', include(api_v2_patterns)), # External apps url diff --git a/apps/settings/__init__.py b/apps/settings/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/settings/admin.py b/apps/settings/admin.py new file mode 100644 index 000000000..8c38f3f3d --- /dev/null +++ b/apps/settings/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apps/settings/api.py b/apps/settings/api.py new file mode 100644 index 000000000..fea869edc --- /dev/null +++ b/apps/settings/api.py @@ -0,0 +1,194 @@ +# -*- coding: utf-8 -*- +# + +import os +import json +import jms_storage + +from rest_framework.views import Response, APIView +from ldap3 import Server, Connection +from django.core.mail import send_mail +from django.utils.translation import ugettext_lazy as _ +from django.conf import settings + +from common.permissions import IsOrgAdmin, IsSuperUser +from .serializers import ( + MailTestSerializer, LDAPTestSerializer +) +from .models import Setting + + +class MailTestingAPI(APIView): + permission_classes = (IsOrgAdmin,) + serializer_class = MailTestSerializer + success_message = _("Test mail sent to {}, please check") + + def post(self, request): + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + email_host_user = serializer.validated_data["EMAIL_HOST_USER"] + for k, v in serializer.validated_data.items(): + if k.startswith('EMAIL'): + setattr(settings, k, v) + try: + subject = "Test" + message = "Test smtp setting" + send_mail(subject, message, email_host_user, [email_host_user]) + except Exception as e: + return Response({"error": str(e)}, status=401) + + return Response({"msg": self.success_message.format(email_host_user)}) + else: + return Response({"error": str(serializer.errors)}, status=401) + + +class LDAPTestingAPI(APIView): + permission_classes = (IsOrgAdmin,) + serializer_class = LDAPTestSerializer + success_message = _("Test ldap success") + + def post(self, request): + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + host = serializer.validated_data["AUTH_LDAP_SERVER_URI"] + bind_dn = serializer.validated_data["AUTH_LDAP_BIND_DN"] + password = serializer.validated_data["AUTH_LDAP_BIND_PASSWORD"] + use_ssl = serializer.validated_data.get("AUTH_LDAP_START_TLS", False) + search_ougroup = serializer.validated_data["AUTH_LDAP_SEARCH_OU"] + search_filter = serializer.validated_data["AUTH_LDAP_SEARCH_FILTER"] + attr_map = serializer.validated_data["AUTH_LDAP_USER_ATTR_MAP"] + + try: + attr_map = json.loads(attr_map) + except json.JSONDecodeError: + return Response({"error": "AUTH_LDAP_USER_ATTR_MAP not valid"}, status=401) + + server = Server(host, use_ssl=use_ssl) + conn = Connection(server, bind_dn, password) + try: + conn.bind() + except Exception as e: + return Response({"error": str(e)}, status=401) + + users = [] + for search_ou in str(search_ougroup).split("|"): + ok = conn.search(search_ou, search_filter % ({"user": "*"}), + attributes=list(attr_map.values())) + if not ok: + return Response({"error": _("Search no entry matched in ou {}").format(search_ou)}, status=401) + + for entry in conn.entries: + user = {} + for attr, mapping in attr_map.items(): + if hasattr(entry, mapping): + user[attr] = getattr(entry, mapping) + users.append(user) + if len(users) > 0: + return Response({"msg": _("Match {} s users").format(len(users))}) + else: + return Response({"error": "Have user but attr mapping error"}, status=401) + else: + return Response({"error": str(serializer.errors)}, status=401) + + +class ReplayStorageCreateAPI(APIView): + permission_classes = (IsSuperUser,) + + def post(self, request): + storage_data = request.data + + if storage_data.get('TYPE') == 'ceph': + port = storage_data.get('PORT') + if port.isdigit(): + storage_data['PORT'] = int(storage_data.get('PORT')) + + storage_name = storage_data.pop('NAME') + data = {storage_name: storage_data} + + if not self.is_valid(storage_data): + return Response({ + "error": _("Error: Account invalid (Please make sure the " + "information such as Access key or Secret key is correct)")}, + status=401 + ) + + Setting.save_storage('TERMINAL_REPLAY_STORAGE', data) + return Response({"msg": _('Create succeed')}, status=200) + + @staticmethod + def is_valid(storage_data): + if storage_data.get('TYPE') == 'server': + return True + storage = jms_storage.get_object_storage(storage_data) + target = 'tests.py' + src = os.path.join(settings.BASE_DIR, 'common', target) + return storage.is_valid(src, target) + + +class ReplayStorageDeleteAPI(APIView): + permission_classes = (IsSuperUser,) + + def post(self, request): + storage_name = str(request.data.get('name')) + Setting.delete_storage('TERMINAL_REPLAY_STORAGE', storage_name) + return Response({"msg": _('Delete succeed')}, status=200) + + +class CommandStorageCreateAPI(APIView): + permission_classes = (IsSuperUser,) + + def post(self, request): + storage_data = request.data + storage_name = storage_data.pop('NAME') + data = {storage_name: storage_data} + if not self.is_valid(storage_data): + return Response( + {"error": _("Error: Account invalid (Please make sure the " + "information such as Access key or Secret key is correct)")}, + status=401 + ) + + Setting.save_storage('TERMINAL_COMMAND_STORAGE', data) + return Response({"msg": _('Create succeed')}, status=200) + + @staticmethod + def is_valid(storage_data): + if storage_data.get('TYPE') == 'server': + return True + try: + storage = jms_storage.get_log_storage(storage_data) + except Exception: + return False + + return storage.ping() + + +class CommandStorageDeleteAPI(APIView): + permission_classes = (IsSuperUser,) + + def post(self, request): + storage_name = str(request.data.get('name')) + Setting.delete_storage('TERMINAL_COMMAND_STORAGE', storage_name) + return Response({"msg": _('Delete succeed')}, status=200) + + +class DjangoSettingsAPI(APIView): + def get(self, request): + if not settings.DEBUG: + return Response("Not in debug mode") + + data = {} + for i in [settings, getattr(settings, '_wrapped')]: + if not i: + continue + for k, v in i.__dict__.items(): + if k and k.isupper(): + try: + json.dumps(v) + data[k] = v + except (json.JSONDecodeError, TypeError): + data[k] = str(v) + return Response(data) + + + diff --git a/apps/settings/apps.py b/apps/settings/apps.py new file mode 100644 index 000000000..05af85c46 --- /dev/null +++ b/apps/settings/apps.py @@ -0,0 +1,8 @@ +from django.apps import AppConfig + + +class SettingsConfig(AppConfig): + name = 'settings' + + def ready(self): + from . import signals_handler diff --git a/apps/common/forms.py b/apps/settings/forms.py similarity index 98% rename from apps/common/forms.py rename to apps/settings/forms.py index 1f7e4c1fd..6721d07d1 100644 --- a/apps/common/forms.py +++ b/apps/settings/forms.py @@ -6,8 +6,9 @@ from django.utils.translation import ugettext_lazy as _ from django.db import transaction from .models import Setting, settings -from .fields import FormDictField, FormEncryptCharField, \ - FormEncryptMixin +from common.fields import ( + FormDictField, FormEncryptCharField, FormEncryptMixin +) class BaseForm(forms.Form): diff --git a/apps/common/migrations/0001_initial.py b/apps/settings/migrations/0001_initial.py similarity index 66% rename from apps/common/migrations/0001_initial.py rename to apps/settings/migrations/0001_initial.py index 2b612dc1d..f332e8d93 100644 --- a/apps/common/migrations/0001_initial.py +++ b/apps/settings/migrations/0001_initial.py @@ -1,9 +1,6 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-11 05:35 -from __future__ import unicode_literals +# Generated by Django 2.1.7 on 2019-02-26 03:11 from django.db import migrations, models -import django.db.models.manager class Migration(migrations.Migration): @@ -15,16 +12,19 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Settings', + name='Setting', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), ('value', models.TextField(verbose_name='Value')), + ('category', models.CharField(default='default', max_length=128)), + ('encrypted', models.BooleanField(default=False)), ('enabled', models.BooleanField(default=True, verbose_name='Enabled')), ('comment', models.TextField(verbose_name='Comment')), ], - managers=[ - ('configs', django.db.models.manager.Manager()), - ], + options={ + 'verbose_name': 'Setting', + 'db_table': 'setting', + }, ), ] diff --git a/apps/settings/migrations/0002_migrate_data.py b/apps/settings/migrations/0002_migrate_data.py new file mode 100644 index 000000000..0d76d1386 --- /dev/null +++ b/apps/settings/migrations/0002_migrate_data.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# +from django.db import migrations, connection + + +class Migration(migrations.Migration): + + dependencies = [ + ("settings", "0001_initial"), + ] + sql = "INSERT INTO setting(name, value, category, encrypted, enabled, comment) " \ + "SELECT name, value, category, encrypted, enabled, comment from settings" + settings_table_exist = 'settings' in connection.introspection.table_names() + + operations = [] + if settings_table_exist: + operations.append(migrations.RunSQL(sql)) diff --git a/apps/settings/migrations/__init__.py b/apps/settings/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/common/models.py b/apps/settings/models.py similarity index 98% rename from apps/common/models.py rename to apps/settings/models.py index a6755a6d4..bc70bdb50 100644 --- a/apps/common/models.py +++ b/apps/settings/models.py @@ -6,7 +6,7 @@ from django.db.utils import ProgrammingError, OperationalError from django.utils.translation import ugettext_lazy as _ from django.conf import settings -from .utils import get_signer +from common.utils import get_signer signer = get_signer() @@ -122,5 +122,5 @@ class Setting(models.Model): settings.AUTHENTICATION_BACKENDS = old_setting class Meta: - db_table = "settings" + db_table = "setting" verbose_name = _("Setting") diff --git a/apps/common/serializers.py b/apps/settings/serializers.py similarity index 85% rename from apps/common/serializers.py rename to apps/settings/serializers.py index 4c8e6d3b5..731823df9 100644 --- a/apps/common/serializers.py +++ b/apps/settings/serializers.py @@ -20,7 +20,4 @@ class LDAPTestSerializer(serializers.Serializer): AUTH_LDAP_START_TLS = serializers.BooleanField(required=False) -class OutputSerializer(serializers.Serializer): - output = serializers.CharField() - is_end = serializers.BooleanField() - mark = serializers.CharField() + diff --git a/apps/common/signals_handler.py b/apps/settings/signals_handler.py similarity index 94% rename from apps/common/signals_handler.py rename to apps/settings/signals_handler.py index b44dca787..c8fa92e27 100644 --- a/apps/common/signals_handler.py +++ b/apps/settings/signals_handler.py @@ -3,15 +3,15 @@ import json from django.dispatch import receiver -from django.db.models.signals import post_save, pre_save +from django.db.models.signals import post_save, pre_save, pre_migrate from django.conf import LazySettings, empty from django.db.utils import ProgrammingError, OperationalError from django.core.cache import cache from jumpserver.utils import current_request +from common.utils import get_logger, ssh_key_gen +from common.signals import django_ready from .models import Setting -from .utils import get_logger, ssh_key_gen -from .signals import django_ready logger = get_logger(__file__) diff --git a/apps/common/templates/common/basic_setting.html b/apps/settings/templates/settings/basic_setting.html similarity index 100% rename from apps/common/templates/common/basic_setting.html rename to apps/settings/templates/settings/basic_setting.html diff --git a/apps/common/templates/common/command_storage_create.html b/apps/settings/templates/settings/command_storage_create.html similarity index 98% rename from apps/common/templates/common/command_storage_create.html rename to apps/settings/templates/settings/command_storage_create.html index 671b11c94..9c60e2d85 100644 --- a/apps/common/templates/common/command_storage_create.html +++ b/apps/settings/templates/settings/command_storage_create.html @@ -159,10 +159,10 @@ $(document).ready(function() { data[name] = value } }); - var url = "{% url 'api-common:command-storage-create' %}"; + var url = "{% url 'api-settings:command-storage-create' %}"; var success = function(data, textStatus) { console.log(data, textStatus); - location = "{% url 'common:terminal-setting' %}"; + location = "{% url 'settings:terminal-setting' %}"; }; var error = function(data, textStatus) { var error_msg = data.responseJSON.error; diff --git a/apps/common/templates/common/email_setting.html b/apps/settings/templates/settings/email_setting.html similarity index 98% rename from apps/common/templates/common/email_setting.html rename to apps/settings/templates/settings/email_setting.html index 2f0951e00..46846d7dc 100644 --- a/apps/common/templates/common/email_setting.html +++ b/apps/settings/templates/settings/email_setting.html @@ -84,7 +84,7 @@ $(document).ready(function () { data[field.name] = field.value; }); - var the_url = "{% url 'api-common:mail-testing' %}"; + var the_url = "{% url 'api-settings:mail-testing' %}"; function error(message) { toastr.error(message) diff --git a/apps/common/templates/common/ldap_setting.html b/apps/settings/templates/settings/ldap_setting.html similarity index 98% rename from apps/common/templates/common/ldap_setting.html rename to apps/settings/templates/settings/ldap_setting.html index e55da5a8f..45820b97c 100644 --- a/apps/common/templates/common/ldap_setting.html +++ b/apps/settings/templates/settings/ldap_setting.html @@ -84,7 +84,7 @@ $(document).ready(function () { data[field.name] = field.value; }); - var the_url = "{% url 'api-common:ldap-testing' %}"; + var the_url = "{% url 'api-settings:ldap-testing' %}"; function error(message) { toastr.error(message) diff --git a/apps/common/templates/common/replay_storage_create.html b/apps/settings/templates/settings/replay_storage_create.html similarity index 99% rename from apps/common/templates/common/replay_storage_create.html rename to apps/settings/templates/settings/replay_storage_create.html index c8f99240a..69a1ba9fc 100644 --- a/apps/common/templates/common/replay_storage_create.html +++ b/apps/settings/templates/settings/replay_storage_create.html @@ -251,9 +251,9 @@ $(document).ready(function() { var name = $(id_field).attr('name'); data[name] = $(id_field).val(); }); - var url = "{% url 'api-common:replay-storage-create' %}"; + var url = "{% url 'api-settings:replay-storage-create' %}"; var success = function(data, textStatus) { - location = "{% url 'common:terminal-setting' %}"; + location = "{% url 'settings:terminal-setting' %}"; submitBtn.removeClass('disabled'); submitBtn.html(origin_text); }; diff --git a/apps/common/templates/common/security_setting.html b/apps/settings/templates/settings/security_setting.html similarity index 100% rename from apps/common/templates/common/security_setting.html rename to apps/settings/templates/settings/security_setting.html diff --git a/apps/common/templates/common/terminal_setting.html b/apps/settings/templates/settings/terminal_setting.html similarity index 95% rename from apps/common/templates/common/terminal_setting.html rename to apps/settings/templates/settings/terminal_setting.html index 994d1714b..e6eb72982 100644 --- a/apps/common/templates/common/terminal_setting.html +++ b/apps/settings/templates/settings/terminal_setting.html @@ -92,7 +92,7 @@ {% endfor %} - {% trans 'Add' %} + {% trans 'Add' %}

{% trans "Replay storage" %}

@@ -114,7 +114,7 @@ {% endfor %} - {% trans 'Add' %} + {% trans 'Add' %}
@@ -174,12 +174,12 @@ $(document).ready(function () { }) .on('click', '.btn-del-replay', function(){ var $this = $(this); - var the_url = "{% url 'api-common:replay-storage-delete' %}"; + var the_url = "{% url 'api-settings:replay-storage-delete' %}"; deleteStorage($this, the_url); }) .on('click', '.btn-del-command', function() { var $this = $(this); - var the_url = "{% url 'api-common:command-storage-delete' %}"; + var the_url = "{% url 'api-settings:command-storage-delete' %}"; deleteStorage($this, the_url) }); diff --git a/apps/settings/tests.py b/apps/settings/tests.py new file mode 100644 index 000000000..7ce503c2d --- /dev/null +++ b/apps/settings/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/common/urls/api_urls.py b/apps/settings/urls/api_urls.py similarity index 100% rename from apps/common/urls/api_urls.py rename to apps/settings/urls/api_urls.py diff --git a/apps/common/urls/view_urls.py b/apps/settings/urls/view_urls.py similarity index 100% rename from apps/common/urls/view_urls.py rename to apps/settings/urls/view_urls.py diff --git a/apps/common/views.py b/apps/settings/views.py similarity index 92% rename from apps/common/views.py rename to apps/settings/views.py index 2500d96a3..b6ac0bd89 100644 --- a/apps/common/views.py +++ b/apps/settings/views.py @@ -3,15 +3,15 @@ from django.shortcuts import render, redirect from django.contrib import messages from django.utils.translation import ugettext as _ +from common.permissions import SuperUserRequiredMixin +from common import utils from .forms import EmailSettingForm, LDAPSettingForm, BasicSettingForm, \ TerminalSettingForm, SecuritySettingForm -from common.permissions import SuperUserRequiredMixin -from . import utils class BasicSettingView(SuperUserRequiredMixin, TemplateView): form_class = BasicSettingForm - template_name = "common/basic_setting.html" + template_name = "settings/basic_setting.html" def get_context_data(self, **kwargs): context = { @@ -37,7 +37,7 @@ class BasicSettingView(SuperUserRequiredMixin, TemplateView): class EmailSettingView(SuperUserRequiredMixin, TemplateView): form_class = EmailSettingForm - template_name = "common/email_setting.html" + template_name = "settings/email_setting.html" def get_context_data(self, **kwargs): context = { @@ -63,7 +63,7 @@ class EmailSettingView(SuperUserRequiredMixin, TemplateView): class LDAPSettingView(SuperUserRequiredMixin, TemplateView): form_class = LDAPSettingForm - template_name = "common/ldap_setting.html" + template_name = "settings/ldap_setting.html" def get_context_data(self, **kwargs): context = { @@ -89,7 +89,7 @@ class LDAPSettingView(SuperUserRequiredMixin, TemplateView): class TerminalSettingView(SuperUserRequiredMixin, TemplateView): form_class = TerminalSettingForm - template_name = "common/terminal_setting.html" + template_name = "settings/terminal_setting.html" def get_context_data(self, **kwargs): command_storage = utils.get_command_storage_setting() @@ -119,7 +119,7 @@ class TerminalSettingView(SuperUserRequiredMixin, TemplateView): class ReplayStorageCreateView(SuperUserRequiredMixin, TemplateView): - template_name = 'common/replay_storage_create.html' + template_name = 'settings/replay_storage_create.html' def get_context_data(self, **kwargs): context = { @@ -131,7 +131,7 @@ class ReplayStorageCreateView(SuperUserRequiredMixin, TemplateView): class CommandStorageCreateView(SuperUserRequiredMixin, TemplateView): - template_name = 'common/command_storage_create.html' + template_name = 'settings/command_storage_create.html' def get_context_data(self, **kwargs): context = { @@ -144,7 +144,7 @@ class CommandStorageCreateView(SuperUserRequiredMixin, TemplateView): class SecuritySettingView(SuperUserRequiredMixin, TemplateView): form_class = SecuritySettingForm - template_name = "common/security_setting.html" + template_name = "settings/security_setting.html" def get_context_data(self, **kwargs): context = { diff --git a/apps/users/utils.py b/apps/users/utils.py index c998774b0..db69fd093 100644 --- a/apps/users/utils.py +++ b/apps/users/utils.py @@ -6,7 +6,6 @@ import re import pyotp import base64 import logging -import uuid import requests import ipaddress @@ -20,8 +19,6 @@ from datetime import datetime from common.tasks import send_mail_async from common.utils import reverse, get_object_or_none -from common.forms import SecuritySettingForm -from common.models import Setting from .models import User, LoginLog diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index 526c8f5df..000000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -SPHINXPROJ = Jumpserver -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/_static/img/admin_asset.png b/docs/_static/img/admin_asset.png deleted file mode 100644 index a4d33d475..000000000 Binary files a/docs/_static/img/admin_asset.png and /dev/null differ diff --git a/docs/_static/img/admin_user.png b/docs/_static/img/admin_user.png deleted file mode 100644 index de844ad21..000000000 Binary files a/docs/_static/img/admin_user.png and /dev/null differ diff --git a/docs/_static/img/dash_board.png b/docs/_static/img/dash_board.png deleted file mode 100644 index ffb940668..000000000 Binary files a/docs/_static/img/dash_board.png and /dev/null differ diff --git a/docs/_static/img/linux_terminal.png b/docs/_static/img/linux_terminal.png deleted file mode 100644 index e721f4898..000000000 Binary files a/docs/_static/img/linux_terminal.png and /dev/null differ diff --git a/docs/_static/img/logo-text.png b/docs/_static/img/logo-text.png deleted file mode 100755 index f4912a08f..000000000 Binary files a/docs/_static/img/logo-text.png and /dev/null differ diff --git a/docs/_static/img/structure.png b/docs/_static/img/structure.png deleted file mode 100644 index 90476014c..000000000 Binary files a/docs/_static/img/structure.png and /dev/null differ diff --git a/docs/_static/img/windows_terminal.png b/docs/_static/img/windows_terminal.png deleted file mode 100644 index 14f56e57b..000000000 Binary files a/docs/_static/img/windows_terminal.png and /dev/null differ diff --git a/docs/admin_asset.rst b/docs/admin_asset.rst deleted file mode 100644 index 03aec1675..000000000 --- a/docs/admin_asset.rst +++ /dev/null @@ -1,12 +0,0 @@ -资产管理模块 -============= - -这里介绍资产管理模块功能。 - -.. toctree:: - :maxdepth: 1 - - asset_list - asset_admin_user - asset_system_user - asset_label \ No newline at end of file diff --git a/docs/admin_guide.rst b/docs/admin_guide.rst deleted file mode 100644 index fd770c17c..000000000 --- a/docs/admin_guide.rst +++ /dev/null @@ -1,15 +0,0 @@ -管理文档 -========= - -这里介绍管理员功能。 - -.. toctree:: - :maxdepth: 1 - - admin_instruction - admin_user - admin_asset - admin_permission - admin_work_center - admin_session - admin_system_settings diff --git a/docs/admin_instruction.rst b/docs/admin_instruction.rst deleted file mode 100644 index 77719f5b1..000000000 --- a/docs/admin_instruction.rst +++ /dev/null @@ -1,44 +0,0 @@ -架构说明 -================= - -.. image:: _static/img/structure.png - :alt: 组件架构图 - - -组件说明 -================= - -Jumpserver -````````````` -现指 Jumpserver 管理后台,是核心组件(Core), 使用 Django Class Based View 风格开发,支持 Restful API。 - -`Github `_ - - -Coco -```````` -实现了 SSH Server 和 Web Terminal Server 的组件,提供 SSH 和 WebSocket 接口, 使用 Paramiko 和 Flask 开发。 - - -`Github `__ - - -Luna -```````` -现在是 Web Terminal 前端,计划前端页面都由该项目提供,Jumpserver 只提供 API,不再负责后台渲染html等。 - -`Github `__ - - -Guacamole -``````````` -Apache 跳板机项目,Jumpserver 使用其组件实现 RDP 功能,Jumpserver 并没有修改其代码而是添加了额外的插件,支持 Jumpserver 调用。 - - -Jumpserver-Python-SDK -``````````````````````` -Jumpserver API Python SDK,Coco 目前使用该 SDK 与 Jumpserver API 交互。 - -`Github `__ - - diff --git a/docs/admin_permission.rst b/docs/admin_permission.rst deleted file mode 100644 index 0bd5c3bde..000000000 --- a/docs/admin_permission.rst +++ /dev/null @@ -1,9 +0,0 @@ -权限管理模块 -============= - -这里介绍权限管理功能。 - -.. toctree:: - :maxdepth: 1 - - permission_asset_authorized diff --git a/docs/admin_session.rst b/docs/admin_session.rst deleted file mode 100644 index 90b38e4e8..000000000 --- a/docs/admin_session.rst +++ /dev/null @@ -1,13 +0,0 @@ -会话管理模块 -============== - -这里介绍会话管理功能。 - -.. toctree:: - :maxdepth: 1 - - session_history - session_online - session_command - session_web_terminal - session_terminal \ No newline at end of file diff --git a/docs/admin_system_settings.rst b/docs/admin_system_settings.rst deleted file mode 100644 index e6d6f4590..000000000 --- a/docs/admin_system_settings.rst +++ /dev/null @@ -1,41 +0,0 @@ -系统设置 -============= - -这里介绍系统设置的功能。 - -.. contents:: Topics - -.. _view_system_settings: - -查看系统设置 -````````````` - -点击页面左侧“系统设置”按钮,进入系统设置页面,产看基本设置、邮件设置、LDAP 设置和终端设置等内容。 - -.. _basic_settings: - -基本设置 -````````` - -点击页面上边的"基本设置" TAB ,进入基本设置页面,编辑当前站点 URL、用户想到 URL、Email 主题前缀等信息,点击“提交”按钮,基本设置完成。 - -.. _email_settings: - -邮件设置 -````````` - -点击页面上边的"邮件设置" TAB ,进入邮件设置页面,编辑 SMTP 主机、SMTP 端口、SMTP 账号、SMTP 密码和使用 SSL 或者 TSL 等信息,点击“测试连接”按钮,测试是否正确设置,点击“提交”按钮,邮件设置完成。 - -.. _ladp_settings: - -LDAP 设置 -```````````` - -点击页面上边的" LDAP 设置" TAB ,进入 LDAP 设置页面,编辑 LDAP 地址、DN、用户 OU、用户过滤器、LDAP 属性映射和是否使用 SSL、是否启用 LDAP 认证等信息,点击“测试连接”按钮,测试是否正确设置,点击“提交”按钮,完成 LDAP 设置。 - -.. _terminal_settings: - -终端设置 -```````````` - -点击页面上边的“终端设置” TAB ,进入终端设置页面,编辑终端信息,点击“提交”按钮,终端设置完成。 \ No newline at end of file diff --git a/docs/admin_user.rst b/docs/admin_user.rst deleted file mode 100644 index 0d74b38b3..000000000 --- a/docs/admin_user.rst +++ /dev/null @@ -1,11 +0,0 @@ -用户管理模块 -============= - -这里介绍用户管理功能。 - -.. toctree:: - :maxdepth: 1 - - user - user_group - login_log \ No newline at end of file diff --git a/docs/admin_work_center.rst b/docs/admin_work_center.rst deleted file mode 100644 index a15e2095c..000000000 --- a/docs/admin_work_center.rst +++ /dev/null @@ -1,9 +0,0 @@ -作业中心模块 -============== - -这里介绍作业中心功能。 - -.. toctree:: - :maxdepth: 1 - - work_center_list \ No newline at end of file diff --git a/docs/api_style_guide.rst b/docs/api_style_guide.rst deleted file mode 100644 index ee0103afb..000000000 --- a/docs/api_style_guide.rst +++ /dev/null @@ -1,163 +0,0 @@ -REST API规范约定 ----------------- - -这里仅考虑 REST API 的基本情况。参考 - -`RESTful API 设计指南`_ - -`Github API 文档`_ - -协议 -~~~~ - -API 与用户的通信协议,总是使用 HTTPS 协议。 - -域名 -~~~~ - -这版 API 相对简单, 没有前后端分离, 没有独立 APP, 所以放在主域名下 - -:: - - https://example.org/api/ - -版本 -~~~~ - -将 API 的版本号放入 URL 中,由于一个项目多个 APP 所以 Jumpserver 使用以下风格,将版本号放到 APP 后面 - -:: - - https://example.com/api/:app:/:version:/:resource: - https://example.com/api/assets/v1.0/assets [GET, POST] - https://example.com/api/assets/v1.0/assets/1 [GET, PUT, DELETE] - -路径 -~~~~ - -路径又称“终点”(endpoint),表示 API 的具体网址。 -在 RESTful 架构中,每个网址代表一种资源(Resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的“集合”(Collection),所以 API 中的名词也应该使用复数。 -举例来说 Cmdb 中的 Assets 列表, IDC 列表。 - -:: - - https://example.com/api/:app:/:version:/:resource: - - https://example.com/api/assets/v1.0/assets [GET, POST] - https://example.com/api/assets/v1.0/assets/1 [GET, PUT, DELETE] - https://example.com/api/assets/v1.0/idcs [GET, POST] - -一般性的增删查改(CRUD)API,完全使用 HTTP Method 加上 URL 提供的语义,URL 中的可变部分(比如上面提到的),一般用来传递该API操作的核心实体对象的唯一 ID,如果有更多的参数需要提供,GET 方法请使用 URL Parameter(例如:“?client_id=xxxxx&app_id=xxxxxx”),PUT/POST/DELETE 方法请使用请求体传递参数。 - -HTTP Method -~~~~~~~~~~~ - -对于资源的具体操作类型,由 HTTP 动词表示。 - -常用的HTTP动词有下面五个(括号里是对应的 SQL 命令)。 - -- GET(SELECT):从服务器取出资源(一项或多项)。 -- POST(CREATE):在服务器新建一个资源。 -- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源, 幂等 -- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。 -- DELETE(DELETE):从服务器删除资源。 - -.. _RESTful API 设计指南: http://www.ruanyifeng.com/blog/2014/05/restful_api.html -.. _Github API 文档: https://developer.github.com/v3/ - - -过滤信息 -~~~~~~~~ - -常见参数约定 - -:: - - ?keyword=localhost 模糊搜索 - ?limit=10:指定返回记录的数量 - ?offset=10:指定返回记录的开始位置。 - ?page=2&per_page=100:指定第几页,以及每页的记录数。 - ?sort=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。 - ?asset_id=1:指定筛选条件 - -状态码 -~~~~~~ - -服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的HTTP动词)。 - -- 200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。 -- 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。 -- 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务) -- 204 NO CONTENT - [DELETE]:用户删除数据成功。 -- 400 INVALID REQUEST - - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。 -- 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。 -- 403 Forbidden - [*] - 表示用户得到授权(与401错误相对),但是访问是被禁止的。 -- 404 NOT FOUND - - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。 -- 406 Not Acceptable - - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。 -- 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。 -- 422 Unprocesable entity - [POST/PUT/PATCH] - 当创建一个对象时,发生一个验证错误。 -- 500 INTERNAL SERVER ERROR - - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。 - -错误处理 -~~~~~~~~ - -如果状态码是4xx,就应该向用户返回出错信息。一般来说,返回的信息中将 error 作为键名,出错信息作为键值即可。 - -:: - - { - error: "Invalid API key" - } - - -返回结果 -~~~~~~~~ - -针对不同操作,服务器向用户返回的结果应该符合以下规范。 - -:: - - GET /collection:返回资源对象的列表(数组) - GET /collection/resource:返回单个资源对象 - POST /collection:返回新生成的资源对象 - PUT /collection/resource:返回完整的资源对象 - PATCH /collection/resource:返回完整的资源对象 - DELETE /collection/resource:返回一个空文档 - -Hypermedia API -~~~~~~~~~~~~~~ - -RESTful -API 最好做到 Hypermedia,即返回结果中提供链接,连向其他 API 方法,使得用户不查文档,也知道下一步应该做什么。 -比如,当用户向 api.example.com 的根目录发出请求,会得到这样一个文档。 - -:: - - {"link": { - "rel": "collection https://www.example.com/zoos", - "href": "https://api.example.com/zoos", - "title": "List of zoos", - "type": "application/vnd.yourformat+json" - }} - -上面代码表示,文档中有一个 Link 属性,用户读取这个属性就知道下一步该调用什么 API 了。 - -- rel 表示这个 API 与当前网址的关系(Collection 关系,并给出该 Collection 的网址) -- href 表示 API 的路径 -- title 表示 API 的标题 -- type 表示返回类型 - -Hypermedia API 的设计被称为 HATEOAS。 Github API 就是这种设计. - -其它 -~~~~ - -(1)API 的身份认证应该使用 OAuth 2.0 框架。 - -(2)服务器返回的数据格式,应该尽量使用 JSON。 \ No newline at end of file diff --git a/docs/asset_admin_user.rst b/docs/asset_admin_user.rst deleted file mode 100644 index 4ebebe8b5..000000000 --- a/docs/asset_admin_user.rst +++ /dev/null @@ -1,35 +0,0 @@ -管理用户 -========== - -这里介绍管理用户的功能。 - -.. contents:: Topics - -.. _view_admin_user_list: - -查看管理用户列表 -```````````````` - -点击页面左侧“资产管理“菜单下的“管理用户”按钮,进入管理用户列表页面,查看管理用户的名称、资产数等信息。 - - -.. _create_admin_user: - -创建管理用户 -```````````` - -点击页面左上角的“创建管理用户“按钮,进入创建管理用户界面,填写名称、用户名、密码、ssh私钥等信息,点击“提交”按钮,完成管理用户创建。 - -.. _update_admin_user: - -更新管理用户 -```````````` - -点击页面右边动作栏的“更新”按钮,进入更新管理用户页面,编辑管理用户的信息,点击“提交”按钮,完成管理用户更新。 - -.. _delete_admin_user: - -删除管理用户 -```````````` - -点击页面右边动作栏的“删除”按钮,弹出删除确认框,点击"确认"按钮,管理用户删除完成。 \ No newline at end of file diff --git a/docs/asset_label.rst b/docs/asset_label.rst deleted file mode 100644 index abc723df3..000000000 --- a/docs/asset_label.rst +++ /dev/null @@ -1,34 +0,0 @@ -标签管理 -============ - -这里介绍标签管理的功能。 - -.. contents:: Topics - -.. _view_label_list: - -查看标签列表 -```````````````` - -点击页面左边“资产管理”菜单下的“标签管理”按钮,进入标签列表页面,产看标签的名称、值、资产数等信息。 - -.. _create_label: - -创建标签 -```````````` - -点击页面左上角“创建标签”按钮,进入创建标签页面,填写标签的名称、值等信息,选择资产,点击“提交”按钮,标签创建完成。 - -.. _update_label: - -更新标签 -```````````` - -点击页面右边动作栏的“更新”按钮,进入更新标签页面,编辑标签信息,点击“提交”按钮,标签更新完成。 - -.. _delete_label: - -删除标签 -````````` - -点击页面右边动作栏的“删除”按钮,弹出删除确认框,点击“确认”按钮,完成标签删除。 \ No newline at end of file diff --git a/docs/asset_list.rst b/docs/asset_list.rst deleted file mode 100644 index 3d1f75adc..000000000 --- a/docs/asset_list.rst +++ /dev/null @@ -1,41 +0,0 @@ -资产列表 -=========== - -这里介绍资产列表的功能。 - -.. contents:: Topics - -.. _view_asset_list: - -查看资产列表 -````````````` - -点击页面左侧的“资产管理”菜单下的“资产列表”按钮,查看当前所有的资产列表。 - -.. _create_asset: - -创建资产 -```````````` - -点击页面左上角的“创建资产”按钮,进入资产创建页面,填写资产信息,点击“提交”按钮,完成资产创建。 - -.. _update_asset: - -更新资产 -```````````` - -点击页面右边的“更新”按钮,进入编辑资产页面,更新资产信息,点击“提交”按钮,完成资产更新。 - -.. _delete_asset: - -删除资产 -````````` - -点击页面右边的“删除”按钮,弹出删除确认框,点击“确认”按钮,完成资产删除。 - -.. _batch_operation: - -批量操作 -```````````` - -选中资产,选择页面左下角批量操作选项,点击“提交”按钮,完成批量操作。 \ No newline at end of file diff --git a/docs/asset_system_user.rst b/docs/asset_system_user.rst deleted file mode 100644 index de695eeb8..000000000 --- a/docs/asset_system_user.rst +++ /dev/null @@ -1,34 +0,0 @@ -系统用户 -=========== - -这里介绍系统用户功能。 - -.. contents:: Topics - -.. _view_admin_system_user: - -查看系统用户 -```````````` - -点击页面左侧“资产管理“菜单下的”系统用户“按钮,进入系统用户列表页面,查看系统用户的名称,资产数和连接数等信息。 - -.. _create_admin_system_user: - -创建系统用户 -```````````` - -点击页面左上角的“创建系统用户“按钮,进入创建系统用户页面,填写系统用户的基本信息、认证信息和其它信息,点击“提交“按钮,完成系统用户创建。 - -.. _update_admin_system_user: - -更新系统用户 -````````````` - -点击页面动作栏的“更新”按钮,进入更新系统用户页面,编辑系统用户信息,点击“提交”按钮,系统用户更新完成。 - -.. _delete_admin_system_user: - -删除系统用户 -````````````` - -点击页面动作栏的“删除”按钮,弹出删除确认框,点击“删除”按钮,完成删除系统用户。 \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index 2012ac65e..000000000 --- a/docs/conf.py +++ /dev/null @@ -1,168 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Configuration file for the Sphinx documentation builder. -# -# This file does only contain a selection of the most common options. For a -# full list see the documentation: -# http://www.sphinx-doc.org/en/stable/config - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) -import sphinx_rtd_theme - - -# -- Project information ----------------------------------------------------- - -project = 'Jumpserver' -copyright = '北京堆栈科技有限公司 © 2014-2018' -author = 'Jumpserver team' - -# The short X.Y version -version = '' -# The full version, including alpha/beta/rc tags -release = '0.5.0' - - -# -- General configuration --------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.viewcode', - 'sphinx.ext.githubpages', -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = 'zh_CN' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path . -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' -html_show_sourcelink = False - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -# html_theme = 'alabaster' -html_theme = "sphinx_rtd_theme" -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -html_theme_options = { - 'logo_only': True, - 'display_version': True -} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# The default sidebars (for documents that don't match any pattern) are -# defined by theme itself. Builtin themes are using these templates by -# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', -# 'searchbox.html']``. -# -# html_sidebars = {} - - -# -- Options for HTMLHelp output --------------------------------------------- - -# Output file base name for HTML help builder. -htmlhelp_basename = 'Jumpserver 文档' - - -# -- Options for LaTeX output ------------------------------------------------ - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'Jumpserver.tex', 'Jumpserver Documentation', - 'Jumpserver team', 'manual'), -] - - -# -- Options for manual page output ------------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'Jumpserver', 'Jumpserver Documentation', - [author], 1) -] - - -# -- Options for Texinfo output ---------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'Jumpserver', 'Jumpserver 文档', - author, 'Jumpserver', ' Jumpserver是全球首款完全开源的堡垒机,是符合 4A 的专业运维审计系统', - 'Miscellaneous'), -] - - -# -- Extension configuration ------------------------------------------------- -html_logo = '_static/img/logo-text.png' diff --git a/docs/contact.rst b/docs/contact.rst deleted file mode 100644 index d7b8fb71e..000000000 --- a/docs/contact.rst +++ /dev/null @@ -1,41 +0,0 @@ -联系方式 -+++++++++++++++++++++++++ - -商业支持 -~~~~~~~~~~~ - -`阿里云市场购买: `_ - - -QQ 群 -~~~~~~~~ - -群1: 390139816 (推荐) - -群2: 399218702 (满) - -群3: 552054376 (满) - - -Github -~~~~~~~~ - -https://github.com/jumpserver/jumpserver.git - - -官网 -~~~~~~~~ - -http://www.jumpserver.org - - -Demo -~~~~~~~~ - -http://demo.jumpserver.org - - -邮件 -~~~~~~~~ - -support@fit2cloud.com (#替换为@) \ No newline at end of file diff --git a/docs/contributor.rst b/docs/contributor.rst deleted file mode 100644 index 579d105f6..000000000 --- a/docs/contributor.rst +++ /dev/null @@ -1,17 +0,0 @@ -贡献者 -============= - -感谢以下朋友为 Jumpserver 做出的贡献,世界因你们而不同,排名不分先后 - - -- **小彧 <李磊>** Django 资深开发者,为用户模块贡献了很多代码 -- **sofia <周小侠>** 资深前端工程师, 前端代码贡献者 -- **liuz <刘正> 全栈工程师** 编写了 Web Terminal 大部分代码 -- **jiaxiangkong <陈尚委>** Jumpserver 测试运营 -- **halcyon <王墉>** DevOps 资深开发者, 0.3.2 核心开发者之一 -- **yumaojun03 <喻茂峻>** DevOps 资深开发者,擅长 Python、Go 以及 PaaS 平台开发 -- **kelianchun <柯连春>** DevOps 资产开发者,修复了很多 Bugs -- **q4speed <莫鹍>** 架构师,贡献了 0.5.0 Windows 远程桌面登录大部分代码 -- **ZhangFengyi <张峰毅>** 贡献了 0.5.0 新版文档 -- **Aaron3S <沈晨阳>** 贡献了 0.5.0 新版文档 -- **liqiang-fit2cloud <张立强>** 0.5.0 版本测试,给资产树设计贡献了很多建议 \ No newline at end of file diff --git a/docs/development.rst b/docs/development.rst deleted file mode 100644 index 9e2411ea9..000000000 --- a/docs/development.rst +++ /dev/null @@ -1,12 +0,0 @@ -开发文档 -====================================== - -.. toctree:: - :maxdepth: 1 - :caption: 开发文档 - - api_style_guide - python_style_guide - project_structure - - diff --git a/docs/faq.rst b/docs/faq.rst deleted file mode 100644 index 90775dc54..000000000 --- a/docs/faq.rst +++ /dev/null @@ -1,19 +0,0 @@ -FAQ -========== - -1. Windows 无法连接 - -:: - - (1). 如果白屏 可能是nginx设置的不对,也可能运行guacamole的docker容器有问题,总之请求到不了guacamole - (2). 如果显示没有权限 可能是你在 终端管理里没有接受 guacamole的注册,请接受一下,如果还是不行,就删除刚才的注册,重启guacamole的docker重新注册 - (3). 如果显示未知问题 可能是你的资产填写的端口不对,或者授权的系统用户的协议不是rdp - - -2. 用户、系统用户、管理用户的关系 - -:: - - 用户:每个公司的同事创建一个用户账号,用来登录Jumpserver - 系统用户:使用来登录到服务器的用户,如 web, dba, root等 - 管理用户:是服务器上已存在的特权用户,Ansible用来获取硬件信息, 如 root, 或者其它拥有 sudo NOPASSWD: ALL权限的用户 diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index ac111c690..000000000 --- a/docs/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. jumpserver documentation master file, created by - sphinx-quickstart on Mon Feb 26 23:28:27 2018. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Jumpserver 文档 -====================================== - -目录: - -.. toctree:: - :maxdepth: 2 - - introduce - installation - admin_guide - user_guide - development - contributor - contact - snapshot - faq diff --git a/docs/installation.rst b/docs/installation.rst deleted file mode 100644 index e9dde1f48..000000000 --- a/docs/installation.rst +++ /dev/null @@ -1,9 +0,0 @@ -安装文档 -++++++++++++++++++++++++ - -.. toctree:: - :maxdepth: 1 - - quickstart - step_by_step - upgrade diff --git a/docs/introduce.rst b/docs/introduce.rst deleted file mode 100644 index 910f21052..000000000 --- a/docs/introduce.rst +++ /dev/null @@ -1,12 +0,0 @@ -总体介绍 -================== - -欢迎来到 Jumpserver 文档。 - -Jumpserver 是全球首款完全开源的堡垒机,使用 GNU GPL v2.0 开源协议,是符合 4A 的专业运维审计系统。 - -Jumpserver 使用 Python / Django 进行开发,遵循 Web 2.0 规范,配备了业界领先的 Web Terminal 解决方案,交互界面美观、用户体验好。 - -Jumpserver 采纳分布式架构,支持多机房跨区域部署,中心节点提供 API,各机房部署登录节点,可横向扩展、无并发访问限制。 - -改变世界,从一点点开始。 \ No newline at end of file diff --git a/docs/login_log.rst b/docs/login_log.rst deleted file mode 100644 index 73debfa8a..000000000 --- a/docs/login_log.rst +++ /dev/null @@ -1,6 +0,0 @@ -登录日志 -========== - -这里介绍登录日志的功能。 - -点击页面左侧“用户管理”菜单下的“登录日志”按钮,进入登录日志页面。 \ No newline at end of file diff --git a/docs/permission_asset_authorized.rst b/docs/permission_asset_authorized.rst deleted file mode 100644 index 70e109b26..000000000 --- a/docs/permission_asset_authorized.rst +++ /dev/null @@ -1,34 +0,0 @@ -资产授权 -========= - -这里介绍资产授权的相关的功能。 - -.. contents:: Topics - -.. _view_asset_authorized: - -查看资产授权规则列表 -```````````````````` - -资产授权页面默认展示资产授权列表。点击左侧资产节点树下的节点,右侧展示此节点下的资产授权规则。 - -.. _create_asset_authorized: - -创建授权规则 -```````````` -在左侧资产节点树下选择要创建授权规则的节点,点击页面右侧创建授权规则进入创建授权规则页面,填写授权规则信息,点击提交,完成创建授权规则。 - -.. _update_asset_authorized: - -更新授权规则 -```````````` - -在左侧资产节点树下选择要更新授权规则的节点,在右侧授权规则列表中找到要更新的授权规则,点击“动作”标题下的“更新”按钮进入授权规则更新页面,填写授权规则信息,点击提交,完成创建授权规则。 - -.. _delete_asset_authorized: - -删除授权规则 -```````````` - -在左侧资产节点树下选择要删除授权规则的节点,在右侧授权规则列表中找到要删除的授权规则,点击“动作”标题下的“删除”按钮,弹出确认删除页面,点击确认,完成删除授权规则。 - diff --git a/docs/project_structure.rst b/docs/project_structure.rst deleted file mode 100644 index d809733a9..000000000 --- a/docs/project_structure.rst +++ /dev/null @@ -1,51 +0,0 @@ -项目骨架 --------- - -说明如下: - -:: - - . - ├── config-example.py // 配置文件样例 - ├── docs // 所有 DOC 文件放到该目录 - │ └── README.md - ├── LICENSE - ├── README.md - ├── install // 安装说明 - ├── logs // 日志目录 - ├── apps // 管理后台目录,也是各 APP 所在目录 - │ └── assets // APP 目录 - │ │ ├── admin.py - │ │ ├── apps.py // 新版本 Django APP 设置文件 - │ │ ├── api.py // API 文件 - │ │ ├── __init__.py // 对外暴露的接口,放到该文件中,方便别的 APP 引用 - │ │ ├── migrations // Models Migrations 版本控制目录 - │ │ │ └── __init__.py - │ │ ├── models.py // 数据模型目录 - │ │ ├── static // APP 下静态资源目录,如果需要 - │ │ │ └── assets // 多一层目录,防止资源重名 - │ │ │ └── some_image.png - │ │ ├── templates // APP 下模板目录 - │ │ │ └── assets // 多一层目录,防止资源重名 - │ │ │ └── asset_list.html - │ │ ├── templatetags // 模板标签目录 - │ │ ├── tests.py // 测试用例文件 - │ │ ├── urls.py // Urlconf 文件 - │ │ ├── utils.py // 将 Views 和 API 可复用的代码放在这里, API 和 Views 只是请求和返回不同 - │ │ └── views.py // Views 文件 - │ ├── common - │ │ ├── templatetags // 通用 Template Tag - │ │ ├── utils.py // 通用的函数方法 - │ │ └── views.py - │ ├── fixtures // 初始化数据目录 - │ │ ├── init.json // 初始化项目数据库 - │ │ └── fake.json // 生成大量测试数据 - │ ├── jumpserver // 项目设置目录 - │ │ ├── __init__.py - │ │ ├── settings.py // 项目设置文件 - │ │ ├── urls.py // 项目入口 Urlconf - │ │ └── wsgi.py - │ ├── manage.py - │ ├── static // 项目静态资源目录 - │ ├── i18n // 项目多语言目录 - │ └── templates // 项目模板目录 \ No newline at end of file diff --git a/docs/python_style_guide.rst b/docs/python_style_guide.rst deleted file mode 100644 index d182a8dd2..000000000 --- a/docs/python_style_guide.rst +++ /dev/null @@ -1,211 +0,0 @@ -Jumpserver 项目规范(Draft) -============================ - -语言框架 ----------- - -1. Python 3.6.1 (当前最新) -2. Django 1.11 (当前最新) -3. Flask 0.12 Luna (当前最新) -4. Paramiko 2.12 Coco (当前最新) - -Django 规范 --------------- - -1. 尽量使用 Class Base View 编程,更少代码 -2. 使用 Django Form -3. 每个 URL 独立命名,不要硬编码,同理 Static 也是 -4. 数据库表名手动指定,不要使用默认 -5. 代码优雅简洁 -6. 注释明确优美 -7. 测试案例尽可能完整 -8. 尽可能利用 Django 造好的轮子 - -代码风格 ------------ - -Python 方面大致的风格,我们采用 pocoo 的\ `Style -Guidance`_\ ,但是有些细节部分会尽量放开 参考国内翻译 - -基本的代码布局 -~~~~~~~~~~~~~~ - -缩进 -^^^^^^^^ - -1. Python 严格采用4个空格的缩进,任何 Python 代码都都必须遵守此规定。 -2. Web 部分代码(HTML、CSS、JavaScript),Node.js 采用2空格缩进,同样不使用 TAB。 - 之所以与 Python 不同,是因为 JS 中有大量回调式的写法,2空格可以显著降低视觉上的负担。 - -最大行长度 -^^^^^^^^^^^^^ - -按 PEP8 规范,Python 一般限制最大79个字符, -但是 Django 的命名,URL 等通常比较长, -而且21世纪都是宽屏了,所以我们限制最大120字符 - -**补充说明:HTML 代码不受此规范约束。** - -长语句缩进 -^^^^^^^^^^^^ - -编写长语句时,可以使用换行符"\"换行。在这种情况下,下一行应该与上一行的最后一个“.”句点或“=”对齐,或者是缩进4个空格符。 - -:: - - this_is_a_very_long(function_call, 'with many parameters') \ - .that_returns_an_object_with_an_attribute - - MyModel.query.filter(MyModel.scalar > 120) \ - .order_by(MyModel.name.desc()) \ - .limit(10) - -如果你使用括号“()”或花括号“{}”为长语句换行,那么下一行应与括号或花括号对齐: - -:: - - this_is_a_very_long(function_call, 'with many parameters', - 23, 42, 'and even more') - -对于元素众多的列表或元组,在第一个“[”或“(”之后马上换行: - -:: - - items = [ - 'this is the first', 'set of items', 'with more items', - 'to come in this line', 'like this' - ] - -.. _Style Guidance: http://www.pocoo.org/internal/styleguide/ - - -空行 -^^^^^^ - -顶层函数与类之间空两行,此外都只空一行。不要在代码中使用太多的空行来区分不同的逻辑模块。 - -:: - - def hello(name): - print 'Hello %s!' % name - - - def goodbye(name): - print 'See you %s.' % name - - - class MyClass(object): - """This is a simple docstring.""" - - def __init__(self, name): - self.name = name - - def get_annoying_name(self): - return self.name.upper() + '!!!!111' - -语句和表达式 -~~~~~~~~~~~~ - -一般空格规则 -^^^^^^^^^^^^ - -1. 单目运算符与运算对象之间不空格(例如,-,~等),即使单目运算符位于括号内部也一样。 -2. 双目运算符与运算对象之间要空格。 - -:: - - exp = -1.05 - value = (item_value / item_count) * offset / exp - value = my_list[index] - value = my_dict['key'] - -比较 -^^^^ - -1. 任意类型之间的比较,使用“==”和“!=”。 -2. 与单例(singletons)进行比较时,使用 is 和 is not。 -3. 永远不要与True或False进行比较(例如,不要这样写:foo == - False,而应该这样写:not foo)。 - -否定成员关系检查 -^^^^^^^^^^^^^^^^ - -使用 foo not in bar,而不是 not foo in bar。 - -命名约定 -~~~~~~~~ - -1. 类名称:采用骆驼拼写法(CamelCase),首字母缩略词保持大写不变(HTTPWriter,而不是 HttpWriter)。 -2. 变量名:小写_以及_下划线(lowercase_with_underscores)。 -3. 方法与函数名:小写_以及_下划线(lowercase_with_underscores)。 -4. 常量:大写_以及_下划线(UPPERCASE_WITH_UNDERSCORES)。 -5. 预编译的正则表达式:name_re。 -6. 受保护的元素以一个下划线为前缀。双下划线前缀只有定义混入类(mixin classes)时才使用。 -7. 如果使用关键词(keywords)作为类名称,应在名称后添加后置下划线(trailing underscore)。 - 允许与内建变量重名,不要在变量名后添加下划线进行区分。如果函数需要访问重名的内建变量,请将内建变量重新绑定为其他名称。 -8. 命名要有寓意, 不使用拼音,不使用无意义简单字母命名 (循环中计数例外 for i in) -9. 命名缩写要谨慎, 尽量是大家认可的缩写 - -函数和方法的参数: -^^^^^^^^^^^^^^^^^^ - -1. 类方法:cls 为第一个参数。 -2. 实例方法:self 为第一个参数。 -3. property函数中使用匿名函数(lambdas)时,匿名函数的第一个参数可以用 x 替代, - 例如:display_name = property(lambda x: x.real_name or x.username)。 - - -文档注释(Docstring,即各方法,类的说明文档注释) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -所有文档字符串均以 reStructuredText 格式编写,方便 Sphinx 处理。文档字符串的行数不同,布局也不一样。 -如果只有一行,代表字符串结束的三个引号与代表字符串开始的三个引号在同一行。 -如果为多行,文档字符串中的文本紧接着代表字符串开始的三个引号编写,代表字符串结束的三个引号则自己独立成一行。 -(有能力尽可能用英文, 否则请中文优雅注释) - -:: - - def foo(): - """This is a simple docstring.""" - - - def bar(): - """This is a longer docstring with so much information in there - that it spans three lines. In this case, the closing triple quote - is on its own line. - """ - -文档字符串应分成简短摘要(尽量一行)和详细介绍。如果必要的话,摘要与详细介绍之间空一行。 - -模块头部 -~~~~~~~~ - -模块文件的头部包含有 utf-8 编码声明(如果模块中使用了非 ASCII 编码的字符,建议进行声明),以及标准的文档字符串。 - -:: - - # -*- coding: utf-8 -*- - """ - package.module - ~~~~~~~~~~~~~~ - - A brief description goes here. - - :copyright: (c) YEAR by AUTHOR. - :license: LICENSE_NAME, see LICENSE_FILE for more details. - """ - -注释(Comment) -~~~~~~~~~~~~~~~~ - -注释的规范与文档字符串编写规范类似。二者均以 reStructuredText 格式编写。 -如果使用注释来编写类属性的文档,请在#符号后添加一个冒号“:”。 -(有能力尽可能用英文, 否则请中文优雅注释) - -:: - - class User(object): - #: the name of the user as unicode string - name = Column(String) - #: the sha1 hash of the password + inline salt - pw_hash = Column(String) \ No newline at end of file diff --git a/docs/quickstart.rst b/docs/quickstart.rst deleted file mode 100644 index 58aac783c..000000000 --- a/docs/quickstart.rst +++ /dev/null @@ -1,54 +0,0 @@ -快速安装 -========================== - -Jumpserver 封装了一个 All in one Docker,可以快速启动。该镜像集成了所需要的组件(Windows组件未暂未集成),也支持使用外置 Database 和 Redis - -Tips: 不建议在生产中使用, 生产中请使用 详细安装 `CentOS `_ `Ubuntu `_ - - -Docker 安装见: `Docker官方安装文档 `_ - - -快速启动 -``````````````` -使用 root 命令行输入:: - - $ docker run -d -p 8080:80 -p 2222:2222 registry.jumpserver.org/public/jumpserver:1.0.0 - -访问 -``````````````` - -浏览器访问: http://<容器所在服务器IP>:8080 - -SSH访问: ssh -p 2222 <容器所在服务器IP> - -XShell等工具请添加connection连接 - - - -额外环境变量 -``````````````` - -- DB_ENGINE = mysql -- DB_HOST = mysql_host -- DB_PORT = 3306 -- DB_USER = xxx -- DB_PASSWORD = xxxx -- DB_NAME = jumpserver - -- REDIS_HOST = -- REDIS_PORT = -- REDIS_PASSWORD = < - - :: - - docker run -d -p 8080:80 -p 2222:2222 -e DB_ENGINE=mysql -e DB_HOST=192.168.1.1 -e DB_PORT=3306 -e DB_USER=root -e DB_PASSWORD=xxx -e DB_NAME=jumpserver registry.jumpserver.org/public/jumpserver:1.0.0 - - -仓库地址 -``````````````` - -https://github.com/jumpserver/Dockerfile - - - diff --git a/docs/session_command.rst b/docs/session_command.rst deleted file mode 100644 index a1296f86f..000000000 --- a/docs/session_command.rst +++ /dev/null @@ -1,30 +0,0 @@ -命令记录 -========= - -这里介绍命令记录功能。 - -点击页面左侧“会话管理”菜单下的“命令记录”,进入命令记录列表页面。 - -.. contents:: Topics - -.. _view_command_session: - -查看命令记录 -````````````` - -命令记录页面默认展示一周内命令记录,页面左上角提供起止时间、用户、资产、系统用户等搜索过滤条件。 - -.. _detial_command_invoke: - -查看命令执行详情 -```````````````` - -点击命令记录列表中需要查看命令执行详情的行,即可显示命令执行详情。 - -.. _detial_command_session: - -转到会话详情 -````````````` - -在命令记录列表中找到需要转到会话详情的记录,点击“会话”标题下的“转到”按钮,完成转到会话详情。 - diff --git a/docs/session_history.rst b/docs/session_history.rst deleted file mode 100644 index c4b63231f..000000000 --- a/docs/session_history.rst +++ /dev/null @@ -1,22 +0,0 @@ -历史会话 -========= - -这里介绍历史会话功能。 - -点击页面左侧“会话管理”菜单下的“历史会话”,进入历史会话列表页面。 - -.. contents:: Topics - -.. _view_history_session: - -查看历史会话 -````````````` - -历史会话页面默认展示一周内历史会话,页面左上角提供起止时间、用户、资产、系统用户等搜索过滤条件。 - -.. _playback_history_session: - -历史会话回放 -````````````` - -在在线会话列表中找到要回放的历史会话,点击动作标签下的“回放”按钮,弹出回放页面,完成回放历史会话。 \ No newline at end of file diff --git a/docs/session_online.rst b/docs/session_online.rst deleted file mode 100644 index 741725c1f..000000000 --- a/docs/session_online.rst +++ /dev/null @@ -1,25 +0,0 @@ -在线会话 -========= - -这里介绍在线会话功能。 - -点击页面左侧“会话管理”菜单下的“在线会话”,进入在线会话列表页面。 - -.. contents:: Topics - -.. _view_online_session: - -查看在线会话 -````````````` - -在线会话页面默认展示一周内在线会话,页面左上角提供起止时间、用户、资产、系统用户等搜索过滤条件。 - -.. _stop_online_session: - -终断在线会话 -````````````` - -在在线会话列表中找到要终止的在线会话,点击动作标签下的“终断”按钮,完成终断在线会话。 - - - diff --git a/docs/session_terminal.rst b/docs/session_terminal.rst deleted file mode 100644 index 3f749af5c..000000000 --- a/docs/session_terminal.rst +++ /dev/null @@ -1,29 +0,0 @@ -终端管理 -========= - -这里介绍终端管理功能。 - -点击页面左侧“会话管理”菜单下的“终端管理”,进入终端列表页面。 - -.. contents:: Topics - -.. _view_terminal_session: - -查看终端列表 -````````````` - -终端列表页面默认展示全部终端列表。 - -.. _upate_terminal_session: - -更新终端 -````````````` - -在在线会话列表中找到要更新的终端,点击动作标签下的“更新”按钮,在更新终端页面填写相关信息,点击提交,完成更新终端。 - -.. _delete_terminal_session: - -删除终端 -````````````` - -在在线会话列表中找到要删除的终端,点击动作标签下的“删除”按钮,在弹出确认删除页面点击确认,完成删除终端。 diff --git a/docs/session_web_terminal.rst b/docs/session_web_terminal.rst deleted file mode 100644 index c388e44c4..000000000 --- a/docs/session_web_terminal.rst +++ /dev/null @@ -1,23 +0,0 @@ -Web终端 -========= - -这里介绍Web终端功能。 - -点击页面左侧“会话管理”菜单下的“Web终端”,进入Web终端页面。 - -.. contents:: Topics - -.. _login: - -主机登录 -````````````` - -点解页面左侧的”Web终端”,进入主机登录页,然后点击页面右侧的主机IP地址,连接主机,页面右侧会展示当前连接的终端信息。 - -.. _logout: - -主机登出 -````````````` - -在主机登录页面,选择左上角的“服务器”按钮,出现两个选项,一个“断开链接“按钮,断开当前连接的主机;另一个”断开所有链接“,断开当前所有连接的主机。 - diff --git a/docs/snapshot.rst b/docs/snapshot.rst deleted file mode 100644 index 7266495c3..000000000 --- a/docs/snapshot.rst +++ /dev/null @@ -1,27 +0,0 @@ -Snapshot 截图 -+++++++++++++++++ - -仪表盘 -~~~~~~~~ - -.. image:: _static/img/dash_board.png - -用户管理 -~~~~~~~~~~ - -.. image:: _static/img/admin_user.png - -资产管理 -~~~~~~~~~~ - -.. image:: _static/img/admin_asset.png - -Linux 终端 -~~~~~~~~~~~~~ - -.. image:: _static/img/linux_terminal.png - -Windows 终端 -~~~~~~~~~~~~~~~~ - -.. image:: _static/img/windows_terminal.png diff --git a/docs/step_by_step.rst b/docs/step_by_step.rst deleted file mode 100644 index 300e1a3a2..000000000 --- a/docs/step_by_step.rst +++ /dev/null @@ -1,307 +0,0 @@ -一步一步安装 --------------------------- - -环境 -~~~~~~~ - -- 系统: CentOS 7 -- IP: 192.168.244.144 -- 关闭 selinux 和防火墙 - -:: - - # CentOS 7 - $ setenforce 0 # 可以设置配置文件永久关闭 - $ systemctl stop iptables.service - $ systemctl stop firewalld.service - - # CentOS6 - $ setenforce 0 - $ service iptables stop - -一. 准备 Python3 和 Python 虚拟环境 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**1.1 安装依赖包** - -:: - - $ yum -y install wget sqlite-devel xz gcc automake zlib-devel openssl-devel epel-release git - -**1.2 编译安装** - -:: - - $ wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tar.xz - $ tar xvf Python-3.6.1.tar.xz && cd Python-3.6.1 - $ ./configure && make && make install - -**1.3 建立 Python 虚拟环境** - -因为 CentOS 6/7 自带的是 Python2,而 Yum 等工具依赖原来的 Python,为了不扰乱原来的环境我们来使用 Python 虚拟环境 - -:: - - $ cd /opt - $ python3 -m venv py3 - $ source /opt/py3/bin/activate - - # 看到下面的提示符代表成功,以后运行 Jumpserver 都要先运行以上 source 命令,以下所有命令均在该虚拟环境中运行 - (py3) [root@localhost py3] - -二. 安装 Jumpserver 1.0.0 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**2.1 下载或 Clone 项目** - -项目提交较多 git clone 时较大,你可以选择去 Github 项目页面直接下载zip包。 - -:: - - $ cd /opt/ - $ git clone --depth=1 https://github.com/jumpserver/jumpserver.git && cd jumpserver && git checkout master - -**2.2 安装依赖 RPM 包** - -:: - - $ cd /opt/jumpserver/requirements - $ yum -y install $(cat rpm_requirements.txt) # 如果没有任何报错请继续 - -**2.3 安装 Python 库依赖** - -:: - - $ pip install -r requirements.txt # 不要指定-i参数,因为镜像上可能没有最新的包,如果没有任何报错请继续 - -**2.4 安装 Redis, Jumpserver 使用 Redis 做 cache 和 celery broke** - -:: - - $ yum -y install redis - $ service redis start - -**2.5 安装 MySQL** - -本教程使用 Mysql 作为数据库,如果不使用 Mysql 可以跳过相关 Mysql 安装和配置 - -:: - - # centos7 - $ yum -y install mariadb mariadb-devel mariadb-server # centos7下安装的是mariadb - $ service mariadb start - - # centos6 - $ yum -y install mysql mysql-devel mysql-server - $ service mysqld start - -**2.6 创建数据库 Jumpserver 并授权** - -:: - - $ mysql - > create database jumpserver default charset 'utf8'; - > grant all on jumpserver.* to 'jumpserver'@'127.0.0.1' identified by 'somepassword'; - -**2.7 修改 Jumpserver 配置文件** - -:: - - $ cd /opt/jumpserver - $ cp config_example.py config.py - $ vi config.py # 我们计划修改 DevelopmentConfig中的配置,因为默认jumpserver是使用该配置,它继承自Config - -**注意: 配置文件是 Python 格式,不要用 TAB,而要用空格** - -:: - - class DevelopmentConfig(Config): - DEBUG = True - DB_ENGINE = 'mysql' - DB_HOST = '127.0.0.1' - DB_PORT = 3306 - DB_USER = 'jumpserver' - DB_PASSWORD = 'somepassword' - DB_NAME = 'jumpserver' - - ... - - config = DevelopmentConfig() # 确保使用的是刚才设置的配置文件 - -**2.8 生成数据库表结构和初始化数据** - -:: - - $ cd /opt/jumpserver/utils - $ bash make_migrations.sh - -**2.9 运行 Jumpserver** - -:: - - $ cd /opt/jumpserver - $ python run_server.py all - -运行不报错,请浏览器访问 http://192.168.244.144:8080/ -(这里只是 Jumpserver, 没有 Web Terminal,所以访问 Web Terminal 会报错) - -账号: admin 密码: admin - -三. 安装 SSH Server 和 WebSocket Server: Coco -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**3.1 下载或 Clone 项目** - -新开一个终端,连接测试机,别忘了 source /opt/py3/bin/activate - -:: - - $ cd /opt - $ git clone https://github.com/jumpserver/coco.git && cd coco && git checkout master - - -**3.2 安装依赖** - -:: - - $ cd /opt/coco/requirements - $ yum -y install $(cat rpm_requirements.txt) - $ pip install -r requirements.txt - -**3.3 查看配置文件并运行** - -:: - - $ cd /opt/coco - $ cp conf_example.py conf.py - $ python run_server.py - -这时需要去 Jumpserver 管理后台-会话管理-终端管理(http://192.168.244.144:8080/terminal/terminal/)接受 Coco 的注册 - -:: - - Coco version 0.4.0, more see https://www.jumpserver.org - Starting ssh server at 0.0.0.0:2222 - Quit the server with CONTROL-C. - -**3.4 测试连接** - -:: - - $ ssh -p2222 admin@192.168.244.144 - 密码: admin - - 如果是用在 Windows 下,Xshell Terminal 登录语法如下 - $ssh admin@192.168.244.144 2222 - 密码: admin - 如果能登陆代表部署成功 - -四. 安装 Web Terminal 前端: Luna -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Luna 已改为纯前端,需要 Nginx 来运行访问 - -访问(https://github.com/jumpserver/luna/releases)下载对应版本的 release 包,直接解压,不需要编译 - -4.1 解压 Luna - -:: - - $ pwd - /opt/ - - $ tar xvf luna.tar.gz - $ ls /opt/luna - ... - -五. 安装 Windows 支持组件 -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -因为手动安装 guacamole 组件比较复杂,这里提供打包好的 docker 使用, 启动 guacamole - -.. code:: shell - - - # 注意:这里一定要改写一下本机的IP地址, 否则会出错 - - docker run --name jms_guacamole -d \ - -p 8081:8080 -v /opt/guacamole/key:/config/guacamole/key \ - -e JUMPSERVER_KEY_DIR=/config/guacamole/key \ - -e JUMPSERVER_SERVER=http://<填写本机的IP地址>:8080 \ - registry.jumpserver.org/public/guacamole:latest - -这里所需要注意的是 guacamole 暴露出来的端口是 8081,若与主机上其他端口冲突请自定义一下。 - -再次强调:修改 JUMPSERVER_SERVER 环境变量的配置,填上 Jumpserver 的内网地址, 这时 -去 Jumpserver-会话管理-终端管理 接受[Gua]开头的一个注册 - - - -六. 配置 Nginx 整合各组件 -~~~~~~~~~~~~~~~~~~~~~~~~~ - -6.1 安装 Nginx 根据喜好选择安装方式和版本 - -.. code:: shell - - yum -y install nginx - - -6.2 准备配置文件 修改 /etc/nginx/nginx.conf - - -:: - - server { - listen 80; - - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - location /luna/ { - try_files $uri / /index.html; - alias /opt/luna/; - } - - location /media/ { - add_header Content-Encoding gzip; - root /opt/jumpserver/data/; - } - - location /static/ { - root /opt/jumpserver/data/; - } - - location /socket.io/ { - proxy_pass http://localhost:5000/socket.io/; - proxy_buffering off; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - } - - location /guacamole/ { - proxy_pass http://localhost:8081/; - proxy_buffering off; - proxy_http_version 1.1; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $http_connection; - access_log off; - } - - location / { - proxy_pass http://localhost:8080; - } - } - -6.3 运行 Nginx - -:: - - nginx -t - service nginx start - - -6.4 访问 http://192.168.244.144 diff --git a/docs/upgrade.rst b/docs/upgrade.rst deleted file mode 100644 index 2b423dfd5..000000000 --- a/docs/upgrade.rst +++ /dev/null @@ -1,142 +0,0 @@ -更新升级 -------------- - -1. 升级 Jumpserver - -:: - - $ git pull && pip install -r requirements/requirements.txt && cd utils && sh make_migrations.sh - -2. 升级 Coco - -:: - - $ git pull && cd requirements && pip install -r requirements.txt # 不要指定 -i参数 - -3. 升级 Luna - -重新下载 release 包(https://github.com/jumpserver/luna/releases) - -4. 升级 guacamole - -:: - - $ docker pull registry.jumpserver.org/public/guacamole:latest - $ docker stop jms_guacamole # 或者写guacamole的容器ID - $ docker run --name jms_guacamole -d \ - -p 8081:8080 -v /opt/guacamole/key:/config/guacamole/key \ - -e JUMPSERVER_KEY_DIR=/config/guacamole/key \ - -e JUMPSERVER_SERVER=http://<填写本机的IP地址>:8080 \ - registry.jumpserver.org/public/guacamole:latest - - -切换分支或离线升级 -------------------------------- - - -**Jumpserver** - -说明: 以下操作,都在jumpserver所在目录运行 - -1. 备份配置文件 - -:: - - $ jumpserver_backup=/tmp/jumpserver_backup - $ mkdir -p $jumpserver_backup - $ cp config.py $jumpserver_backup - -2. 备份migrations migrations中存的是数据库表结构的变更,切换分支会丢失 - -:: - - $ for app in common users assets ops perms terminal;do - mkdir -p $jumpserver_backup/${app}_migrations - cp apps/${app}/migrations/*.py $jumpserver_backup/${app}_migrations - done - - -3. 备份数据库,已被不时之需 - -:: - - $ mysqldump -u你的数据库账号 -h数据库地址 -p 数据库名称 > $jumpserver_backup/db_backup.sql - -4. 备份录像文件 - -:: - - $ cp -r data/media $jumpserver_backup/ - -5. 切换分支或下载离线包, 更新代码 - -:: - - $ git checkout master # or other branch - - -6. 还原配置文件 - -:: - - $ cp $jumpserver_backup/config.py . - -7. 还原数据库表结构记录 - -:: - - $ for app in common users assets ops perms terminal;do - cp $jumpserver_backup/${app}_migrations/*.py ${app}/migrations/ - done - -8. 还原录像文件 - -:: - - $ cp -r $jumpserver_backup/media/* data/media/ - -9. 更新依赖或表结构 - -:: - $ pip install -r requirements/requirements.txt && cd utils && sh make_migrations.sh - - -**Coco** - -说明: 以下操作都在 coco 项目所在目录 - -coco是无状态的,备份 keys 目录即可 - -1. 备份keys - -:: - - $ cp -r keys $jumpserver_backup/ - - -2. 离线更新升级coco - -3. 还原 keys目录 - -:: - - $ mv keys keys_backup - $ cp -r $jumpserver_backup/keys . - -4. 升级依赖 - -:: - - $ git pull && cd requirements && pip install -r requirements.txt - - -**Luna** - -直接下载最新Release包替换即可 - - -**Guacamole** - -直接参考上面的升级即可, 需要注意的是如果更换机器,请备份 - - diff --git a/docs/user.rst b/docs/user.rst deleted file mode 100644 index c3bb1f61f..000000000 --- a/docs/user.rst +++ /dev/null @@ -1,51 +0,0 @@ -用户列表 -======== - -这里介绍用户列表的功能。 - -点击页面左侧“用户列表”菜单下的“用户列表“,进入用户列表页面。 - -.. contents:: Topics - -.. _create_user: - -创建用户 -```````` - -点击页面左上角“创建用户”按钮,进入创建用户页面,填写账户,角色安全,个人等信息,点击“提交”按钮,用户创建完成。 - - -.. _update_user: - -更新用户 -```````` - -点击页面右边的“更新”按钮,进入编辑用户页面,编辑用户信息,点击“提交”按钮,更新用户完成。 - -.. _delete_user: - -删除用户 -```````` - -点击页面右边的“删除”按钮,弹出是否删除确认框,点击“确定”按钮,删除用户完成。 - -.. _export_user: - -导出用户 -```````` - -选中用户,点击右上角的“导出”按钮,导出用户完成。 - -.. _import_user: - -导入用户 -```````` - -点击右上角的“导入”按钮,弹出导入对话框,选择要导入的CSV格式文件,点击“确认”按钮,导入用户完成。 - -.. _batch_user_operation: - -批量操作 -```````` - -选中用户,选择页面左下角的批量操作选项,点击”提交“按钮,批量操作完成。 \ No newline at end of file diff --git a/docs/user_asset.rst b/docs/user_asset.rst deleted file mode 100644 index 71855f76e..000000000 --- a/docs/user_asset.rst +++ /dev/null @@ -1,27 +0,0 @@ -个人资产 -========= - -这里介绍用户个人资产相关的功能。 - -.. contents:: Topics - -.. _view_personal_assets: - -查看个人资产 -```````````` - -登录个人用户,默认展示个人资产列表。点击主机名,查看资产的详细信息。 - -.. _host_login: - -主机登录 -````````` - -点解页面左侧的"Web终端",进入主机登录页,然后点击页面右侧的主机IP地址,连接主机,页面右侧会展示当前连接的终端信息。 - -.. _host_logout: - -主机登出 -````````` - -在主机登录页面,选择左上角的“服务器”按钮,出现两个选项,一个“断开链接“按钮,断开当前连接的主机;另一个”断开所有链接“,断开当前所有连接的主机。 \ No newline at end of file diff --git a/docs/user_group.rst b/docs/user_group.rst deleted file mode 100644 index 90aca6c05..000000000 --- a/docs/user_group.rst +++ /dev/null @@ -1,29 +0,0 @@ -用户组列表 -============ - -这里介绍用户组列表的功能。 - -点击页面左侧“用户管理”菜单下的”用户组“,进入用户组列表页面。 - -.. contents:: Topics - -.. _create_user_group: - -创建用户组 -`````````` - -点击页面左上角“创建用户组”按钮,进入创建用户组页面,填写用户组信息,点击“提交”按钮,创建用户完成。 - -.. _update_user_group: - -更新用户组 -`````````` - -点击页面右边的“更新”按钮,进入编辑用户组页面,编辑用户组信息,点击“确认”按钮,更新用户组完成。 - -.. _delete_user_group: - -删除用户组 -```````````` - -点击页面右边的“删除”按钮,弹出删除确认框,点击“确认”按钮,删除用户组完成。 \ No newline at end of file diff --git a/docs/user_guide.rst b/docs/user_guide.rst deleted file mode 100644 index 97d9810b3..000000000 --- a/docs/user_guide.rst +++ /dev/null @@ -1,10 +0,0 @@ -用户使用文档 -============= - -这部分给您介绍Jumpserver的用户管理模块的使用方法。 - -.. toctree:: - :maxdepth: 1 - - user_asset - user_info \ No newline at end of file diff --git a/docs/user_info.rst b/docs/user_info.rst deleted file mode 100644 index 23feb4754..000000000 --- a/docs/user_info.rst +++ /dev/null @@ -1,34 +0,0 @@ -个人信息 -========= - -这里介绍个人信息相关的功能。 - -.. contents:: Topics - -.. _view_personal_info: - -查看个人信息 -```````````` - -点击页面左侧的“个人信息”,查看用户的个人信息、SSH密钥。 - -.. _modify_personal_info: - -修改个人信息 -```````````` - -在个人信息页,点击页面右上角的“设置”按钮,进入个人信息修改页面,填写个人信息,点击“提交”按钮,完成个人信息修改。 - -.. _update_password: - -更新密码 -````````` - -在个人信息页,点击页面右上角的“重置密码“按钮,进入密码更新页面,填写原来密码、新密码等信息,点击“提交”按钮,完成密码更新。 - -.. _update_ssh_key: - -密钥更新 -````````` - -在个人信息页,点击页面左上角的“重置SSH密钥“按钮,进入密钥更新页面,填写SSH公钥,点击“提交”按钮,完成密钥更新。 \ No newline at end of file diff --git a/docs/work_center_list.rst b/docs/work_center_list.rst deleted file mode 100644 index 2ba982676..000000000 --- a/docs/work_center_list.rst +++ /dev/null @@ -1,35 +0,0 @@ -任务列表 -========= - -这里介绍任务列表的相关的功能。 - -.. contents:: Topics - -.. _view_asset_works: - -查看任务列表 -```````````` - -任务列表页面默认展示一周内所有任务。点击标题可根据当前字段进行排序。 - -.. _invoke_asset_work: - -手动执行任务 -```````````` - -在任务列表中找到要手动执行的任务,点击“动作”标题下的“执行”按钮,完成手动执行当前任务。 - -.. _delete_asset_work: - -删除任务 -````````` - -在任务列表中找到要删除的任务,点击“动作”标题下的“删除”按钮,完成删除当前任务。 - -.. _detial_asset_work: - -查看任务详情 -````````````` - -在任务列表中找到要查看的任务,点击要查看的任务名称,即可进入任务详情页面。 -