Multiple Service Endpoints to multiple services

Use case: I have a central thingy that needs to talk to a service protected by a service endpoints (e.g. storage account, Azure SQL DB, Azure Maria DB, etc.). That service is also accessible to another compute in other Virtual Networks.

Is that possible?

Just to make it a little more concrete, let’s give an example. Let’s say I have a CI/CD agent (e.g. Azure DevOps agent) in a VNET. My CI/CD needs to access a database protected by Service Endpoint (e.g. to deploy some DB scripts). That database also needs to be accessed by a web server in another VNET.

In this article, I’ll demonstrate this to be possible and easy. We’ll deploy something demonstrating that.

As usual, the code is in GitHub.

Mental Model

The reason the scenario above might seem hard or impossible is a misconception of Service Endpoints in Azure.

We often have the following model for a service endpoint:

Mental Model (wrong) (Typical mental model: Wrong!)

We think a Service Endpoint puts an Azure PaaS service inside a VNET. It doesn’t.

The PaaS service still is outside our VNET. Service Endpoints simply add a networking filter on the service to accept inbound connection from certain subnets.

So, it’s not about injecting the PaaS inside a subnet. It’s about allowing only some subnets access to the PaaS.


Let’s demonstrate the scenario above with a simplified solution:

demo solution

Here we have three (3) storage accounts accessed by three (3) applications in three (3) separate VNETs. We also have an Azure Container Instance (ACI), representing our CI/CD, sitting in another VNET. That ACI is granted access to two (2) of the storage account but not the third one.

We see here the storage accounts aren’t in any VNET. Two of them are accessed by compute in different VNETs.

As a note, we use ACI because it’s easy & quick to deploy. Also, ACI does get injected inside a Virtual Network. Therefore, the Service Endpoints rule will apply to it.


Let’s deploy that solution using our ARM template:

Deploy button

It is important to deploy the solution in one of the following regions: EastUS2EUAP, CentralUSEUAP, WestUS, WestCentralUS, NorthEurope, WestEurope, EastUS or AustraliaEast. This is because those are the only regions where ACI integration with VNETs are currently (as of mid April 2019) available.

The only parameter is storage-prefix. This is used to prefix the three (3) storage account. This needs to be unique throughout Azure and be compatible with a storage account name, i.e. lowercase and no special characters.

Looking at deployment

Let’s look at the deployment. We should have the following resources corresponding to the diagram:


The three VNETs app-a, app-b & app-c do represent the “normal workloads” (although they not have actual compute in them) while central-vnet represents our CI/CD or whatever secondary workload. central-aci is deployed within central-vnet, hence will be able to give us the perspective of a workload running in that VNET.

There are three storage accounts.

Now if we look at all the subnet, we’ll find they have enabled service endpoints for Microsoft.Storage:


If we look at the storage accounts now, we see the subnets they allow to pass. For instance, for the ‘a’ storage account:

Storage Account service endpoint

We have a similar picture for the ‘b’ storage account. For the ‘c’ account though, only the app-c VNET has an allowed subnet:


This means that the central-vnet’s subnet should have access to ‘a’ & ‘b’ but not ‘c’.

Testing access

We could easily test the access. Sitting in central-vnet we could simply curl to the storage REST API.

Actually, this is exactly what we did by deploying three containers in ACI curling to the three different storage account.

We can look at the logs of the containers and see that witness-a received an empty list of blobs (we are listing the blobs in a blob container):

Curl storage A

witness-b is similar while witness-c receives an authorization error:

Curl storage C

So we proved that we can access a multi-tenant PaaS resource (e.g. Storage account, Azure SQL DB, etc., here for an up-to-date list) from different VNETs using different service endpoints.

Technically, we didn’t show that a compute sitting in the *app-** would have access to their respective storage. We leave that as an exercise to the reader!


What is the RBAC model for Security endpoints?

This is well explained in the online documentation.


We did dive a little bit into Azure Service Endpoints.

We saw that it isn’t the same thing as injecting a PaaS service in a subnet. Instead, it is about authorizing compute in a given subnet to access a PaaS service.

Given that, multiple compute from different VNETs can access the same PaaS service.

Those VNETs do not need to be peered together. In the demo we did, the VNETs were even made of identical IP ranges (hence couldn’t be peered).

Leave a comment