From e056430fce10dbc8994fd58ce1bc9c9044cb593c Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 11 Dec 2020 17:38:33 +0800 Subject: [PATCH 1/6] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=8F=AA=E9=85=8D?= =?UTF-8?q?=E7=BD=AEDC=E5=9F=9F=E6=97=B6=EF=BC=8CLDAP=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E8=AE=A4=E8=AF=81=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/backends/ldap.py | 11 ++++++++++- apps/settings/utils/ldap.py | 20 ++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/apps/authentication/backends/ldap.py b/apps/authentication/backends/ldap.py index ac3cfc254..5a5e16081 100644 --- a/apps/authentication/backends/ldap.py +++ b/apps/authentication/backends/ldap.py @@ -82,6 +82,12 @@ class LDAPAuthorizationBackend(LDAPBackend): class LDAPUser(_LDAPUser): + def _search_for_user_dn_from_ldap_util(self): + from settings.utils import LDAPServerUtil + util = LDAPServerUtil() + user_dn = util.search_for_user_dn(self._username) + return user_dn + def _search_for_user_dn(self): """ This method was overridden because the AUTH_LDAP_USER_SEARCH @@ -107,7 +113,10 @@ class LDAPUser(_LDAPUser): if results is not None and len(results) == 1: (user_dn, self._user_attrs) = next(iter(results)) else: - user_dn = None + # 解决直接配置DC域,用户认证失败的问题(库不能从整棵树中搜索) + user_dn = self._search_for_user_dn_from_ldap_util() + self._user_dn = user_dn + self._user_attrs = self._load_user_attrs() return user_dn diff --git a/apps/settings/utils/ldap.py b/apps/settings/utils/ldap.py index 5ca455380..45bdd6018 100644 --- a/apps/settings/utils/ldap.py +++ b/apps/settings/utils/ldap.py @@ -146,8 +146,10 @@ class LDAPServerUtil(object): ) @timeit - def search_user_entries(self): + def search_user_entries(self, search_users=None, search_value=None): logger.info("Search user entries") + self.search_users = search_users + self.search_value = search_value user_entries = list() search_ous = str(self.config.search_ou).split('|') for search_ou in search_ous: @@ -180,12 +182,22 @@ class LDAPServerUtil(object): users.append(user) return users + @timeit + def search_for_user_dn(self, username): + user_entries = self.search_user_entries(search_users=[username]) + if len(user_entries) == 1: + user_entry = user_entries[0] + user_dn = user_entry.entry_dn + else: + user_dn = None + return user_dn + @timeit def search(self, search_users=None, search_value=None): logger.info("Search ldap users") - self.search_users = search_users - self.search_value = search_value - user_entries = self.search_user_entries() + user_entries = self.search_user_entries( + search_users=search_users, search_value=search_value + ) users = self.user_entries_to_dict(user_entries) return users From f9cf2a243bde715979b6e6feb4b4963a33688680 Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 11 Dec 2020 18:23:12 +0800 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dsettings=E4=B8=AD?= =?UTF-8?q?=E6=90=9C=E7=B4=A2LDAP=E7=94=A8=E6=88=B7=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/settings/utils/ldap.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/settings/utils/ldap.py b/apps/settings/utils/ldap.py index 45bdd6018..9b7cd34a2 100644 --- a/apps/settings/utils/ldap.py +++ b/apps/settings/utils/ldap.py @@ -145,6 +145,17 @@ class LDAPServerUtil(object): paged_cookie=paged_cookie ) + @staticmethod + def distinct_user_entries(user_entries): + distinct_user_entries = list() + distinct_user_entries_dn = set() + for user_entry in user_entries: + if user_entry.entry_dn in distinct_user_entries_dn: + continue + distinct_user_entries_dn.add(user_entry.entry_dn) + distinct_user_entries.append(user_entry) + return distinct_user_entries + @timeit def search_user_entries(self, search_users=None, search_value=None): logger.info("Search user entries") @@ -159,6 +170,7 @@ class LDAPServerUtil(object): while self.paged_cookie(): self.search_user_entries_ou(search_ou, self.paged_cookie()) user_entries.extend(self.connection.entries) + user_entries = self.distinct_user_entries(user_entries) return user_entries def user_entry_to_dict(self, entry): From b9717eece317ce07df4f9054096ccd39754f522d Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 11 Dec 2020 17:21:52 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E8=AE=BF=E9=97=AE?= =?UTF-8?q?swagger=E4=BC=9A=E4=BA=A7=E7=94=9F=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/applications/api/mixin.py | 10 +++++- apps/assets/api/asset.py | 1 - apps/jumpserver/settings/base.py | 3 ++ apps/jumpserver/urls.py | 35 +++++++++++++++++++ apps/ops/serializers/adhoc.py | 1 + apps/perms/api/asset/user_group_permission.py | 2 ++ .../user_permission/user_permission_assets.py | 8 +++++ apps/perms/models/asset_permission.py | 2 ++ .../serializers/system_user_permission.py | 1 + apps/terminal/serializers/terminal.py | 1 + 10 files changed, 62 insertions(+), 2 deletions(-) diff --git a/apps/applications/api/mixin.py b/apps/applications/api/mixin.py index 91c7d7b3f..6bab179a0 100644 --- a/apps/applications/api/mixin.py +++ b/apps/applications/api/mixin.py @@ -1,3 +1,5 @@ +import uuid + from common.exceptions import JMSException from orgs.models import Organization from .. import models @@ -7,6 +9,8 @@ class ApplicationAttrsSerializerViewMixin: def get_serializer_class(self): serializer_class = super().get_serializer_class() + if getattr(self, 'swagger_fake_view', False): + return serializer_class app_type = self.request.query_params.get('type') app_category = self.request.query_params.get('category') type_options = list(dict(models.Category.get_all_type_serializer_mapper()).keys()) @@ -38,12 +42,16 @@ class ApplicationAttrsSerializerViewMixin: if app_type: # action: create / update / list / retrieve / metadata attrs_cls = models.Category.get_type_serializer_cls(app_type) + class_name = 'ApplicationDynamicSerializer{}'.format(app_type.title()) elif app_category: # action: list / retrieve / metadata attrs_cls = models.Category.get_category_serializer_cls(app_category) + class_name = 'ApplicationDynamicSerializer{}'.format(app_category.title()) else: attrs_cls = models.Category.get_no_password_serializer_cls() - return type('ApplicationDynamicSerializer', (serializer_class,), {'attrs': attrs_cls()}) + class_name = 'ApplicationDynamicSerializer' + cls = type(class_name, (serializer_class,), {'attrs': attrs_cls()}) + return cls class SerializeApplicationToTreeNodeMixin: diff --git a/apps/assets/api/asset.py b/apps/assets/api/asset.py index b6331db11..7ce3b1f8e 100644 --- a/apps/assets/api/asset.py +++ b/apps/assets/api/asset.py @@ -115,7 +115,6 @@ class AssetTaskCreateApi(generics.CreateAPIView): class AssetGatewayListApi(generics.ListAPIView): permission_classes = (IsOrgAdminOrAppUser,) serializer_class = serializers.GatewayWithAuthSerializer - model = Asset def get_queryset(self): asset_id = self.kwargs.get('pk') diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index 2a6291751..252c02dd0 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -57,6 +57,7 @@ INSTALLED_APPS = [ 'django_filters', 'bootstrap3', 'captcha', + 'django_prometheus', 'django_celery_beat', 'django.contrib.auth', 'django.contrib.admin', @@ -69,6 +70,7 @@ INSTALLED_APPS = [ MIDDLEWARE = [ + 'django_prometheus.middleware.PrometheusBeforeMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', @@ -84,6 +86,7 @@ MIDDLEWARE = [ 'orgs.middleware.OrgMiddleware', 'authentication.backends.oidc.middleware.OIDCRefreshIDTokenMiddleware', 'authentication.backends.cas.middleware.CASMiddleware', + 'django_prometheus.middleware.PrometheusAfterMiddleware', ] diff --git a/apps/jumpserver/urls.py b/apps/jumpserver/urls.py index d03c20ba3..0a492e073 100644 --- a/apps/jumpserver/urls.py +++ b/apps/jumpserver/urls.py @@ -5,6 +5,7 @@ from django.urls import path, include, re_path from django.conf import settings from django.conf.urls.static import static from django.conf.urls.i18n import i18n_patterns +from django.http import HttpResponse from django.views.i18n import JavaScriptCatalog from . import views, api @@ -54,7 +55,41 @@ apps = [ ] +def test_metric(request): + import random + data = "" + components = ['koko', 'guacamole', 'omnidb'] + status = ['normal', 'high', 'critical', 'total'] + + data += "# JumpServer 各组件状态个数汇总\n" + for com in components: + data += f"## 组件: {com}\n" + for s in status: + key = 'jumpserver_components_status_total{component_type="%s", status="%s"}' % (com, s) + value = round(10 * random.random() * 10, 2) + data += f"{key} {value}\n" + + data += "\n# JumpServer 各组件在线会话数汇总\n" + for com in components: + for item in ['session_active']: + key = 'jumpserver_components_%s_total{component_type="%s"}' % (item, com) + value = round(40 * random.random() * 10, 2) + data += f"{key} {value}\n" + + data += "\n# JumpServer 各组件节点一些指标\n" + for item in ['cpu1_load', 'memory_used_percent', 'disk_used_percent', 'session_active']: + data += f"## 指标: {item}\n" + for com in components: + for instance in ['node1', 'node2', 'node3']: + key = 'jumpserver_components_%s{component_type="%s", component="%s"}' % (item, com, instance) + value = round(20 * random.random() * 10, 2) + data += f"{key} {value}\n" + return HttpResponse(data, content_type='text/plain; version=0.0.4; charset=utf-8') + + urlpatterns = [ + # path('prometheus/', include('django_prometheus.urls')), + path('prometheus/metrics', test_metric), path('', views.IndexView.as_view(), name='index'), path('api/v1/', include(api_v1)), path('api/v2/', include(api_v2)), diff --git a/apps/ops/serializers/adhoc.py b/apps/ops/serializers/adhoc.py index c3a660e37..9327ce0a8 100644 --- a/apps/ops/serializers/adhoc.py +++ b/apps/ops/serializers/adhoc.py @@ -128,6 +128,7 @@ class CommandExecutionSerializer(serializers.ModelSerializer): 'result', 'is_finished', 'log_url', 'date_created', 'date_finished' ] + ref_name = 'OpsCommandExecution' @staticmethod def get_log_url(obj): diff --git a/apps/perms/api/asset/user_group_permission.py b/apps/perms/api/asset/user_group_permission.py index fa71da9b5..8f48a0342 100644 --- a/apps/perms/api/asset/user_group_permission.py +++ b/apps/perms/api/asset/user_group_permission.py @@ -72,6 +72,8 @@ class UserGroupGrantedNodeAssetsApi(ListAPIView): search_fields = ['hostname', 'ip', 'comment'] def get_queryset(self): + if getattr(self, 'swagger_fake_view', False): + return Asset.objects.none() user_group_id = self.kwargs.get('pk', '') node_id = self.kwargs.get("node_id") node = Node.objects.get(id=node_id) diff --git a/apps/perms/api/asset/user_permission/user_permission_assets.py b/apps/perms/api/asset/user_permission/user_permission_assets.py index 35b9da257..771f83bbf 100644 --- a/apps/perms/api/asset/user_permission/user_permission_assets.py +++ b/apps/perms/api/asset/user_permission/user_permission_assets.py @@ -31,6 +31,8 @@ class UserDirectGrantedAssetsApi(ListAPIView): search_fields = ['hostname', 'ip', 'comment'] def get_queryset(self): + if getattr(self, 'swagger_fake_view', False): + return Asset.objects.none() user = self.user assets = get_user_direct_granted_assets(user)\ .prefetch_related('platform')\ @@ -45,6 +47,8 @@ class UserFavoriteGrantedAssetsApi(ListAPIView): search_fields = ['hostname', 'ip', 'comment'] def get_queryset(self): + if getattr(self, 'swagger_fake_view', False): + return Asset.objects.none() user = self.user assets = FavoriteAsset.get_user_favorite_assets(user)\ .prefetch_related('platform')\ @@ -101,6 +105,8 @@ class UserAllGrantedAssetsApi(ForAdminMixin, ListAPIView): search_fields = ['hostname', 'ip', 'comment'] def get_queryset(self): + if getattr(self, 'swagger_fake_view', False): + return Asset.objects.none() queryset = get_user_granted_all_assets(self.user) queryset = queryset.prefetch_related('platform') return queryset.only(*self.only_fields) @@ -123,6 +129,8 @@ class UserGrantedNodeAssetsApi(UserNodeGrantStatusDispatchMixin, ListAPIView): pagination_node: Node def get_queryset(self): + if getattr(self, 'swagger_fake_view', False): + return Asset.objects.none() node_id = self.kwargs.get("node_id") node = Node.objects.get(id=node_id) self.pagination_node = node diff --git a/apps/perms/models/asset_permission.py b/apps/perms/models/asset_permission.py index 9fc00f4a7..983805720 100644 --- a/apps/perms/models/asset_permission.py +++ b/apps/perms/models/asset_permission.py @@ -62,6 +62,8 @@ class Action: @classmethod def value_to_choices(cls, value): + if isinstance(value, list): + return value value = int(value) choices = [cls.NAME_MAP[i] for i, j in cls.DB_CHOICES if value & i == i] return choices diff --git a/apps/perms/serializers/system_user_permission.py b/apps/perms/serializers/system_user_permission.py index a383ffbd0..3452d7af3 100644 --- a/apps/perms/serializers/system_user_permission.py +++ b/apps/perms/serializers/system_user_permission.py @@ -16,3 +16,4 @@ class SystemUserSerializer(serializers.ModelSerializer): 'auto_push', 'cmd_filters', 'sudo', 'shell', 'comment', 'sftp_root', 'date_created', 'created_by' ] + ref_name = 'PermedSystemUserSerializer' diff --git a/apps/terminal/serializers/terminal.py b/apps/terminal/serializers/terminal.py index ef285c869..33d46ada1 100644 --- a/apps/terminal/serializers/terminal.py +++ b/apps/terminal/serializers/terminal.py @@ -68,3 +68,4 @@ class TaskSerializer(BulkModelSerializer): fields = '__all__' model = Task list_serializer_class = AdaptedBulkListSerializer + ref_name = 'TerminalTaskSerializer' From b9cbff1a5f99acbe8a5a8fe3176dd743f0af8f23 Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 11 Dec 2020 18:38:24 +0800 Subject: [PATCH 4/6] =?UTF-8?q?del:=20=E5=88=A0=E9=99=A4=E6=B5=8B=E8=AF=95?= =?UTF-8?q?prometheus=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/settings/base.py | 3 --- apps/jumpserver/urls.py | 34 -------------------------------- 2 files changed, 37 deletions(-) diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index 252c02dd0..2a6291751 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -57,7 +57,6 @@ INSTALLED_APPS = [ 'django_filters', 'bootstrap3', 'captcha', - 'django_prometheus', 'django_celery_beat', 'django.contrib.auth', 'django.contrib.admin', @@ -70,7 +69,6 @@ INSTALLED_APPS = [ MIDDLEWARE = [ - 'django_prometheus.middleware.PrometheusBeforeMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', @@ -86,7 +84,6 @@ MIDDLEWARE = [ 'orgs.middleware.OrgMiddleware', 'authentication.backends.oidc.middleware.OIDCRefreshIDTokenMiddleware', 'authentication.backends.cas.middleware.CASMiddleware', - 'django_prometheus.middleware.PrometheusAfterMiddleware', ] diff --git a/apps/jumpserver/urls.py b/apps/jumpserver/urls.py index 0a492e073..e34c3e3a3 100644 --- a/apps/jumpserver/urls.py +++ b/apps/jumpserver/urls.py @@ -55,41 +55,7 @@ apps = [ ] -def test_metric(request): - import random - data = "" - components = ['koko', 'guacamole', 'omnidb'] - status = ['normal', 'high', 'critical', 'total'] - - data += "# JumpServer 各组件状态个数汇总\n" - for com in components: - data += f"## 组件: {com}\n" - for s in status: - key = 'jumpserver_components_status_total{component_type="%s", status="%s"}' % (com, s) - value = round(10 * random.random() * 10, 2) - data += f"{key} {value}\n" - - data += "\n# JumpServer 各组件在线会话数汇总\n" - for com in components: - for item in ['session_active']: - key = 'jumpserver_components_%s_total{component_type="%s"}' % (item, com) - value = round(40 * random.random() * 10, 2) - data += f"{key} {value}\n" - - data += "\n# JumpServer 各组件节点一些指标\n" - for item in ['cpu1_load', 'memory_used_percent', 'disk_used_percent', 'session_active']: - data += f"## 指标: {item}\n" - for com in components: - for instance in ['node1', 'node2', 'node3']: - key = 'jumpserver_components_%s{component_type="%s", component="%s"}' % (item, com, instance) - value = round(20 * random.random() * 10, 2) - data += f"{key} {value}\n" - return HttpResponse(data, content_type='text/plain; version=0.0.4; charset=utf-8') - - urlpatterns = [ - # path('prometheus/', include('django_prometheus.urls')), - path('prometheus/metrics', test_metric), path('', views.IndexView.as_view(), name='index'), path('api/v1/', include(api_v1)), path('api/v2/', include(api_v2)), From 90df4049319f3ff082f9b638805a3f166b56bb5c Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 11 Dec 2020 19:01:50 +0800 Subject: [PATCH 5/6] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dswagger=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/perms/api/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/perms/api/base.py b/apps/perms/api/base.py index 61caab19c..b56c161d7 100644 --- a/apps/perms/api/base.py +++ b/apps/perms/api/base.py @@ -15,7 +15,7 @@ __all__ = [ class BasePermissionViewSet(OrgBulkModelViewSet): custom_filter_fields = [ - 'user_id', 'username', 'search', 'system_user_id', 'system_user', + 'user_id', 'username', 'system_user_id', 'system_user', 'user_group_id', 'user_group' ] permission_classes = (IsOrgAdmin,) From ddbbc8df17e188fa3bbf0ce49b9f50b9a484a586 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 11 Dec 2020 19:24:58 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix(docker):=20=E4=BF=AE=E5=A4=8DDockerfile?= =?UTF-8?q?=E4=B8=AD=20echo=E5=BC=95=E8=B5=B7=E7=9A=84sh=E5=92=8Cbash?= =?UTF-8?q?=E6=8D=A2=E8=A1=8C=E5=85=BC=E5=AE=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5ed72c554..e32b3ea10 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,7 +34,7 @@ RUN pip install --upgrade pip==20.2.4 setuptools==49.6.0 wheel==0.34.2 -i ${PIP_ COPY --from=stage-build /opt/jumpserver/release/jumpserver /opt/jumpserver RUN mkdir -p /root/.ssh/ \ - && echo -e "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null" > /root/.ssh/config + && echo "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null" > /root/.ssh/config RUN echo > config.yml VOLUME /opt/jumpserver/data