From acaa4cf2d5ed0ad8c82cc9f37b8e3669b875f459 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 7 Apr 2025 19:10:12 +0800 Subject: [PATCH] perf: rename ad to ds --- apps/accounts/models/account.py | 18 +- apps/accounts/serializers/account/account.py | 2 +- apps/accounts/serializers/account/base.py | 2 +- apps/accounts/serializers/account/virtual.py | 2 +- apps/assets/api/asset/__init__.py | 2 +- apps/assets/api/asset/ad.py | 16 -- apps/assets/api/asset/ds.py | 16 ++ apps/assets/const/base.py | 5 +- apps/assets/const/category.py | 2 +- apps/assets/const/device.py | 2 +- apps/assets/const/{ad.py => ds.py} | 35 ++-- apps/assets/const/host.py | 2 +- apps/assets/const/types.py | 6 +- .../migrations/0016_auto_20250331_1149.bak | 64 +++++++ .../migrations/0016_auto_20250331_1149.py | 166 ----------------- .../migrations/0016_directory_service.py | 59 ++++++ .../migrations/0017_auto_20250407_1124.py | 168 ++++++++++++++++++ apps/assets/models/asset/__init__.py | 2 +- apps/assets/models/asset/common.py | 14 +- apps/assets/models/asset/{ad.py => ds.py} | 6 +- apps/assets/models/platform.py | 12 +- apps/assets/serializers/asset/__init__.py | 2 +- .../assets/serializers/asset/{ad.py => ds.py} | 9 +- apps/assets/serializers/platform.py | 4 +- apps/assets/urls/api_urls.py | 2 +- .../authentication/models/connection_token.py | 3 +- .../serializers/connect_token_secret.py | 2 + apps/common/const/common.py | 2 +- apps/jumpserver/settings/logging.py | 5 +- apps/settings/serializers/terminal.py | 10 +- apps/settings/utils/ldap.py | 6 +- apps/users/migrations/0001_initial.py | 2 +- apps/users/models/user/_source.py | 4 +- apps/users/serializers/user.py | 2 +- config_example.yml | 4 +- 35 files changed, 391 insertions(+), 267 deletions(-) delete mode 100644 apps/assets/api/asset/ad.py create mode 100644 apps/assets/api/asset/ds.py rename apps/assets/const/{ad.py => ds.py} (68%) create mode 100644 apps/assets/migrations/0016_auto_20250331_1149.bak delete mode 100644 apps/assets/migrations/0016_auto_20250331_1149.py create mode 100644 apps/assets/migrations/0016_directory_service.py create mode 100644 apps/assets/migrations/0017_auto_20250407_1124.py rename apps/assets/models/asset/{ad.py => ds.py} (68%) rename apps/assets/serializers/asset/{ad.py => ds.py} (76%) diff --git a/apps/accounts/models/account.py b/apps/accounts/models/account.py index d4aeabfa7..43f51c9aa 100644 --- a/apps/accounts/models/account.py +++ b/apps/accounts/models/account.py @@ -139,17 +139,25 @@ class Account(AbsConnectivity, LabeledMixin, BaseAccount, JSONFilterMixin): return self.id @lazyproperty - def ad_domain(self): + def ds_id(self): if self.username.startswith('@'): return None - if self.platform.category == 'ad': - return self.asset.ad.domain_name + if self.platform.category == 'ds': + return self.asset.directoryservice.id + return None + + @lazyproperty + def ds_domain(self): + if self.username.startswith('@'): + return None + if self.ds_id: + return self.asset.ds.domain_name return None @lazyproperty def full_username(self): - if self.ad_domain: - return '{}@{}'.format(self.username, self.ad_domain) + if self.ds_domain: + return '{}@{}'.format(self.username, self.ds_domain) return self.username @lazyproperty diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py index 28c160d22..e6932e546 100644 --- a/apps/accounts/serializers/account/account.py +++ b/apps/accounts/serializers/account/account.py @@ -241,7 +241,7 @@ class AccountSerializer(AccountCreateUpdateSerializerMixin, BaseAccountSerialize 'date_change_secret', 'change_secret_status' ] fields = BaseAccountSerializer.Meta.fields + [ - 'su_from', 'asset', 'version', "ad_domain", + 'su_from', 'asset', 'version', 'ds_domain', 'source', 'source_id', 'secret_reset', ] + AccountCreateUpdateSerializerMixin.Meta.fields + automation_fields read_only_fields = BaseAccountSerializer.Meta.read_only_fields + automation_fields diff --git a/apps/accounts/serializers/account/base.py b/apps/accounts/serializers/account/base.py index a6eacd83b..4270a1bb4 100644 --- a/apps/accounts/serializers/account/base.py +++ b/apps/accounts/serializers/account/base.py @@ -87,7 +87,7 @@ class BaseAccountSerializer( "username": { "help_text": _( "* If no username is required for authentication, enter null. " - "For AD accounts, use the format username@domain." + "For DS accounts, use the format username@domain." ) }, } diff --git a/apps/accounts/serializers/account/virtual.py b/apps/accounts/serializers/account/virtual.py index a1d107b20..5f6ea493a 100644 --- a/apps/accounts/serializers/account/virtual.py +++ b/apps/accounts/serializers/account/virtual.py @@ -21,7 +21,7 @@ class VirtualAccountSerializer(serializers.ModelSerializer): 'username': {'label': _('Username')}, 'secret_from_login': { 'help_text': _( - 'Current only support login from AD/LDAP. Secret priority: ' + 'Current only support login from DS/LDAP. Secret priority: ' 'Same account in asset secret > Login secret > Manual input.
' 'For security, please set config CACHE_LOGIN_PASSWORD_ENABLED to true' ) diff --git a/apps/assets/api/asset/__init__.py b/apps/assets/api/asset/__init__.py index a7db63855..4c1981ebd 100644 --- a/apps/assets/api/asset/__init__.py +++ b/apps/assets/api/asset/__init__.py @@ -3,8 +3,8 @@ from .cloud import * from .custom import * from .database import * from .device import * +from .ds import * from .gpt import * from .host import * from .permission import * from .web import * -from .ad import * diff --git a/apps/assets/api/asset/ad.py b/apps/assets/api/asset/ad.py deleted file mode 100644 index 301d4f440..000000000 --- a/apps/assets/api/asset/ad.py +++ /dev/null @@ -1,16 +0,0 @@ -from assets.models import AD, Asset -from assets.serializers import ADSerializer - -from .asset import AssetViewSet - -__all__ = ['ADViewSet'] - - -class ADViewSet(AssetViewSet): - model = AD - perm_model = Asset - - def get_serializer_classes(self): - serializer_classes = super().get_serializer_classes() - serializer_classes['default'] = ADSerializer - return serializer_classes diff --git a/apps/assets/api/asset/ds.py b/apps/assets/api/asset/ds.py new file mode 100644 index 000000000..00d215541 --- /dev/null +++ b/apps/assets/api/asset/ds.py @@ -0,0 +1,16 @@ +from assets.models import DirectoryService, Asset +from assets.serializers import DSSerializer + +from .asset import AssetViewSet + +__all__ = ['DSViewSet'] + + +class DSViewSet(AssetViewSet): + model = DirectoryService + perm_model = Asset + + def get_serializer_classes(self): + serializer_classes = super().get_serializer_classes() + serializer_classes['default'] = DSSerializer + return serializer_classes diff --git a/apps/assets/const/base.py b/apps/assets/const/base.py index 425e384f0..7df231eb5 100644 --- a/apps/assets/const/base.py +++ b/apps/assets/const/base.py @@ -112,8 +112,7 @@ class BaseType(TextChoices): @classmethod def get_choices(cls): - if not settings.XPACK_LICENSE_IS_VALID: + choices = cls.choices + if not settings.XPACK_LICENSE_IS_VALID and hasattr(cls, 'get_community_types'): choices = [(tp.value, tp.label) for tp in cls.get_community_types()] - else: - choices = cls.choices return choices diff --git a/apps/assets/const/category.py b/apps/assets/const/category.py index f7a27af32..bf109b8ff 100644 --- a/apps/assets/const/category.py +++ b/apps/assets/const/category.py @@ -12,7 +12,7 @@ class Category(ChoicesMixin, models.TextChoices): DATABASE = 'database', _("Database") CLOUD = 'cloud', _("Cloud service") WEB = 'web', _("Web") - AD = 'ad', _("Active Directory") + DS = 'ds', _("Directory service") CUSTOM = 'custom', _("Custom type") @classmethod diff --git a/apps/assets/const/device.py b/apps/assets/const/device.py index e069a2248..9336d129d 100644 --- a/apps/assets/const/device.py +++ b/apps/assets/const/device.py @@ -20,7 +20,7 @@ class DeviceTypes(BaseType): '*': { 'charset_enabled': False, 'domain_enabled': True, - 'ad_enabled': False, + 'ds_enabled': False, 'su_enabled': True, 'su_methods': ['enable', 'super', 'super_level'] } diff --git a/apps/assets/const/ad.py b/apps/assets/const/ds.py similarity index 68% rename from apps/assets/const/ad.py rename to apps/assets/const/ds.py index ebfa2055f..064c3b1fd 100644 --- a/apps/assets/const/ad.py +++ b/apps/assets/const/ds.py @@ -3,11 +3,13 @@ from django.utils.translation import gettext_lazy as _ from .base import BaseType -class ADTypes(BaseType): - AD = 'ad', _('Active Directory') +class DirectoryTypes(BaseType): + GENERAL = 'general', _('General') + # LDAP = 'ldap', _('LDAP') + # AD = 'ad', _('Active Directory') WINDOWS_AD = 'windows_ad', _('Windows Active Directory') - LDAP = 'ldap', _('LDAP') - AZURE_AD = 'azure_ad', _('Azure Active Directory') + + # AZURE_AD = 'azure_ad', _('Azure Active Directory') @classmethod def _get_base_constrains(cls) -> dict: @@ -15,7 +17,7 @@ class ADTypes(BaseType): '*': { 'charset_enabled': False, 'domain_enabled': True, - 'ad_enabled': False, + 'ds_enabled': False, 'su_enabled': True, } } @@ -24,6 +26,9 @@ class ADTypes(BaseType): def _get_automation_constrains(cls) -> dict: constrains = { '*': { + 'ansible_enabled': False, + }, + cls.WINDOWS_AD: { 'ansible_enabled': True, 'ping_enabled': True, 'gather_facts_enabled': False, @@ -38,36 +43,24 @@ class ADTypes(BaseType): @classmethod def _get_protocol_constrains(cls) -> dict: return { + cls.GENERAL: { + 'choices': ['ssh'] + }, cls.WINDOWS_AD: { 'choices': ['rdp', 'ssh', 'vnc', 'winrm'] }, - cls.LDAP: { - 'choices': ['ssh', 'ldap'] - }, - cls.AZURE_AD: { - 'choices': ['ldap'] - } } @classmethod def internal_platforms(cls): return { - cls.AD: [ - {'name': 'Active Directory'} - ], cls.WINDOWS_AD: [ {'name': 'Windows Active Directory'} ], - cls.LDAP: [ - {'name': 'LDAP'} - ], - cls.AZURE_AD: [ - {'name': 'Azure Active Directory'} - ], } @classmethod def get_community_types(cls): return [ - cls.LDAP, + cls.GENERAL, ] diff --git a/apps/assets/const/host.py b/apps/assets/const/host.py index 4435c4482..cd0103f8c 100644 --- a/apps/assets/const/host.py +++ b/apps/assets/const/host.py @@ -20,7 +20,7 @@ class HostTypes(BaseType): 'charset': 'utf-8', # default 'domain_enabled': True, 'su_enabled': True, - 'ad_enabled': True, + 'ds_enabled': True, 'su_methods': ['sudo', 'su', 'only_sudo', 'only_su'], }, cls.WINDOWS: { diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py index ab0f1377b..dfa8ba399 100644 --- a/apps/assets/const/types.py +++ b/apps/assets/const/types.py @@ -13,10 +13,10 @@ from .cloud import CloudTypes from .custom import CustomTypes from .database import DatabaseTypes from .device import DeviceTypes +from .ds import DirectoryTypes from .gpt import GPTTypes from .host import HostTypes from .web import WebTypes -from .ad import ADTypes class AllTypes(ChoicesMixin): @@ -24,7 +24,7 @@ class AllTypes(ChoicesMixin): includes = [ HostTypes, DeviceTypes, DatabaseTypes, CloudTypes, WebTypes, CustomTypes, - ADTypes, GPTTypes + DirectoryTypes, GPTTypes ] _category_constrains = {} _automation_methods = None @@ -175,7 +175,7 @@ class AllTypes(ChoicesMixin): (Category.DATABASE, DatabaseTypes), (Category.WEB, WebTypes), (Category.CLOUD, CloudTypes), - (Category.AD, ADTypes), + (Category.DS, DirectoryTypes), (Category.CUSTOM, CustomTypes) ] return types diff --git a/apps/assets/migrations/0016_auto_20250331_1149.bak b/apps/assets/migrations/0016_auto_20250331_1149.bak new file mode 100644 index 000000000..3b135e3ab --- /dev/null +++ b/apps/assets/migrations/0016_auto_20250331_1149.bak @@ -0,0 +1,64 @@ +# Generated by Django 4.1.13 on 2025-03-31 02:49 + +import json + +import django +from django.db import migrations, models + +from assets.const.types import AllTypes + + +class Migration(migrations.Migration): + dependencies = [ + ("assets", "0015_automationexecution_type"), + ] + + operations = [ + migrations.RunPython(add_ad_host_type), + migrations.CreateModel( + name="DS", + fields=[ + ( + "asset_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="assets.asset", + ), + ), + ( + "domain_name", + models.CharField( + blank=True, + default="", + max_length=128, + verbose_name="Domain name", + ), + ), + ], + options={ + "verbose_name": "Active Directory", + }, + bases=("assets.asset",), + ), + migrations.AddField( + model_name="platform", + name="ds", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="ad_platforms", + to="assets.ds", + verbose_name="Active Directory", + ), + ), + migrations.AddField( + model_name="platform", + name="ds_enabled", + field=models.BooleanField(default=False, verbose_name="DS enabled"), + ), + ] diff --git a/apps/assets/migrations/0016_auto_20250331_1149.py b/apps/assets/migrations/0016_auto_20250331_1149.py deleted file mode 100644 index ff14fdf9b..000000000 --- a/apps/assets/migrations/0016_auto_20250331_1149.py +++ /dev/null @@ -1,166 +0,0 @@ -# Generated by Django 4.1.13 on 2025-03-31 02:49 - -import json - -import django -from django.db import migrations, models - -from assets.const.types import AllTypes - - -def add_ad_host_type(apps, schema_editor): - data = """ - [ - { - "created_by": "system", - "updated_by": "system", - "comment": "", - "name": "Windows AD", - "category": "ad", - "type": "windows_ad", - "meta": {}, - "internal": true, - "domain_enabled": true, - "su_enabled": false, - "su_method": null, - "custom_fields": [], - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_shell_type": "cmd", - "ansible_connection": "ssh" - }, - "ping_enabled": true, - "ping_method": "ping_by_rdp", - "ping_params": {}, - "gather_facts_enabled": true, - "gather_facts_method": "gather_facts_windows", - "gather_facts_params": {}, - "change_secret_enabled": true, - "change_secret_method": "change_secret_ad_windows", - "change_secret_params": {}, - "push_account_enabled": true, - "push_account_method": "push_account_ad_windows", - "push_account_params": {}, - "verify_account_enabled": true, - "verify_account_method": "verify_account_by_rdp", - "verify_account_params": {}, - "gather_accounts_enabled": true, - "gather_accounts_method": "gather_accounts_ad_windows", - "gather_accounts_params": {}, - "remove_account_enabled": true, - "remove_account_method": "remove_account_ad_windows", - "remove_account_params": {} - }, - "protocols": [ - { - "name": "rdp", - "port": 3389, - "primary": true, - "required": false, - "default": false, - "public": true, - "setting": { - "console": false, - "security": "any" - } - }, - { - "name": "ssh", - "port": 22, - "primary": false, - "required": false, - "default": false, - "public": true, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - } - }, - { - "name": "vnc", - "port": 5900, - "primary": false, - "required": false, - "default": false, - "public": true, - "setting": {} - }, - { - "name": "winrm", - "port": 5985, - "primary": false, - "required": false, - "default": false, - "public": false, - "setting": { - "use_ssl": false - } - } - ] - } - ] - """ - platform_model = apps.get_model('assets', 'Platform') - automation_cls = apps.get_model('assets', 'PlatformAutomation') - platform_datas = json.loads(data) - - for platform_data in platform_datas: - AllTypes.create_or_update_by_platform_data(platform_data, platform_cls=platform_model, - automation_cls=automation_cls) - - -class Migration(migrations.Migration): - dependencies = [ - ("assets", "0015_automationexecution_type"), - ] - - operations = [ - migrations.RunPython(add_ad_host_type), - migrations.CreateModel( - name="AD", - fields=[ - ( - "asset_ptr", - models.OneToOneField( - auto_created=True, - on_delete=django.db.models.deletion.CASCADE, - parent_link=True, - primary_key=True, - serialize=False, - to="assets.asset", - ), - ), - ( - "domain_name", - models.CharField( - blank=True, - default="", - max_length=128, - verbose_name="Domain name", - ), - ), - ], - options={ - "verbose_name": "Active Directory", - }, - bases=("assets.asset",), - ), - migrations.AddField( - model_name="platform", - name="ad", - field=models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="ad_platforms", - to="assets.ad", - verbose_name="Active Directory", - ), - ), - migrations.AddField( - model_name="platform", - name="ad_enabled", - field=models.BooleanField(default=False, verbose_name="AD enabled"), - ), - ] diff --git a/apps/assets/migrations/0016_directory_service.py b/apps/assets/migrations/0016_directory_service.py new file mode 100644 index 000000000..417b42d05 --- /dev/null +++ b/apps/assets/migrations/0016_directory_service.py @@ -0,0 +1,59 @@ +# Generated by Django 4.1.13 on 2025-04-03 09:51 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("assets", "0015_automationexecution_type"), + ] + + operations = [ + migrations.CreateModel( + name="DirectoryService", + fields=[ + ( + "asset_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="assets.asset", + ), + ), + ( + "domain_name", + models.CharField( + blank=True, + default="", + max_length=128, + verbose_name="Domain name", + ), + ), + ], + options={ + "verbose_name": "Directory service", + }, + bases=("assets.asset",), + ), + migrations.AddField( + model_name="platform", + name="ds_enabled", + field=models.BooleanField(default=False, verbose_name="DS enabled"), + ), + migrations.AddField( + model_name="platform", + name="ds", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="ds_platforms", + to="assets.directoryservice", + verbose_name="Active Directory", + ), + ), + ] diff --git a/apps/assets/migrations/0017_auto_20250407_1124.py b/apps/assets/migrations/0017_auto_20250407_1124.py new file mode 100644 index 000000000..a3a6c1dd0 --- /dev/null +++ b/apps/assets/migrations/0017_auto_20250407_1124.py @@ -0,0 +1,168 @@ +# Generated by Django 4.1.13 on 2025-04-07 03:24 + +import json + +from django.db import migrations + +from assets.const import AllTypes + + +def add_ds_platforms(apps, schema_editor): + data = """ +[ + { + "created_by": "system", + "updated_by": "system", + "comment": "", + "name": "Windows active directory", + "category": "ds", + "type": "windows_ad", + "meta": {}, + "internal": true, + "domain_enabled": true, + "su_enabled": false, + "su_method": null, + "custom_fields": [], + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_shell_type": "cmd", + "ansible_connection": "ssh" + }, + "ping_enabled": true, + "ping_method": "ping_by_rdp", + "ping_params": {}, + "gather_facts_enabled": true, + "gather_facts_method": "gather_facts_windows", + "gather_facts_params": {}, + "change_secret_enabled": true, + "change_secret_method": "change_secret_ad_windows", + "change_secret_params": { + }, + "push_account_enabled": true, + "push_account_method": "push_account_ad_windows", + "push_account_params": {}, + "verify_account_enabled": true, + "verify_account_method": "verify_account_by_rdp", + "verify_account_params": { + + }, + "gather_accounts_enabled": true, + "gather_accounts_method": "gather_accounts_ad_windows", + "gather_accounts_params": { + + }, + "remove_account_enabled": true, + "remove_account_method": "remove_account_ad_windows", + "remove_account_params": { + + } + }, + "protocols": [ + { + "name": "rdp", + "port": 3389, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "console": false, + "security": "any" + } + }, + { + "name": "ssh", + "port": 22, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + }, + { + "name": "vnc", + "port": 5900, + "primary": false, + "required": false, + "default": false, + "public": true, + "setting": { + + } + }, + { + "name": "winrm", + "port": 5985, + "primary": false, + "required": false, + "default": false, + "public": false, + "setting": { + "use_ssl": false + } + } + ] + }, + { + "created_by": "system", + "updated_by": "system", + "comment": "", + "name": "General", + "category": "ds", + "type": "general", + "meta": { + + }, + "internal": true, + "domain_enabled": false, + "su_enabled": false, + "su_method": null, + "custom_fields": [ + + ], + "automation": { + "ansible_enabled": false, + "ansible_config": { + + } + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "primary": true, + "required": false, + "default": false, + "public": true, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + } + } + ] + } +] + """ + platform_model = apps.get_model('assets', 'Platform') + automation_cls = apps.get_model('assets', 'PlatformAutomation') + platform_datas = json.loads(data) + + for platform_data in platform_datas: + AllTypes.create_or_update_by_platform_data( + platform_data, platform_cls=platform_model, + automation_cls=automation_cls + ) + + +class Migration(migrations.Migration): + dependencies = [ + ("assets", "0016_directory_service"), + ] + + operations = [ + migrations.RunPython(add_ds_platforms) + ] diff --git a/apps/assets/models/asset/__init__.py b/apps/assets/models/asset/__init__.py index f93503da6..ef92ed9b4 100644 --- a/apps/assets/models/asset/__init__.py +++ b/apps/assets/models/asset/__init__.py @@ -1,9 +1,9 @@ -from .ad import * from .cloud import * from .common import * from .custom import * from .database import * from .device import * +from .ds import * from .gpt import * from .host import * from .web import * diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index ea1367893..c219984b2 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -247,10 +247,10 @@ class Asset(NodesRelationMixin, LabeledMixin, AbsConnectivity, JSONFilterMixin, @property def all_accounts(self): - if not self.joined_ad_id: + if not self.joined_dir_svc_id: queryset = self.accounts.all() else: - queryset = self.accounts.model.objects.filter(asset__in=[self.id, self.joined_ad_id]) + queryset = self.accounts.model.objects.filter(asset__in=[self.id, self.joined_dir_svc_id]) return queryset @lazyproperty @@ -273,15 +273,15 @@ class Asset(NodesRelationMixin, LabeledMixin, AbsConnectivity, JSONFilterMixin, protocol = self.protocols.all().filter(name=protocol).first() return protocol.port if protocol else 0 - def is_ad(self): - return self.category == const.Category.AD + def is_dir_svc(self): + return self.category == const.Category.DS @property - def joined_ad_id(self): - return self.platform.ad_id + def joined_dir_svc_id(self): + return self.platform.ds_id def is_joined_ad(self): - if self.joined_ad_id: + if self.joined_dir_svc_id: return True else: return False diff --git a/apps/assets/models/asset/ad.py b/apps/assets/models/asset/ds.py similarity index 68% rename from apps/assets/models/asset/ad.py rename to apps/assets/models/asset/ds.py index e44017d7d..343c58664 100644 --- a/apps/assets/models/asset/ad.py +++ b/apps/assets/models/asset/ds.py @@ -3,11 +3,11 @@ from django.utils.translation import gettext_lazy as _ from .common import Asset -__all__ = ['AD'] +__all__ = ['DirectoryService'] -class AD(Asset): +class DirectoryService(Asset): domain_name = models.CharField(max_length=128, blank=True, default='', verbose_name=_("Domain name")) class Meta: - verbose_name = _("Active Directory") + verbose_name = _("Directory service") diff --git a/apps/assets/models/platform.py b/apps/assets/models/platform.py index 1e45b22ab..906bd9dcc 100644 --- a/apps/assets/models/platform.py +++ b/apps/assets/models/platform.py @@ -102,10 +102,10 @@ class Platform(LabeledMixin, JMSBaseModel): max_length=8, verbose_name=_("Charset") ) domain_enabled = models.BooleanField(default=True, verbose_name=_("Gateway enabled")) - ad_enabled = models.BooleanField(default=False, verbose_name=_("AD enabled")) - ad = models.ForeignKey( - 'assets.AD', on_delete=models.SET_NULL, null=True, blank=True, - verbose_name=_("Active Directory"), related_name='ad_platforms' + ds_enabled = models.BooleanField(default=False, verbose_name=_("DS enabled")) + ds = models.ForeignKey( + 'DirectoryService', on_delete=models.SET_NULL, null=True, blank=True, + verbose_name=_("Directory service"), related_name='ds_platforms' ) # 账号有关的 su_enabled = models.BooleanField(default=False, verbose_name=_("Su enabled")) @@ -121,8 +121,8 @@ class Platform(LabeledMixin, JMSBaseModel): return self.assets.count() def save(self, *args, **kwargs): - if not self.ad_enabled: - self.ad = None + if not self.ds_enabled: + self.ds = None super().save(*args, **kwargs) @classmethod diff --git a/apps/assets/serializers/asset/__init__.py b/apps/assets/serializers/asset/__init__.py index e0f1e9b7b..c07cee68f 100644 --- a/apps/assets/serializers/asset/__init__.py +++ b/apps/assets/serializers/asset/__init__.py @@ -4,7 +4,7 @@ from .common import * from .custom import * from .database import * from .device import * +from .ds import * from .gpt import * from .host import * from .web import * -from .ad import * \ No newline at end of file diff --git a/apps/assets/serializers/asset/ad.py b/apps/assets/serializers/asset/ds.py similarity index 76% rename from apps/assets/serializers/asset/ad.py rename to apps/assets/serializers/asset/ds.py index 2c8a3eac2..f5a619783 100644 --- a/apps/assets/serializers/asset/ad.py +++ b/apps/assets/serializers/asset/ds.py @@ -1,15 +1,14 @@ from django.utils.translation import gettext_lazy as _ -from rest_framework import serializers -from assets.models import AD +from assets.models import DirectoryService from .common import AssetSerializer -__all__ = ['ADSerializer'] +__all__ = ['DSSerializer'] -class ADSerializer(AssetSerializer): +class DSSerializer(AssetSerializer): class Meta(AssetSerializer.Meta): - model = AD + model = DirectoryService fields = AssetSerializer.Meta.fields + [ 'domain_name', ] diff --git a/apps/assets/serializers/platform.py b/apps/assets/serializers/platform.py index 86921e330..75cbe8c3c 100644 --- a/apps/assets/serializers/platform.py +++ b/apps/assets/serializers/platform.py @@ -194,8 +194,8 @@ class PlatformSerializer(ResourceLabelsMixin, CommonSerializerMixin, WritableNes ] fields_m2m = ['assets', 'assets_amount'] fields = fields_small + fields_m2m + [ - "protocols", "domain_enabled", "su_enabled", "su_method", "ad_enabled", "ad", - "automation", "comment", "custom_fields", "labels" + "protocols", "domain_enabled", "su_enabled", "su_method", + "ds_enabled", "ds", "automation", "comment", "custom_fields", "labels" ] + read_only_fields extra_kwargs = { "su_enabled": { diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py index 7d23738cf..0ff108802 100644 --- a/apps/assets/urls/api_urls.py +++ b/apps/assets/urls/api_urls.py @@ -16,7 +16,7 @@ router.register(r'databases', api.DatabaseViewSet, 'database') router.register(r'webs', api.WebViewSet, 'web') router.register(r'clouds', api.CloudViewSet, 'cloud') router.register(r'gpts', api.GPTViewSet, 'gpt') -router.register(r'directories', api.ADViewSet, 'ad') +router.register(r'directories', api.DSViewSet, 'ds') router.register(r'customs', api.CustomViewSet, 'custom') router.register(r'platforms', api.AssetPlatformViewSet, 'platform') router.register(r'nodes', api.NodeViewSet, 'node') diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py index bcdabb71b..80ecda74a 100644 --- a/apps/authentication/models/connection_token.py +++ b/apps/authentication/models/connection_token.py @@ -8,7 +8,6 @@ from django.db import models from django.shortcuts import get_object_or_404 from django.utils import timezone from django.utils.translation import gettext_lazy as _ -from django.forms.models import model_to_dict from rest_framework.exceptions import PermissionDenied from accounts.models import VirtualAccount @@ -267,7 +266,7 @@ class ConnectionToken(JMSOrgBaseModel): input_secret=self.input_secret, from_permed=False ) else: - account = self.asset.accounts.filter(name=self.account).first() + account = self.asset.all_valid_accounts.filter(id=self.account).first() if not account.secret and self.input_secret: account.secret = self.input_secret return account diff --git a/apps/authentication/serializers/connect_token_secret.py b/apps/authentication/serializers/connect_token_secret.py index 40d6a0352..e38cbea18 100644 --- a/apps/authentication/serializers/connect_token_secret.py +++ b/apps/authentication/serializers/connect_token_secret.py @@ -40,6 +40,7 @@ class _ConnectionTokenAssetSerializer(serializers.ModelSerializer): class _SimpleAccountSerializer(serializers.ModelSerializer): secret_type = LabeledChoiceField(choices=SecretType.choices, required=False, label=_('Secret type')) + username = serializers.CharField(label=_('Username'), source='full_username', read_only=True) class Meta: model = Account @@ -49,6 +50,7 @@ class _SimpleAccountSerializer(serializers.ModelSerializer): class _ConnectionTokenAccountSerializer(serializers.ModelSerializer): su_from = serializers.SerializerMethodField(label=_('Su from')) secret_type = LabeledChoiceField(choices=SecretType.choices, required=False, label=_('Secret type')) + username = serializers.CharField(label=_('Username'), source='full_username', read_only=True) class Meta: model = Account diff --git a/apps/common/const/common.py b/apps/common/const/common.py index ab149fef5..8374f0016 100644 --- a/apps/common/const/common.py +++ b/apps/common/const/common.py @@ -8,7 +8,7 @@ FILE_END_GUARD = ">>> Content End <<<" celery_task_pre_key = "CELERY_" KEY_CACHE_RESOURCE_IDS = "RESOURCE_IDS_{}" -# AD User AccountDisable +# DS User AccountDisable # https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties LDAP_AD_ACCOUNT_DISABLE = 2 UUID_PATTERN = re.compile(r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') diff --git a/apps/jumpserver/settings/logging.py b/apps/jumpserver/settings/logging.py index 23d15d970..289f4fa4f 100644 --- a/apps/jumpserver/settings/logging.py +++ b/apps/jumpserver/settings/logging.py @@ -121,8 +121,8 @@ LOGGING = { if CONFIG.DEBUG_DEV: LOGGING['loggers']['django.db'] = { - 'handlers': ['console', 'file'], - 'level': 'DEBUG' + 'handlers': ['console', 'file'], + 'level': 'DEBUG' } SYSLOG_ENABLE = CONFIG.SYSLOG_ENABLE @@ -138,4 +138,3 @@ if CONFIG.SYSLOG_ADDR != '' and len(CONFIG.SYSLOG_ADDR.split(':')) == 2: if not os.path.isdir(LOG_DIR): os.makedirs(LOG_DIR, mode=0o755) - diff --git a/apps/settings/serializers/terminal.py b/apps/settings/serializers/terminal.py index 8e484e5ad..d672bf0bc 100644 --- a/apps/settings/serializers/terminal.py +++ b/apps/settings/serializers/terminal.py @@ -20,7 +20,7 @@ class TerminalSettingSerializer(serializers.Serializer): ) SECURITY_SERVICE_ACCOUNT_REGISTRATION = serializers.ChoiceField( choices=[ - ('auto', _('Auto(Enabled for the first 5 minutes after startup, then disabled.)')), + ('auto', _('Auto(Enabled for the first 5 minutes after startup, then disabled.)')), (True, _('Enable')), (False, _('Disable')) ], required=True, label=_('Registration'), @@ -29,7 +29,7 @@ class TerminalSettingSerializer(serializers.Serializer): ) ) TERMINAL_PASSWORD_AUTH = serializers.BooleanField( - required=False, label=_("Password"), + required=False, label=_("Password"), help_text=_( '* Allow users to log in to the KoKo component via password authentication' ) @@ -39,8 +39,8 @@ class TerminalSettingSerializer(serializers.Serializer): help_text=_( '* Allow users to log in to the KoKo component via Public key authentication' '
' - 'If third-party authentication services, such as AD/LDAP, are enabled, you should ' - 'disable this option to prevent users from logging in after being deleted from the AD/LDAP server' + 'If third-party authentication services, such as DS/LDAP, are enabled, you should ' + 'disable this option to prevent users from logging in after being deleted from the DS/LDAP server' ) ) TERMINAL_ASSET_LIST_SORT_BY = serializers.ChoiceField( @@ -50,7 +50,7 @@ class TerminalSettingSerializer(serializers.Serializer): PAGE_SIZE_CHOICES, required=False, label=_('Asset page size') ) TERMINAL_MAGNUS_ENABLED = serializers.BooleanField( - label="Magnus", + label="Magnus", help_text=_( '* You can individually configure the service address and port in the service endpoint' '
' diff --git a/apps/settings/utils/ldap.py b/apps/settings/utils/ldap.py index 24311adab..9df5df2c9 100644 --- a/apps/settings/utils/ldap.py +++ b/apps/settings/utils/ldap.py @@ -197,7 +197,7 @@ class LDAPServerUtil(object): value = is_true(value) if attr == 'groups' and mapping.lower() == 'memberof': - # AD: {'groups': 'memberOf'} + # DS: {'groups': 'memberOf'} if isinstance(value, str) and value: value = [value] if not isinstance(value, list): @@ -366,7 +366,7 @@ class LDAPSyncUtil(object): class LDAPImportUtil(object): - user_group_name_prefix = 'AD ' + user_group_name_prefix = 'DS ' def __init__(self, category=User.Source.ldap.value, is_sync_all=True): self.category = category @@ -399,7 +399,7 @@ class LDAPImportUtil(object): continue if not isinstance(group, str): continue - # get group name for AD, Such as: CN=Users,CN=Builtin,DC=jms,DC=com + # get group name for DS, Such as: CN=Users,CN=Builtin,DC=jms,DC=com group_name = group.split(',')[0].split('=')[-1] group_name = f'{self.user_group_name_prefix}{group_name}'.strip() group_names.append(group_name) diff --git a/apps/users/migrations/0001_initial.py b/apps/users/migrations/0001_initial.py index 5b47304b2..11b76779c 100644 --- a/apps/users/migrations/0001_initial.py +++ b/apps/users/migrations/0001_initial.py @@ -81,7 +81,7 @@ class Migration(migrations.Migration): models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date password last updated')), ('need_update_password', models.BooleanField(default=False, verbose_name='Need update password')), ('source', models.CharField( - choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('ldap_ha', 'LDAP/AD (HA)'), ('openid', 'OpenID'), + choices=[('local', 'Local'), ('ldap', 'LDAP/DS'), ('ldap_ha', 'LDAP/DS (HA)'), ('openid', 'OpenID'), ('radius', 'Radius'), ('cas', 'CAS'), ('saml2', 'SAML2'), ('oauth2', 'OAuth2'), ('wecom', 'WeCom'), ('dingtalk', 'DingTalk'), ('feishu', 'FeiShu'), ('lark', 'Lark'), ('slack', 'Slack'), ('custom', 'Custom')], default='local', max_length=30, diff --git a/apps/users/models/user/_source.py b/apps/users/models/user/_source.py index e7e0dd21f..adb25c410 100644 --- a/apps/users/models/user/_source.py +++ b/apps/users/models/user/_source.py @@ -9,8 +9,8 @@ from django.utils.translation import gettext_lazy as _ class Source(models.TextChoices): local = "local", _("Local") - ldap = "ldap", "LDAP/AD" - ldap_ha = "ldap_ha", "LDAP/AD (HA)" + ldap = "ldap", "LDAP/DS" + ldap_ha = "ldap_ha", "LDAP/DS (HA)" openid = "openid", "OpenID" radius = "radius", "Radius" cas = "cas", "CAS" diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index e494234c9..255b1799b 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -247,7 +247,7 @@ class UserSerializer( }, "source": { "help_text": _( - "User source identifies where the user was created, which could be AD or other sources." + "User source identifies where the user was created, which could be DS or other sources." "There are security settings that can restrict users to log in to the system only from the sources." ), }, diff --git a/config_example.yml b/config_example.yml index 1d3e4a141..8afa73458 100644 --- a/config_example.yml +++ b/config_example.yml @@ -53,7 +53,7 @@ REDIS_PORT: 6379 # REDIS_DB_CELERY: 3 # REDIS_DB_CACHE: 4 -# LDAP/AD settings +# LDAP/DS settings # LDAP 搜索分页数量 # AUTH_LDAP_SEARCH_PAGED_SIZE: 1000 # @@ -99,4 +99,4 @@ REDIS_PORT: 6379 # 开启人脸识别 XPACK 功能 #FACE_RECOGNITION_ENABLED: true #FACE_RECOGNITION_DISTANCE_THRESHOLD': 0.35 -#FACE_RECOGNITION_COSINE_THRESHOLD': 0.95 \ No newline at end of file +#FACE_RECOGNITION_COSINE_THRESHOLD': 0.95