Posted in:

One of the challenges of working from home is that if you want to access cloud resources that are protected by IP restrictions, you need to add your own home IP address to the allow list for those services. This can be slow to do manually, especially if your home IP address changes frequently or if there are many services you need to access.

I decided to see if I could automate the Azure CLI to add my home IP address for various Azure Web Apps, Network Security Groups and SQL Servers I needed to access. I've created this as a PowerShell script with a function for each type of rule I wanted to add.

Discovering your home IP address

Here's a handy bit of PowerShell to retrieve your current public IP address:

$myIp = (Invoke-WebRequest -uri "https://ifconfig.me/ip").Content

Add a Web App Access Restriction

We can add a web app access restriction with the az webapp config access-restriction add command. First, I use a JMESPath query to check whether there is already an access restriction for my IP.

function Add-WebAppAccessRestriction {
    Param([String]$Sub, [String]$ResGroup, [String]$WebApp, [String]$IpAddress, [String]$RuleName)
    az account set -s $Sub
    if (!$?) {
        Write-Output "Could not select subscription"
        return
    }
    # to query by name instead use --query "ipSecurityRestrictions[?name=='$ruleName'].name"
    $exists = az webapp config access-restriction show `
        -g $ResGroup -n $WebApp `
        --query "ipSecurityRestrictions[?ip_address=='$IpAddress/32'].name" `
        -o tsv
    if (!$?) {
        Write-Output "Error checking for access restriction"
        return
    }
    if (!$exists) {
        Write-Output "Adding rule to webapp $WebApp";
        az webapp config access-restriction add `
            -g $ResGroup `
            -n $WebApp `
            --rule-name $RuleName `
            --action Allow `
            --ip-address "$IpAddress/32" `
            --priority 65000
        if (!$?) {
            Write-Output "Failed to add webapp rule"
        }
    }
    else {
        Write-Output "Restriction for webapp $WebApp already exists with name '$exists'";
    }
}

Adding a Network Security Group rule

We can follow a similar pattern for adding an NSG rule with az network nsg rule create. I again use a JMESPath query to avoid adding a new rule if my IP address is already configured.

function Add-NsgRule {
    Param([String]$Sub, [String]$ResGroup, [String]$NsgName, [String]$IpAddress, [String]$RuleName)
    az account set -s $Sub
    if (!$?) {
        Write-Output "Could not select subscription"
        return
    }
    $exists = az network nsg rule list `
        --nsg-name $NsgName -g $ResGroup `
        --query "[?sourceAddressPrefix=='$IpAddress/32' || sourceAddressPrefix=='$IpAddress'].name" `
        -o tsv
    if (!$?) {
        Write-Output "Error checking if NSG rule exists"
        return
    }
    if ($exists) {
        Write-Output "Rule for NSG $NsgName already exists with name '$exists'";
    }
    else {
        Write-Output "Adding rule to NSG $NsgName";
        az network nsg rule create -g $ResGroup `
            --nsg-name $NsgName -n $RuleName `
            --priority 4096 --access Allow `
            --source-address-prefixes "$IpAddress/32" `
            --source-port-ranges '*' `
            --destination-address-prefixes '*' `
            --destination-port-ranges '*'
        if (!$?) {
            Write-Output "Failed to add NSG Rule"
        }
    }
}

Adding a SQL Server Firewall Rule

For the SQL Server Firewall rule we need the az sql server firewall-rule create command.

function Add-SqlServerFirewallRule {
    Param([String]$Sub, [String]$ResGroup, [String]$SqlServerName, [String]$IpAddress, [String]$RuleName)
    az account set -s $Sub
    if (!$?) {
        Write-Output "Could not select subscription"
        return
    }
    $exists = az sql server firewall-rule list `
        -s $SqlServerName -g $ResGroup `
        --query "[?startIpAddress=='$IpAddress'].name" `
        -o tsv
    if (!$?) {
        Write-Output "Error checking if SQL Server firewall rule exists"
        return
    }
    if ($exists) {
        Write-Output "Firewall rule for SQL Server $SqlServerName already exists with name '$exists'";
    }
    else {
        Write-Output "Adding firewall rule to SQL Server $SqlServerName";
        az sql server firewall-rule create -g $ResGroup -s $SqlServerName `
                -n $RuleName --start-ip-address $IpAddress --end-ip-address $IpAddress
        if (!$?) {
            Write-Output "Failed to add SQL Server firewall rule"
        }
    }
}

Summary

The Azure CLI is great for automating tedious and repetitive tasks. I have a list of Azure resources that I can now quickly iterate through and allow myself access to. I can of course also automate the removal of those rules when I no longer need access.

By the way, I know my PowerShell skills are not the greatest, so do let me know if I missed any nice tricks to make the PowerShell code simpler.

Want to learn more about the Azure CLI? Be sure to check out my Pluralsight course Azure CLI: Getting Started.

Comments

Comment by Mikhail Shilkov

Why specifically with Azure CLI? I'm biased, but the Pulumi code for the same task would look much more maintainable to me.

Mikhail Shilkov