Feste Outbound-IP-Adressen mit Azure Functions

post-thumb

Bei der Entwicklung von Cloud-Lösungen ist man heutzutage nicht mehr darauf beschränkt, einzig und allein Cloud-Ressourcen zu verwenden. Das Ansprechen und Einbinden von On-Premises-Ressourcen gehört mittlerweile genauso zur Entwicklung dazu, wie die automatisierte Bereitstellung von Ressourcen via Pipelines. Die On-Premises-Server haben meistens und richtigerweise eine Firewall vorgeschaltet, welche nur bestimmte IP-Adressen und Port-Protokolle zulässt. Nun klingt es erstmal simpel, dass der Cloud-Entwickler eine Liste von IP-Adressen zur Verfügung stellt, welche das Team der Netzwerkverantwortlichen in der Firewall in die Whitelist aufnimmt. Wenn man sich allerdings die möglichen IP-Adressen der Azure-Datencenter anschaut, ist die Liste der möglichen IP-Adressen sehr lang. So wird schnell klar: Man sollte nicht eine Liste von über 30 IP-Adressen in der Firewall freischalten.

In diesem Beitrag möchte ich zeigen, wie wir mithilfe von Azure Functions eine festgelegte Outbound-IP-Adresse definieren, mit welcher die Azure Functions “nach draußen” kommuniziert.

Zielarchitektur

Unsere Zielarchitektur beinhaltet eine Azure Function, welche über ein VNET und NAT mithilfe einer definierte öffentliche IP-Adresse nach außen (outbound) kommuniziert. In diesem Beispiel wurde exemplarisch ein On-Premises-Server mit vorgeschalteter Firewall dargestellt.

Outbound-IP-Adresse

Azure Function Outbound-IP-Adressen

Zunächst einmal möchten wir einsehen, welche IP-Adressen einer Azure Function überhaupt verwendet werden. Hierbei wird zwischen outboundIpAddresses und possibleOutboundIpAddresses unterschieden. Dabei stehen die outboundIpAddresses für die gerade in Verwendung befindlichen IP-Adressen. Die possibleOutboundIpAddresses beinhalten somit alle möglichen Outbound-IP-Adressen für diese Azure Function. Die outboundIpAddresses bilden demnach eine Untermenge der possibleOutboundIpAddresses. Diese kann man sich über die Azure CLI anzeigen lassen.

Das heißt, wir melden uns zunächst via Azure CLI an und wählen die entsprechende Subscription für uns aus.

az login
az account set -s "Subscription-GUID"

Mit dem folgenden Befehl erhalten wir eine Liste der Untermenge outboundIpAddresses:

az functionapp show --resource-group "Ressource-Group" --name "Function-Name" --query outboundIpAddresses --output tsv

Durch Anpassen des query-Parameter zu possibleOutboundIpAddresses erhalten wir die komplette Liste aller möglichen IP-Adressen:

az functionapp show --resource-group "Ressource-Group" --name "Function-Name" --query possibleOutboundIpAddresses --output tsv

Umsetzen der Zielarchitektur mit Azure CLI

In diesem Szenario gehen wir davon aus, dass noch keine Azure-Ressourcen bereitgestellt wurden und somit alle Ressourcen from scratch erstellt werden sollen.

Erstellen der Netzwerkressourcen

Zunächst müssen alle notwendigen Netzwerkressourcen, wie das VNET, einer Public-IP und einem NAT erzeugt werden.

Beginnen wir mit dem VNET, welches wir in West-Europa und mit dem Standard-Adress-Prefix 10.0.0.0/16 bereitstellen möchten:

az network vnet create --resource-group "MyRessourceGroup" --name "vnet-okblog-euwest" --location westeurope --address-prefix 10.0.0.0/16 

Anschließend erstellen wir ein Subnet, welches dem bestehenden VNET zugeordnet wird:

az network vnet subnet create --name "snet-okblog-euwest-prod" --resource-group "MyRessourceGroup" --vnet-name "vnet-okblog-euwest" --address-prefixes 10.0.0.0/29 --delegations 'Microsoft.Web/serverFarms'

Nun erstellen wir eine Public-IP-Adresse, welche später unsere Outbound-IP-Adresse für die Requests der Azure Function verwendet:

az network public-ip create --name "pip-func-okblog-euwest-prod"  --resource-group "MyRessourceGroup" --version "IPv4" --tier "Regional" --sku "Standard" --location westeurope

Als letzte Netzwerkressource wird das NAT erstellt, welche unsere zuvor erstellte öffentliche IP-Adresse als public-ip-addresses zugewiesen hat:

az network nat gateway create --name "nat-func-okblog-euwest-prod" --resource-group "MyRessourceGroup" --location westeurope --public-ip-addresses "pip-func-okblog-euwest-prod"

Durch ein Update des Subnets mit dem entsprechenden NAT-Gateway ist die Konfiguration der Netzwerkressourcen abgeschlossen:

az network vnet subnet update --resource-group "MyRessourceGroup"--vnet-name "vnet-okblog-euwest" --name "snet-okblog-euwest-prod" --nat-gateway "nat-func-okblog-euwest-prod"

Azure Function

Azure Functions können VNETs nur in einem Serviceplan verwenden (also kein Consumption-Plan). Hierzu wird zunächst ein App-Serviceplan benötigt, welchen wir in westeurope im Standardplan S1 erstellen:

$appServicePlanId = az appservice plan create --resource-group "MyRessourceGroup" --name "MyAppServicPlanName" --location westeurope --sku S1 

Die Service-Plan-ID können wir nun verwenden, um die zugehörige Azure Function zu erstellen:

 az functionapp create --resource-group "MyRessourceGroup" --plan ($appServicePlanId | convertfrom-json).id --name "MyFunctionName" --storage-account "MyStorageAccountName" --functions-version 4 --runtime dotnet --os Windows

Nun muss nur noch die entsprechende vnet-integration zur Function-App hinzugefügt werden:

$myExistingVnet = az network vnet list --resource-group "MyRessourceGroup" --query "[?name=='vnet-okblog-euwest']" | convertfrom-json 

az functionapp vnet-integration add --resource-group "MyRessourceGroup" --name "MyFunctionName" --vnet $myExistingVnet.id --subnet "snet-okblog-euwest-prod"

Testen der Netzwerkfunktionalität

Um zu prüfen, ob das Erzeugen der Ressourcen und die Konfiguration derselben funktioniert hat und wir nun nur noch eine Outbound-IP-Adresse der Azure Function zur Folge haben, können wir eine Hilfsfunktion in dem Functions-Projekt hinzufügen. Diese Hilfsfunktion ruft intern die Adresse https://ifconfig.me auf. Die Antwort beinhaltet die IP-Adresse, über welche ein Request ausgeführt wurde - also der Outbound-IP-Adresse. Natürlich muss die Function zunächst in Azure deployed sein, damit man die zuvor erstellte öffentliche IP-Adresse als Antwort der Function erhält.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Threading.Tasks;

namespace Application.Functions.Todo
{
    public static class IfConfigFunction
    {
        [FunctionName("IfConfig")]
        public static async Task<IActionResult> Run(
           [HttpTrigger(AuthorizationLevel.Function, "get", Route = "ifconfig")] HttpRequest req, ILogger log)
        {
            var client = new HttpClient();
            var response = await client.GetAsync(@"https://ifconfig.me");
            var responseMessage = await response.Content.ReadAsStringAsync();

            return new OkObjectResult(responseMessage);
        }
    }
}

Zusammenfassung

In diesem Blog-Beitrag konnte ich einen Überblick geben, wie man zum einen die verfügbaren Outbound-IP-Adressen verwaltet (outboundIpAddresses und possibleOutboundIpAddresses) und zu anderen wie man die Outbound-IP-Adressen auf eine einzige reduzieren kann. Somit muss der Netzwerkadministrator nicht mehr eine sehr große Liste von IP-Adressen als Ausnahme in der Firewall freischalten, sondern kann ganz gezielt auf die zuvor definierte IP-Adresse festlegen. Mit der Hilfs-Function kann man als Entwickler zum Ende der Erzeugung der Netzwerkressourcen prüfen, ob alles ordnungsgemäß funktioniert.

Lernen Sie uns kennen

Das sind wir

Wir sind ein Software-Unternehmen mit Hauptsitz in Karlsruhe und auf die Umsetzung von Digitalstrategien durch vernetzte Cloud-Anwendungen spezialisiert. Wir sind Microsoft-Partner und erweitern Standard-Anwendungen bei Bedarf – egal ob Modernisierung, Integration, Implementierung von CRM- oder ERP-Systemen, Cloud Security oder Identity- und Access-Management: Wir unterstützen Sie!

Mehr über uns

Der Objektkultur-Newsletter

Mit unserem Newsletter informieren wir Sie stets über die neuesten Blogbeiträge,
Webcasts und weiteren spannenden Themen rund um die Digitalisierung.

Newsletter abonnieren