Execute this script maybe meme

How to update application settings for (all of your) App Services and Azure Functions on Azure using az cli?

4 min read.

Anyone still remember Log4Shell? The incredibly easy-to-exploit, zero-day vulnerability in Log4j, a popular Java logging framework, that made arbitrary code execution extremely simple and straightforward.

The vulnerability had existed unnoticed since 2013 and was simply a side effect of a nifty new feature implemented way back when.

But that’s enough of that. How serious was it?

Well – Apache gave Log4Shell a CVSS severity rating of 10, the highest available score. The exploit is simple to execute and is estimated to affect hundreds of millions of devices.

Affected commercial services included Azure, Amazon Web Services, Cloudflare, iCloud, Minecraft: Java Edition, Steam and many, MANY other environments running Java.

Yes, even Azure – if you’re running Java or relying on functionality running Java behind the scenes. According to Wiz and EY, the vulnerability affected 93% of enterprise cloud environments.

The vulnerability’s disclosure received strong reactions from cybersecurity experts. Cybersecurity company Tenable said the exploit was “the single biggest, most critical vulnerability ever” and Ars Technica called it “arguably the most severe vulnerability ever”.

Problem

Azure web apps and Azure Function apps can both, under the right circumstances, be vulnerable.

Microsoft has, however, published mitigation instructions. Applying the mitigation requires changing a couple of application settings for your apps.

Now – chances are that Log4Shell is patched in your environments. But to make sure they were safe, a customer wanted a script that’d apply the workaround/mitigation properties to all of their app services and function apps.

But the API / CLI / Commandlet support for a scenario like this isn’t exactly great.

Luckily – this is a problem just waiting for a scripted solution :) I was surprised to find out there weren’t many (if any?) available online. So I made one myself.

Solution

So, long story short, below is the script I came up with. Could do with some prettifying, but eh – guess it does the trick.

It’ll go through all of your subscriptions and all of the Azure App Services and Azure Functions in them, create a list of them, and then go through them all and update the required application settings, configurations or properties.

I’d really, REALLY hope that running this is under any circumstances actually required to mitigate Log4Shell anymore – but perhaps you can use the script for some actual use case.

It comes with 2 simple prerequisites.

Prerequisites

  1. Install az cli
  2. Refresh all of your az account sessions

Installing az cli is pretty quick. Refreshing your old sessions is not, but there’s at least a script available for that as well:
How to refresh all Az CLI subscriptions?

Script sample

And here’s the script:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine

az login

$output = @()
$Subscriptions = az account list --all | ConvertFrom-Json

foreach ($sub in $Subscriptions) {

    az account set --subscription $sub.id

    $apps = az webapp list | ConvertFrom-Json
    
    foreach ($app in $apps) {

        $appSettings = az webapp config appsettings list --name $app.name --resource-group $app.resourceGroup | ConvertFrom-Json
        $config = (az webapp show -n $app.name -g $app.resourceGroup | ConvertFrom-Json).SiteConfig

        Write-Host $app.name "has" $appSettings.Count "appsettings &" ($config | Get-Member).Count "config values."

        $row = "" | Select-Object Name, RG, Type, OS, Kind, SKU, Properties, Sub
        $row.Name = $app.Name
        $row.RG = $app.ResourceGroup
        $row.Type = $app.Kind
        if ($row.Type -like "*linux*") {
            $row.OS = "Linux"
        }
        else {
            $row.OS = "Windows"
        }
        $row.Kind = "app"
        $row.SKU = (az appservice plan show --ids $app.appServicePlanId | ConvertFrom-JSON).sku.family

        $row.Properties = $appSettings

        $row.Sub = $sub.id
        $output += $row
    }

    $appfunctions = az functionapp list | ConvertFrom-Json

    foreach ($app in $appfunctions) {

        $appSettings = az webapp config appsettings list --name $app.name --resource-group $app.resourceGroup | ConvertFrom-Json
        $config = (az webapp show -n $app.name -g $app.resourceGroup | ConvertFrom-Json).SiteConfig
        # $config | Get-Member | out-gridview

        Write-Host $app.name "has" $appSettings.Count "appsettings &" ($config | Get-Member).Count "config values."

        $row = "" | Select-Object Name, RG, Type, OS, Kind, SKU, Properties, Sub
        $row.Name = $app.Name
        $row.RG = $app.ResourceGroup
        $row.Type = $app.Kind
        if ($row.Type -like "*linux*") {
            $row.OS = "Linux"
        }
        else {
            $row.OS = "Windows"
        }
        $row.Kind = "functionapp"
        $row.SKU = (az functionapp plan show --ids $app.appServicePlanId | ConvertFrom-JSON).sku.family # If this is "Y", we have a consumption plan

        $row.Properties = $appSettings

        $row.Sub = $sub.id
        $output += $row
    }
}

$output | Out-GridView

Write-Host "Now adding the required settings..."

$apps_linux = 0
$apps_windows = 0
$functions_windows = 0
$functions_linux = 0
$functions_consumption_linux = 0
$functions_consumption_windows = 0

$errors = @()

foreach ($r in $output) {
    try {
        az account set --subscription $r.Sub

        if ($r.Kind -like "app" -and $r.OS -like "Linux") {
            Write-Host "Adding Linux settings for app service" $r.Name
    
            $apps_linux++
    
            az webapp config appsettings set --resource-group $r.RG --name $r.Name --settings "LOG4J_FORMAT_MSG_NO_LOOKUPS=true"
        }
        elseif ($r.Kind -like "app" -and $r.OS -like "Windows") {
            Write-Host "Adding Windows settings for app service" $r.Name
    
            $apps_windows++
    
            az webapp config appsettings set --resource-group $r.RG --name $r.Name --settings "LOG4J_FORMAT_MSG_NO_LOOKUPS=true"
        }
        elseif ($r.Kind -like "functionapp" -and $r.OS -like "Windows" -and $r.SKU -like "Y") {
            Write-Host "Adding Windows settings for consumption function app" $r.Name
    
            $functions_windows++
    
            az functionapp config appsettings set --subscription $r.Sub --name $r.Name --resource-group $r.RG --settings "languageWorkers:java:arguments=-Dlog4j2.formatMsgNoLookups=true"
        }
        elseif ($r.Kind -like "functionapp" -and $r.OS -like "Linux"  -and $r.SKU -like "Y") {
            Write-Host "Adding Linux settings for consumption function app" $r.Name
    
            $functions_linux++
    
            az functionapp config appsettings set --subscription $r.Sub --name $r.Name --resource-group $r.RG --settings "languageWorkers__java__arguments=-Dlog4j2.formatMsgNoLookups=true"
        }
        elseif ($r.Kind -like "functionapp" -and $r.OS -like "Windows" -and $r.SKU -notlike "Y") {
            Write-Host "Adding Windows settings for dedicated/premium function app" $r.Name
    
            $functions_consumption_windows++
    
            az functionapp config appsettings set --subscription $r.Sub --name $r.Name --resource-group $r.RG --settings "LOG4J_FORMAT_MSG_NO_LOOKUPS=true" "WEBSITE_USE_PLACEHOLDER=0"
        }
        elseif ($r.Kind -like "functionapp" -and $r.OS -like "Linux"  -and $r.SKU -notlike "Y") {
            Write-Host "Adding Linux settings for dedicated/premium function app" $r.Name
    
            $functions_consumption_linux++
    
            az functionapp config appsettings set --subscription $r.Sub --name $r.Name --resource-group $r.RG --settings "LOG4J_FORMAT_MSG_NO_LOOKUPS=true" "WEBSITE_USE_PLACEHOLDER=0"
        }
        else {
            Write-Host "Couldn't recognize this row: " $r.Name
        }
    }
    catch 
    {
        $errors += $_
    }
}

Write-Host "App Service Linux:" $apps_linux", App Service Windows:" $apps_windows", Function App Windows:" $functions_windows", Function App Linux:" $functions_linux", Function App Consumption Windows:" $functions_consumption_windows", Function App Consumption Linux:" $functions_consumption_linux

if ($errors.Count -gt 0) {

    Write-Host "OH SNAP! Errors inbound:"

    foreach($e in $errors) {
        Write-Host $e
    }

    $errors | Out-GridView
}

References

mm
0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments