App Service to Storage Account Connection Condition Summary
Published Nov 15 2021 11:02 PM 12.1K Views
Microsoft

Currently, there are 4 main conditions the Azure App Service can connect to Azure Storage Account. 

  • Condition 1: App Service (Public ) --> Storage Account (Public, Same region)
  • Condition 2: App Service (Public ) --> Storage Account (Public, Different region)
  • Condition 3: App Service (Regional Vnet Integration) --> Storage Account (Private, Service Endpoint )
  • Condition 4: App Service (Regional Vnet Integration) --> Storage Account (Private, Private Endpoint)

 

Before going deeper, here is a brief summary for your to choose the suitable design for your system.

Requirements:

  • If your security require the Firewall on the Storage Account. And the Storage Account and Azure App Service are in the same region.

          --> Use the above Condition 3 for 4 for your design.

  • If your security require the Firewall on the Storage Account. And the Storage Account and Azure App Service are in the different region.

         --> Use the Condition 1 or Condition 4 for your design. When you would like to make the connection private, use the Condition 4.

 

For the deeper analysis for the above 4 conditions, please see following:

Background knowledge:

============

Azure Storage Account Network restricting logic is different from the Azure App Service.

Even when we configured the Network restricting from the Azure Storage Account side, the tcpping will still working well like this:

Boqian_13-1637044755386.png

 

And the "List" request to the Azure Storage Account will not be locked.

 

In order to verify if the Network Restricting is working or not, you can use the script to upload a file to Azure Storage Account to test. I am using the code:

<?php

 

$accesskey = "xxxx";

$storageAccount = 'xxxx';

$filetoUpload = realpath('xxxx');

$containerName = 'xxxx';

$blobName = 'xxxx';

 

$destinationURL = "https://$storageAccount.blob.core.windows.net/$containerName/$blobName";

 

function uploadBlob($filetoUpload, $storageAccount, $containerName, $blobName, $destinationURL, $accesskey) {

 

    $currentDate = gmdate("D, d M Y H:i:s T", time());

    $handle = fopen($filetoUpload, "r");

    $fileLen = filesize($filetoUpload);

 

    $headerResource = "x-ms-blob-cache-control:max-age=3600\nx-ms-blob-type:BlockBlob\nx-ms-date:$currentDate\nx-ms-version:2015-12-11";

    $urlResource = "/$storageAccount/$containerName/$blobName";

 

    $arraysign = array();

    $arraysign[] = 'PUT';               /*HTTP Verb*/ 

    $arraysign[] = '';                  /*Content-Encoding*/ 

    $arraysign[] = '';                  /*Content-Language*/ 

    $arraysign[] = $fileLen;            /*Content-Length (include value when zero)*/ 

    $arraysign[] = '';                  /*Content-MD5*/ 

    $arraysign[] = 'image/png';         /*Content-Type*/ 

    $arraysign[] = '';                  /*Date*/ 

    $arraysign[] = '';                  /*If-Modified-Since */ 

    $arraysign[] = '';                  /*If-Match*/ 

    $arraysign[] = '';                  /*If-None-Match*/ 

    $arraysign[] = '';                  /*If-Unmodified-Since*/ 

    $arraysign[] = '';                  /*Range*/ 

    $arraysign[] = $headerResource;     /*CanonicalizedHeaders*/

    $arraysign[] = $urlResource;        /*CanonicalizedResource*/

 

    $str2sign = implode("\n", $arraysign);

 

    $sig = base64_encode(hash_hmac('sha256', urldecode(utf8_encode($str2sign)), base64_decode($accesskey), true)); 

    $authHeader = "SharedKey $storageAccount:$sig";

 

    $headers = [

        'Authorization: ' . $authHeader,

        'x-ms-blob-cache-control: max-age=3600',

        'x-ms-blob-type: BlockBlob',

        'x-ms-date: ' . $currentDate,

        'x-ms-version: 2015-12-11',

        'Content-Type: image/png',

        'Content-Length: ' . $fileLen

    ];

 

    $ch = curl_init($destinationURL);

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");

    curl_setopt($ch, CURLOPT_INFILE, $handle);

    curl_setopt($ch, CURLOPT_INFILESIZE, $fileLen);

    curl_setopt($ch, CURLOPT_UPLOAD, true);

    $result = curl_exec($ch);

 

    echo ('Result<br/>');

    print_r($result);

 

    echo ('Error<br/>');

    print_r(curl_error($ch));

 

    curl_close($ch);

}

 

uploadBlob($filetoUpload, $storageAccount, $containerName, $blobName, $destinationURL, $accesskey);

 

Preparation:

============

  1. Write code to upload the file to Azure Storage Account for testing as mentioned in above. Create xxx.php file under the wwwroot folder for testing.
  2. Enable the "Diagnostic settings" from Azure Portal

      Boqian_14-1637044755389.png

 

Test:

============

Condition 1:  App Service (Public ) --> Storage Account (Public, Same region)

By Default, Azure App Service can access the Storage Account and upload the files.

 

But if we enable the Firewall settings under the Networking blade of Storage Account, and add the Azure App Service Outbound IP to the whitelist like following screenshot, the Azure App Service will still not able to access Azure Storage Account.

Boqian_15-1637044755391.png

 

If we check the Azure Storage Account log, we will see the Azure App Service was trying to use an internal IP (100.x.x.x) to access the Storage Account. Not using the Azure App Service public outbound IP:

Boqian_16-1637044755393.png

Why? 

I discussed this behavior with the Azure Storage Account and Azure App Service Product Group, and the result showed if the Azure App Service and Azure Storage Account are in the same datacenter, they did some optimization, so the Azure App Service will always reach the Storage Account via the fastest route, so the resource IP (Azure App Service) observed from Azure Storage Account could be an un-predicted IP (could start with 100.x.x.x or 10.x.x.x or other others) and this IP could  change at any time.

 

Question:

Considering the resource IP from Azure App Service looks like start with 100.x.x.x for now, if I whitelist the 100.0.0.0/8 in the Azure Storage Account, will the Azure App Service can upload the file on it?

Answer:

Yes it will make the Azure App Service can access the Storage Account for now. But cannot promise it will always work, it is a not officially support scenery.

Because the IP could change to 10.x.x.x and some other un-predicted IPs. Another thing is, the x.0.0.0/8 is a huge range, so it is not a good design. 

Boqian_17-1637044755414.png

 

If you would like to enable the Firewall in the Azure Storage Account and would like to make sure the Azure App Service in the same region still could access this Storage Account, please see the details in the Condition 3 and Condition 4.

 

Condition 2: App Service (Public ) --> Storage Account (Public, Different region)

As we can see in the Azure Storage Account log, the Azure App Service is using the public IP accessing the Azure Storage Account (13.x.x.x is one of the public outbound IP of my test Azure App Service. )

And you can enable the Firewall on Azure Storage Account and whitelist all the Azure App Service outbound IP (Inbound/Outbound IP addresses - Azure App Service | Microsoft Docs). That will make sure the Azure App Service can always access the Storage Account.

Boqian_18-1637044755396.png

 

Condition 3: App Service (Regional Vnet Integration) --> Storage Account (Private, Service Endpoint )

  1. Create Vnet Integration from Azure App Service to Azure Vnet Subnet.
  2. Make sure the "Microsoft.Storage" is enabled as Service Endpoint for the Subnet that App Service is integrated with.

  Boqian_19-1637044755398.png

 

  1. Make sure the "Route All" is enabled for the Vnet Integration:

    Boqian_20-1637044755400.png

 

Configure Azure Storage firewalls and virtual networks | Microsoft Docs

Boqian_21-1637044755402.png

 

After doing above, if we check the Azure App Service resource IP, it will be one of the IP under the Vnet Subnet:

Boqian_22-1637044755403.png

 

Condition 4: App Service (Regional Vnet Integration) --> Storage Account (Private, Private Endpoint)

Similar configuration as the Condition 3, but please make sure:

  1. Disable the Service Endpoint on the Vnet Subnet.
  2. Create Private Endpoint on the Storage Account side.
  3. Make sure the Storage Account FQDN could be resolved to private endpoint IP from Azure App Service:

Boqian_23-1637044755405.png

 

We can see the similar private IP records as we saw when using the Service Endpoint.

Boqian_24-1637044755407.png

 

But the different between the condition 3 is the Private Endpoint support cross region traffic , and the Service Endpoint only support the connection from the Azure App Service in the same region.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Co-Authors
Version history
Last update:
‎Nov 16 2021 05:47 PM
Updated by: