<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Robbie</title>
    <description>The latest articles on Forem by Robbie (@rcoenmans).</description>
    <link>https://forem.com/rcoenmans</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F415869%2F0000864c-2226-44ba-81cd-cdb947324bdf.png</url>
      <title>Forem: Robbie</title>
      <link>https://forem.com/rcoenmans</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rcoenmans"/>
    <language>en</language>
    <item>
      <title>Azure API Management Standard v2 Secure Baseline</title>
      <dc:creator>Robbie</dc:creator>
      <pubDate>Tue, 13 Jan 2026 11:00:41 +0000</pubDate>
      <link>https://forem.com/rcoenmans/azure-api-management-standard-v2-secure-baseline-1f52</link>
      <guid>https://forem.com/rcoenmans/azure-api-management-standard-v2-secure-baseline-1f52</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This reference implementation demonstrates a secure baseline infrastructure architecture for provisioning Azure API Management Standard v2. Specifically this scenario addresses deploying Azure API Management with a &lt;a href="https://learn.microsoft.com/en-us/azure/api-management/integrate-vnet-outbound" rel="noopener noreferrer"&gt;private virtual network for outbound connections&lt;/a&gt; and a &lt;a href="https://learn.microsoft.com/en-us/azure/api-management/private-endpoint" rel="noopener noreferrer"&gt;private endpoint for inbound connections&lt;/a&gt;. This allows secure communication between Azure API Management and other services within the same virtual network, as well as secure access to Azure API Management from on-premises networks or other virtual networks.&lt;/p&gt;

&lt;p&gt;This is intended to be a starting point for those who want to deploy Azure API Management in a &lt;strong&gt;cost-effective&lt;/strong&gt; and &lt;strong&gt;secure&lt;/strong&gt; manner, following best practices for network isolation and access control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Only the API Management instance's &lt;strong&gt;Gateway endpoint&lt;/strong&gt; supports inbound Private Link connections.&lt;/li&gt;
&lt;li&gt;Connections aren't supported on the &lt;a href="https://learn.microsoft.com/en-us/azure/api-management/self-hosted-gateway-overview" rel="noopener noreferrer"&gt;self-hosted gateway&lt;/a&gt; or on a &lt;a href="https://learn.microsoft.com/en-us/azure/api-management/workspaces-overview#workspace-gateway" rel="noopener noreferrer"&gt;workspace gateway&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An active Azure subscription.&lt;/li&gt;
&lt;li&gt;The Owner &lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles" rel="noopener noreferrer"&gt;Azure built-in role&lt;/a&gt; or the User Access Administrator and Contributor built-in roles, on a subscription in your Azure account.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://learn.microsoft.com/en-us/cli/azure/install-azure-cli" rel="noopener noreferrer"&gt;Azure CLI&lt;/a&gt; version 2.61.0 or later.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; installed on one of the supported platforms along with the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-bicep" rel="noopener noreferrer"&gt;Bicep extension&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;An existing Azure Key Vault resource with a valid TLS certificate for the application gateway.&lt;/li&gt;
&lt;li&gt;An existing Azure DNS Zone or equivalent DNS server for the name resolution of the application gateway.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Frcoenmans%2Fappgw-apim-std-v2%2Frefs%2Fheads%2Fmaster%2Fdocs%2Fassets%2Farchitecture.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Frcoenmans%2Fappgw-apim-std-v2%2Frefs%2Fheads%2Fmaster%2Fdocs%2Fassets%2Farchitecture.png" alt="Architecture Diagram" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The solution architecture is designed as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Application Gateway handles TLS termination and communicates with API Management over HTTPS.&lt;/li&gt;
&lt;li&gt;The Application Gateway Listener utilizes an SSL certificate obtained from Azure Key Vault.&lt;/li&gt;
&lt;li&gt;The Azure WAF Policy associated to the Listener is used to run OWASP rules and custom rules against the incoming request and block malicous attacks.&lt;/li&gt;
&lt;li&gt;The Application Gateway Backend HTTP Settings are configured to invoke API Management via HTTPS on port 443.&lt;/li&gt;
&lt;li&gt;The Application Gateway Backend Pool and Health Probe are set to call the API Management's status endpoint.&lt;/li&gt;
&lt;li&gt;API Management is deployed with a dedicated subnet, ensuring that all outbound traffic is routed through the virtual network.&lt;/li&gt;
&lt;li&gt;A Private Endpoint is created for API Management, allowing secure inbound connections from the Application Gateway.&lt;/li&gt;
&lt;li&gt;Azure Key Vault is used to securely store the TLS certificate for the Application Gateway.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Message Flow
&lt;/h2&gt;

&lt;p&gt;The following diagram shows the steps for the message flow during deployment and runtime.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Frcoenmans%2Fappgw-apim-std-v2%2Frefs%2Fheads%2Fmaster%2Fdocs%2Fassets%2Fmessage-flow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Frcoenmans%2Fappgw-apim-std-v2%2Frefs%2Fheads%2Fmaster%2Fdocs%2Fassets%2Fmessage-flow.png" alt="Message Flow Diagram" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A security engineer generates a certificate for the custom domain that the workload uses and saves it in an Azure key vault.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A platform engineer specifies the necessary information in the &lt;code&gt;main.bicepparams&lt;/code&gt; Bicep parameters file and deploys the Bicep modules to create the Azure resources. The necessary information includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A prefix for the Azure resources.&lt;/li&gt;
&lt;li&gt;A location for the Azure resources.&lt;/li&gt;
&lt;li&gt;The name and resource group of the existing key vault that holds the TLS certificate for the Application Gateway custom domain.&lt;/li&gt;
&lt;li&gt;The name of the certificate in the key vault.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Application Gateway Listener is configured to use the TLS certificate from the key vault. This certificate is used by the custom domain that's associated with the Application Gateway endpoint. The Application Gateway uses a user-assigned managed identity to access the key vault and retrieve the TLS certificate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A developer can deploy APIs to App Services or other backend services that are secured with a private endpoint.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A developer or platform engineer can then publish those APIs to the API Management instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Runtime workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The client application calls the backend web application using its hostname and path. The DNS zone that's associated with the custom domain of the Application Gateway Listener uses an A record to resolve the DNS query with the addres of the Azure Public IP used by the Frontend IP Configuration of the Application Gateway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The request is sent to the Azure Public IP used by the Frontend IP Configuration of the Application Gateway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Application Gateway performs thw following actions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Application Gateway handles TLS termination and communicates with the backend application over HTTPS.&lt;/li&gt;
&lt;li&gt;The Azure WAF Policy associated to the Listener is used to run OWASP rules and custom rules against the incoming request and block malicous attacks.&lt;/li&gt;
&lt;li&gt;The Application Gateway Backend HTTP Settings are configured to forward the request to API Management via HTTPS on port 443.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Application Gateway Backend Pool forwards the request to API Management using its Private Endpoint.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API Management processes the request and forwards it to the corresponding backend web application. The request is sent over a private connection within the virtual network.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;p&gt;You can deploy the Bicep modules in the &lt;code&gt;infra&lt;/code&gt; folder using the &lt;code&gt;deploy.sh&lt;/code&gt; Bash script in the same folder. Specify a value for the following parameters in the &lt;code&gt;deploy.sh&lt;/code&gt; script and &lt;code&gt;main.bicepparam&lt;/code&gt; parameter files before deploying the Bicep modules.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;prefix&lt;/code&gt;: A prefix for the resource names.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;apimName&lt;/code&gt;: The globally unique name of the API Management instance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;apimResourceGroupName&lt;/code&gt;: The name of the resource group where the API Management instance will be deployed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;location&lt;/code&gt;: The Azure region where the resources will be deployed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hostnames&lt;/code&gt;: The custom domain name(s) for the Application Gateway instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prior to deployment, ensure you have an Azure Key Vault deployed with the TLS certificate for the Application Gateway and the following parameters set in the &lt;code&gt;main.bicepparam&lt;/code&gt; file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;keyVaultName&lt;/code&gt;: The name of the Key Vault containing the SSL certificate.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;keyVaultResourceGroupName&lt;/code&gt;: The resource group name of the Key Vault.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;keyVaultCertificateName&lt;/code&gt;: The name of the SSL certificate in the Key Vault.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have set the parameters, you can run the &lt;code&gt;deploy.sh&lt;/code&gt; script to deploy the Bicep modules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone the repo&lt;/span&gt;
git clone https://github.com/rcoenmans/appgw-apim-std-v2.git

&lt;span class="c"&gt;# Change directory to infra&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;appgw-apim-std-v2/infra

&lt;span class="c"&gt;# Deploy the infrastructure&lt;/span&gt;
./deploy.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the deployment is complete, you can verify the network configuration of Azure API Management in the Azure portal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsetwfefbwcbeekvzwhlm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsetwfefbwcbeekvzwhlm.png" alt="Azure API Management Network Configuration" width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;&lt;br&gt;
You can only disable public network access for Azure API Management &lt;em&gt;after&lt;/em&gt; you have configured a private endpoint for inbound connections.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cleanup
&lt;/h2&gt;

&lt;p&gt;To delete all the resources created by this deployment, you can delete the resource group where the resources were deployed. You can do this using the Azure CLI with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az group delete &lt;span class="nt"&gt;--name&lt;/span&gt; &amp;lt;resource-group-name&amp;gt; &lt;span class="nt"&gt;--yes&lt;/span&gt; &lt;span class="nt"&gt;--no-wait&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/api-management/integrate-vnet-outbound" rel="noopener noreferrer"&gt;Integrate an Azure API Management instance with a private virtual network for outbound connections&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/api-management/private-endpoint" rel="noopener noreferrer"&gt;Connect privately to API Management by using an inbound private endpoint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>azure</category>
      <category>apigateway</category>
      <category>bicep</category>
      <category>infrastructure</category>
    </item>
  </channel>
</rss>
