Azure / azure-sdk-for-net

This repository is for active development of the Azure SDK for .NET. For consumers of the SDK we recommend visiting our public developer docs at https://learn.microsoft.com/dotnet/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-net.
MIT License
5.47k stars 4.8k forks source link

[FEATURE REQ] support using SAS to AddBlobServiceClient #34945

Open lbsong opened 1 year ago

lbsong commented 1 year ago

Library name

Azure.Storage.Blobs

Please describe the feature.

why does AddBlobServiceClient not support using SAS? https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/storage/Azure.Storage.Blobs/src/BlobClientBuilderExtensions.cs

ghost commented 1 year ago

Thank you for your feedback. This has been routed to the support team for assistance.

ghost commented 1 year ago

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

Issue Details
### Library name Azure.Storage.Blobs ### Please describe the feature. why does AddBlobServiceClient not support using SAS? https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/storage/Azure.Storage.Blobs/src/BlobClientBuilderExtensions.cs
Author: lbsong
Assignees: -
Labels: `Storage`, `Service Attention`, `Client`, `customer-reported`, `question`, `needs-team-attention`
Milestone: -
navba-MSFT commented 1 year ago

Adding Service team to look into this.

@lbsong You can use the BlobServiceClient which will take the SAS token as the parameter. You can check if the below sample helps.

        // You can generate a service SAS or account SAS from application. The below SAS token is generated from Azure Portal

              var sasToken = "?sv=2021-12-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2023-03-30T15:25:29Z&st=2023-03-16T07:25:29Z&spr=https&sig=XXXXXXXXXXXXXXX";

                // Update the Container Name
                string containerName = "test";

                // Construct a new BlobServiceClient using a AzureSasCredential.
                BlobServiceClient blobServiceClient = new BlobServiceClient(new Uri(serviceUri), new AzureSasCredential(sasToken));
waynebrantley commented 1 year ago

The issue was not about BlobServiceClient not supporting this. This is about AddBlobServiceClient not working properly with SASUrl.

Given this:

            var baseBlobUri = new Uri("https://redacted.blob.core.windows.net/somecontainer?si=readwrite&spr=https&sv=2022-11-02&sr=c&sig=xxxx");
            builder.Services.AddAzureClients(builder =>
            {
                builder.AddBlobServiceClient(baseBlobUri).WithName("TEST");
            });

Then use it like this:

            var blobClientFactory = app.Services.GetRequiredService<IAzureClientFactory<BlobServiceClient>>();
            var blobServiceClientDi = blobClientFactory.CreateClient("TEST");
            //container is already in the sas url
            var blobContainerClientDi = blobServiceClientDi.GetBlobContainerClient(string.Empty);
            var blobClientDi = blobContainerClientDi.GetBlobClient("text0.txt");
            await blobClientDi.UploadAsync(somedata, new BlobHttpHeaders { ContentType = "text/html" });

This will fail. However the same code without DI works properly:

            var blobServiceClient = new BlobServiceClient(baseBlobUri);
            //container is already in the sas url
            var blobContainerClient = blobServiceClient.GetBlobContainerClient(string.Empty);
            var blobClient = blobContainerClient.GetBlobClient("text1.txt");
            await blobClient.UploadAsync(somedata, new BlobHttpHeaders { ContentType = "text/html" });

Might be related to the token param here: https://github.com/Azure/azure-sdk-for-net/blob/e5cc0d08699b7808a82dc86b166c9a059503cb49/sdk/storage/Azure.Storage.Blobs/src/BlobClientBuilderExtensions.cs#L32

Adding this method (and using it instead) resolves this:

    public static IAzureClientBuilder<BlobServiceClient, BlobClientOptions> AddBlobServiceClientSas<TBuilder>(this TBuilder builder, Uri serviceUri)
        where TBuilder : IAzureClientFactoryBuilderWithCredential
    {
        return builder.RegisterClientFactory<BlobServiceClient, BlobClientOptions>((options, _) => new BlobServiceClient(serviceUri, options), requiresCredential: false);
    }
waynebrantley commented 1 year ago

@navba-MSFT any thoughts?

th3ragex commented 5 months ago

Summary based on previous answers:

builder.Services.AddAzureClients(clientBuilder =>
{
    ((IAzureClientFactoryBuilder)clientBuilder).RegisterClientFactory<BlobServiceClient, BlobClientOptions>(
        options => new BlobServiceClient(new Uri(url), new AzureSasCredential(sas), options))
        .WithName("...");
});
waynebrantley commented 1 month ago

@th3ragex typically SAS urls are not provided in two pieces - the SAS and the url. They come all as one. It would be nice if it just supported this standard scenario.