From 598ec07c911785321813ff6c030b5cafbe8d0728 Mon Sep 17 00:00:00 2001 From: kenwoodjw Date: Mon, 8 Sep 2025 18:03:24 +0800 Subject: [PATCH] feat: enable dsl export encrypt dataset id or not (#25102) Signed-off-by: kenwoodjw --- api/.env.example | 4 ++++ api/configs/feature/__init__.py | 5 +++++ api/services/app_dsl_service.py | 32 +++++++++++++++++++++++++++++--- docker/.env.example | 10 ++++++++++ docker/docker-compose.yaml | 1 + 5 files changed, 49 insertions(+), 3 deletions(-) diff --git a/api/.env.example b/api/.env.example index 76f4c505f5..2986402e9e 100644 --- a/api/.env.example +++ b/api/.env.example @@ -570,3 +570,7 @@ QUEUE_MONITOR_INTERVAL=30 # Swagger UI configuration SWAGGER_UI_ENABLED=true SWAGGER_UI_PATH=/swagger-ui.html + +# Whether to encrypt dataset IDs when exporting DSL files (default: true) +# Set to false to export dataset IDs as plain text for easier cross-environment import +DSL_EXPORT_ENCRYPT_DATASET_ID=true diff --git a/api/configs/feature/__init__.py b/api/configs/feature/__init__.py index d6dc9710fb..0d6f4e416e 100644 --- a/api/configs/feature/__init__.py +++ b/api/configs/feature/__init__.py @@ -807,6 +807,11 @@ class DataSetConfig(BaseSettings): default=30, ) + DSL_EXPORT_ENCRYPT_DATASET_ID: bool = Field( + description="Enable or disable dataset ID encryption when exporting DSL files", + default=True, + ) + class WorkspaceConfig(BaseSettings): """ diff --git a/api/services/app_dsl_service.py b/api/services/app_dsl_service.py index 2344be0aaf..2ed73ffec1 100644 --- a/api/services/app_dsl_service.py +++ b/api/services/app_dsl_service.py @@ -17,6 +17,7 @@ from pydantic import BaseModel, Field from sqlalchemy import select from sqlalchemy.orm import Session +from configs import dify_config from core.helper import ssrf_proxy from core.model_runtime.utils.encoders import jsonable_encoder from core.plugin.entities.plugin import PluginDependency @@ -786,7 +787,10 @@ class AppDslService: @classmethod def encrypt_dataset_id(cls, dataset_id: str, tenant_id: str) -> str: - """Encrypt dataset_id using AES-CBC mode""" + """Encrypt dataset_id using AES-CBC mode or return plain text based on configuration""" + if not dify_config.DSL_EXPORT_ENCRYPT_DATASET_ID: + return dataset_id + key = cls._generate_aes_key(tenant_id) iv = key[:16] cipher = AES.new(key, AES.MODE_CBC, iv) @@ -795,12 +799,34 @@ class AppDslService: @classmethod def decrypt_dataset_id(cls, encrypted_data: str, tenant_id: str) -> str | None: - """AES decryption""" + """AES decryption with fallback to plain text UUID""" + # First, check if it's already a plain UUID (not encrypted) + if cls._is_valid_uuid(encrypted_data): + return encrypted_data + + # If it's not a UUID, try to decrypt it try: key = cls._generate_aes_key(tenant_id) iv = key[:16] cipher = AES.new(key, AES.MODE_CBC, iv) pt = unpad(cipher.decrypt(base64.b64decode(encrypted_data)), AES.block_size) - return pt.decode() + decrypted_text = pt.decode() + + # Validate that the decrypted result is a valid UUID + if cls._is_valid_uuid(decrypted_text): + return decrypted_text + else: + # If decrypted result is not a valid UUID, it's probably not our encrypted data + return None except Exception: + # If decryption fails completely, return None return None + + @staticmethod + def _is_valid_uuid(value: str) -> bool: + """Check if string is a valid UUID format""" + try: + uuid.UUID(value) + return True + except (ValueError, TypeError): + return False diff --git a/docker/.env.example b/docker/.env.example index 8f4037b7d7..92347a6e76 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -908,6 +908,12 @@ WORKFLOW_LOG_CLEANUP_BATCH_SIZE=100 HTTP_REQUEST_NODE_MAX_BINARY_SIZE=10485760 HTTP_REQUEST_NODE_MAX_TEXT_SIZE=1048576 HTTP_REQUEST_NODE_SSL_VERIFY=True +# Base64 encoded CA certificate data for custom certificate verification (PEM format, optional) +# HTTP_REQUEST_NODE_SSL_CERT_DATA=LS0tLS1CRUdJTi... +# Base64 encoded client certificate data for mutual TLS authentication (PEM format, optional) +# HTTP_REQUEST_NODE_SSL_CLIENT_CERT_DATA=LS0tLS1CRUdJTi... +# Base64 encoded client private key data for mutual TLS authentication (PEM format, optional) +# HTTP_REQUEST_NODE_SSL_CLIENT_KEY_DATA=LS0tLS1CRUdJTi... # Respect X-* headers to redirect clients RESPECT_XFORWARD_HEADERS_ENABLED=false @@ -1261,6 +1267,10 @@ QUEUE_MONITOR_INTERVAL=30 SWAGGER_UI_ENABLED=true SWAGGER_UI_PATH=/swagger-ui.html +# Whether to encrypt dataset IDs when exporting DSL files (default: true) +# Set to false to export dataset IDs as plain text for easier cross-environment import +DSL_EXPORT_ENCRYPT_DATASET_ID=true + # Celery schedule tasks configuration ENABLE_CLEAN_EMBEDDING_CACHE_TASK=false ENABLE_CLEAN_UNUSED_DATASETS_TASK=false diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 058741825b..193157b54f 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -571,6 +571,7 @@ x-shared-env: &shared-api-worker-env QUEUE_MONITOR_INTERVAL: ${QUEUE_MONITOR_INTERVAL:-30} SWAGGER_UI_ENABLED: ${SWAGGER_UI_ENABLED:-true} SWAGGER_UI_PATH: ${SWAGGER_UI_PATH:-/swagger-ui.html} + DSL_EXPORT_ENCRYPT_DATASET_ID: ${DSL_EXPORT_ENCRYPT_DATASET_ID:-true} ENABLE_CLEAN_EMBEDDING_CACHE_TASK: ${ENABLE_CLEAN_EMBEDDING_CACHE_TASK:-false} ENABLE_CLEAN_UNUSED_DATASETS_TASK: ${ENABLE_CLEAN_UNUSED_DATASETS_TASK:-false} ENABLE_CREATE_TIDB_SERVERLESS_TASK: ${ENABLE_CREATE_TIDB_SERVERLESS_TASK:-false}