4

Use Azure Function to Update IP Address in Azure VM NSG Firewall Rule

 1 year ago
source link: https://edi.wang/post/2023/3/17/use-azure-function-to-update-ip-address-in-azure-vm-nsg-firewall-rule
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Problem


I have Azure VMs that require being accessed only from 3 IP addresses. Two of these IPs are static, the other is dynamic. Every time the dynamic IP changes, I must manually go to Azure portal and update NSG rules. Because this happens every few days, it makes me work 996. To solve this issue, I created Azure Function to automatically update the NSG rule with a simple HTTP request. I no longer need to manually go into Azure portal. Let's see how to do it.

Create Azure Function App


PowerShell Function

Create a new Azure Function and select PowerShell as runtime. After creation is completed, go to Identity blade, and enable system assigned managed identity.

img-fb8cba45-7bbf-42f4-9b09-271199397eb4.png

Add Az modules

Go to App files - requirements.psd1 and add PowerShell modules:

@{
    'Az.Accounts' = '2.*'
    'Az.Network' = '5.*'
}
img-cab8d92a-47f7-40bd-9842-d436a90b42de.png

Allow Function Access for NSG

Go to Access control (IAM) of the NSG, add a new role assignment

img-131cf237-b616-4518-92bb-65645769fa01.png

Select "Contributor" in "Privileged administrator roles"

img-49fcc41e-9d6a-4b71-963e-7eb0718e2c5a.png

Select "Managed identity" and add the function app.

img-7952ace5-cb99-4591-9c9d-a4819ee89595.png

Write Function Logic


HTTP Trigger

Create a new Function with HTTP Trigger

img-4390c2dc-872f-4012-b34e-28ff7c81b899.png

Logic code

Copy the code and replace variables to your own values. In my case, cnBridgeIp and corpIp are two static IP addresses. The dynamic IP will come from HTTP request query string or body. You can modify the code to your need.

using namespace System.Net

param($Request, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."

$ip = $Request.Query.ip
if (-not $ip) {
    $ip = $Request.Body.Ip
}

$subscriptionId = "<id>"
$tenantId = "<id>"
$rsgName = "<group>"
$nsgName = "<nsg>"
$ruleName = "<rule>"
$cnBridgeIp = "<ip>"
$corpIp = "<ip>"

$body = "251"

if ($ip) {
    # Set-AzNetworkSecurityRuleConfig
    # https://learn.microsoft.com/en-us/powershell/module/az.network/set-aznetworksecurityruleconfig?view=azps-9.5.0

    Select-AzSubscription -SubscriptionID $subscriptionId -TenantID $tenantId
    $nsg = Get-AzNetworkSecurityGroup -Name $nsgName -ResourceGroupName $rsgName
    # $httpsRule = $nsg | Get-AzNetworkSecurityRuleConfig -Name $ruleName

    ($nsg.SecurityRules | Where-Object { $_.Name -eq $ruleName }).SourceAddressPrefix = ([System.String[]] @($cnBridgeIp, $corpIp, $ip))
    $nsg | Set-AzNetworkSecurityGroup | Get-AzNetworkSecurityRuleConfig -Name $ruleName

    $body = "Updated NSG $nsgName for IP: $ip."

    Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
            StatusCode = [HttpStatusCode]::OK
            Body       = $body
        })
}
else {
    Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
            StatusCode = [HttpStatusCode]::NotFound
        })
}

Click Test/Run, enter an IP address in HTTP request body.

img-5da03571-e50d-448d-a539-1fc31944dbdf.png

Then go to your NSG to verify if the function logic is successful.

If everything is fine, click "Get function URL", then you can integrate this API endpoint to other part of your system to update NSG rule fully automatically for a dynamic IP address.

img-2ad5c55f-edee-40f8-97fc-1b91232b835b.png

You may get your dynamic IP address by Azure Function or third-party APIs. For example, in a C# Function, you can do this:

// #r "System.Text.Json"

using System.Net;
// using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    // log.LogInformation("C# HTTP trigger function processed a request.");

    var clientIp = req.HttpContext.Connection.RemoteIpAddress.ToString();
    return new OkObjectResult(clientIp);
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK