Rest API with Private Endpoint, exposed to API Management by Terraform

Welcome to the Networking Series in Azure!

Do you want to learn how to create a secure Rest API that is using a Private Endpoint for Azure SQL, KeyVault, Storage Account, and Container Registry exposed using API Management, managed by Terraform and Azure DevOps?  If the answer is yes, this article is for you!

As always in my blog, if you need only sources and know what you are doing, download them here. You find there Terraform sources, and pipelines for Azure DevOps. See also how to set parameters for Terraform: #set-params-for-terraform.

First of all, take a look at the architecture of the solution:

Rest API on APIM with Azure SQL, KeyVault, and Container Registry using Private Endpoints by Terraform

Architecture overview

All components are created by Terraform scripts, which you can find at top of the page.

The main idea of this solution is to create Rest API which can be reached only from API Management instance. What is more, databases, storage, and secrets have to remain private. No public access, because we want to keep data in our Virtual Network.

Architecture is built using three main components:

  • API Management – acts as a gateway to our Virtual network (VNET)
  • API services – Azure Function, App Service API SQL, App Service Sample API
  • Dependency services – Azure Key Vault, Azure SQL, Azure Container Registry, Azure Storage Account, and Azure Private DNS.

Application VNET and Azure DevOps VNET have links to Azure Private DNS, so they resolve private IP from Private Endpoint for these resources.

If you are interested in how to create a private endpoint in Terraform please jump to the #what-next section.

API services have IP restrictions set for two subnets:

  • Integration subnet
  • Azure DevOps subnet

So API services can be reached from the APIM instance or Self-hosted agent.

Accessing resources inside the network

If you need access to resources inside Virtual Network, you must deploy Virtual Machine, to one of these VNETs. However, it’s better to deploy the VM into Ado VNET, because it isn’t managed by Terraform.

Of course, you can create a VM in other VNET, but please remember to add a Virtual network link in the related Private DNS zones:

  • privatelink.azurecr.io
  • privatelink.blob.core.windows.net
  • privatelink.database.windows.net
  • privatelink.vaultcore.azure.net

Azure Key Vault, Azure Container Registry Managed Identity authentication

API Serivces use Managed Identity to access dependent services. All required permission is set up by Terraform.

If you need more details please reach #what-next section or review 03_Terraform_network_restrictions/2_terraform/modules/application_management/main.tf file from the repository.

Azure SQL enables Managed Identity

In order to enable Managed Identity for Azure SQL, you must run the below query, on the {your-server-name}-todo-db:

CREATE USER [MI_NAME] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [MI_NAME];
ALTER ROLE db_datawriter ADD MEMBER [MI_NAME];
ALTER ROLE db_ddladmin ADD MEMBER [MI_NAME];

Where:

MI_NAME – stands for Managed identity name, if you set MI for some service, the name will be just equal to the name of that service 🙂

You must run the above query, for each Managed Identity accessing your database.

In the Terraform script, you must provide the Azure Active Directory Administrator name. Using this account, you can log in to Azure SQL and run queries.

Set params for Terraform

In the file 03_Terraform_network_restrictions/2_terraform/environment/dev/dev.tfvars you can find parameters for Terraform.

If you don’t know how to setup Terraform in Azure, please go to the https://azureway.cloud/terraform-deploy-pipeline-in-azure-devops

environment              = "" 
applicationName          = ""
locationShortName        = ""
location                 = ""

service_plan_sku         = ""

administrator_name       = ""
administrator_object_id  = ""
administrator_email      = ""
ado_resource_group       = ""
ado_virtual_network_name = ""
ado_subnet_name          = ""
  • environment – name of your environment, used to generate names for the resources
  • applicationName – name of your application, used to generate names for the resources
  • locationShortName and location – location where you want to create resources
  • service_plan_sku – SKU for service plan used in API services
  • administrator_name – name of the administrator
  • administrator_object_id – object Id of the administrator, can be found in the Azure Active Directory
  • administrator_email – administrator email
  • ado_resource_group – resource group where you created a Self-hosted agent
  • ado_virtual_network_name, ado_subnet_name – VNET and subnet name where you created a Self-hosted agent

Only administrator account have access to the Azure SQL, so be sure you set the proper one.

Additionally, the name of the VNET where you created a Self-hosted agent is needed, because Terraform will create peering for the ado virtual network and application virtual network.

What next?

In this article, I explained how resources are isolated on the network level and how easily you can set up Managed Identity authentication.

However, this is only part of the solution, the whole solution contains the:

If you have any suggestions please leave a comment or use the contact form!

Leave a Reply

Your email address will not be published. Required fields are marked *