implement private access to azure services : virtual network service endpoints

In your organization there are scenarios where you require private access to services hosted on the Azure platform where you need to eliminate data exposure to the public internet and reduce the attack surface.

So, when deploying Azure Pass Services, you will need to restrict network accees to VNET through the use of virtual network service endpoint or private link.

In this tutorial I will design and implement a virtual network service endpoint .

Virtual Network (VNet) service endpoint provides secure and direct connectivity to Azure services over an optimized route over the Azure backbone network. Endpoints allow us to secure our critical Azure service resources to only your virtual networks. Service Endpoints enables private IP addresses in the VNet to reach the endpoint of an Azure service without needing a public IP address on the VNet. https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-service-endpoints-overview

Service Endpoints doesn’t remove the public endpoint, it provides a redirection of traffic.

To implement a service enpoint we should desable the public access to the ressource and add a service enpoint to a virtual network or subnet.

SCENARIO

Consider the followng scenario :

My company is implementing an file management system using Asp.Net core web api hoted on azure appservice and an azure blog storage.

Then the files and blobs must only be accessible from computers located in a Databases subnet inside my corporate network.

Then computers inside my corporate network and located in another subnet than database subnet should not be able to connect to the storage account.

I will create a virtual network Service Endpoint for Azure Storage to secure the connectivity to my storage accounts.

The virtual network will contains 2 subnets : a databaseSubnet and a webApiSubnet .

So I will create a virtual network Service Endpoint for Azure Storage on the Databases subnet and verify that my DataServer VM can access Azure Storage. But the WebApiServer VM, which is on a different subnet, can’t access storage.

CREATE AN AZURE STORAGE ACCOUNT AND A FILESHARE

The following powershell script will create an azure storage account logcorner07092022 ( you should choose a different name) in a resource group virtual-network-service-endpoints and create a fileshare blog-file-share

$resourceGroup = "virtual-network-service-endpoints"
$storageAcctName="logcorner07092022"
$fileShareName="blog-file-share"
$location="westeurope"

az group create `
  --name $resourceGroup `
  --location $location
  
# Create an Azure storage account
az storage account create `
  --name $storageAcctName `
  --resource-group $resourceGroup `
  --sku Standard_LRS `
  --kind StorageV2

# retrieve the connection string for the storage account into a variable 
$saConnectionString=$(az storage account show-connection-string `
  --name $storageAcctName `
  --resource-group $resourceGroup `
  --query 'connectionString' `
  --out tsv)

  Write-Host $saConnectionString

# Create a file share in the storage account

az storage share create `
  --name $fileShareName `
  --quota 2048 `
  --connection-string $saConnectionString 


DOWNLOAD AZURE STORAGE EXPLORER

Download and install the azure storage explorer tool to test that we can cannot and upload file to the filshare

https://azure.microsoft.com/en-us/products/storage/storage-explorer/

Go to the azure portal and search for your storage account deployed previously ,  and click the file share blad

upload a file

Open the storage account and select Access keys and copy the connection string

Launch the storage account explorer installed previously and right click Storage Accounts blade, select Connect to storage Accounts, and select Storage account or service

Choose Connection string and paste the connection string copied previouly and connect

When the connection id stablished, you can upload a file and the uploaded file should appear to the azure portal

CREATE A VIRTUAL NETWORL WITH 3 SUBNETS : DATABASE, WEBAPI AND AZURE BASTIONHOST

Now let us create a virtual network that contains 3 subnets : WebApiSubnet , DatabaseSubnet and AzureBastionSubnet

$resourceGroup = "virtual-network-service-endpoints"
$virtualNetworkName="logcorner-vnet"

# Create a virtual network with a WebApiSubnet subnet and a DatabaseSubnet and a AzureBastionSubnet.
  az network vnet create `
  --name $virtualNetworkName `
  --resource-group $resourceGroup `
  --address-prefix 10.0.0.0/16 
 
# Create WebApiSubnet subnet
  az network vnet subnet create `
  --vnet-name $virtualNetworkName `
  --resource-group $resourceGroup `
  --name "WebApiSubnet" `
  --address-prefix 10.0.1.0/24 

# Create DatabaseSubnet subnet
  az network vnet subnet create `
  --vnet-name $virtualNetworkName `
  --resource-group $resourceGroup `
  --name "DatabaseSubnet" `
  --address-prefix 10.0.2.0/24 
  

 # Create AzureBastionSubnet subnet
    az network vnet subnet create `
    --vnet-name $virtualNetworkName `
    --resource-group $resourceGroup `
    --name "AzureBastionSubnet" `
    --address-prefix 10.0.3.0/26 

CREATE A DATABASE SERVER A WEPAPI SERVER AND AN AZURE BASTION HOST

Next , let us create a database server in the DatabaseSubnet , a web api server in the WebApiSubnet and an azure bastion host to connect to servers via rdb using the portal

$resourceGroup = "virtual-network-service-endpoints"
$virtualNetworkName="logcorner-vnet"
$DatabaseSubnet="DatabaseSubnet"
$WebApiSubnet="WebApiSubnet"

# Create a VM in the Public subnet 

az vm create `
  --resource-group $resourceGroup `
  --image "Win2019Datacenter" `
  --name "webApiServer" `
  --vnet-name $virtualNetworkName `
  --public-ip-sku Standard `
  --subnet $WebApiSubnet `
  --admin-username 'username' --admin-password 'Password123!'


# Create a VM in the private subnet (DatabaseSubnet)

az vm create `
  --resource-group $resourceGroup `
  --image "Win2019Datacenter" `
  --name "dataBaseServer"  `
  --vnet-name $virtualNetworkName `
  --public-ip-sku Standard `
  --subnet $DatabaseSubnet `
  --admin-username 'username' --admin-password 'Password123!'


  # Create a public IP address for Azure Bastion. The public IP is the public IP address the Bastion resource on which RDP/SSH will be accessed (over port 443). The public IP address must be in the same region as the Bastion resource you're creating.
  $publicPip='AzureBastionPip'
  $sku ='Standard'
  az network public-ip create --resource-group $resourceGroup --name $publicPip --sku  $sku 

# Create a new Azure Bastion resource in the AzureBastionSubnet of your virtual network
 $AzureBastionName='AzureBastionLogCorner'
  az network bastion create --name $AzureBastionName --public-ip-address $publicPip --resource-group $resourceGroup --vnet-name $virtualNetworkName 

MOUNT A FILE SHARE TO WEBAPI AND DATABASE SERVERS USING THE AZURE BLOB STORAGE FILESHARE

To mount a azure file share , I should map a network drive and provide the following :

Folder = \\logcorner07092022.file.core.windows.net\blog-file-share where \\logcorner07092022.file.core.windows.net\blog-file-share is the file share url

username = storageAccountName in our case logcorner07092022

password = storageAccountKey

ENABLE VIRTUAL NETWORK SERVICE ENDPOINT

Let us implement a service enpoint to disable the public access to the storage account by adding a service enpoint to the DatabaseSubnet.

So only virtual machines on the DatabaseSubnet can access the stotage account

$resourceGroup = "virtual-network-service-endpoints"
$storageAcctName="logcorner07092022"
$virtualNetworkName="logcorner-vnet"

# assign the Microsoft.Storage endpoint to the subnet
az network vnet subnet update `
--vnet-name $virtualNetworkName `
--resource-group $resourceGroup `
--name "DatabaseSubnet" `
--service-endpoints "Microsoft.Storage"

# Deny all network access to a storage account
az storage account update `
  --name $storageAcctName `
  --resource-group $resourceGroup `
  --default-action Deny

# Enable network access from a subnet (Private)
az storage account network-rule add `
  --resource-group $resourceGroup `
  --account-name $storageAcctName `
  --vnet-name $virtualNetworkName `
  --subnet "DatabaseSubnet"



Navigate to the storage account networking section , we can observe that only traffic from DatabaseSubnet is allowed

You can no longer mount a file share from the webaapi server to connect to the blob storage fileshare.

HARDENING NETWORK TRAFFIC USING NETWORK SECURITY GROUP

$resourceGroup = "virtual-network-service-endpoints"
$virtualNetworkName="logcorner-vnet"
$databaseNetworkSecurityGroupName="DatabaseSubnetNSG"
$webApiNetworkSecurityGroupName="WebApiSubnetNSG"

# Create a network security group  for database subnet
az network nsg create `
  --resource-group $resourceGroup `
  --name $databaseNetworkSecurityGroupName

# Associate the network security group to the Private subnet  (database subnet)
az network vnet subnet update `
  --vnet-name $virtualNetworkName `
  --name "DatabaseSubnet" `
  --resource-group $resourceGroup `
  --network-security-group $databaseNetworkSecurityGroupName

# rule that follows allows outbound access to the public IP addresses assigned to the Azure Storage service:

az network nsg rule create `
  --resource-group $resourceGroup `
  --nsg-name $databaseNetworkSecurityGroupName `
  --name "Allow-Storage-All" `
  --access Allow `
  --protocol "*" `
  --direction Outbound `
  --priority 100 `
  --source-address-prefix "VirtualNetwork" `
  --source-port-range "*" `
  --destination-address-prefix "Storage" `
  --destination-port-range "*" `
  --description "Allow access to Azure Storage"

# Create another outbound security rule that denies communication to the internet

az network nsg rule create `
  --resource-group $resourceGroup `
  --nsg-name $databaseNetworkSecurityGroupName `
  --name "Deny-Internet-All" `
  --access Deny `
  --protocol "*" `
  --direction Outbound `
  --priority 110 `
  --source-address-prefix "VirtualNetwork" `
  --source-port-range "*" `
  --destination-address-prefix "Internet" `
  --destination-port-range "*"  `
  --description "Deny access to Internet."


  # Create a network security group for web api subnet
az network nsg create `
--resource-group $resourceGroup `
--name $webApiNetworkSecurityGroupName

# Associate the network security group to the public subnet

az network vnet subnet update `
  --vnet-name $virtualNetworkName `
  --name "WebApiSubnet" `
  --resource-group $resourceGroup `
  --network-security-group $webApiNetworkSecurityGroupName

  # Allow access to web api

  az network nsg rule create `
  --resource-group $resourceGroup `
  --nsg-name $webApiNetworkSecurityGroupName `
  --name "Allow-Web-All" `
  --access Allow `
  --protocol Tcp `
  --direction Inbound `
  --priority 100 `
  --source-address-prefix "*" `
  --source-port-range "*" `
  --destination-address-prefix "VirtualNetwork" `
  --destination-port-range 80 443 `
  --description "Allow access to web api"

DATABASE SUBNET NETWORK SECURITY GROUP

WEBAPISUBNET NETWORK SECURITY GROUP

Leave a Comment