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:
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:
- Architecture creation using Terraform scripts – you just read it!
- Efficient terraform modules structure
- Build a docker image in a self-hosted agent running on Azure Container Instances
- Execute entity framework migration on a Linux
- Setup Azure DevOps with Self-hosted agents and VNET
- Deploy Azure Function and expose it using API Management
- Deploy Azure App Service integrated with Azure SQL and APIM
- Coming soon – Deploy sample App Service for Containers and API Management integration
If you have any suggestions please leave a comment or use the contact form!