The purpose of todays blog is to walk through the process of enabling and connecting to an Azure Storage account via a Private Endpoint.
Private Endpoints for Azure Services are great as they allows us to ensure that traffic to required Storage account is kept internal to Azure for both security and efficiency.
Create a Storage Account
In this example I will be creating a new Storage Account which will be used to configure the Private Endpoint.
Firstly, create a new Storage Account Resource. Fill in the Resource Group, Storage Account Name and Location as required.
I will select the Account Kind as StorageV2, and as this Storage Account is only for testing I will configure it as LRS for its replication settings
The Private Endpoint can be created at this point. However, for this example I will skip this now as I want to show how you would add an Private Endpoint to an existing Storage Account. Therefore, leave the Connectivity method on Public Endpoint.
On the Data Protection blade configure your settings as required. I am going to skip this and leave all features off at this time.
Same for the Advanced blade. I will leave default settings.
Finally, set any required Tags
Check the settings on the Review + Create blade and if all okay click Create.
After a few minutes we should have a nice newly created Storage Account.
Configure Private Endpoint
Now we have a Storage Account created we can get on with configuring the Private Endpoint.
To do this we must open the Storage Account in the Portal and click the Networking tab.
Once this has loaded we need to click the + Private endpoint button.
On the Create a private endpoint screen select the Resource Group and a suitable name and location for the Endpoint.
We now need to select the service that this Private Endpoint will serve.
For this example we need to select Microsoft.Storage/storageAccounts for the Resource Type. With the Resource being the relevant Storage account (in my case tigheprivateendpoint).
Finally, the Target sub-resource needs to be set to file (this can be set to other storage services if needed like Blob)
Next, select the network that this Private Endpoint will be deployed into. This is the network that will natively have access to the service. Set this to the network hosting the service that require this access.
We also need to configure Private DNS Integration this is the creation of a Private Link between the Storage Account and an Azure Private DNS Zone containing the the requisite DNS records for connection.
This is required for allow connectivity to the Private Endpoint.
Again, Tag as required.
Finally, review the settings and then click Create
Configuring DNS Resolution
There are a number of configurations for the DNS resolution of Private Endpoint. I am going to focus on the 2 main cases I have come across.
Azure Only Infrastructure with Azure DNS
This scenario is mostly likely going to be used for small test bed/development environments. In this case all servers and application services are run in Azure, with all DNS resolution being through the Azure provided DNS services.
This is the easiest form of Private Endpoint to configure as it will not actually need ANY changes to work.
DNS resolution will be going through Azure as standard and is shown as in the below Microsoft diagram.
In our case we will resolve tigheprivateendpoint.file.core.windows.net. This request will go via the Azure DNS services and a CNAME for tigheprivateendpoint.privatelink.file.core.windows.net will be returned.
Azure will then query this address and will resolve to our Private DNS zone where the internal IP will be returned.
Azure and On-Premise Infrastructure with Custom DNS (AD etc)
This configuration is one that most people will have in some form.
In this case the Server and Application workload is hosted in a hybrid manner between both Azure and On-Premises. In this case rather that using Azure for DNS a custom DNS provider is deployed. In most cases (and indeed ours) this will be Active Directory.
In this environment there is a new step that must be included in order for the network resources to resolve the Private Endpoint internal IP address.
We can see the example for this configuration below:
We can see that the Client VM is using the DNS forwarder machine for its DNS resolution. In our case this would be an Active Directory Domain Controller.
So, in order for this machine to resolve the internal IP for the Private Endpoint we need to ensure the Domain Controller is able to query Azure DNS.
If the Domain Controller is hosted in Azure then we can complete this process quite simply by adding a Server Level DNS forwarder to DNS on the Domain Controller.
The forwarder must be set to 188.8.131.52 this is the Azure DNS server IP.
This is a static IP and will NOT change.
With the Server Forwarder in place any DNS request that cannot be resolved (such as the tigheprivateendpoint.privatelink.file.core.windows.net address) will be sent to Azure DNS for resolution.
Azure DNS will then resolve the internal IP from the Private DNS zone.
If the Domain Controller is situated On-Premises and we are connected by VPN/Express Route, then we must provision an Azure based Domain Controller (or another form of DNS Proxy) and configure as above.
We then need to add a conditional forwarder to the On-Premises Domain Controller
This is due to the fact the On-Premises Domain Controller will not be able to resolve the Azure DNS IP correctly. Therefore, we need to ensure requests are forwarded to the Azure based DNS server.
Therefore, we must look to add a Conditional Forwarder to the On-Premises DNS server. This conditional forwarder will needs to be configured to redirect the requests for the required service. In our case it will be file.core.windows.net.
This Conditional Forwarder should resolve to the IP of the Azure based Domain Controller. It is important that you put the forward as the relevant service URL NOT the privatelink.file.core.windows.net. This is highlighted in the Microsoft documentation Azure Private Endpoint DNS configuration | Microsoft Docs.
In the Conditional Forwarder below I have set file.core.windows.net to point to 10.0.0.5 for DNS resolution.
Once you have configured the DNS resolution as per your needs, we need to test that the the Private Endpoint is working as we would expect.
To test we need to log onto a machine within the network. The DNS resolution must have been setup to ensure the Azure DNS is handling the privatelink.file.core.windows.net resolution. Whether this is direct using Azure DNS on the VMs or via a Custom DNS.
Once we are sure this is configured open up a Command Prompt on the test machine.
Run a simple NSLOOKUP <SAname>.file.core.windows.net command to check the resolution returns the private link IP.
We should see that the DNS answer returned is tigheprivateendpoint.privatelink.file.core.windows.net and will resolve to the internal private link IP. In this case 10.0.4.4
If however, I run this from a public machine not within the realms of our configured DNS resolution I will see the below:
In this case the public IP address of the storage account is returned.
We can also check that connections to the file share are indeed going through the Private Endpoint.
First, I need to ensure I have a container to connect to. In the portal under the Storage Account. I need to select the File Shares tab.
Then select + File share and give a relevant name. In this case test. Select the Quota and Tiers as required, and click Create.
Once the share has been completed we need to test the connectivity. To do this I will map the File Share to a drive using
net use j: \tigheprivateendpoint.file.core.windows.net\test /user:Azure\tigheprivateendpoint <account key>
The share should successfully mapped.
Now we can check that the connection has been correctly passed through the Private Endpoint.
Run a netstat -ano | findstr 445 to view all connections using the SMB port 445.
As we can see above there is an established connection between the machine 10.0.0.6 and the file share via its Private Endpoint on 10.0.4.4
Removing Public Access
Now we have configured the Private Endpoint we can remove the public access to the Storage Account if we want to completely lock it down.
This is achieved via the Networking tab of the Storage Account.
Change the Allow access from to Selected networks then click + Add existing virtual network.
Next select the relevant networks you wish to have access to this Storage Account and click Add
Lastly, ensure you click Save to save the Network settings.
Now if we attempt to connect from a external machine we will get an Access denied message.
But we will still be able to connect from the internal network and we can see the traffic is still internally routed through the Private Endpoint.
Hopefully, this has shown how we can utilize the Azure Private Endpoints to secure connections to Azure Storage accounts.
DNS Resolution images were originally from the following Microsoft article: Azure Private Endpoint DNS configuration | Microsoft Docs.