Detect and notify when outbound IP address changes in Azure Web App

As per Microsoft documentation, Azure App Service is a multi-tenant service. Unless you are using App Service Environment, you are sharing network infrastructure with other App Services. This means your Inbound and Outbound addresses can be different and can change as well. Change of Inbound address may not be a big issue. Change of Outbound IP address can be a problem if your application is making outbound requests to a target that is filtering incoming requests based on IP addresses. Azure does not assign a single outbound IP address to your application. It assigns a set of outbound IP addresses. When an outgoing request is made from your app service, infrastructure will pick one of the IP addresses from the available set. This means that you have to tell other parties about not just one IP address but a set of IP addresses. As per Azure documentation, under certain circumstances this set of Outbound IP addresses can change. Documentation lists following conditions that can result in new set of IP addresses.

  • Delete an app and recreate it in a different resource group (deployment unit may change).
  • Delete the last app in a resource group and region combination and recreate it (deployment unit may change).
  • Scale your app between the lower tiers (Basic, Standard, and Premium) and the Premium V2 tier (IP addresses may be added to or subtracted from the set).

If your application's continuity depends on outbound IP addressed, then it is critical that you have means of knowing as and when Outbound IP addresses have changed. I developed a timer based Azure Function that queries my Web Application's configuration every 24 hours. The function compares current values of Outbound IP addresses with values that were set 24 hours ago. If a change is detected, it notifies all the relevant stake holders about new IP addresses.

Following code snippet shows a sample of Azure Function that can be used to accomplish the task of detection of IP address changes in your Azure Web App. This implementation uses Azure Table to store values of Web App settings that I want to keep track of. The sample code uses hard coded credentials for connecting to Azure services. I will not recommend this. Use Azure Key Vault for secure access to credentials. You will also need to a service principal with just enough privileges to read the configuration values. Do not use your user account for automation tasks.

using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication;
using System.Diagnostics;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using Microsoft.Azure.Management.AppService.Fluent.Models;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;

namespace Byteblocks.Workflow.CloudHealth
{
    public static class MicroserviceIntegration
    {
        [FunctionName("CheckOutboudIp")]
        public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
                        "{Datastorage connection string goes here}");
            CloudTable table = new CloudTable(new Uri("{Azure Table Uri goes here}"), storageAccount.Credentials);
            TableOperation readOp = TableOperation.Retrieve<WebAppConfig>("homerp", "settings");
            WebAppConfig existingValues = null;
            var existingSettingsResult = Task.Run(async ()=> await table.ExecuteAsync(readOp)).Result;
            if (existingSettingsResult.HttpStatusCode != 404)
            {
                existingValues = existingSettingsResult.Result as WebAppConfig;
            }
            var spLogin = new ServicePrincipalLoginInformation 
                  { ClientId = "{id goes here}", ClientSecret = "{password goes here}" };
            var azureCred = new AzureCredentials(spLogin, "{tenant id goes here}", AzureEnvironment.AzureGlobalCloud);

            var am = AppServiceManager.Configure().Authenticate(azureCred, "subscription id goes here");
            var webApps = Task.Run(async () => await am.WebApps.ListAsync());
            foreach (var app in webApps.Result)
            {
                log.LogInformation($"Outbound Addresses: {string.Join(",", app.OutboundIPAddresses)}, 
                        Possible Outbound Addresses: {app.Inner.PossibleOutboundIpAddresses}");
                var newValues = new WebAppConfig("homerp", "settings");
                newValues.OutboundIp = string.Join(",", app.OutboundIPAddresses);
                newValues.PossibleOutboundIp = app.Inner.PossibleOutboundIpAddresses;
                if (null != existingValues)
                {
                    var currentSet = new HashSet<string>(existingValues.OutboundIp.Split(","));
                    var newIps = app.OutboundIPAddresses.Except<string>(currentSet);
                    if (newIps.Any())
                    {
                        log.LogInformation($"Notifying target that outbound ip addresses have changed");
                    }
                }
                

                TableOperation insertOrMergeOperation = TableOperation.InsertOrMerge(newValues);
                TableResult result = 
                     Task.Run(async ()=> await table.ExecuteAsync(insertOrMergeOperation)).Result;
                WebAppConfig insertedValues = result.Result as WebAppConfig;
            }
        }
    }

    public class WebAppConfig:TableEntity
    {
        public WebAppConfig() { }
        public WebAppConfig(string app, string type) {
            PartitionKey = app;
            RowKey = type;
        }
        public string OutboundIp { get; set; }
        public string PossibleOutboundIp { get; set; }
    }
}

This code has set CRON expression for execution of Azure Function after every 5 minutes. This is just to test it locally. You can use an appropriate CRON expression depending on your frequency requirements.

Search

Social

Weather

2.1 °C / 35.7 °F

weather conditions Rain

Monthly Posts

Blog Tags