{"id":1312,"date":"2022-05-29T11:09:03","date_gmt":"2022-05-29T10:09:03","guid":{"rendered":"http:\/\/www.klaushaller.net\/?p=1312"},"modified":"2022-05-29T11:09:03","modified_gmt":"2022-05-29T10:09:03","slug":"tutorial-azure-function-storage-accounts-and-managed-identity-based-authentication","status":"publish","type":"post","link":"https:\/\/www.klaushaller.net\/?p=1312","title":{"rendered":"Tutorial: Azure Function, Storage Accounts, and Managed-Identity-based Authentication"},"content":{"rendered":"\n<p>Serverless application logic, storage accounts, platform-as-a-service identity and access management, this small tutorial combines state-of-the-art Azure technologies in a four-step demo or tutorial. The result: a serverless Azure Function invoked via a web browser that returns a welcome text, which the Azure Function reads from an Azure Storage account using Azure Identity for authentication and authorization.<\/p>\n\n\n\n<p>Prerequisites for performing this tutorial are:<\/p>\n\n\n\n<ol class=\"wp-block-list\" type=\"1\"><li>An Azure cloud account (we use only free services)<\/li><li>A local Visual Studio installation (free version sufficient)<\/li><\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Setting up the Azure Storage Account backend<\/strong><\/h2>\n\n\n\n<p>Create a resource group named \u201crg_Demo26a\u201d (Figure 1, A). The resource group collects and stores all the resources we create in the following. Having all resources in a dedicated resource group eases cleaning them up after completing this demo.<\/p>\n\n\n\n<p>Next, create an Azure Storage account \u201csta26a\u201d (Figure 1, B) in the resource group \u201crg_Demo26a\u201d. On the \u201cadvanced\u201d tab, disable public access and storage account key access and enable default Azure Active Directory authorization (C). Then, advance to the \u201cnetworking\u201d tab. Here, make sure to have \u201cenable public access\u201d activated (D). This setting means that our storage is directly connected to the Internet and only protected by access management methods. It is a dangerous setting, though it saves us time in the demo. Never do this in any Azure subscription used for anything but for playing around.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-1-Creating-a-Resource-Group-and-an-Azure-Storage-Account.png\"><img loading=\"lazy\" decoding=\"async\" width=\"605\" height=\"242\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-1-Creating-a-Resource-Group-and-an-Azure-Storage-Account.png\" alt=\"\" class=\"wp-image-1315\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-1-Creating-a-Resource-Group-and-an-Azure-Storage-Account.png 605w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-1-Creating-a-Resource-Group-and-an-Azure-Storage-Account-300x120.png 300w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><figcaption><a>Figure <\/a>1: Creating a Resource Group and an Azure Storage Account<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Creating a Storage account does not allow you to upload or read files. Thus, before actually uploading any file to the Storage Account, you need to grant yourself \u201cContributor\u201d rights for the Storage Account. Therefore, go to your Storage Account \u201csta26a\u201d, select \u201cAccess Control (IAM)\u201d in the menu to the left (Figure 2, A), and push the \u201cAdd role assignment\u201d button (B).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-2-Starting-a-role-assignment.png\"><img loading=\"lazy\" decoding=\"async\" width=\"489\" height=\"205\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-2-Starting-a-role-assignment.png\" alt=\"\" class=\"wp-image-1316\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-2-Starting-a-role-assignment.png 489w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-2-Starting-a-role-assignment-300x126.png 300w\" sizes=\"auto, (max-width: 489px) 100vw, 489px\" \/><\/a><figcaption>Figure 2: Starting a role assignment<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Then, search for roles containing \u201cblob\u201d (Figure 3, A), select the role \u201cStorage Blob Data Contributor\u201d (B), and click \u201cnext\u201d (C) to proceed to the next submask. Here, choose \u201cuser, grout\u201d for the \u201cAssign access to\u201c setting (D) and click on \u201csel3ect members\u201d (E). A new submask appears to the right. It presents the users of this Azure tenant. Select the user you are currently logged in (F) and have a coffee afterward. It takes a few minutes until the new rights are active. If you proceed too early, the next step fails.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-3-The-actual-role-assignment-to-an-AAD-registered-user.png\"><img loading=\"lazy\" decoding=\"async\" width=\"605\" height=\"291\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-3-The-actual-role-assignment-to-an-AAD-registered-user.png\" alt=\"\" class=\"wp-image-1317\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-3-The-actual-role-assignment-to-an-AAD-registered-user.png 605w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-3-The-actual-role-assignment-to-an-AAD-registered-user-300x144.png 300w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><figcaption><a>Figure <\/a>3: The actual role assignment to an AAD registered user<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Now you are ready to upload a file. Create a text file \u201coutput.txt\u201d on your laptop with the content \u201c<em>Hello world, hello Klaus!\u201d<\/em>. Upload this file into our Azure Storage Account.<\/p>\n\n\n\n<p>Switch to the newly created Storage Account and select \u201cupload\u201d (Figure 4, A). Select \u201cCreate new\u201d and type in \u201ccont26a\u201d as container name (B). Open the file explorer by clicking on the symbol to the right. Select the file we just created (C). Then, press \u201cUpload\u201d to load the file \u201coutput.txt\u201d to the cloud (D). If the upload button is not blue, something went wrong in any of the previous steps.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-4-Creating-a-container-and-uploading-a-file-to-an-Azure-Storage-Account..png\"><img loading=\"lazy\" decoding=\"async\" width=\"369\" height=\"206\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-4-Creating-a-container-and-uploading-a-file-to-an-Azure-Storage-Account..png\" alt=\"\" class=\"wp-image-1319\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-4-Creating-a-container-and-uploading-a-file-to-an-Azure-Storage-Account..png 369w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-4-Creating-a-container-and-uploading-a-file-to-an-Azure-Storage-Account.-300x167.png 300w\" sizes=\"auto, (max-width: 369px) 100vw, 369px\" \/><\/a><figcaption><a>Figure <\/a>4: Creating a container and uploading a file to an Azure Storage Account.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>As a last step in the Azure Portal, for now, open the Storage Account sta26 and select the storage browser (A). Click on the blob containers (B), then on \u201csta26a\u201d (C). You see the list of files stored there. Click on the three points at the right of the row \u201coutput.txt\u201d (D) and click \u201cCopy URL\u201d (E). Paste the URL in some document or file. You need the string in half an hour. Then, for the next step, switch to Visual Studio.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-5-Retrieving-the-URL-of-a-file-stored-in-an-Azure-Storage-Account.png\"><img loading=\"lazy\" decoding=\"async\" width=\"605\" height=\"181\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-5-Retrieving-the-URL-of-a-file-stored-in-an-Azure-Storage-Account.png\" alt=\"\" class=\"wp-image-1320\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-5-Retrieving-the-URL-of-a-file-stored-in-an-Azure-Storage-Account.png 605w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-5-Retrieving-the-URL-of-a-file-stored-in-an-Azure-Storage-Account-300x90.png 300w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><figcaption>Figure 5: Retrieving the URL of a file stored in an Azure Storage Account<\/figcaption><\/figure>\n<\/div>\n\n\n<p><strong>Creating an Azure Function<\/strong><\/p>\n\n\n\n<p>We create, first, a simple predefined Azure Function and deploy it to the cloud. It does not connect to our Storage Account. The step is more for verifying that the overall setup is correct. In VisualStudio, select \u201cFile &gt; New &gt; Project\u201d (Figure 5, A). VisualStudio will propose various templates. Type in \u201cFunctions\u201d into the search field (B), select \u201cAzure Functions,\u201d and continue (C). If you do not find this template, you can install missing ones after clicking on \u201cNot finding what you are looking for? Install more tools and features\u201d and search for \u201cAzure development\u201d.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-6-Starting-to-create-an-Azure-Function-project.png\"><img loading=\"lazy\" decoding=\"async\" width=\"574\" height=\"254\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-6-Starting-to-create-an-Azure-Function-project.png\" alt=\"\" class=\"wp-image-1321\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-6-Starting-to-create-an-Azure-Function-project.png 574w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-6-Starting-to-create-an-Azure-Function-project-300x133.png 300w\" sizes=\"auto, (max-width: 574px) 100vw, 574px\" \/><\/a><figcaption><a>Figure <\/a>6: Starting to create an Azure Function project<\/figcaption><\/figure>\n<\/div>\n\n\n<p>The next mask asks you for a function name (use \u201cFunctionAlpha\u201d) and a location where to save your files (Figure 6, A). Then comes the \u201cadditional information\u201d tab. Select \u201c.NET 6\u201d and \u201chttp trigger\u201d as the function you want to get created. Make sure that the other settings are as in figure (B): select \u201cUse Azure,\u201d deselect \u201cDocker,\u201d and use the function scope as authorization level. As a result, VisualStudio creates a simple function that returns some output when invoked.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-7-Configuring-and-creating-the-http-listener-example.png\"><img loading=\"lazy\" decoding=\"async\" width=\"587\" height=\"323\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-7-Configuring-and-creating-the-http-listener-example.png\" alt=\"\" class=\"wp-image-1322\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-7-Configuring-and-creating-the-http-listener-example.png 587w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-7-Configuring-and-creating-the-http-listener-example-300x165.png 300w\" sizes=\"auto, (max-width: 587px) 100vw, 587px\" \/><\/a><figcaption><a>Figure <\/a>7: Configuring and creating the http listener example<\/figcaption><\/figure>\n<\/div>\n\n\n<p>We execute the code now locally on your laptop. Run the function by clicking on \u201cFunctionAlpha\u201d next to a green triangular on the menu to the top (Figure 6, A). A new window opens up, in which the listener process runs. This process waits for incoming http requests. To send a request, copy the URL provided in the window (B) and paste it into a web browser window. You should get the output as shown in the figure (C).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-8-Running-the-http-listener-example.png\"><img loading=\"lazy\" decoding=\"async\" width=\"587\" height=\"324\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-8-Running-the-http-listener-example.png\" alt=\"\" class=\"wp-image-1323\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-8-Running-the-http-listener-example.png 587w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-8-Running-the-http-listener-example-300x166.png 300w\" sizes=\"auto, (max-width: 587px) 100vw, 587px\" \/><\/a><figcaption><a>Figure <\/a>8: Running the http listener example<\/figcaption><\/figure>\n<\/div>\n\n\n<p>We now know that the function works locally on the laptop. Next, we deploy this function to an Azure runtime environment so that the function runs \u2013 serverless \u2013 in the cloud.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Deploying and Invoking an Azure Function<\/strong><\/h2>\n\n\n\n<p>Azure comes with a feature to structure your functions \u2013 you do not create an Azure Function directly in a resource group but collect them in one or more Azure Function Apps. Create one in the Azure portal (Figure 8, A). Use resource group \u201crg_26a\u201d and type in \u201cFunctionApp26a\u201d as the name for the Function App. Select \u201cCode\u201d as the way of publishing, \u201c.NET\u201d as runtime stack, \u201c6\u201d as the version, and \u201cWindows\u201d as the operating system. On the next mask (B), choose to create a new storage account and type in \u201cstafa26a\u201d as its name. Select \u201creview and create\u201d and start the creation process.<\/p>\n\n\n\n<p>Wait until you see that the resource has been created (C). <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-9-Creating-an-Azure-Function-App..png\"><img loading=\"lazy\" decoding=\"async\" width=\"605\" height=\"301\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-9-Creating-an-Azure-Function-App..png\" alt=\"\" class=\"wp-image-1324\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-9-Creating-an-Azure-Function-App..png 605w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-9-Creating-an-Azure-Function-App.-300x149.png 300w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><figcaption><a>Figure <\/a>9: Creating an Azure Function App.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>To deploy the function to the Azure cloud, select \u201cBuild > Publish Selection\u201d (Figure 8, B), then \u201cAzure\u201d as target (B), and \u201cAzure Function App (Windows)\u201d (C). Finally, choose your subscription, then select the resource group \u201crg_Demo26a\u201d and the recently created Azure Function App \u201cFunctionApp26a\u201d (D). Continue and wait for the (quick) configurations to take place.<\/p>\n\n\n\n<p>You might think you are done. I thought precisely the same several times. However, you have to go back to \u201cBuild &gt; Publish Selection\u201d and click the publish button (E).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-10-Deploying-an-Azure-Function-prepared-in-Visual-Studio-to-the-Azure-Cloud..png\"><img loading=\"lazy\" decoding=\"async\" width=\"605\" height=\"340\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-10-Deploying-an-Azure-Function-prepared-in-Visual-Studio-to-the-Azure-Cloud..png\" alt=\"\" class=\"wp-image-1325\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-10-Deploying-an-Azure-Function-prepared-in-Visual-Studio-to-the-Azure-Cloud..png 605w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-10-Deploying-an-Azure-Function-prepared-in-Visual-Studio-to-the-Azure-Cloud.-300x169.png 300w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><figcaption><a>Figure <\/a>10: Deploying an Azure Function prepared in Visual Studio to the Azure Cloud.<\/figcaption><\/figure>\n\n\n\n<p>Now, switch back to the Azure Portal. In the Azure Function App screen, we choose \u201cFunctions\u201d in the menu bar to the left (A). We now see our function with the name \u201cFunction 1\u201d (B). Click on the name to open the details page, where you can retrieve the web function\u2019s URL (C). Click on \u201cGet Function URL,\u201d copy the link, and paste it into a web browser (D).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-11-Invoking-the-Azure-Function-deployed-in-the-Azure-Cloud.png\"><img loading=\"lazy\" decoding=\"async\" width=\"605\" height=\"340\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-11-Invoking-the-Azure-Function-deployed-in-the-Azure-Cloud.png\" alt=\"\" class=\"wp-image-1326\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-11-Invoking-the-Azure-Function-deployed-in-the-Azure-Cloud.png 605w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-11-Invoking-the-Azure-Function-deployed-in-the-Azure-Cloud-300x169.png 300w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><figcaption><a>Figure <\/a>11: Invoking the Azure Function deployed in the Azure Cloud<\/figcaption><\/figure>\n\n\n\n<p><strong>Connecting the Worlds \u2026<\/strong><\/p>\n\n\n\n<p>We have created a Storage Account with one text file that our function should display when invoked via an internet browser. Therefore, we modify the function and read the welcome text from the Storage Account.<\/p>\n\n\n\n<p>Open Visual Studio again and replace the Azure Function code with the following (check and update the blob URL if necessary):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using system;\r\nusing system.Threading.Tasks;\r\nusing Microsoft.AspNetCore.Mvc;\r\nusing Microsoft.Azure.WebJobs;\r\nusing Microsoft.Azure.WebJobs.Extensions.Http;\r\nusing Microsoft.AspNetCore.Http;\r\nusing Microsoft.Extensions.Logging;\r\nusing Azure.Storage.Blobs;\r\nusing Azure.Storage.Blobs.Models;\r\nusing Azure.Identity;\r\n\r\nnamespace FunctionAlpha\r\n{\r\n    public static class Function1\r\n    {\r\n        &#91;FunctionName(\"Function1\")]\r\n        \r\n        public static async Task&lt;IActionResult> Run(\r\n            &#91;HttpTrigger(AuthorizationLevel.Function, \"get\", \"post\", Route = null)] HttpRequest req,\r\n             ILogger log)\r\n        {\r\n            \r\n            log.LogInformation(\"C# HTTP trigger function processed a request.\");\r\n\r\n            ManagedIdentityCredential myCredentials = new ManagedIdentityCredential();\r\n\r\n            log.LogInformation(\"**1**\");\r\n\r\n            var myBlobUrl = \"https:\/\/sta26a.blob.core.windows.net\/sta26a\/output.txt\";\r\n            BlobClient bc = new BlobClient(new Uri(myBlobUrl), myCredentials);\r\n\r\n            log.LogInformation(\"**2**\");\r\n\r\n            BlobDownloadResult downloadResult = await bc.DownloadContentAsync();\r\n            string downloadedData = downloadResult.Content.ToString();\r\n            \r\n            log.LogInformation(\"**3**\");\r\n\r\n            return new OkObjectResult(\"Output text from file in the cloud: \"+ downloadedData);\r\n        }\r        \r\n    }\r\n}\r<\/code><\/pre>\n\n\n\n<p>Save the file, run it locally, and invoke it as before in Figure 8. Now you should get an error message in the browser; the listener process should display an error message (see Figure 12).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-12-Invoking-the-Azure-Function-accessing-a-blob-in-an-Azure-Storage-account-from-a-local-laptop-without-proper-access-rights.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-12-Invoking-the-Azure-Function-accessing-a-blob-in-an-Azure-Storage-account-from-a-local-laptop-without-proper-access-rights-1024x599.png\" alt=\"\" class=\"wp-image-1327\" width=\"655\" height=\"383\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-12-Invoking-the-Azure-Function-accessing-a-blob-in-an-Azure-Storage-account-from-a-local-laptop-without-proper-access-rights-1024x599.png 1024w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-12-Invoking-the-Azure-Function-accessing-a-blob-in-an-Azure-Storage-account-from-a-local-laptop-without-proper-access-rights-300x175.png 300w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-12-Invoking-the-Azure-Function-accessing-a-blob-in-an-Azure-Storage-account-from-a-local-laptop-without-proper-access-rights-768x449.png 768w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-12-Invoking-the-Azure-Function-accessing-a-blob-in-an-Azure-Storage-account-from-a-local-laptop-without-proper-access-rights-624x365.png 624w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-12-Invoking-the-Azure-Function-accessing-a-blob-in-an-Azure-Storage-account-from-a-local-laptop-without-proper-access-rights.png 1130w\" sizes=\"auto, (max-width: 655px) 100vw, 655px\" \/><\/a><figcaption><a>Figure <\/a>12: Invoking the Azure Function accessing a blob in an Azure Storage account from a local laptop &#8211; without proper access rights<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Next, deploy the updated Azure Function to the Azure Cloud, following the steps already shown in Figure 10. Then, run the function as illustrated in Figure 11. The result is another error message (HTTP Error 500), as Figure 13 illustrates. The exact text depends on your browser and the browser (language) settings.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-13-Failing-invocation-of-the-updated-Azure-Function-resulting-in-an-HTTP-ERROR-500.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-13-Failing-invocation-of-the-updated-Azure-Function-resulting-in-an-HTTP-ERROR-500.png\" alt=\"\" class=\"wp-image-1328\" width=\"466\" height=\"175\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-13-Failing-invocation-of-the-updated-Azure-Function-resulting-in-an-HTTP-ERROR-500.png 466w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-13-Failing-invocation-of-the-updated-Azure-Function-resulting-in-an-HTTP-ERROR-500-300x113.png 300w\" sizes=\"auto, (max-width: 466px) 100vw, 466px\" \/><\/a><figcaption><a>Figure <\/a>13: Failing invocation of the updated Azure Function, resulting in an HTTP ERROR 500<\/figcaption><\/figure>\n<\/div>\n\n\n<p>The reason is simple: the Azure Function still has no read access to the file in the Azure Storage Account. To reach this aim, we have to switch on the system-assigned managed identity for our Azure Function App \u201cFunctionApp26a\u201d. Go to this Function App and select \u201cIdentity\u201d in the menu bar to the left (Figure 14, A), change the status to \u201con\u201d (B), and save the change (C).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-14-Activating-system-assigned-managed-identity.png\"><img loading=\"lazy\" decoding=\"async\" width=\"433\" height=\"165\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-14-Activating-system-assigned-managed-identity.png\" alt=\"\" class=\"wp-image-1330\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-14-Activating-system-assigned-managed-identity.png 433w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-14-Activating-system-assigned-managed-identity-300x114.png 300w\" sizes=\"auto, (max-width: 433px) 100vw, 433px\" \/><\/a><figcaption><a>Figure <\/a>14: Activating system-assigned managed identity<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Now, we do one final reconfiguration add grant the function\u2019s managed identity read access to the storage account. Therefore, switch to the storage account \u201csta26a\u201d (Figure 15, A), open \u201cAccess Control (IAM)\u201d (B), and click on \u201cadd role assignment\u201d (C).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-15-Preparing-to-assign-roles.png\"><img loading=\"lazy\" decoding=\"async\" width=\"446\" height=\"202\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-15-Preparing-to-assign-roles.png\" alt=\"\" class=\"wp-image-1331\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-15-Preparing-to-assign-roles.png 446w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-15-Preparing-to-assign-roles-300x136.png 300w\" sizes=\"auto, (max-width: 446px) 100vw, 446px\" \/><\/a><figcaption><a>Figure <\/a>15: Preparing to assign roles<\/figcaption><\/figure>\n<\/div>\n\n\n<p>On the next mask, search for the \u201cStorage Blob Data Reader\u201d role and click on \u201cnext\u201d (Figure 16, A). On the next mask (B), select \u201cManaged Identity,\u201d click on \u201c+ Select members,\u201d and select \u201cFunctionApp26a\u201d. Then, click on \u201cSelect\u201d and \u201cReview + assign.\u201d<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-16-Assigning-a-role-to-an-Azure-Managed-Identity.png\"><img loading=\"lazy\" decoding=\"async\" width=\"593\" height=\"208\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-16-Assigning-a-role-to-an-Azure-Managed-Identity.png\" alt=\"\" class=\"wp-image-1332\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-16-Assigning-a-role-to-an-Azure-Managed-Identity.png 593w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-16-Assigning-a-role-to-an-Azure-Managed-Identity-300x105.png 300w\" sizes=\"auto, (max-width: 593px) 100vw, 593px\" \/><\/a><figcaption><a>Figure <\/a>16: Assigning a role to an Azure Managed Identity<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Now copy the Azure Function\u2019s URL again into a web browser. Be sure to retrieve the full URL, not just the beginning. If your URL looks like <em>https:\/\/functionapp26a.azurewebsites.net\/api\/Function1<\/em>, it will fail. It should look like <em>https:\/\/functionapp26a.azurewebsites.net\/api\/Function1?code=**SOME-STRAGE-CHARACTERS**==<\/em>. The result should look like Figure 17. If so, you made it. Time to celebrate!<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-17-Finally-what-you-should-see-at-the-end-of-the-tutorial.-The-Azure-Function-retrieves-text-from-the-Azure-Storage-Account-and-returns-it.png\"><img loading=\"lazy\" decoding=\"async\" width=\"354\" height=\"98\" src=\"http:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-17-Finally-what-you-should-see-at-the-end-of-the-tutorial.-The-Azure-Function-retrieves-text-from-the-Azure-Storage-Account-and-returns-it.png\" alt=\"\" class=\"wp-image-1333\" srcset=\"https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-17-Finally-what-you-should-see-at-the-end-of-the-tutorial.-The-Azure-Function-retrieves-text-from-the-Azure-Storage-Account-and-returns-it.png 354w, https:\/\/www.klaushaller.net\/wp-content\/uploads\/2022\/05\/Figure-17-Finally-what-you-should-see-at-the-end-of-the-tutorial.-The-Azure-Function-retrieves-text-from-the-Azure-Storage-Account-and-returns-it-300x83.png 300w\" sizes=\"auto, (max-width: 354px) 100vw, 354px\" \/><\/a><figcaption><a>Figure <\/a>17: Finally, what you should see at the end of the tutorial. The Azure Function retrieves text from the Azure Storage Account and returns it<\/figcaption><\/figure>\n<\/div>\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Serverless application logic, storage accounts, platform-as-a-service identity and access management, this small tutorial combines state-of-the-art Azure technologies in a four-step demo or tutorial. The result: a serverless Azure Function invoked via a web browser that returns a welcome text, which the Azure Function reads from an Azure Storage account using Azure Identity for authentication and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1313,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24,22,16,43],"tags":[44,45,46],"class_list":["post-1312","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","category-cloudsecurity","category-information-security","category-tutorial","tag-azure-function","tag-azure-storage-account","tag-managed-identity"],"_links":{"self":[{"href":"https:\/\/www.klaushaller.net\/index.php?rest_route=\/wp\/v2\/posts\/1312","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.klaushaller.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.klaushaller.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.klaushaller.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.klaushaller.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1312"}],"version-history":[{"count":4,"href":"https:\/\/www.klaushaller.net\/index.php?rest_route=\/wp\/v2\/posts\/1312\/revisions"}],"predecessor-version":[{"id":1334,"href":"https:\/\/www.klaushaller.net\/index.php?rest_route=\/wp\/v2\/posts\/1312\/revisions\/1334"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.klaushaller.net\/index.php?rest_route=\/wp\/v2\/media\/1313"}],"wp:attachment":[{"href":"https:\/\/www.klaushaller.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.klaushaller.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1312"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.klaushaller.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}