Merge pull request #5231 from jumpserver/dev

chore(merge): 合并 dev 到 master
pull/5308/head
老广 2020-12-11 19:29:45 +08:00 committed by GitHub
commit 1d5e603c0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 65 additions and 9 deletions

View File

@ -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 COPY --from=stage-build /opt/jumpserver/release/jumpserver /opt/jumpserver
RUN mkdir -p /root/.ssh/ \ 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 RUN echo > config.yml
VOLUME /opt/jumpserver/data VOLUME /opt/jumpserver/data

View File

@ -1,3 +1,5 @@
import uuid
from common.exceptions import JMSException from common.exceptions import JMSException
from orgs.models import Organization from orgs.models import Organization
from .. import models from .. import models
@ -7,6 +9,8 @@ class ApplicationAttrsSerializerViewMixin:
def get_serializer_class(self): def get_serializer_class(self):
serializer_class = super().get_serializer_class() 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_type = self.request.query_params.get('type')
app_category = self.request.query_params.get('category') app_category = self.request.query_params.get('category')
type_options = list(dict(models.Category.get_all_type_serializer_mapper()).keys()) type_options = list(dict(models.Category.get_all_type_serializer_mapper()).keys())
@ -38,12 +42,16 @@ class ApplicationAttrsSerializerViewMixin:
if app_type: if app_type:
# action: create / update / list / retrieve / metadata # action: create / update / list / retrieve / metadata
attrs_cls = models.Category.get_type_serializer_cls(app_type) attrs_cls = models.Category.get_type_serializer_cls(app_type)
class_name = 'ApplicationDynamicSerializer{}'.format(app_type.title())
elif app_category: elif app_category:
# action: list / retrieve / metadata # action: list / retrieve / metadata
attrs_cls = models.Category.get_category_serializer_cls(app_category) attrs_cls = models.Category.get_category_serializer_cls(app_category)
class_name = 'ApplicationDynamicSerializer{}'.format(app_category.title())
else: else:
attrs_cls = models.Category.get_no_password_serializer_cls() 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: class SerializeApplicationToTreeNodeMixin:

View File

@ -115,7 +115,6 @@ class AssetTaskCreateApi(generics.CreateAPIView):
class AssetGatewayListApi(generics.ListAPIView): class AssetGatewayListApi(generics.ListAPIView):
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.GatewayWithAuthSerializer serializer_class = serializers.GatewayWithAuthSerializer
model = Asset
def get_queryset(self): def get_queryset(self):
asset_id = self.kwargs.get('pk') asset_id = self.kwargs.get('pk')

View File

@ -82,6 +82,12 @@ class LDAPAuthorizationBackend(LDAPBackend):
class LDAPUser(_LDAPUser): 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): def _search_for_user_dn(self):
""" """
This method was overridden because the AUTH_LDAP_USER_SEARCH 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: if results is not None and len(results) == 1:
(user_dn, self._user_attrs) = next(iter(results)) (user_dn, self._user_attrs) = next(iter(results))
else: 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 return user_dn

View File

@ -5,6 +5,7 @@ from django.urls import path, include, re_path
from django.conf import settings from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from django.conf.urls.i18n import i18n_patterns from django.conf.urls.i18n import i18n_patterns
from django.http import HttpResponse
from django.views.i18n import JavaScriptCatalog from django.views.i18n import JavaScriptCatalog
from . import views, api from . import views, api

View File

@ -128,6 +128,7 @@ class CommandExecutionSerializer(serializers.ModelSerializer):
'result', 'is_finished', 'log_url', 'date_created', 'result', 'is_finished', 'log_url', 'date_created',
'date_finished' 'date_finished'
] ]
ref_name = 'OpsCommandExecution'
@staticmethod @staticmethod
def get_log_url(obj): def get_log_url(obj):

View File

@ -72,6 +72,8 @@ class UserGroupGrantedNodeAssetsApi(ListAPIView):
search_fields = ['hostname', 'ip', 'comment'] search_fields = ['hostname', 'ip', 'comment']
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False):
return Asset.objects.none()
user_group_id = self.kwargs.get('pk', '') user_group_id = self.kwargs.get('pk', '')
node_id = self.kwargs.get("node_id") node_id = self.kwargs.get("node_id")
node = Node.objects.get(id=node_id) node = Node.objects.get(id=node_id)

View File

@ -31,6 +31,8 @@ class UserDirectGrantedAssetsApi(ListAPIView):
search_fields = ['hostname', 'ip', 'comment'] search_fields = ['hostname', 'ip', 'comment']
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False):
return Asset.objects.none()
user = self.user user = self.user
assets = get_user_direct_granted_assets(user)\ assets = get_user_direct_granted_assets(user)\
.prefetch_related('platform')\ .prefetch_related('platform')\
@ -45,6 +47,8 @@ class UserFavoriteGrantedAssetsApi(ListAPIView):
search_fields = ['hostname', 'ip', 'comment'] search_fields = ['hostname', 'ip', 'comment']
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False):
return Asset.objects.none()
user = self.user user = self.user
assets = FavoriteAsset.get_user_favorite_assets(user)\ assets = FavoriteAsset.get_user_favorite_assets(user)\
.prefetch_related('platform')\ .prefetch_related('platform')\
@ -101,6 +105,8 @@ class UserAllGrantedAssetsApi(ForAdminMixin, ListAPIView):
search_fields = ['hostname', 'ip', 'comment'] search_fields = ['hostname', 'ip', 'comment']
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False):
return Asset.objects.none()
queryset = get_user_granted_all_assets(self.user) queryset = get_user_granted_all_assets(self.user)
queryset = queryset.prefetch_related('platform') queryset = queryset.prefetch_related('platform')
return queryset.only(*self.only_fields) return queryset.only(*self.only_fields)
@ -123,6 +129,8 @@ class UserGrantedNodeAssetsApi(UserNodeGrantStatusDispatchMixin, ListAPIView):
pagination_node: Node pagination_node: Node
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False):
return Asset.objects.none()
node_id = self.kwargs.get("node_id") node_id = self.kwargs.get("node_id")
node = Node.objects.get(id=node_id) node = Node.objects.get(id=node_id)
self.pagination_node = node self.pagination_node = node

View File

@ -15,7 +15,7 @@ __all__ = [
class BasePermissionViewSet(OrgBulkModelViewSet): class BasePermissionViewSet(OrgBulkModelViewSet):
custom_filter_fields = [ 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' 'user_group_id', 'user_group'
] ]
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)

View File

@ -62,6 +62,8 @@ class Action:
@classmethod @classmethod
def value_to_choices(cls, value): def value_to_choices(cls, value):
if isinstance(value, list):
return value
value = int(value) value = int(value)
choices = [cls.NAME_MAP[i] for i, j in cls.DB_CHOICES if value & i == i] choices = [cls.NAME_MAP[i] for i, j in cls.DB_CHOICES if value & i == i]
return choices return choices

View File

@ -16,3 +16,4 @@ class SystemUserSerializer(serializers.ModelSerializer):
'auto_push', 'cmd_filters', 'sudo', 'shell', 'comment', 'auto_push', 'cmd_filters', 'sudo', 'shell', 'comment',
'sftp_root', 'date_created', 'created_by' 'sftp_root', 'date_created', 'created_by'
] ]
ref_name = 'PermedSystemUserSerializer'

View File

@ -145,9 +145,22 @@ class LDAPServerUtil(object):
paged_cookie=paged_cookie 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 @timeit
def search_user_entries(self): def search_user_entries(self, search_users=None, search_value=None):
logger.info("Search user entries") logger.info("Search user entries")
self.search_users = search_users
self.search_value = search_value
user_entries = list() user_entries = list()
search_ous = str(self.config.search_ou).split('|') search_ous = str(self.config.search_ou).split('|')
for search_ou in search_ous: for search_ou in search_ous:
@ -157,6 +170,7 @@ class LDAPServerUtil(object):
while self.paged_cookie(): while self.paged_cookie():
self.search_user_entries_ou(search_ou, self.paged_cookie()) self.search_user_entries_ou(search_ou, self.paged_cookie())
user_entries.extend(self.connection.entries) user_entries.extend(self.connection.entries)
user_entries = self.distinct_user_entries(user_entries)
return user_entries return user_entries
def user_entry_to_dict(self, entry): def user_entry_to_dict(self, entry):
@ -180,12 +194,22 @@ class LDAPServerUtil(object):
users.append(user) users.append(user)
return users 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 @timeit
def search(self, search_users=None, search_value=None): def search(self, search_users=None, search_value=None):
logger.info("Search ldap users") logger.info("Search ldap users")
self.search_users = search_users user_entries = self.search_user_entries(
self.search_value = search_value search_users=search_users, search_value=search_value
user_entries = self.search_user_entries() )
users = self.user_entries_to_dict(user_entries) users = self.user_entries_to_dict(user_entries)
return users return users

View File

@ -68,3 +68,4 @@ class TaskSerializer(BulkModelSerializer):
fields = '__all__' fields = '__all__'
model = Task model = Task
list_serializer_class = AdaptedBulkListSerializer list_serializer_class = AdaptedBulkListSerializer
ref_name = 'TerminalTaskSerializer'