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 Output binding doesn't work with ACL only right #2578

Open
hugogirard opened this issue Jan 27, 2025 · 0 comments
Open

Azure Storage Output binding doesn't work with ACL only right #2578

hugogirard opened this issue Jan 27, 2025 · 0 comments
Labels

Comments

@hugogirard
Copy link

Using Azure Functions in Isolated worker process using .NET 8, I am trying to use the BlobOutput trigger to write to a storage account using identity-based connections (managed identity).

I am not using RBAC but rather ACL in the storage account (datalake storage)
I am getting a permissions denied when trying to write to a folder.

Image

For reference here is the ACL configuration:
On the root container

Image

On the folder:

Image

Here is the code (very simple example):

Image

Is there something in the BlobOutput code that makes writing to ACL not working? Using pure SDK code, as shown below, it works. As you can see, we are using the ManagedIdentityCredential to connect to the storage.

using System;
using System.Net;
using System.Reflection.Metadata;
using System.Text;
using Azure.Identity;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace Contoso
{
    public class GetFile
    {
        private readonly ILogger _logger;
        private readonly BlobServiceClient _blobServiceClient;

        public GetFile(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<GetFile>();

            _blobServiceClient = new BlobServiceClient(new Uri($"https://dteastushg29.blob.core.windows.net"),
                                                       new ManagedIdentityCredential());
        }

        [Function("GetFile")]
        public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestData req, FunctionContext context)
        //public void Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer)
        {
            _logger.LogInformation($"Function executed: {DateTime.Now}");

            var container = _blobServiceClient.GetBlobContainerClient("doc");

            string inputFolder = "result/";
            string outputFolder = "labs";

            await foreach (BlobItem blobItem in container.GetBlobsAsync(prefix: inputFolder))
            {
                Console.WriteLine($"Found blob: {blobItem.Name}");

                BlobClient blobClient = container.GetBlobClient(blobItem.Name);

                // Download the blob's content
                BlobDownloadInfo download = await blobClient.DownloadAsync();

                // Read the content
                using (StreamReader reader = new StreamReader(download.Content))
                {
                    string content = await reader.ReadToEndAsync();
                    _logger.LogInformation($"Content of {blobItem.Name}:\n{content}\n");

                    string outputBlob = $"{outputFolder}/{blobItem.Name.Split('/')[1]}";
                    var output = container.GetBlobClient(outputBlob);

                    try
                    {
                        byte[] bytes = Encoding.UTF8.GetBytes(content);
                        using (MemoryStream stream2 = new MemoryStream(bytes))
                        {
                            var uploadOptions = new BlobUploadOptions
                            {
                                Conditions = new BlobRequestConditions() // This allows overwriting the blob
                            };
                            await output.UploadAsync(stream2, uploadOptions);
                        }

                    }
                    catch (System.Exception ex)
                    {
                        _logger.LogError(ex.Message);
                    }
                }
            }

            var httpResponse = req.CreateResponse(HttpStatusCode.OK);

            return httpResponse;
        }
    }
}

Side note that the BlobTrigger works using ACL, only the output binding doesn't.

Thank

@hugogirard hugogirard added the bug label Jan 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant