From 7c36973d312c72dcd6545146302e9ce5dfe31c57 Mon Sep 17 00:00:00 2001 From: Kafeel Hasan Date: Tue, 4 Nov 2025 14:49:37 +0530 Subject: [PATCH 1/3] NGINXaaS: Add private subnet OIDC with Microsoft Entra ID guide --- .../private-subnet-oidc-entra.md | 313 ++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md diff --git a/content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md b/content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md new file mode 100644 index 000000000..0799a93d9 --- /dev/null +++ b/content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md @@ -0,0 +1,313 @@ +--- +title: OIDC with Microsoft Entra ID in Private Subnets +url: /nginxaas/azure/quickstart/security-controls/private-subnet-oidc-entra/ +toc: true +weight: 350 +nd-content-type: how-to +nd-product: N4Azure +--- + +## Overview + +Learn how to configure F5 NGINXaaS for Azure with OpenID Connect (OIDC) authentication using Microsoft Entra ID when your NGINXaaS deployment is in a private subnet. This guide addresses the networking requirements to enable authentication traffic to reach Microsoft Entra ID endpoints while maintaining security controls. + +When NGINXaaS is deployed in a private subnet, authentication traffic must reach external Microsoft Entra ID endpoints at `login.microsoftonline.com`. This guide provides two solutions to enable this connectivity while controlling outbound traffic: + +1. **Azure NAT Gateway with NSG rules** - Lower cost, simpler configuration +1. **Azure Firewall** - Higher security, more granular control + +## Before you begin + +- [An NGINXaaS deployment]({{< ref "/nginxaas-azure/getting-started/create-deployment" >}}) with a private IP address +- A configured Microsoft Entra ID application registration. See [Configure Entra ID]({{< ref "/nginx/deployment-guides/single-sign-on/entra-id/#entra-setup" >}}) for detailed setup instructions. +- [SSL/TLS certificates]({{< ref "/nginxaas-azure/getting-started/ssl-tls-certificates/" >}}) configured for your NGINXaaS deployment +- [Runtime State Sharing]({{< ref "/nginxaas-azure/quickstart/runtime-state-sharing.md" >}}) enabled on the NGINXaaS deployment + +## Solution Comparison + +Choose the networking solution that best fits your security and cost requirements: + +{{< table >}} +| Feature | Azure NAT Gateway | Azure Firewall | +|---------|-------------------|----------------| +| **Hourly Cost** | Lower ($0.045+ per hour) | Higher ($1.25+ per hour) | +| **Address Space** | Less required | More required (2 additional /26 subnets) | +| **Security** | Less secure - broader IP range filtering | More secure - precise FQDN-based filtering | +| **Configuration** | Simple setup, less overhead | More complex configuration, more overhead | +| **Public IPs** | 1 required | 2 required | +| **Filtering Precision** | Generic rules enabling broader filtering | Surgical precision for traffic filtering | +{{< /table >}} + +## Common Configuration Steps + +Both solutions require these initial steps: + +### Configure OIDC in NGINXaaS + +1. Follow the standard [OIDC authentication]({{< ref "/nginxaas-azure/quickstart/security-controls/oidc/" >}}) guide with these Microsoft Entra ID specific considerations. + +1. Set the `oidc_jwt_keyfile` endpoint in your `openid_connect_configuration.conf`: + + ```nginx + # Use the correct Microsoft Entra ID keys endpoint + map $host $oidc_jwt_keyfile { + default "https://login.microsoftonline.com//discovery/v2.0/keys"; + } + ``` + + {{< call-out "note" >}}The `oidc_jwt_keyfile` endpoint is not listed in the Microsoft App Registration's endpoints pane but is required for proper OIDC configuration.{{< /call-out >}} + +1. Configure DNS resolution appropriately: + - For IPv4-only deployments, set `ipv6=off` in your resolver directive in the `openid_connect.server_conf` file + - For dual-stack subnets, ensure both IPv4 and IPv6 address spaces are configured + - Use Azure DNS (127.0.0.1:49153) or configure firewall rules for your preferred DNS service + + ```nginx + http { + # For IPv4-only deployments + resolver 127.0.0.1:49153 ipv4=on ipv6=off valid=300s; + + # For dual-stack deployments + resolver 127.0.0.1:49153 ipv4=on valid=300s; + } + ``` + + {{< call-out "important" >}}If you plan to use IPv6 addresses on the frontend, ensure your subnet is dual-stack with both IPv4 and IPv6 address spaces. For IPv4-only deployments, set `ipv6=off` in your resolver configuration.{{< /call-out >}} + +## Configure connectivity using Azure NAT Gateway + +This solution uses Azure NAT Gateway with Network Security Group (NSG) rules to enable controlled outbound connectivity. + +### Configure NSG rules + +When you create an NGINXaaS deployment, Azure automatically creates and attaches an NSG to the delegated subnet. You need to modify this NSG to allow Microsoft Entra ID connectivity. + +1. Add Microsoft IP address ranges to NSG rules: + + Navigate to your NGINXaaS subnet's NSG and add inbound and outbound rules for the Microsoft IP addresses listed in the [Microsoft 365 URLs and IP address ranges documentation](https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges?view=o365-worldwide#microsoft-365-common-and-office-online) under section #56. + +1. Create a custom outbound rule to deny general internet access: + + - **Priority**: Higher numerical value (lower priority) than the Microsoft IP rules + - **Action**: Deny + - **Destination**: Internet + - **Purpose**: Override the default `AllowInternetOutBound` rule + + {{< call-out "important" >}}The default `AllowInternetOutBound` rule cannot be edited, so you must create a higher-priority rule to deny general internet access while allowing the specific Microsoft IP ranges. The priority of the custom deny rule should be a higher numerical value (lower priority) than the Microsoft IP allow rules.{{< /call-out >}} + +### Create and configure NAT Gateway + +1. Create an Azure NAT Gateway: + + ```bash + # Create NAT Gateway + az network nat gateway create \ + --resource-group \ + --name \ + --location \ + --public-ip-addresses + ``` + +1. Associate the NAT Gateway with your NGINXaaS subnet: + + ```bash + # Associate NAT Gateway with subnet + az network vnet subnet update \ + --resource-group \ + --vnet-name \ + --name \ + --nat-gateway + ``` + +This configuration allows NGINXaaS to reach Microsoft Entra ID endpoints while blocking general internet access. + +{{< call-out "note" >}}Using NAT Gateway with NSG rules still requires allowing broad IP address ranges. Based on Microsoft's documentation, you need to allow at least two /18 subnets and two /19 subnets for complete Microsoft Entra ID connectivity. For more precise filtering, consider using Azure Firewall instead.{{< /call-out >}} + +## Configure connectivity using Azure Firewall + +This solution provides more granular control using Azure Firewall with DNS-based filtering. + +{{< call-out "note" >}}Azure Firewall provides DNS-based filtering capabilities but comes at a significantly higher cost compared to NAT Gateway (approximately 28x cost increase). However, it enables more precise firewall rules for better security.{{< /call-out >}} + +### Create firewall subnets + +Create two new subnets in your virtual network: + +1. **Azure Firewall subnet**: + - Name: `AzureFirewallSubnet` (immutable) + - Address space: /26 subnet + - Purpose: Azure Firewall + +1. **Firewall Management subnet**: + - Name: `AzureFirewallManagementSubnet` (immutable) + - Address space: /26 subnet + - Purpose: Firewall Management + +```bash +# Create Azure Firewall subnet +az network vnet subnet create \ + --resource-group \ + --vnet-name \ + --name AzureFirewallSubnet \ + --address-prefixes + +# Create Firewall Management subnet +az network vnet subnet create \ + --resource-group \ + --vnet-name \ + --name AzureFirewallManagementSubnet \ + --address-prefixes +``` + +### Create Azure Firewall + +1. Create the firewall with Standard SKU (required for DNS proxy functionality): + + ```bash + # Create public IPs for firewall + az network public-ip create \ + --name \ + --resource-group \ + --allocation-method Static \ + --sku Standard + + az network public-ip create \ + --name \ + --resource-group \ + --allocation-method Static \ + --sku Standard + + # Create firewall with new policy + az extension add --name azure-firewall + az network firewall create \ + --name \ + --resource-group \ + --vnet-name \ + --public-ip \ + --firewall-policy + ``` + + {{< call-out "note" >}}The Standard SKU is required at minimum because it allows Azure Firewall to be configured as a DNS proxy, which is necessary for FQDN-based filtering. During creation, choose to create a new Firewall Policy and use your existing virtual network that contains the NGINXaaS subnet.{{< /call-out >}} + +### Configure firewall policy + +1. Enable DNS proxy in the firewall policy: + + ```bash + # Enable DNS proxy + az network firewall policy update \ + --name \ + --resource-group \ + --enable-dns-proxy true \ + --dns-servers 168.63.129.16 + ``` + +1. Configure private IP ranges to avoid SNAT for internal traffic: + + Navigate to your firewall policy in the Azure portal and under **Private IP ranges**, select "Always" or specify your NGINXaaS subnet IP addresses. + +### Create network rules + +Create a network rule collection to allow NGINXaaS subnet access to Microsoft Entra ID: + +```bash +# Create network rule collection +az network firewall policy rule-collection-group create \ + --name NetworkRuleCollectionGroup \ + --policy-name \ + --resource-group \ + --priority 200 + +# Add network rule for Microsoft Entra ID +az network firewall policy rule-collection-group collection add-filter-collection \ + --name EntraIDAccess \ + --policy-name \ + --resource-group \ + --collection-priority 100 \ + --rule-collection-group-name NetworkRuleCollectionGroup \ + --action Allow \ + --rule-name AllowEntraID \ + --rule-type NetworkRule \ + --protocols TCP \ + --source-addresses \ + --destination-fqdns login.microsoftonline.com \ + --destination-ports 443 +``` + +### Configure route table + +Direct NGINXaaS subnet traffic through the firewall: + +1. Note the private IP address of your Azure Firewall (found in the firewall's overview page). + +1. Create a route table: + + ```bash + # Create route table + az network route-table create \ + --name \ + --resource-group \ + --location + + # Add default route pointing to firewall + az network route-table route create \ + --route-table-name \ + --resource-group \ + --name DefaultRoute \ + --address-prefix 0.0.0.0/0 \ + --next-hop-type VirtualAppliance \ + --next-hop-ip-address + ``` + +1. Associate the route table with the NGINXaaS subnet: + + ```bash + # Associate route table with NGINXaaS subnet + az network vnet subnet update \ + --resource-group \ + --vnet-name \ + --name \ + --route-table + ``` + +## Testing the configuration + +After implementing either solution, test the OIDC authentication: + +1. Access your NGINXaaS deployment URL. +1. Verify you are redirected to Microsoft Entra ID for authentication. +1. Complete the login process and confirm successful authentication. +1. Check NGINXaaS logs for any connectivity issues. + +### Troubleshooting + +If authentication fails, check the following: + +1. **DNS Resolution**: Ensure your firewall rules allow DNS queries. +1. **Certificate Validation**: Verify that the firewall allows HTTPS traffic to Microsoft endpoints. +1. **Timeout Settings**: Increase timeout values if experiencing slow authentication responses. +1. **Route Configuration**: Confirm the route table is properly associated with the NGINXaaS subnet. + +## Security considerations + +- **Principle of Least Privilege**: Both solutions limit outbound connectivity to only required Microsoft endpoints. +- **Monitoring**: Implement logging and monitoring for authentication traffic. +- **Regular Updates**: Keep Microsoft IP address ranges updated in your NSG rules. +- **Network Segmentation**: Consider additional network segmentation for enhanced security. + +## Cost optimization + +- **NAT Gateway**: More cost-effective for basic filtering needs. +- **Azure Firewall**: Better ROI when you need advanced filtering capabilities. +- **Public IP Management**: Minimize the number of public IP addresses to reduce costs. + +Both solutions enable the minimal connectivity required between NGINXaaS and Microsoft Entra ID for OIDC authentication while maintaining security controls appropriate to your requirements. + +## See also + +- [Set up OIDC authentication]({{< ref "/nginxaas-azure/quickstart/security-controls/oidc/" >}}) +- [Single Sign-On with Microsoft Entra ID]({{< ref "/nginx/deployment-guides/single-sign-on/entra-id.md" >}}) +- [Private Link to Upstreams]({{< ref "/nginxaas-azure/quickstart/security-controls/private-link-to-upstreams.md" >}}) +- [Microsoft 365 URLs and IP address ranges](https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges) +- [Azure NAT Gateway pricing](https://azure.microsoft.com/en-us/pricing/details/virtual-network/) +- [Azure Firewall pricing](https://azure.microsoft.com/en-us/pricing/details/azure-firewall/) From 642dec79a0d394c6c79976fb72afc2b577535350 Mon Sep 17 00:00:00 2001 From: Kafeel Hasan Date: Thu, 6 Nov 2025 11:36:24 +0530 Subject: [PATCH 2/3] Address PR Comments --- .../security-controls/private-subnet-oidc-entra.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md b/content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md index 0799a93d9..8ca17b682 100644 --- a/content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md +++ b/content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md @@ -11,12 +11,12 @@ nd-product: N4Azure Learn how to configure F5 NGINXaaS for Azure with OpenID Connect (OIDC) authentication using Microsoft Entra ID when your NGINXaaS deployment is in a private subnet. This guide addresses the networking requirements to enable authentication traffic to reach Microsoft Entra ID endpoints while maintaining security controls. -When NGINXaaS is deployed in a private subnet, authentication traffic must reach external Microsoft Entra ID endpoints at `login.microsoftonline.com`. This guide provides two solutions to enable this connectivity while controlling outbound traffic: +When NGINXaaS is deployed in a private subnet, authentication traffic must reach external Microsoft Entra ID endpoints at `login.microsoftonline.com`. This guide provides the following solutions to enable this connectivity while controlling outbound traffic: 1. **Azure NAT Gateway with NSG rules** - Lower cost, simpler configuration 1. **Azure Firewall** - Higher security, more granular control -## Before you begin +## To complete this guide, you need to set up the following: - [An NGINXaaS deployment]({{< ref "/nginxaas-azure/getting-started/create-deployment" >}}) with a private IP address - A configured Microsoft Entra ID application registration. See [Configure Entra ID]({{< ref "/nginx/deployment-guides/single-sign-on/entra-id/#entra-setup" >}}) for detailed setup instructions. @@ -30,7 +30,7 @@ Choose the networking solution that best fits your security and cost requirement {{< table >}} | Feature | Azure NAT Gateway | Azure Firewall | |---------|-------------------|----------------| -| **Hourly Cost** | Lower ($0.045+ per hour) | Higher ($1.25+ per hour) | +| **Hourly Cost** | Lower - see [NAT Gateway pricing](https://azure.microsoft.com/en-us/pricing/details/azure-nat-gateway/) | Higher - see [Firewall pricing](https://azure.microsoft.com/en-us/pricing/details/azure-firewall/) | | **Address Space** | Less required | More required (2 additional /26 subnets) | | **Security** | Less secure - broader IP range filtering | More secure - precise FQDN-based filtering | | **Configuration** | Simple setup, less overhead | More complex configuration, more overhead | @@ -58,7 +58,6 @@ Both solutions require these initial steps: {{< call-out "note" >}}The `oidc_jwt_keyfile` endpoint is not listed in the Microsoft App Registration's endpoints pane but is required for proper OIDC configuration.{{< /call-out >}} 1. Configure DNS resolution appropriately: - - For IPv4-only deployments, set `ipv6=off` in your resolver directive in the `openid_connect.server_conf` file - For dual-stack subnets, ensure both IPv4 and IPv6 address spaces are configured - Use Azure DNS (127.0.0.1:49153) or configure firewall rules for your preferred DNS service @@ -288,14 +287,14 @@ If authentication fails, check the following: 1. **Timeout Settings**: Increase timeout values if experiencing slow authentication responses. 1. **Route Configuration**: Confirm the route table is properly associated with the NGINXaaS subnet. -## Security considerations +## To secure your systems, address the following: - **Principle of Least Privilege**: Both solutions limit outbound connectivity to only required Microsoft endpoints. - **Monitoring**: Implement logging and monitoring for authentication traffic. - **Regular Updates**: Keep Microsoft IP address ranges updated in your NSG rules. - **Network Segmentation**: Consider additional network segmentation for enhanced security. -## Cost optimization +## To optimize your systems, we recommend: - **NAT Gateway**: More cost-effective for basic filtering needs. - **Azure Firewall**: Better ROI when you need advanced filtering capabilities. @@ -309,5 +308,3 @@ Both solutions enable the minimal connectivity required between NGINXaaS and Mic - [Single Sign-On with Microsoft Entra ID]({{< ref "/nginx/deployment-guides/single-sign-on/entra-id.md" >}}) - [Private Link to Upstreams]({{< ref "/nginxaas-azure/quickstart/security-controls/private-link-to-upstreams.md" >}}) - [Microsoft 365 URLs and IP address ranges](https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges) -- [Azure NAT Gateway pricing](https://azure.microsoft.com/en-us/pricing/details/virtual-network/) -- [Azure Firewall pricing](https://azure.microsoft.com/en-us/pricing/details/azure-firewall/) From fdac71bbc6f814f67efeed5a3a1d721cd2262e58 Mon Sep 17 00:00:00 2001 From: Kafeel Hasan Date: Thu, 6 Nov 2025 23:13:51 +0530 Subject: [PATCH 3/3] Address PR Comments --- .../private-subnet-oidc-entra.md | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md b/content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md index 8ca17b682..7819c0aaa 100644 --- a/content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md +++ b/content/nginxaas-azure/quickstart/security-controls/private-subnet-oidc-entra.md @@ -16,29 +16,31 @@ When NGINXaaS is deployed in a private subnet, authentication traffic must reach 1. **Azure NAT Gateway with NSG rules** - Lower cost, simpler configuration 1. **Azure Firewall** - Higher security, more granular control -## To complete this guide, you need to set up the following: +## Before you begin + +To complete this guide, you need to set up the following: - [An NGINXaaS deployment]({{< ref "/nginxaas-azure/getting-started/create-deployment" >}}) with a private IP address - A configured Microsoft Entra ID application registration. See [Configure Entra ID]({{< ref "/nginx/deployment-guides/single-sign-on/entra-id/#entra-setup" >}}) for detailed setup instructions. - [SSL/TLS certificates]({{< ref "/nginxaas-azure/getting-started/ssl-tls-certificates/" >}}) configured for your NGINXaaS deployment - [Runtime State Sharing]({{< ref "/nginxaas-azure/quickstart/runtime-state-sharing.md" >}}) enabled on the NGINXaaS deployment -## Solution Comparison +## Solution comparison Choose the networking solution that best fits your security and cost requirements: {{< table >}} | Feature | Azure NAT Gateway | Azure Firewall | |---------|-------------------|----------------| -| **Hourly Cost** | Lower - see [NAT Gateway pricing](https://azure.microsoft.com/en-us/pricing/details/azure-nat-gateway/) | Higher - see [Firewall pricing](https://azure.microsoft.com/en-us/pricing/details/azure-firewall/) | -| **Address Space** | Less required | More required (2 additional /26 subnets) | +| **Hourly cost** | Lower - see [NAT Gateway pricing](https://azure.microsoft.com/en-us/pricing/details/azure-nat-gateway/) | Higher - see [Firewall pricing](https://azure.microsoft.com/en-us/pricing/details/azure-firewall/) | +| **Address space** | Less required | More required (2 additional /26 subnets) | | **Security** | Less secure - broader IP range filtering | More secure - precise FQDN-based filtering | | **Configuration** | Simple setup, less overhead | More complex configuration, more overhead | | **Public IPs** | 1 required | 2 required | -| **Filtering Precision** | Generic rules enabling broader filtering | Surgical precision for traffic filtering | +| **Filtering precision** | Generic rules enabling broader filtering | Surgical precision for traffic filtering | {{< /table >}} -## Common Configuration Steps +## Common configuration steps Both solutions require these initial steps: @@ -94,12 +96,12 @@ When you create an NGINXaaS deployment, Azure automatically creates and attaches {{< call-out "important" >}}The default `AllowInternetOutBound` rule cannot be edited, so you must create a higher-priority rule to deny general internet access while allowing the specific Microsoft IP ranges. The priority of the custom deny rule should be a higher numerical value (lower priority) than the Microsoft IP allow rules.{{< /call-out >}} -### Create and configure NAT Gateway +### Create and configure Azure NAT Gateway 1. Create an Azure NAT Gateway: ```bash - # Create NAT Gateway + # Create Azure NAT Gateway az network nat gateway create \ --resource-group \ --name \ @@ -107,10 +109,10 @@ When you create an NGINXaaS deployment, Azure automatically creates and attaches --public-ip-addresses ``` -1. Associate the NAT Gateway with your NGINXaaS subnet: +1. Associate the Azure NAT Gateway with your NGINXaaS subnet: ```bash - # Associate NAT Gateway with subnet + # Associate Azure NAT Gateway with subnet az network vnet subnet update \ --resource-group \ --vnet-name \ @@ -120,13 +122,13 @@ When you create an NGINXaaS deployment, Azure automatically creates and attaches This configuration allows NGINXaaS to reach Microsoft Entra ID endpoints while blocking general internet access. -{{< call-out "note" >}}Using NAT Gateway with NSG rules still requires allowing broad IP address ranges. Based on Microsoft's documentation, you need to allow at least two /18 subnets and two /19 subnets for complete Microsoft Entra ID connectivity. For more precise filtering, consider using Azure Firewall instead.{{< /call-out >}} +{{< call-out "note" >}}Using Azure NAT Gateway with NSG rules still requires allowing broad IP address ranges. Based on Microsoft's documentation, you need to allow at least two /18 subnets and two /19 subnets for complete Microsoft Entra ID connectivity. For more precise filtering, consider using Azure Firewall instead.{{< /call-out >}} ## Configure connectivity using Azure Firewall This solution provides more granular control using Azure Firewall with DNS-based filtering. -{{< call-out "note" >}}Azure Firewall provides DNS-based filtering capabilities but comes at a significantly higher cost compared to NAT Gateway (approximately 28x cost increase). However, it enables more precise firewall rules for better security.{{< /call-out >}} +{{< call-out "note" >}}Azure Firewall provides DNS-based filtering capabilities but comes at a significantly higher cost compared to Azure NAT Gateway (approximately 28x cost increase). However, it enables more precise firewall rules for better security.{{< /call-out >}} ### Create firewall subnets @@ -296,7 +298,7 @@ If authentication fails, check the following: ## To optimize your systems, we recommend: -- **NAT Gateway**: More cost-effective for basic filtering needs. +- **Azure NAT Gateway**: More cost-effective for basic filtering needs. - **Azure Firewall**: Better ROI when you need advanced filtering capabilities. - **Public IP Management**: Minimize the number of public IP addresses to reduce costs.