/images/avatar.png

Work and live with IT

Is this ip address part of the Office 365 IP address range?

The analysis of firewall logs in Office 365 projects repeatedly raises the question: Is this blocked IP address part of the Office 365 address range?

Thanks to PowerShell and the information published by Microsoft, the answer is only a few lines of code away.

My script “Test-IsO365IpAddress.ps1” simply needs the IP address in question and optionally the TCP/UDP port. It retrieves the current list of address ranges from Microsoft and checks if the IP address is part of one of the IP networks. If this is the case, the script outputs all services that use this network.

SCHANNEL settings in Azure Windows Marketplace image changed

A couple of weeks ago I recognized new registry keys the SCHANNEL settings of the Windows 2016 Azure Marketplace image. Those setting are different from a manually deployed and updated Windows machine!

The newly created registry keys disable the following ciphers and protocols

  • Ciphers
    • RC4 128/128
    • RC4 40/128
    • RC4 56/128
  • Protocols
    • SSL 2.0 Client
    • SSL 3.0 Client/Server

First of all: The settings changed are regarding old ciphers and protocols that should be disabled in any secure environment after all! Some of them are even disabled without any registry keys starting Windows 2016 already.

Query the Log Analytics Workspace for all Azure VM

Sometimes you just need to know to which Log Analytics Workspace (OMS for the old folks out there) a VM send it’s data to. Or even all of you Azure VMs an once.

With the following script this task is easy as pie. And thanks to RamblingCookieMonster and his PSExcel modul you can send the result straight to everybody who is fond of Excel.

ReportLogAnalyticsWorkspacePerVM.ps1

#region Report: All VMs including the status, and OMS workplace
$Subscriptions = Get-AzureRmSubscription | Where-Object { $_.Name -in ("SUB01","SUB02") }
$OmsWorkspaces = @()
ForEach ($Subscription in $Subscriptions) {
    $SubscriptionName = $Subscription.Name
    Set-AzureRmContext -SubscriptionName "$SubscriptionName" | Out-Null
    $OmsWorkspaces += Get-AzureRmOperationalInsightsWorkspace
}
$Report = ForEach ($Subscription in $Subscriptions) {
    $SubscriptionName = $Subscription.Name
    Set-AzureRmContext -SubscriptionName "$SubscriptionName" | Out-Null
    $RGs = Get-AzureRMResourceGroup
    foreach ($RG in $RGs) {
        $VMs = Get-AzureRmVM -ResourceGroupName $RG.ResourceGroupName
        foreach ($VM in $VMs) {
            # Query OMS Workspace
            $VM = Get-AzureRmVM -ResourceGroupName $RG.ResourceGroupName -Name $VM.Name
            $ExtensionName = $VM.Extensions | Where-Object { $_.VirtualMachineExtensionType -in ("MicrosoftMonitoringAgent", "OmsAgentForLinux") } | Select-Object -ExpandProperty Name -First 1
            if ( $ExtensionName ) {
                $ExtensionInformation = Get-AzureRmVMExtension -ResourceGroupName $VM.ResourceGroupName -VMName $VM.Name -Name $ExtensionName
                $OmsWorkspaceId = ($ExtensionInformation.PublicSettings | ConvertFrom-Json).workspaceId
                if ( $OmsWorkspaceId ) {
                    $OmsWorkspace = $OmsWorkspaces | Where-Object { $_.CustomerId -eq $OmsWorkspaceId }
                    $OmsWorkspaceName = "$($OmsWorkspace.Name)"
                } else {
                    $OmsWorkspaceName = "n/a"
                    $OmsWorkspaceId = "n/a"
                }
            } else {
                $OmsWorkspaceName = "n/a"
                $OmsWorkspaceId = "n/a"
            }
            # VM Status (running/deallocated/stopped)
            $VMDetail = Get-AzureRmVM -ResourceGroupName $RG.ResourceGroupName -Name $VM.Name -Status
            $VMStatusDetail = $VMDetail.Statuses.DisplayStatus -match "^VM .*$"
            New-Object psobject -Property @{
                "VMName"           = $VM.Name
                "OSType"           = $VM.StorageProfile.OSDisk.OSType
                "ResourceGroup"    = $RG.ResourceGroupName
                "VMStatus"         = "$VMStatusDetail"
                "SubscriptionName" = $SubscriptionName
                "OmsWorkspaceName" = $OmsWorkspaceName
                "OmsWorkspaceId"   = $OmsWorkspaceId
            }
            Remove-Variable -Name OmsWorkspaceId -ErrorAction SilentlyContinue
            Remove-Variable -Name ExtensionName -ErrorAction SilentlyContinue
        }
    }
}
# Export as XLSX file
Import-Module PSExcel
$Filename = "LogAnalytics_Report_" + (Get-Date).ToString("yyyy-MM-dd_HHmmss")
$Report | Export-XLSX -Path "~/$Filename.xlsx" -Table -Autofit

Azure Log Analytics - RegEx case insensitive

When searching in Log Analytics, matches regex can be very helpful. By default, the Regular Expression Case is Sensitive. To change this, the parameter i must be passed.

Here is a sample query that searches the IIS logs for logs from a particular computer.

W3CIISLog
| where ( Computer matches regex "(?i)MyCoMpUtEr" )
// (?i) = Case insensitive

AzureRM.Network 0.9 breaks Azure Automation Runbooks

If you are using Azure Automation and use the AzureRM.Network module in one of the versions from 0.9.0 to min. 0.10.0, you may experience problems running Azure Automation Runbooks.

If the runbooks used are more complex overall, this version may result in a high memory load. If more than 400 MB RAM are used, the runbook ends after three attempts in the status “Suspended”.

Failure

The runbook job was attempted 3 times, but it failed each time. Common reasons that runbook jobs fail can be found here:
https://docs.microsoft.com/en-us/azure/automation/automation-troubleshooting-automation-errors

Find a free IP address in Azure

Whether with automated deployment or when creating a load balancer in Azure. Finding a free IP address is unfortunately not an easy task with the existing cmdlets.

Test-AzureRmPrivateIPAddressAvailability

A popular way to archive that is to use the cmdlet Test-AzureRmPrivateIPAddressAvailability. It returns the value TRUE or FALSE when specifying the network and an IP address. Some people now loop through every network address in a subnet until a free IP address is confirmed by TRUE.