fix(azure_sentinel): add AZURE_SENTINEL_AUTHORITY_HOST as a Sentinel scoped override (#36165)

Making Sentinel follow AZURE_AUTHORITY_HOST is a breaking change for a
deployment that sets that variable for Azure OpenAI or the azure_storage
callback while keeping a commercial Sentinel workspace. That deployment had no
opt-out, because the proxy constructs the logger with no arguments and the
authority_host parameter is reachable only from the SDK.

Resolve the authority from AZURE_SENTINEL_AUTHORITY_HOST before falling back to
AZURE_AUTHORITY_HOST, matching how tenant id, client id and client secret
already resolve in this constructor.
This commit is contained in:
yucheng-berri 2026-08-07 11:14:20 -07:00 • committed by GitHub
parent 0cd58a04d7
commit bd289c151c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 42 additions and 3 deletions

View file

@ -78,8 +78,8 @@ class AzureSentinelLogger(CustomBatchLogger):
If not provided, will use AZURE_SENTINEL_AUDIT_STREAM_NAME env var or the standard stream name.
authority_host (str, optional): Microsoft Entra authority host that issues the OAuth2 token,
e.g. "https://login.microsoftonline.us" for Azure Government. If not provided, will use
AZURE_AUTHORITY_HOST env var or default to the Azure Public Cloud authority. The Azure
Monitor audience is derived from it.
AZURE_SENTINEL_AUTHORITY_HOST or AZURE_AUTHORITY_HOST env vars, or default to the Azure
Public Cloud authority. The Azure Monitor audience is derived from it.
"""
self.async_httpx_client = get_async_httpx_client(llm_provider=httpxSpecialProvider.LoggingCallback)
@ -95,7 +95,10 @@ class AzureSentinelLogger(CustomBatchLogger):
client_secret or os.getenv("AZURE_SENTINEL_CLIENT_SECRET") or os.getenv("AZURE_CLIENT_SECRET")
)
resolved_authority_host: Final = self._normalize_authority_host(
authority_host or os.getenv("AZURE_AUTHORITY_HOST") or DEFAULT_AZURE_AUTHORITY_HOST
authority_host
or os.getenv("AZURE_SENTINEL_AUTHORITY_HOST")
or os.getenv("AZURE_AUTHORITY_HOST")
or DEFAULT_AZURE_AUTHORITY_HOST
)
if not resolved_dcr_immutable_id:

View file

@ -313,6 +313,7 @@ def _build_logger(**overrides):
@pytest.fixture
def _no_authority_host_env(monkeypatch):
monkeypatch.delenv("AZURE_SENTINEL_AUTHORITY_HOST", raising=False)
monkeypatch.delenv("AZURE_AUTHORITY_HOST", raising=False)
@ -389,3 +390,38 @@ async def test_azure_sentinel_token_request_uses_sovereign_authority_and_audienc
assert len(token_calls) == 1
assert token_calls[0].kwargs["url"] == "https://login.microsoftonline.us/test-tenant-id/oauth2/v2.0/token"
assert token_calls[0].kwargs["data"]["scope"] == "https://monitor.azure.us/.default"
def test_azure_sentinel_authority_host_prefers_the_sentinel_scoped_env_var(_no_authority_host_env, monkeypatch):
"""AZURE_AUTHORITY_HOST is shared with Azure OpenAI and the azure_storage callback, so a deployment
whose Sentinel workspace lives in a different cloud than the rest of its Azure resources needs a
Sentinel-scoped override. This mirrors how tenant, client id and secret already resolve."""
monkeypatch.setenv("AZURE_AUTHORITY_HOST", "https://login.microsoftonline.com")
monkeypatch.setenv("AZURE_SENTINEL_AUTHORITY_HOST", "https://login.microsoftonline.us")
logger = _build_logger()
assert logger.authority_host == "https://login.microsoftonline.us"
assert logger.oauth_scope == "https://monitor.azure.us/.default"
def test_azure_sentinel_falls_back_to_the_shared_authority_host(_no_authority_host_env, monkeypatch):
"""With no Sentinel-scoped override the shared variable still applies, which is the behavior
shipped in the original fix."""
monkeypatch.setenv("AZURE_AUTHORITY_HOST", "https://login.microsoftonline.us")
logger = _build_logger()
assert logger.authority_host == "https://login.microsoftonline.us"
assert logger.oauth_scope == "https://monitor.azure.us/.default"
def test_azure_sentinel_authority_host_argument_outranks_the_scoped_env_var(_no_authority_host_env, monkeypatch):
"""An explicit constructor argument is the most specific source and has to win, otherwise a
deployment that exports the scoped variable silently overrides an SDK caller."""
monkeypatch.setenv("AZURE_SENTINEL_AUTHORITY_HOST", "https://login.microsoftonline.us")
logger = _build_logger(authority_host="https://login.microsoftonline.com")
assert logger.authority_host == "https://login.microsoftonline.com"
assert logger.oauth_scope == "https://monitor.azure.com/.default"