KwackMaster
KwackMaster

Reputation: 220

Load and execute code from an Azure Blob container from a function app?

I have a multitenant application which stores certain custom assemblies for each tenant in blobs in their Azure storage account. These assemblies contain custom code to run reports for the specific tenant who is logged in.

The most straightforward approach I think would be to have the Azure function download the DLLs into it's local workspace and load & execute from there (we use MEF to do this).

Is it possible for an Azure function or a webapp to execute code directly from that blob container?

Azure websites can run out of Azure storage so curious if an azure function can dynamically load and run those assemblies remotely. Obviously, there are security risks to doing so but that what would be the workarounds?

Also, Azure functions actually execute code out of blob storage I discovered while chatting with an Azure rep on a support call though I don't know how they do so and haven't done a POC.

Just looking if this is even possible before running POCs.

Upvotes: 3

Views: 752

Answers (1)

Vlad DX
Vlad DX

Reputation: 4730

You can simply download a blob from a blob storage as byte array, load it as assembly, and use it.

This is a naive implementation of a static function:

[FunctionName("LoadDll")]
public static async Task<object> RunDll(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
    ILogger log)
{
    var containerName = "dlls";
    var filename = "ClassLibrary1.dll";

    // Connect to Storage Account (in case of local development – Azurite)
    var blobServiceClient = new BlobServiceClient("AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;DefaultEndpointsProtocol=http;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;");

    var blobContainerClient = blobServiceClient.GetBlobContainerClient(containerName);
    var blobClient = blobContainerClient.GetBlobClient(filename);
    // Read the assembly file from the Blob Storage
    var stream = await blobClient.OpenReadAsync();

    using var memoryStream = new MemoryStream();
    await stream.CopyToAsync(memoryStream);
    // Read it to a byte array
    var assemblyBytes = memoryStream.ToArray();

    // Load the assembly from the byte array
    var assembly = Assembly.Load(assemblyBytes);

    // Find a class
    var class1Type = assembly.GetType("ClassLibrary1.Class1");
    // Find a method in the class
    var method = class1Type.GetMethod("GetInt");

    // Instantiate the class
    var obj = Activator.CreateInstance(class1Type);
    // Call the method
    var result = method.Invoke(obj, null);
    return result;
}

I created a class library project ClassLibrary1 and defined a class:

namespace ClassLibrary1
{
    public class Class1
    {
        public int GetInt()
        {
            return 1;
        }
    }
}

Then I uploaded it to Azurite (Local Storage Account Emulator) to blob container dlls:

Assembly in the Blob Storage


Result

When I run the Azure Function app and open the URL http://localhost:7208/api/LoadDll in browser, the result is:

Result in the browser

Upvotes: 3

Related Questions