Control egress traffic for an Azure Spring Apps instance

Note

The Basic, Standard, and Enterprise plans will be deprecated starting from mid-March, 2025, with a 3 year retirement period. We recommend transitioning to Azure Container Apps. For more information, see the Azure Spring Apps retirement announcement.

The Standard consumption and dedicated plan will be deprecated starting September 30, 2024, with a complete shutdown after six months. We recommend transitioning to Azure Container Apps.

This article describes how to secure outbound traffic from your applications hosted in Azure Spring Apps. The article provides an example of a user-defined route. A user-defined route is an advanced feature that lets you fully control egress traffic. You can use a user-defined route in scenarios such as disallowing an Azure Spring Apps autogenerated public IP address.

Prerequisites

Create a virtual network by using a user-defined route

The following illustration shows an example of an Azure Spring Apps virtual network that uses a user-defined route (UDR).

Diagram that shows the architecture of an Azure Spring Apps virtual network that uses a user-defined route (UDR).

This diagram illustrates the following features of the architecture:

  • Public ingress traffic must flow through firewall filters.
  • Each Azure Spring Apps instance is isolated within a dedicated subnet.
  • Customers own and manage the firewall.
  • This structure ensures that the firewall enables a healthy environment for all the functions you need.
  • Azure Spring Apps doesn't automatically generate public IP resources.

Define environment variables

The following example shows how to define a set of environment variables to be used in resource creation:

export PREFIX="asa-egress"
export RG="${PREFIX}-rg"
export LOC="chinanorth2"
export ASANAME="${PREFIX}"
export VNET_NAME="${PREFIX}-vnet"
export ASA_APP_SUBNET_NAME="asa-app-subnet"
export ASA_SERVICE_RUNTIME_SUBNET_NAME="asa-service-runtime-subnet"
# Do not change FWSUBNET_NAME. This is currently a requirement for Azure Firewall.
export FWSUBNET_NAME="AzureFirewallSubnet"
export FWNAME="${PREFIX}-fw"
export FWPUBLICIP_NAME="${PREFIX}-fwpublicip"
export FWIPCONFIG_NAME="${PREFIX}-fwconfig"
export APP_ROUTE_TABLE_NAME="${PREFIX}-app-rt"
export SERVICE_RUNTIME_ROUTE_TABLE_NAME="${PREFIX}-service-runtime-rt"
export FWROUTE_NAME="${PREFIX}-fwrn"
export ASA_NAME="${PREFIX}-instance"

Create a virtual network with multiple subnets

This section shows you how to provision a virtual network with three separate subnets: one for the user apps, one for the service runtime, and one for the firewall.

First create a resource group, as shown in the following example:

# Create a resource group.

az group create --name $RG --location $LOC

Then create a virtual network with three subnets to host the Azure Spring Apps and Azure Firewall instances, as shown in the following example:

# Dedicated virtual network with an Azure Spring Apps app subnet.

az network vnet create \
    --resource-group $RG \
    --name $VNET_NAME \
    --location $LOC \
    --address-prefixes 10.42.0.0/16 \
    --subnet-name $ASA_APP_SUBNET_NAME \
    --subnet-prefix 10.42.1.0/24

# Dedicated subnet for the Azure Spring Apps service runtime subnet.

az network vnet subnet create \
    --resource-group $RG \
    --vnet-name $VNET_NAME \
    --name $ASA_SERVICE_RUNTIME_SUBNET_NAME\
    --address-prefix 10.42.2.0/24

# Dedicated subnet for Azure Firewall. (Firewall name can't be changed.)

az network vnet subnet create \
    --resource-group $RG \
    --vnet-name $VNET_NAME \
    --name $FWSUBNET_NAME \
    --address-prefix 10.42.3.0/24

Set up an Azure Firewall instance with a user-defined route

Use the following command to create and set up an Azure Firewall instance with a user-defined route, and to configure Azure Firewall outbound rules. The firewall lets you configure granular egress traffic rules from Azure Spring Apps.

Important

If your cluster or application creates a large number of outbound connections directed to the same destination or to a small subset of destinations, you might require more firewall front-end IP addresses to avoid reaching the maximum ports per front-end IP address. For more information on how to create an Azure Firewall instance with multiple IP addresses, see Quickstart: Create an Azure Firewall instance with multiple public IP addresses - ARM template. Create a Standard SKU public IP resource for use as the Azure Firewall front-end address.

az network public-ip create \
    --resource-group $RG \
    --name $FWPUBLICIP_NAME -l $LOC \
    --sku "Standard"

The following example shows how to install the Azure Firewall preview CLI extension and deploy Azure Firewall:

# Install the Azure Firewall preview CLI extension.

az extension add --name azure-firewall

# Deploy Azure Firewall.

az network firewall create \
    --resource-group $RG \
    --name $FWNAME -l $LOC \
    --enable-dns-proxy true

The following example shows how to assign the IP address that you created to the firewall front end.

Note

Setting up the public IP address to the Azure Firewall instance might take a few minutes. To use a fully qualified domain name (FQDN) on network rules, enable a DNS proxy. After you enable the proxy, the firewall listens on port 53 and forwards DNS requests to the specified DNS server. The firewall can then translate the FQDN automatically.

# Configure the firewall IP address.

az network firewall ip-config create \
    --resource-group $RG \
    --firewall-name $FWNAME \
    --name $FWIPCONFIG_NAME \
    --public-ip-address $FWPUBLICIP_NAME \
    --vnet-name $VNET_NAME

When the operation is finished, save the firewall's front-end IP address for configuration later, as shown in the following example:

# Capture the firewall IP address for later use.

export FWPUBLIC_IP=$(az network public-ip show \
    --resource-group $RG \
    --name $FWPUBLICIP_NAME \
    --query "ipAddress" \
    --output tsv)
export FWPRIVATE_IP=$(az network firewall show \
    --resource-group $RG \
    --name $FWNAME \
    --query "ipConfigurations[0].privateIPAddress" \
    --output tsv | tr -d '[:space:]')

Create a user-defined route with a hop to Azure Firewall

Azure automatically routes traffic between Azure subnets, virtual networks, and on-premises networks. If you want to change the default routing in Azure, create a route table.

The following example shows how to create a route table to be associated with a specified subnet. The route table defines the next hop, as in the Azure Firewall instance that you created. Each subnet can have one route table associated with it, or it might have no associated route table.

# Create a user-defined route and add a route for Azure Firewall.

az network route-table create \
    --resource-group $RG -l $LOC \
    --name $APP_ROUTE_TABLE_NAME
az network route-table route create \
    --resource-group $RG \
    --name $FWROUTE_NAME \
    --route-table-name $APP_ROUTE_TABLE_NAME \
    --address-prefix 0.0.0.0/0 \
    --next-hop-type VirtualAppliance \
    --next-hop-ip-address $FWPRIVATE_IP
az network route-table create \
    --resource-group $RG -l $LOC \
    --name $SERVICE_RUNTIME_ROUTE_TABLE_NAME
az network route-table route create \
    --resource-group $RG \
    --name $FWROUTE_NAME \
    --route-table-name $SERVICE_RUNTIME_ROUTE_TABLE_NAME \
    --address-prefix 0.0.0.0/0 \
    --next-hop-type VirtualAppliance \
    --next-hop-ip-address $FWPRIVATE_IP

Add firewall rules

The following example shows how to add rules to your firewall. For more information, see Customer responsibilities for running Azure Spring Apps in a virtual network.

# Add firewall network rules.

az network firewall network-rule create \
    --resource-group $RG \
    --firewall-name $FWNAME \
    --collection-name 'asafwnr' \
    --name 'springcloudtcp' \
    --protocols 'TCP' \
    --source-addresses '*' \
    --destination-addresses "AzureChinaCloud" \
    --destination-ports 443 445 \
    --action allow \
    --priority 100

# Add firewall application rules.

az network firewall application-rule create \
    --resource-group $RG \
    --firewall-name $FWNAME \
    --collection-name 'aksfwar'\
    --name 'fqdn' \
    --source-addresses '*' \
    --protocols 'https=443' \
    --fqdn-tags "AzureKubernetesService" \
    --action allow \
    --priority 100

Associate route tables with subnets

To associate the cluster with the firewall, make sure that the dedicated subnet for the cluster references the route table that you created. App and service runtime subnets must be associated with corresponding route tables. The following example shows how to associate a route table with a subnet:

# Associate the route table with a next hop to the firewall for the Azure Spring Apps subnet.

az network vnet subnet update \
    --resource-group $RG \
    --vnet-name $VNET_NAME \
    --name $ASA_APP_SUBNET_NAME \
    --route-table $APP_ROUTE_TABLE_NAME

az network vnet subnet update
    --resource-group $RG \
    --vnet-name $VNET_NAME \
    --name $ASA_SERVICE_RUNTIME_SUBNET_NAME \
    --route-table $SERVICE_RUNTIME_ROUTE_TABLE_NAME

Add a role for an Azure Spring Apps resource provider

The following example shows how to add a role for the Azure Spring Apps resource provider. The role is assigned to all users identified by the string e8de9221-a19c-4c81-b814-fd37c6caf9d2:

export VIRTUAL_NETWORK_RESOURCE_ID=$(az network vnet show \
    --name $VNET_NAME \
    --resource-group $RG \
    --query "id" \
    --output tsv)

az role assignment create \
    --role "Owner" \
    --scope ${VIRTUAL_NETWORK_RESOURCE_ID} \
    --assignee e8de9221-a19c-4c81-b814-fd37c6caf9d2

export APP_ROUTE_TABLE_RESOURCE_ID=$(az network route-table show \
    --name $APP_ROUTE_TABLE_NAME \
    --resource-group $RG \
    --query "id" \
    --output tsv)

az role assignment create \
    --role "Owner" \
    --scope ${APP_ROUTE_TABLE_RESOURCE_ID} \
    --assignee e8de9221-a19c-4c81-b814-fd37c6caf9d2

export SERVICE_RUNTIME_ROUTE_TABLE_RESOURCE_ID=$(az network route-table show \
    --name $SERVICE_RUNTIME_ROUTE_TABLE_NAME \
    --resource-group $RG \
    --query "id" \
    --output tsv)

az role assignment create \
    --role "Owner" \
    --scope ${SERVICE_RUNTIME_ROUTE_TABLE_RESOURCE_ID} \
    --assignee e8de9221-a19c-4c81-b814-fd37c6caf9d2

Create an Azure Spring Apps instance with user-defined routing

The following example shows how to create an Azure Spring Apps instance with user-defined routing:

az spring create \
    --name $ASA_NAME \
    --resource-group $RG \
    --vnet $VNET_NAME \
    --app-subnet $ASA_APP_SUBNET_NAME \
    --service-runtime-subnet $ASA_SERVICE_RUNTIME_SUBNET_NAME \
    --outbound-type userDefinedRouting

You can now access the public IP address of the firewall from the internet. The firewall routes traffic into Azure Spring Apps subnets according to your routing rules.

Next steps