Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Azure File Storage from Azure Function

I'm attempting to retrieve a file out of Azure File Storage to be used by an .exe that is executed within an Azure Function and can't seem to get pass the UNC credentials.

My app gets the UNC file path out of an Azure SQL database and then attempts to navigate to that UNC path (in Azure File Storage) to import the contents of the file. I can navigate to the file location from my PC in windows explorer but am prompted for the credentials.

I've tried using a "net use" command prior to executing the app but it doesn't seem to authenticate.

net use \\<storage account>.file.core.windows.net\<directory>\ /u:<username> <access key>

MyApp.exe 

Azure Function Log error:

Unhandled Exception: System.UnauthorizedAccessException: Access to the path '<file path>' is denied.

If possible, I'd rather not modify my C# app and do the authentication in the Azure Function (its a Batch function at the moment and will be timer based).

like image 419
BamBamBeano Avatar asked Oct 18 '16 13:10

BamBamBeano


2 Answers

I believe it is not possible to mount an Azure File Service Share in an Azure Function as you don't get access to underlying infrastructure (same deal as WebApps).

What you could do is make use of Azure Storage SDK which is a wrapper over Azure Storage REST API and use that in your application to interact with files in your File Service Share.

like image 128
Gaurav Mantri Avatar answered Nov 11 '22 21:11

Gaurav Mantri


You cannot use SMB (445/TCP). Functions run inside the App Service sandbox.

From https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox#restricted-outgoing-ports:

Restricted Outgoing Ports

Regardless of address, applications cannot connect to anywhere using ports 445, 137, 138, and 139. In other words, even if connecting to a non-private IP address or the address of a virtual network, connections to ports 445, 137, 138, and 139 are not permitted.

Use the Azure Storage SDK to talk to your Azure File endpoint:

using Microsoft.Azure;  // Namespace for CloudConfigurationManager
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.File;

// Parse the connection string and return a reference to the storage account.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create a CloudFileClient object for credentialed access to File storage.
CloudFileClient fileClient = storageAccount.CreateCloudFileClient();

// Get a reference to the file share we created previously.
CloudFileShare share = fileClient.GetShareReference("logs");

// Ensure that the share exists.
if (share.Exists())
{
    // Get a reference to the root directory for the share.
    CloudFileDirectory rootDir = share.GetRootDirectoryReference();

    // Get a reference to the directory we created previously.
    CloudFileDirectory sampleDir = rootDir.GetDirectoryReference("CustomLogs");

    // Ensure that the directory exists.
    if (sampleDir.Exists())
    {
        // Get a reference to the file we created previously.
        CloudFile file = sampleDir.GetFileReference("Log1.txt");

        // Ensure that the file exists.
        if (file.Exists())
        {
            // Write the contents of the file to the console window.
            Console.WriteLine(file.DownloadTextAsync().Result);
        }
    }
}

Sample uses CloudConfigurationManager - i think that's a bit too much for such a simple scenario. I would do this instead:

using System.Configuration;

// "StorConnStr" is the Storage account Connection String
// defined for your Function in the Azure Portal
string connstr = ConfigurationManager.ConnectionStrings["StorConnStr"].ConnectionString;
like image 36
evilSnobu Avatar answered Nov 11 '22 20:11

evilSnobu