From ab358fe9492db122738137e84b18052459dcd508 Mon Sep 17 00:00:00 2001 From: Zhichang Yu Date: Fri, 3 Apr 2026 12:51:26 +0800 Subject: [PATCH] feat: make Azure cloud authority configurable for SPN auth (#13898) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - The Azure SPN storage handler hardcoded `AzureAuthorityHosts.AZURE_CHINA`, preventing users in Azure Public Cloud regions (UK-South, EU, US, etc.) from authenticating - Add a `cloud` config option (env: `AZURE_CLOUD`) supporting all four Azure sovereignties: `public`, `china`, `government`, `germany` - Defaults to `public` (global Azure) — the most common international use case Closes #13259 ## Test plan - [ ] Verify default (`cloud: public`) connects to Azure Public Cloud endpoints - [ ] Verify `cloud: china` retains existing behavior for Azure China users - [ ] Verify `AZURE_CLOUD` env var overrides the config file value 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 --- docker/service_conf.yaml.template | 1 + pyproject.toml | 2 +- rag/utils/azure_spn_conn.py | 11 ++++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docker/service_conf.yaml.template b/docker/service_conf.yaml.template index ba30a0240d..a06e71f9e7 100644 --- a/docker/service_conf.yaml.template +++ b/docker/service_conf.yaml.template @@ -98,6 +98,7 @@ user_default_llm: # secret: 'secret' # tenant_id: 'tenant_id' # container_name: 'container_name' +# cloud: 'public' # Azure cloud: 'public', 'china', 'government', or 'germany' # The OSS object storage uses the MySQL configuration above by default. If you need to switch to another object storage service, please uncomment and configure the following parameters. # opendal: # scheme: 'mysql' # Storage type, such as s3, oss, azure, etc. diff --git a/pyproject.toml b/pyproject.toml index 8c0cc77681..a5ae5cf9f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ dependencies = [ "anthropic==0.34.1", "arxiv==2.1.3", "atlassian-python-api==4.0.7", - "azure-identity==1.17.1", + "azure-identity==1.25.3", "azure-storage-file-datalake==12.16.0", "beartype>=0.20.0,<1.0.0", "bio==1.7.1", diff --git a/rag/utils/azure_spn_conn.py b/rag/utils/azure_spn_conn.py index 12bcc64104..4cfaa0f3e7 100644 --- a/rag/utils/azure_spn_conn.py +++ b/rag/utils/azure_spn_conn.py @@ -22,6 +22,13 @@ from azure.identity import ClientSecretCredential, AzureAuthorityHosts from azure.storage.filedatalake import FileSystemClient from common import settings +_CLOUD_AUTHORITY_MAP = { + "public": AzureAuthorityHosts.AZURE_PUBLIC_CLOUD, + "china": AzureAuthorityHosts.AZURE_CHINA, + "government": AzureAuthorityHosts.AZURE_GOVERNMENT, + "germany": AzureAuthorityHosts.AZURE_GERMANY, +} + @singleton class RAGFlowAzureSpnBlob: @@ -32,6 +39,7 @@ class RAGFlowAzureSpnBlob: self.secret = os.getenv('SECRET', settings.AZURE["secret"]) self.tenant_id = os.getenv('TENANT_ID', settings.AZURE["tenant_id"]) self.container_name = os.getenv('CONTAINER_NAME', settings.AZURE["container_name"]) + self.cloud = os.getenv('AZURE_CLOUD', settings.AZURE.get("cloud", "public")).lower() self.__open__() def __open__(self): @@ -42,8 +50,9 @@ class RAGFlowAzureSpnBlob: pass try: + authority = _CLOUD_AUTHORITY_MAP.get(self.cloud, AzureAuthorityHosts.AZURE_PUBLIC_CLOUD) credentials = ClientSecretCredential(tenant_id=self.tenant_id, client_id=self.client_id, - client_secret=self.secret, authority=AzureAuthorityHosts.AZURE_CHINA) + client_secret=self.secret, authority=authority) self.conn = FileSystemClient(account_url=self.account_url, file_system_name=self.container_name, credential=credentials) except Exception: