Setting up and using private endpoints in Azure with a storage account example in Terraform

Azure Private endpoints have been around for some time, in this blog post I will be looking at how to setup and begin using them – will also include a storage account example in Terraform. As your cloud environment continually grows, security is and should be pretty much top priority and utilising private endpoints will only assist with this.

What are Azure Private Endpoints?

In theory, a private endpoint connects to specific Azure services and allow you to communicate with that associated service over a private link within the Azure network, mitigating the need to access publicly and removing any potential public access. This means that data transfer between your virtual network and the Azure service travels over the Microsoft backbone network, ensuring that your data remains within the Azure network and doesn’t traverse the public internet.

A private endpoint is a network interface that uses a private IP address from your virtual network. This network interface connects you privately and securely to a service that’s powered by Azure Private Link. By enabling a private endpoint, you’re bringing the service into your virtual network.

docs.microsoft.com

Benefits of using Azure Private Endpoints

As you expect, quite a number of security related benefits when you use private endpoints

  1. Reducing exposure to your network: Minimising attack services and potential vulnerabilities that can happen when the service is publicly accessible
  2. Enhanced security: Connectivity to the service remains isolated from the public internet
  3. Even more granular control: You can manage access to the service(s) even more granular, controlling which VNets and subnets have access
  4. Potential to increase performance: Private endpoints can offer lower latency than when going via public internet
  5. Increase compliance: Helps with compliance efforts, data remains within your Azure network

What Azure Resources can I configure with a private endpoint?

Quite a few Azure resources support this functionality and you can also use your own service by using Azure Private link service, more on that here

Potential use cases for using Azure Private endpoints

The list of potential use cases can be near endless, some examples to get you thinking into how private endpoints can assist:

  1. Accessing Azure Storage Accounts
  2. Database access
  3. Your own private service utilising Azure Private link
  4. Hybrid connectivity from on-premise to an Azure service using the likes of express route / VPN to your Azure VNet

Azure Storage account private endpoint setup using Terraform

Now that we’ve covered a brief overview of private endpoints and benefits, I will show an example usage of configuring an Azure Storage Account with private endpoint that can be accessed within an Azure VNet – removing the potential for any public access.

The below diagram gives a high-level overview

Azure Diagram showing the use of Azure Storage Account private endpoint.

As part of this tutorial, I already have configured:

  • Azure Virtual network: tamops01-vnet
  • Subnet1: default which the Virtual Machine is deployed into
  • Subnet2: endpoints which will be used to deploy the storage account private endpoint
  • Virtual Machine: tamops01 which will be used to test storage account connectivity

Azure Private DNS Zone

Firstly for private endpoints and their associated DNS to work correctly a private DNS zone is required, this zone name can vary in its required name, I have linked the associated documentation to assist with this.

resource "azurerm_private_dns_zone" "private_dns_zone" {
  name                = "privatelink.blob.core.windows.net"
  resource_group_name = data.azurerm_resource_group.rg.name
}

resource "azurerm_private_dns_zone_virtual_network_link" "vnet_link" {
  name                  = "vnetlink"
  resource_group_name   = data.azurerm_resource_group.rg.name
  private_dns_zone_name = azurerm_private_dns_zone.private_dns_zone.name
  virtual_network_id    = data.azurerm_virtual_network.vnet.id
}

What the above Terraform does:

  • Creates an Azure Private DNS zone: privatelink.blob.core.windows.net
  • Associates the private DNS zone with the already created VNet to allow for private DNS to work correctly

Azure Storage Account with Private endpoint

Now that the private dns zone is configured, lets create a storage account and its associated private endpoint , along with this a DNS record so you can correctly communicate with the storage account inside your VNet. Similar to the documentation linked above, you will notice private_service_connection references a subresource_names and associates to the correct private DNS zone using private_dns_zone_group

# create storage account with blob storage
resource "azurerm_storage_account" "storage_account" {
  name                      = "tamopsstorageaccount"
  resource_group_name       = data.azurerm_resource_group.rg.name
  location                  = data.azurerm_resource_group.rg.location
  account_tier              = "Standard"
  account_replication_type  = "LRS"
  enable_https_traffic_only = true
}

resource "azurerm_private_endpoint" "private_endpoint" {
  name                = "storage-endpoint"
  location            = data.azurerm_resource_group.rg.location
  resource_group_name = data.azurerm_resource_group.rg.name
  subnet_id           = data.azurerm_subnet.endpoint.id

  private_service_connection {
    name                           = "storage-endpoint-connection"
    private_connection_resource_id = azurerm_storage_account.storage_account.id
    subresource_names              = ["blob"]
    is_manual_connection           = false
  }

  private_dns_zone_group {
    name                 = "storage-endpoint-connection"
    private_dns_zone_ids = [azurerm_private_dns_zone.private_dns_zone.id]
  }

  depends_on = [
    azurerm_storage_account.storage_account
  ]
}

resource "azurerm_private_dns_a_record" "storage_account" {
  name                = "storageaccount"
  zone_name           = "privatelink.blob.core.windows.net"
  resource_group_name = data.azurerm_resource_group.rg.name
  ttl                 = 300
  records             = [azurerm_private_endpoint.private_endpoint.private_service_connection.0.private_ip_address]
}

What the above Terraform does:

  • Create an storage account: tamopsstorageaccount
  • Creates private endpoint: storage-endpoint
  • Adds private DNS record storageaccount to the private DNS zone privatelink.blob.core.windows.net

Reviewing the private DNS zone, we can see a new A record with associated IP belonging to the subnet endpoints

Reviewing the private endpoint configuration, we can see the associated configuration

Testing the setup

Logging into the virtual machine, I can now test successfully the storage account is accessible via the private endpoint

We can see it returns the associated private IP address rather than a public IP for the storage account

Conclusion

Lets finish up, private endpoints provide a robust solution to keep your data safe and your applications performing optimally. Whether you’re dealing with databases, storage, or hosting applications, the adoption of Azure Private Endpoints is a critical step towards securing your Azure infrastructure.

By incorporating these endpoints into your architecture, you can enjoy enhanced security, compliance, and control over your data flows, ensuring the privacy and integrity of your critical resources. So, go ahead, explore the capabilities of private endpoints, and elevate your Azure infrastructure to the next level of data security.

Leave a Reply