Skip to content

Instantly share code, notes, and snippets.

@machv
Created September 1, 2020 15:09
Show Gist options
  • Save machv/1f0c956c546c93d80fb612a975c8678c to your computer and use it in GitHub Desktop.
Save machv/1f0c956c546c93d80fb612a975c8678c to your computer and use it in GitHub Desktop.
Synchronize Routing Table with Azure Service Tag Listing
#region Azure Automation bootstrap
try
{
$servicePrincipalConnection = Get-AutomationConnection -Name "AzureRunAsConnection"
"Logging in to Azure..."
Connect-AzAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection AzureRunAsConnection not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
$smtpCredential = Get-AutomationPSCredential -Name "SendGridCredentials"
#endregion
#region Configuration
# Azure
$routeTableResourceGroupName = "test_group"
$routeTableName = "RT-ForcedTunneling"
$routeNamePrefix = "ps-" # used only to detect candidates for deletion
$services = @{
"AzureBackup" = @("WestEurope", "NorthEurope")
}
# Mail notifications
$smtpServer = "smtp.sendgrid.net"
$emailFrom = "Azure Automations <[email protected]>"
$emailTo = "[email protected]" # CC added to every e-mail sent by this script
#endregion
$routeTable = Get-AzRouteTable -ResourceGroupName $routeTableResourceGroupName -Name $routeTableName
$serviceTags = Get-AzNetworkServiceTag -Location "westeurope"
$seenPrefixes = @()
$addedPrefixes = @()
foreach($service in $services.GetEnumerator()) {
$serviceName = $service.Name
$regions = $service.Value
foreach($region in $regions) {
$serviceGroups = $serviceTags.Values | Where-Object { $_.Properties.SystemService -eq $serviceName -and $_.Properties.Region -eq $region }
$prefixes = $serviceGroups | Select-Object -ExpandProperty Properties | Select-Object -ExpandProperty AddressPrefixes
foreach($prefix in $prefixes) {
$existingRoute = $routeTable.Routes | Where-Object AddressPrefix -eq $prefix
if($existingRoute) {
$seenPrefixes += $existingRoute.AddressPrefix
continue # nothing else is needed
}
$routeName = "$($routeNamePrefix)$($serviceName).$($region)-$($prefix.Replace("/", "_"))"
Write-Output " - Inserting new route for prefix $prefix with name $routeName"
Add-AzRouteConfig -RouteTable $routeTable -Name $routeName -AddressPrefix $prefix -NextHopType "Internet" | Out-Null
$addedPrefixes += $prefix
}
}
}
Write-Output "Commiting changes to the route table"
Set-AzRouteTable -RouteTable $routeTable | Out-Null
# What can be removed?
$routesToRemove = $routeTable.Routes | Where-Object { $_.AddressPrefix -notin $seenPrefixes -and $_.AddressPrefix -notin $addedPrefixes -and $_.Name.StartsWith($routeNamePrefix) }
# should we send an email notification?
if($addedPrefixes.Count -gt 0 -or $removePrefixes) {
}
#region Functions
function Build-HtmlTable {
param(
$Object,
$Columns,
$CustomPrefix,
$Tag = "td",
$Style = ""
)
$row = "<tr style='text-align: left' valign=top>$($CustomPrefix)"
foreach($column in $Columns) {
if($Object) {
$value = $Object.$column
} else {
$value = $column
}
$row += "<$($tag) style=`"$($Style)`">$($value)</$($tag)>"
}
$row += "</tr>"
$row
}
$css = @{
th = "text-align:left;color: #495057; background-color: #e9ecef; border-color: #dee2e6;line-height: 22px; font-size: 14px; border-top-width: 1px; border-top-style: solid; border-bottom-width: 1px; border-bottom-style: solid; margin: 0; padding: 12px;"
td = "text-align:left;border-spacing: 0px; border-collapse: collapse; line-height: 22px; font-size: 14px; border-color: #e9ecef; border-top-width: 1px; border-top-style: solid; border-bottom-width: 1px; border-bottom-style: solid; margin: 0; padding: 12px;"
}
$tableColumns = [Ordered]@{
Indexer = ""
Name = "Name"
AddressPrefix = "Prefix"
NextHopType = "Next Hop Type"
}
#endregion
$messageBody = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'></head><body style='font-size: 14px; font-family: Helvetica, Arial, sans-serif;'>"
$messageBody += "<p style='font-size: 14px;'>Routing table <strong>$($routeTableName)</strong> in the resource group <strong>$($routeTableResourceGroupName)</strong> has been updated.</p>"
if($addedPrefixes.Count -gt 0) {
$routes = $routeTable.Routes | Where-Object AddressPrefix -In $addedPrefixes
$messageBody += "<div style=`"margin-top: 20px; margin-bottom: 10px; font-weight: 500; color: inherit; vertical-align: baseline; font-size: 20px; line-height: 24.4px;`">Created routes</div>"
$messageBody += '<table border="0" cellpadding="0" cellspacing="0" style="font-family: Helvetica, Arial, sans-serif; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-spacing: 0px; border-collapse: collapse; width: 100%; max-width: 100%;" bgcolor="#ffffff">'
$messageBody += Build-HtmlTable -Columns $tableColumns.Values -Tag "th" -Style $css.th
$i = 1
foreach($route in $routes) {
$rowData = $route | Select-Object @{ Name = "Indexer"; Expression = { "<strong>$($i).</strong>" } }, *
$messageBody += Build-HtmlTable -Object $rowData -Columns $tableColumns.Keys -Style $css.td
$i += 1
}
$messageBody += "</table>"
}
if($routesToRemove) {
$messageBody += "<div style=`"margin-top: 20px; margin-bottom: 10px; font-weight: 500; color: inherit; vertical-align: baseline; font-size: 20px; line-height: 24.4px;`">No longer needed routes</div>"
$messageBody += "<p style='font-size: 14px;'>These routes might be removed from the routing table as their prefixes are no longer present in Azure Service Tags reference list.</p>"
$messageBody += '<table border="0" cellpadding="0" cellspacing="0" style="font-family: Helvetica, Arial, sans-serif; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-spacing: 0px; border-collapse: collapse; width: 100%; max-width: 100%;" bgcolor="#ffffff">'
$messageBody += Build-HtmlTable -Columns $tableColumns.Values -Tag "th" -Style $css.th
$i = 1
foreach($route in $routesToRemove) {
$rowData = $route | Select-Object @{ Name = "Indexer"; Expression = { "<strong>$($i).</strong>" } }, *
$messageBody += Build-HtmlTable -Object $rowData -Columns $tableColumns.Keys -Style $css.td
$i += 1
}
$messageBody += "</table>"
}
$messageBody += "</body></html>"
$messageBody | Set-Clipboard
if($addedPrefixes.Count -gt 0 -or $routesToRemove) {
Send-MailMessage -SmtpServer $smtpServer -Credential $smtpCredential -UseSsl -Port 587 `
-From $emailFrom -To $emailTo -Subject "Updated Routing Table $($routeTableName)" `
-Body $messageBody -BodyAsHtml -Encoding UTF8
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment