Setup NAT Gateway For Azure Functions
Description:
In this post, I will setup a NAT Gateway and then connect my Function App (linux app Service Plan) to that gateway so that all outbound requests go through a single IP. I mostly followed this post and the associated Microsoft Blog post.
To Resolve:
- Create a brand new resource group. Inside that resource group, create a VNET:
- Create a
/24
address space and then create 4/26
subnets
- Create a
- Create NAT Gateway:
- Create a public IP for it
- Tie to one subnet
- I selected this in the wizard but it didn’t stick on creation. To fix just go to the gateway => Subnets => Assign to a subnet
- Tie the Function App to the VNET:
- Function App => Networking => VNET Integration => Configure => Add VNET/Subnet that has NAT GW
- Verify that it can see the subnet by click on the subnet name which should show the NAT gateway as well
- Force all outgoing traffic to go through the VNET by:
- Go to configuration => New App Setting =>
WEBSITE_VNET_ROUTE_ALL = 1
. This will force the traffic going to the internet to be routed through public IP address associated to the NAT Gateway.
- Go to configuration => New App Setting =>
- Add
requests==2.25.0
to yourrequirements.txt
Function App - Copy/paste the following into one of your functions
__init__.py
files:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
#!/usr/bin/python3 import sys import logging import azure.functions as func from . import helpers import os import time from datetime import datetime import json import requests def main(req: func.HttpRequest) -> func.HttpResponse: logging.info("Python HTTP trigger function processed a request.") url = "https://ifconfig.me/ip" payload = {} headers = { 'Content-Type': 'application/json', } r = requests.request("GET", url, headers=headers, data=payload) response = r.text logging.info(f"Response: {response}") rspJson = json.dumps([{ "response": response, "date_time": date }]) return func.HttpResponse(rspJson, status_code=200) if __name__ == '__main__': main(req) else: print("function not called correctly")
-
Do your push to Github which should sync with Azure’s Function App and then test with Postman. Did it work? Didn’t for me, I didn’t get any errors, but I ended up getting one of the IP’s of the Function App instead of that of the Gateway.
-
I currently have a case open with Microsoft on this but my guess is that this will work fine for Windows App service plans and Windows Powershell functions like in the posts above. Reason for this assumption is that they seem to always support Windows things first and then python later…
- For Troubleshooting:
- At first, I had read something like mounting storage wasn’t supported and I had done this in the past Per docs:
1 2 3 4 5 6 7 8 9
az webapp config storage-account add \ --resource-group myResourceGroup \ --name $functionAppName \ --custom-id $shareId \ --storage-type AzureFiles \ --share-name $shareName \ --account-name $AZURE_STORAGE_ACCOUNT \ --mount-path $mountPath \ --access-key $AZURE_STORAGE_KEY
-
So I deleted the storage by typing
az webapp config storage-account delete --custom-id CustomId --name MyWebApp --resource-group MyResourceGroup
per docs, still didn’t change anything, Function App was still displaying an IP in the list from the output ofaz webapp show --resource-group MyResourceGroup --name MyWebApp --query outboundIpAddresses --output tsv
and not the NAT Gateway. - I deleted the NAT Gateway multiple times and recreated, no change
- I deployed a new Function App, no change
- Will update this if I have a resolution…
Comments