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

azure-storage-blob - sas credentials break client accessing local Azurite container #11941

Closed
kuba-lilz opened this issue Jun 10, 2020 · 5 comments · Fixed by #13159
Closed
Assignees
Labels
bug This issue requires a change to an existing behavior in the product in order to be resolved. Client This issue points to a problem in the data-plane of the library. customer-reported Issues that are reported by GitHub users external to the Azure organization. Service Attention This issue is responsible by Azure service team. Storage Storage Service (Queues, Blobs, Files)
Milestone

Comments

@kuba-lilz
Copy link

kuba-lilz commented Jun 10, 2020

  • Package Name: azure.storage.blob
  • Package Version: 12.3.1
  • Operating System: OSX 10.15.5
  • Python Version: 3.5.6

Describe the bug
When using sas token credentials for BlobServiceClient, requests sent to Azurite container are malformed

To Reproduce
Start azurite container (e.g. arafato/azurite:2.6.5), then run following code that uses credentials and connection strings for azurite running locally:

shared_access_token = azure.storage.blob.generate_account_sas(
    account_name='devstoreaccount1',
    account_key="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==",
    resource_types=azure.storage.blob.ResourceTypes(service=True, container=True, object=True),
    permission=azure.storage.blob.AccountSasPermissions(read=True, list=True),
    expiry=datetime.datetime.utcnow() + datetime.timedelta(hours=100),
    start=datetime.datetime.utcnow() - datetime.timedelta(hours=100))

storage_client = azure.storage.blob.BlobServiceClient.from_connection_string(
    conn_str="DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;TableEndpoint=http://localhost:10002/devstoreaccount1;QueueEndpoint=http://localhost:10001/devstoreaccount1;BlobEndpoint=http://localhost:10000/devstoreaccount1",
    credential=shared_access_token)

for container in storage_client.list_containers():
    print(container.name)

Expected behavior
Containers can be enumerated.

Additional context

When BlobServiceClient is created using credential=None, then valid requests are sent to Azurite and results returned.
Example of a valid request (from docker logs):

/devstoreaccount1/?comp=list 

When BlobServiceClient is created using credential=shared_access_token, then requests to Azurite contain two slashes after devstoreaccount1 part of url, instead of just one, e.g.:

/devstoreaccount1//?st=2020-06-06T00%3A13%3A14Z&ss=b&se=2020-06-14T08%3A13%3A14Z&comp=list&sv=2019-07-07&srt=sco&sp=rl&sig=Vkr7NDuOyGIrZaGeP1mTJcrLpgpl%2BbIWAb3hT93uZHk%3D 

which of course means Azurite can't understand the request.
No such problems happen when using real azure storage blob accounts in Azure.

@ghost ghost added needs-triage This is a new issue that needs to be triaged to the appropriate team. customer-reported Issues that are reported by GitHub users external to the Azure organization. question The issue doesn't require a change to the product in order to be resolved. Most issues start as that labels Jun 10, 2020
@kuba-lilz kuba-lilz changed the title azure-storage-blob - sas credentials break client with Azurite azure-storage-blob - sas credentials break client accessing local Azurite container Jun 10, 2020
@kuba-lilz
Copy link
Author

Here is a complete script (that runs a small flask server) from which above code snipped was taken away in case that's any help:

import datetime

import azure.storage.blob
import flask

APP = flask.Flask("my_app")


@APP.route("/")
def index():

    shared_access_token = azure.storage.blob.generate_account_sas(
        account_name='devstoreaccount1',
        account_key="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==",
        resource_types=azure.storage.blob.ResourceTypes(service=True, container=True, object=True),
        permission=azure.storage.blob.AccountSasPermissions(read=True, list=True),
        expiry=datetime.datetime.utcnow() + datetime.timedelta(hours=100),
        start=datetime.datetime.utcnow() - datetime.timedelta(hours=100))

    print("shared access token is\n{}\n\n".format(shared_access_token))

    storage_client = azure.storage.blob.BlobServiceClient.from_connection_string(
        conn_str="DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;TableEndpoint=http://localhost:10002/devstoreaccount1;QueueEndpoint=http://localhost:10001/devstoreaccount1;BlobEndpoint=http://localhost:10000/devstoreaccount1",
        credential=shared_access_token)

    container_client = storage_client.get_container_client("sketchpad")

    images_blobs = [blob for blob in container_client.list_blobs() if ".jpg" in blob.name]

    urls = []

    for image_blob in images_blobs:

        blob_client = container_client.get_blob_client(image_blob)
        urls.append('<a href="{}">blob here</a>'.format(blob_client.primary_endpoint))

    images_data = "<br>".join(urls)

    response = ("""
    <html>
    <body>
    {}
    </body>
    </html>
    """.format(images_data))

    return response


APP.run(use_reloader=True)

@kaerm kaerm added Client This issue points to a problem in the data-plane of the library. Storage Storage Service (Queues, Blobs, Files) labels Jun 10, 2020
@ghost
Copy link

ghost commented Jun 10, 2020

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @xgithubtriage.

@ghost ghost removed the needs-triage This is a new issue that needs to be triaged to the appropriate team. label Jun 10, 2020
@kaerm kaerm added the Service Attention This issue is responsible by Azure service team. label Jun 10, 2020
@xiafu-msft
Copy link
Contributor

xiafu-msft commented Jun 15, 2020

Hi @kuba-lilz
Thanks for reporting this! We have logged a bug and it will be fixed later!
Hope it doesn't block you! Let me know if you have any concern

@xiafu-msft xiafu-msft added the bug This issue requires a change to an existing behavior in the product in order to be resolved. label Jun 23, 2020
@xiafu-msft xiafu-msft removed the question The issue doesn't require a change to the product in order to be resolved. Most issues start as that label Jul 13, 2020
@lmazuel lmazuel added this to the Backlog milestone Jul 14, 2020
@tasherif-msft tasherif-msft self-assigned this Aug 13, 2020
@hayesgb
Copy link

hayesgb commented Aug 15, 2020

I'm seeing similar behavior with azure-storage-blob v12.4.0, which manifests in the dask/adlfs package as reported here.

After starting azurite locally using docker, execution of the following:

bbs = BlobServiceClient.from_connection_string(
    conn_str="DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;TableEndpoint=http://localhost:10002/devstoreaccount1;QueueEndpoint=http://localhost:10001/devstoreaccount1;BlobEndpoint=http://localhost:10000/devstoreaccount1",
    key="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")
bbs.create_container("data")
cons = bbs.list_containers()
print([c for c in cons])

returns the following error:


---------------------------------------------------------------------------
StorageErrorException                     Traceback (most recent call last)
~/anaconda3/envs/adlfs/lib/python3.7/site-packages/azure/storage/blob/_models.py in _get_next_cb(self, continuation_token)
    398                 cls=return_context_and_deserialized,
--> 399                 use_location=self.location_mode)
    400         except StorageErrorException as error:

~/anaconda3/envs/adlfs/lib/python3.7/site-packages/azure/storage/blob/_generated/operations/_service_operations.py in list_containers_segment(self, prefix, marker, maxresults, include, timeout, request_id, cls, **kwargs)
    335             map_error(status_code=response.status_code, response=response, error_map=error_map)
--> 336             raise models.StorageErrorException(response, self._deserialize)
    337 

StorageErrorException: Operation returned an invalid status 'Bad Request'

During handling of the above exception, another exception occurred:

HttpResponseError                         Traceback (most recent call last)
<ipython-input-3-beaff551c875> in <module>
      4 bbs.create_container("data")
      5 cons = bbs.list_containers()
----> 6 print([c for c in cons])

<ipython-input-3-beaff551c875> in <listcomp>(.0)
      4 bbs.create_container("data")
      5 cons = bbs.list_containers()
----> 6 print([c for c in cons])

~/anaconda3/envs/adlfs/lib/python3.7/site-packages/azure/core/paging.py in __next__(self)
    120         if self._page_iterator is None:
    121             self._page_iterator = itertools.chain.from_iterable(self.by_page())
--> 122         return next(self._page_iterator)
    123 
    124     next = __next__  # Python 2 compatibility.

~/anaconda3/envs/adlfs/lib/python3.7/site-packages/azure/core/paging.py in __next__(self)
     72             raise StopIteration("End of paging")
     73 
---> 74         self._response = self._get_next(self.continuation_token)
     75         self._did_a_call_already = True
     76 

~/anaconda3/envs/adlfs/lib/python3.7/site-packages/azure/storage/blob/_models.py in _get_next_cb(self, continuation_token)
    399                 use_location=self.location_mode)
    400         except StorageErrorException as error:
--> 401             process_storage_error(error)
    402 
    403     def _extract_data_cb(self, get_next_return):

~/anaconda3/envs/adlfs/lib/python3.7/site-packages/azure/storage/blob/_shared/response_handlers.py in process_storage_error(storage_error)
    145     error.error_code = error_code
    146     error.additional_info = additional_data
--> 147     raise error
    148 
    149 

HttpResponseError: Operation returned an invalid status 'Bad Request'
ErrorCode:None

Execution with azure-storage-blob 12.3.2 returns:

[{'name': 'data', 'last_modified': datetime.datetime(2020, 8, 15, 13, 31, 55, tzinfo=datetime.timezone.utc), 'etag': '"d-uncJpKbVsSBPdz3DP+1dHwJdN1k"', 'lease': {'status': 'unlocked', 'state': 'available', 'duration': None}, 'public_access': None, 'has_immutability_policy': False, 'has_legal_hold': False, 'metadata': {}, 'encryption_scope': None}]

@tasherif-msft
Copy link
Contributor

Hi there,
The changes to fix this issue have been made and it will be available in our September release.
If this is an urgent issue or if there are any concerns, let me know!

openapi-sdkautomation bot pushed a commit to AzureSDKAutomation/azure-sdk-for-python that referenced this issue Dec 8, 2020
@github-actions github-actions bot locked and limited conversation to collaborators Apr 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug This issue requires a change to an existing behavior in the product in order to be resolved. Client This issue points to a problem in the data-plane of the library. customer-reported Issues that are reported by GitHub users external to the Azure organization. Service Attention This issue is responsible by Azure service team. Storage Storage Service (Queues, Blobs, Files)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants