This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new e5bf1e30c1b fix(test_wasb.py): SAS token tests failing with 
azure-storage-blob 12.30.0 (#68490)
e5bf1e30c1b is described below

commit e5bf1e30c1bf7b5ccf14f2f4cd611458f5bb6891
Author: PoAn Yang <[email protected]>
AuthorDate: Sat Jun 13 20:50:26 2026 +0900

    fix(test_wasb.py): SAS token tests failing with azure-storage-blob 12.30.0 
(#68490)
    
    * fix(test_wasb.py): SAS token tests failing with azure-storage-blob 12.30.0
    
    Signed-off-by: PoAn Yang <[email protected]>
    
    * refactor: add SAS link and update test_sas_token_connection assertion
    
    Signed-off-by: PoAn Yang <[email protected]>
    
    * test: assert sas_token in conn.url
    
    Signed-off-by: PoAn Yang <[email protected]>
    
    ---------
    
    Signed-off-by: PoAn Yang <[email protected]>
---
 .../providers/microsoft/azure/hooks/wasb.py        |  7 +++--
 .../tests/unit/microsoft/azure/hooks/test_wasb.py  | 32 ++++++++++++++++------
 2 files changed, 28 insertions(+), 11 deletions(-)

diff --git 
a/providers/microsoft/azure/src/airflow/providers/microsoft/azure/hooks/wasb.py 
b/providers/microsoft/azure/src/airflow/providers/microsoft/azure/hooks/wasb.py
index dabd7280e3d..c363c227690 100644
--- 
a/providers/microsoft/azure/src/airflow/providers/microsoft/azure/hooks/wasb.py
+++ 
b/providers/microsoft/azure/src/airflow/providers/microsoft/azure/hooks/wasb.py
@@ -30,6 +30,7 @@ import logging
 import os
 from typing import TYPE_CHECKING, Any, cast
 
+from azure.core.credentials import AzureSasCredential
 from azure.core.exceptions import HttpResponseError, ResourceExistsError, 
ResourceNotFoundError
 from azure.identity import ClientSecretCredential
 from azure.identity.aio import (
@@ -203,7 +204,9 @@ class WasbHook(BaseHook):
         if sas_token:
             if sas_token.startswith("https"):
                 return BlobServiceClient(account_url=sas_token, **extra)
-            return 
BlobServiceClient(account_url=f"{account_url.rstrip('/')}/{sas_token}", **extra)
+            return BlobServiceClient(
+                account_url=account_url, 
credential=AzureSasCredential(sas_token), **extra
+            )
 
         # Fall back to old auth (password) or use managed identity if not 
provided.
         credential: str | TokenCredential | None = conn.password
@@ -671,7 +674,7 @@ class WasbAsyncHook(WasbHook):
                 self.blob_service_client = 
AsyncBlobServiceClient(account_url=sas_token, **extra)
             else:
                 self.blob_service_client = AsyncBlobServiceClient(
-                    account_url=f"{account_url.rstrip('/')}/{sas_token}", 
**extra
+                    account_url=account_url, 
credential=AzureSasCredential(sas_token), **extra
                 )
             return self.blob_service_client
 
diff --git 
a/providers/microsoft/azure/tests/unit/microsoft/azure/hooks/test_wasb.py 
b/providers/microsoft/azure/tests/unit/microsoft/azure/hooks/test_wasb.py
index 40f72229950..45670510944 100644
--- a/providers/microsoft/azure/tests/unit/microsoft/azure/hooks/test_wasb.py
+++ b/providers/microsoft/azure/tests/unit/microsoft/azure/hooks/test_wasb.py
@@ -23,6 +23,7 @@ from unittest import mock
 from unittest.mock import create_autospec
 
 import pytest
+from azure.core.credentials import AzureSasCredential
 from azure.core.exceptions import ResourceNotFoundError
 from azure.storage.blob import BlobServiceClient, ContainerClient
 from azure.storage.blob._models import BlobProperties
@@ -45,6 +46,11 @@ CONN_STRING = (
 ACCESS_KEY_STRING = "AccountName=name;skdkskd"
 PROXIES = {"http": "http_proxy_uri", "https": "https_proxy_uri"}
 
+# https://learn.microsoft.com/en-us/rest/api/storageservices/create-service-sas
+# The hook wraps plain SAS tokens in AzureSasCredential for the SDK to sign 
requests.
+SAS_TOKEN = "sv=2021-08-06&ss=b&srt=sco&sp=r&sig=samplesignature"
+HTTPS_SAS_TOKEN = f"https://login.blob.core.windows.net/?{SAS_TOKEN}";
+
 
 @pytest.fixture
 def mocked_blob_service_client():
@@ -147,24 +153,24 @@ class TestWasbHook:
                 conn_id="sas_conn_id",
                 conn_type=self.connection_type,
                 login=self.login,
-                extra={"sas_token": "token", "proxies": self.proxies},
+                extra={"sas_token": SAS_TOKEN, "proxies": self.proxies},
             ),
             Connection(
                 conn_id=self.extra__wasb__sas_conn_id,
                 conn_type=self.connection_type,
                 login=self.login,
-                extra={"extra__wasb__sas_token": "token", "proxies": 
self.proxies},
+                extra={"extra__wasb__sas_token": SAS_TOKEN, "proxies": 
self.proxies},
             ),
             Connection(
                 conn_id=self.http_sas_conn_id,
                 conn_type=self.connection_type,
-                extra={"sas_token": 
"https://login.blob.core.windows.net/token";, "proxies": self.proxies},
+                extra={"sas_token": HTTPS_SAS_TOKEN, "proxies": self.proxies},
             ),
             Connection(
                 conn_id=self.extra__wasb__http_sas_conn_id,
                 conn_type=self.connection_type,
                 extra={
-                    "extra__wasb__sas_token": 
"https://login.blob.core.windows.net/token";,
+                    "extra__wasb__sas_token": HTTPS_SAS_TOKEN,
                     "proxies": self.proxies,
                 },
             ),
@@ -304,8 +310,12 @@ class TestWasbHook:
         self, mocked_connection, mocked_blob_service_client
     ):
         WasbHook(wasb_conn_id="testconn").get_conn()
+        called_credential = 
mocked_blob_service_client.call_args[1]["credential"]
+        assert isinstance(called_credential, AzureSasCredential)
+        assert called_credential.signature == "SAStoken"
         mocked_blob_service_client.assert_called_once_with(
-            
account_url="https://testaccountname.blob.core.windows.net/SAStoken";,
+            account_url="https://testaccountname.blob.core.windows.net/";,
+            credential=called_credential,
             sas_token="SAStoken",
         )
 
@@ -361,10 +371,14 @@ class TestWasbHook:
         hook_conn = hook.get_connection(hook.conn_id)
         sas_token = hook_conn.extra_dejson[extra_key]
         assert isinstance(conn, BlobServiceClient)
-        assert conn.url.startswith("https://";)
-        if hook_conn.login:
-            assert hook_conn.login in conn.url
-        assert conn.url.endswith(sas_token + "/")
+        if sas_token.startswith("https"):
+            # HTTPS SAS URL: the full URL is passed to BlobServiceClient as-is;
+            # credential handling is left to the SDK.
+            assert sas_token in conn.url
+        else:
+            # Plain SAS token: the hook wraps it in AzureSasCredential.
+            assert isinstance(conn.credential, AzureSasCredential)
+            assert conn.credential.signature == sas_token
 
     @pytest.mark.parametrize(
         argnames="conn_id_str",

Reply via email to