DHCP Approval using Azure Automation and Powershell

I wanted to try to prevent someone from bringing in an unapproved device onto our local network by simply plugging it into an Ethernet jack and pulling an IP address using DHCP. Microsoft's DHCP server service has a feature named DHCP Filters included with the Windows Server DHCP Server service which allows for MAC address white/black listing. I was able to use a combination of various Microsoft and Azure features to automate the process of approving and adding MAC addresses to our whitelist. Below is an explanation of how I was able to achieve this.

Resources needed:
Azure Automation Hybrid Worker agent installed on DHCP server
Azure Automation Runbook with a webhook to start it
Microsoft Power Automation Flow (formerly Microsoft Flow)
Powershell
Windows Task Scheduler
Microsoft Office 365 Outlook and SharePoint

The first step is to configure your Windows Server DHCP service scope so that IP addresses are only provided to computers with MAC addresses in the Allow List. The Deny list is optional:



Next, add a scheduled task on the DHCP server to run every minute which monitors for events indicating that a computer tried to obtain an IP address from the DHCP server but was denied due to not having its MAC address in the Allow list.

The scheduled task should run the Powershell script below every minute. It will pull the latest relevant event from Event Viewer, write the output to an XML file, and email the file to a mailbox for further processing.

Function Get-WinEventData() {
[cmdletbinding()]
param(
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ValueFromRemainingArguments=$false,
Position=0 )]
[System.Diagnostics.Eventing.Reader.EventLogRecord[]]
$event
)
Process
{
#Loop through provided events
foreach($entry in $event)
{
#Get the XML...
$XML = [xml]$entry.ToXml()
#Some events use other nodes, like 'UserData' on Applocker events...
$XMLData = $null
if( $XMLData = @( $XML.Event.EventData.Data ) )
{
For( $i=0; $i -lt $XMLData.count; $i++ )
{
#We don't want to overwrite properties that might be on the original object, or in another event node.
Add-Member -InputObject $entry -MemberType NoteProperty -name "EventData$($XMLData[$i].name)" -Value $XMLData[$i].'#text' -Force
}
}
$entry
}
}
}
$EmailTo = "your-monitored-mailbox@yourdomain.com"
$EmailFrom = "dhcpevents@yourdomain.com""
$Subject = "DHCP Filter Event"
$SMTPServer = "smtp.office365.com"
$SecureString = "c:\scripts\youremaileraccountcredentials"
$SmtpPort = "587"
# The name of the Event log to operate on
$logName = "Microsoft-Windows-Dhcp-Server/FilterNotifications"
# Read the pre-generated AES key and secure string to convert to credential
$AESKeyFilePath = "c:\scripts\aeskey"
$AESKey = Get-Content $AESKeyFilePath
$pwdText = Get-Content $SecureString
$securePwd = $pwdText | ConvertTo-SecureString -Key $AESKey
$Creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $EmailFrom, $securePwd
# The number of newest events to pull
$maxEvents = "1"
# The temp file
$outputFile = "c:\temp\dhcpfilterevents.txt"
# Get the events and write to temp file
Get-WinEvent -LogName $logName -MaxEvents $maxEvents | where {$_.Id -eq "20097"} | Get-WinEventData | Select EventDataMACAddress,EventDataHostName | ConvertTo-Json | Out-File $outputFile;
# Make sure a file exists
if (Test-Path $outputFile) {
# Make sure the length is greater than 0kb
if ((Get-Item $outputFile).length -gt 0kb) {
# Email the file
Send-MailMessage -To $EmailTo -From $EmailFrom -Subject $Subject -Attachments $outputFile -Port $SmtpPort -SmtpServer $SMTPServer -Credential $Creds -UseSsl $True;
# Give the responders 300 seconds to approve or deny the request before looking at the event viewer again to prevent duplicate emails
Start-Sleep -Seconds 300
# Delete the file
Remove-Item $outputFile
# Clear the event log
[System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession.ClearLog("Microsoft-Windows-Dhcp-Server/FilterNotifications")
}
}
else {
return 0;
}


The script above generates an XML file containing the computer name and MAC address, writes it to a file then emails it to an email address that can be monitored by a Microsoft Power Automation Flow job. Here's a visual image of the Flow:

Flow Connections needed:
Approvals
Office 365 Outlook
SharePoint


Details of each step in the Flow:






The approval process triggers an email with a link to either deny or approve the request for the computer to obtain an IP address. If you have the Microsoft Power Automation app on your phone you'll also get a push notification to which you can respond deny or approve. The name of the computer is displayed in the email notification and the push notification.

If you approve the request a webhook is fired. The webhook needs to be a link to an Azure Automation runbook which runs on a Hybrid Worker agent installed on the DHCP server. The code for the Runbook is below:

[CmdletBinding()]
Param
([object]$WebhookData) #this parameter name needs to be called WebHookData otherwise the webhook does not work as expected.
#region Verify if Runbook is started from Webhook.
# If runbook was called from Webhook, WebhookData will not be null.
if ($WebHookData){
# Collect properties of WebhookData
$WebhookName = $WebHookData.WebhookName
$WebhookHeaders = $WebHookData.RequestHeader
$WebhookBody = $WebHookData.RequestBody
# Collect individual headers. Input converted from JSON.
$From = $WebhookHeaders.From
$Input = (ConvertFrom-Json -InputObject $WebhookBody)
Write-Verbose "WebhookBody: $Input"
Write-Output -InputObject ('Runbook started from webhook {0} by {1}.' -f $WebhookName, $From)
}
else
{
Write-Error -Message 'Runbook was not started from Webhook' -ErrorAction stop
}
#endregion
#region Main
$Mac = $Input.Mac
$Description = $Input.Description
Add-DhcpServerv4Filter -List Allow -MacAddress $Mac -Description $Description -Verbose
#endregion

Comments

Popular posts from this blog

Auto-installing extensions on Firefox using Intune

Disable DNS over HTTPS in Firefox using Intune

How to find the OMA-URI from ingested ADMX files