Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing Default Azure Credential bug in Windows throwing NotImplementedError #328

Merged
merged 13 commits into from
Jul 22, 2022
47 changes: 33 additions & 14 deletions adlfs/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from glob import has_magic

from azure.core.exceptions import (
ClientAuthenticationError,
HttpResponseError,
ResourceExistsError,
ResourceNotFoundError,
Expand All @@ -32,6 +31,7 @@

from .utils import (
close_container_client,
close_credential,
close_service_client,
filter_blobs,
get_blob_metadata,
Expand Down Expand Up @@ -449,8 +449,23 @@ def __init__(
) = self._get_credential_from_service_principal()
else:
self.sync_credential = None

# Solving issue in https://github.com/fsspec/adlfs/issues/270
if (
self.credential is None
and self.anon is False
and self.sas_token is None
and self.account_key is None
):

(
self.credential,
self.sync_credential,
) = self._get_default_azure_credential(**kwargs)

self.do_connect()
weakref.finalize(self, sync, self.loop, close_service_client, self)
weakref.finalize(self, sync, self.loop, close_credential, self)

@classmethod
def _strip_protocol(cls, path: str):
Expand Down Expand Up @@ -517,18 +532,24 @@ def _get_credential_from_service_principal(self):
return (async_credential, sync_credential)

def _get_default_azure_credential(self, **kwargs):
try:
from azure.identity.aio import (
DefaultAzureCredential as AIODefaultAzureCredential,
)

asyncio.get_child_watcher().attach_loop(self.loop)
self.credential = AIODefaultAzureCredential()
self.do_connect()
except: # noqa: E722
raise ClientAuthenticationError(
"No explict credentials provided. Failed with DefaultAzureCredential!"
)
"""
Create a Credential for authentication using DefaultAzureCredential

Returns
-------
Tuple of (Async Credential, Sync Credential).
"""

from azure.identity import DefaultAzureCredential
from azure.identity.aio import (
DefaultAzureCredential as AIODefaultAzureCredential,
)

async_credential = AIODefaultAzureCredential(**kwargs)
sync_credential = DefaultAzureCredential(**kwargs)

return (async_credential, sync_credential)

def do_connect(self):
"""Connect to the BlobServiceClient, using user-specified connection details.
Expand Down Expand Up @@ -567,8 +588,6 @@ def do_connect(self):
credential=None,
_location_mode=self.location_mode,
)
elif self.anon is False:
self._get_default_azure_credential()
else:
# Fall back to anonymous login, and assume public container
self.service_client = AIOBlobServiceClient(
Expand Down
8 changes: 8 additions & 0 deletions adlfs/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,11 @@ async def close_container_client(file_obj):
AzureBlobFile objects
"""
await file_obj.container_client.close()


async def close_credential(file_obj):
"""
Implements asynchronous closure of credentials for
AzureBlobFile objects
"""
await file_obj.credential.close()