Find Java Based Azure App Services

A quick Azure PowerShell command to locate any Java based Azure App Services and Functions so you can check if they are vulnerable to the CVE-2021-44228 Apache Log4j2 vulnerability.

Get-AzWebApp | ForEach-Object{
    Get-AzWebApp -ResourceGroupName $_.ResourceGroup -Name $_.Name | 
    Select-Object -Property Name, @{l='JavaVersion';e={$_.SiteConfig.JavaVersion}}, ResourceGroup, Id 
} | Format-Table
  |  
Practical Automation with PowerShell

After months and months of work, I’m proud to announce my new book is now available for purchase.

Practical Automation with PowerShell

Practical Automation with PowerShell reveals how you can use PowerShell to build automation solutions for a huge number of common admin and DevOps tasks. It takes you beyond scripting basics and shows you how to handle the unforeseen complexities that can keep automations from becoming reusable and resilient. You’ll discover tools and platforms that let you share your automations with your team and even roll them out to non-technical users through easy-to-understand frontends.

All code examples and scripts in the book are available on the GitHub repo for the book.
Practical-Automation-with-PowerShell

The book is in the Manning Early Access Program (MEAP). In MEAP, you read a book chapter-by-chapter while it’s being written and get the final eBook as soon as it’s finished. Which offers several benefits over the traditional “wait to read” model.

  • • Get started now. You can read early versions of the chapters before the book is finished.
  • • Regular updates. We’ll let you know when updates are available, and you can get the new content from your Manning user account.
  • • Get finished books faster. MEAP customers are the first to get final eBooks and pBooks.
  • • Contribute to the writing process. Your feedback in the liveBook Discussion Forum makes the book better.

Be sure to check back here, GitHub, and Manning

Quick and Easy Password Generator

This is a quick and easy password/random character generator. It returns random numbers between 33 and 126 and converts the number to the corresponding ASCII character.

$password = [string]::Empty
1..32 | ForEach-Object {
    $password += [char]$(33..126 | Get-Random)
}
Resubmit Azure Automation Runbook Job

This snippet will allow you to re-run any Azure Automation Runbook job with the same parameters and in the same context (Azure or Hybrid Worker Group).

# Set the variables from the previous job
$AutomationAccountName = ''
$ResourceGroupName     = ''
$JobId                 = ''

# Get the previous job
$AutoAccount = @{
    AutomationAccountName = $AutomationAccountName
    ResourceGroupName     = $ResourceGroupName
}
$PreviousJob = Get-AzAutomationJob @AutoAccount -Id $JobId

# Build the parameters to resubmit
$StartRunbook = $AutoAccount.Clone()
# Add Runbook Name
$StartRunbook.Add('Name',$PreviousJob.RunbookName)
# If Hybrid Worker used, add it
if(-not [string]::IsNullOrEmpty($PreviousJob.HybridWorker)){
    $StartRunbook.Add('RunOn',$PreviousJob.HybridWorker)
}
# Create a hashtable with the parameters
if($PreviousJob.JobParameters.Count -gt 0){
    $Parameters = @{}
    $PreviousJob.JobParameters.GetEnumerator() | ForEach-Object{
        $Parameters.Add($_.Key,$_.Value)
    }
    $StartRunbook.Add('Parameters',$Parameters)
}

# Start the job
$RBjob = Start-AzAutomationRunbook @StartRunbook
$RBjob
  |  |  
Copy Azure Permissions

I was replacing an old service account with a service principal, and needed to replicate the permissions in Azure. I was able to do that without missing anything, using the command below.

$CopyFrom = 'Object to copy from'
$CopyTo = 'Object to copy to'
Get-AzRoleAssignment -ObjectId $CopyFrom | ForEach-Object{
    New-AzRoleAssignment -ObjectId $CopyTo -RoleDefinitionId $_.RoleDefinitionId -Scope $_.Scope
}
  |  |  
Reboot remote computer and wait

This script that will send a reboot command to a remote computer. It will then monitor for it to go offline and then come back online. Optionally, you can have it monitor for a service to return to running.

# The remote computer to reboot
$computer = 'YourComputer'
# the name of a service to check for after reboot
$Service  = 'WinRM'

# send reboot command to remote computer
Restart-Computer -ComputerName $computer -Force -ErrorAction Stop

# ping computer every second until it goes offline
do{
    $test = Test-Connection -ComputerName $Computer -Count 1 -Quiet
    Start-Sleep -s 1
}while($test -ne $false)

# ping computer every 10 seconds until it comes back online
while($test -eq $false){
    $test = Test-Connection -ComputerName $Computer -Count 1 -Quiet
    Start-Sleep -s 10
}

# wait for service to show running
if(-not [string]::IsNullOrEmpty($Service)){
    do{
        $test = Get-Service -Name  -ComputerName $Computer -ErrorAction SilentlyContinue
        Start-Sleep -s 10
    }while($test.Status -ne 'Running')
}
  |  
Testing and Deploying ARM Templates

I often find that when building an ARM template, I need to test it multiple times. So, I created the script below that will create the resource group (is it doesn’t exist), run the test cmdlet (and stop if there is a problem), and deploy the template to Azure. It will create a new name for the deployment each time based on the file name, and the current time. This will allow you to view the details of each individual deployment in Azure.

$ResourceGroupName = ''
$TemplateFile = '' 
$ParameterFile = ''

# Create the resource group, if not already there
try {
    Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction Stop | Out-Null
} catch {
    New-AzResourceGroup -Name $ResourceGroupName -Location "EastUS" 
}

# Create parameter hashtable for splatting
$params = @{
    ResourceGroupName = $ResourceGroupName
    TemplateFile = $TemplateFile
    TemplateParameterFile = $ParameterFile
}

# Test the template first, stop execution if test fails
$test = Test-AzResourceGroupDeployment @params
if($test){
    $test
    $test.Details.Details
    break
}

$DeploymentName = [System.IO.Path]::GetFileNameWithoutExtension($TemplateFile) + '_' +
    (Get-Date).ToString('yyyyMMddHHmm')

New-AzResourceGroupDeployment @params -Name $DeploymentName
  
Apply CVE-2020-1350 Workaround to Remote Computer

A patch has been released for the security vulnerability CVE-2020-1350, which has a 10 out of 10 on the CVSS scale and affects all Windows DNS servers from 2003 to 2019. However, since not everyone can patch systems right away, Microsoft has provided a workaround. The workaround restricts the size of DNS response packets, which only requires a restart of the DNS service and not the entire server. I recommend reading the knowledge base article to understand all the risks, prior to implementing in your environment.

The script below will apply the recommended registry setting and restart the DNS service on a remote computer.

$Computer = 'YourComputer'
Invoke-Command -computername $Computer -ScriptBlock {
    New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\DNS\Parameters" -Name "TcpReceivePacketSize" -Value "0xFF00" -PropertyType "DWord" -Force
    Restart-Service -Name DNS -Force
}
  |  
Quickly Switch Azure Subscriptions with PSNotes

If you are now aware, PSNotes is a PowerShell module I developed that allows you save code snippets, and recall them right in you PowerShell using an alias. One great use for this I have found is for switching between Azure subscriptions. 

I work in multiple different subscriptions throughout the day. Some are in the same tenant, but some require me to authenticate with different accounts. So, I wrote the code block below that attempts to switch subscriptions, but if it can’t with the current logged in user, it prompts me to authenticate.

$SubscriptionId = ''
if($(Get-AzContext).Subscription.SubscriptionId -ne $SubscriptionId){
    Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction SilentlyContinue
    if($(Get-AzContext).Subscription.SubscriptionId -ne $SubscriptionId){
        Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue
        Clear-AzDefault -Force -ErrorAction SilentlyContinue
        $connect = Add-AzAccount -SubscriptionId $SubscriptionId
    }
}

This works great, but I still need to remember the GUID of every subscription I need to connect to. This is where the PSNotes module comes in handy. Using the New-PSNote command, I can create an alias for every subscription I regularly connect to. For example, I used the command below to create an alias for my development subscription.

New-PSNote -Note 'AzDev' -Tags 'AzConnect' -Alias 'AzDev' -ScriptBlock{
	$SubscriptionId = 'ca21f08b-8a8e-4997-9e6e-515aa470c0a2'
	if($(Get-AzContext).Subscription.SubscriptionId -ne $SubscriptionId){
		Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction SilentlyContinue
		if($(Get-AzContext).Subscription.SubscriptionId -ne $SubscriptionId){
			Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue
			Clear-AzDefault -Force -ErrorAction SilentlyContinue
			$connect = Add-AzAccount -SubscriptionId $SubscriptionId
		}
	}
	Write-Host "You are now connected to $($(Get-AzContext).Subscription.Name)"
}

Now all I need to do to connect to this subscription is type “AzDev -run” into my console, and I’m connected to my development subscription.

  |  
Parse Email Address

You can use this snippet to parse an email address and extract the different components of it. (Tip. It works for UPNs too)

New-Object "System.Net.Mail.MailAddress" -ArgumentList $emailAddress

Details

You can also send strings formatted with the display name. For example:

‘Microsoft Azure <[email protected]>’



Example

PS C:\> $emailAddress = '[email protected]'
>> New-Object "System.Net.Mail.MailAddress" -ArgumentList $emailAddress


DisplayName User       Host        Address
----------- ----       ----        -------
            mick.jones contoso.com [email protected]

  |