Cloud Identity: Entra ID Stale Guest Reaper

The Workflow The Implementation External guest accounts are frequently provisioned for vendors but rarely decommissioned, creating a lingering attack surface. This script uses the Microsoft Graph API to identify and remove guest accounts that have been inactive for over 90 days. 1. The Workflow The script performs the following steps: Authentication: Uses App Registration credentials to silently authenticate to MS Graph. Filtering: Queries all users where userType equals “Guest”. Evaluation: Checks the signInActivity property against a 90-day threshold. Purge: Identifies stale guest accounts to close the security loop. 2. The Implementation $ThresholdDate = (Get-Date).AddDays(-90).ToString("yyyy-MM-ddTHH:mm:ssZ") $Url = "[https://graph.microsoft.com/beta/users](https://graph.microsoft.com/beta/users)?`$filter=userType eq 'Guest'&`$select=displayName,userPrincipalName,signInActivity" $Guests = Invoke-RestMethod -Uri $Url -Method Get -Headers $Headers foreach ($Guest in $Guests.value) { if ([string]::IsNullOrEmpty($Guest.signInActivity.lastSignInDateTime) -or ($Guest.signInActivity.lastSignInDateTime -lt $ThresholdDate)) { Write-Host "Stale Guest Found: $($Guest.displayName)" } }

May 3, 2026 · 1 min · Alfred van Ster

Endpoint Security: BitLocker Key Escrow to IT Glue

The Workflow The Implementation Relying on manual documentation for BitLocker recovery keys often results in locked data when an endpoint fails. This script automates the escrow process, pulling the active numeric password from the local disk and pushing it directly into an IT Glue configuration record via their REST API. 1. The Workflow The script performs the following steps: Extraction: Queries the WMI namespace for the active, 48-digit BitLocker Numeric Password on the OS drive. Authentication: Connects to the IT Glue API using a secure organizational API key. Payload Delivery: Matches the local Hostname to the IT Glue Configuration ID and PATCHes the “BitLocker Key” custom field with the extracted key. 2. The Implementation # IT Glue API Configuration $ITGKey = "YOUR_ITGLUE_API_KEY" $ITGBaseUrl = "[https://api.itglue.com](https://api.itglue.com)" $Header = @{ "x-api-key" = $ITGKey "Content-Type" = "application/vnd.api+json" } $BitLocker = Get-BitLockerVolume -MountPoint $env:SystemDrive $RecoveryKey = ($BitLocker.KeyProtector | Where-Object { $_.KeyProtectorType -eq 'RecoveryPassword' }).RecoveryPassword $SearchUri = "$ITGBaseUrl/configurations?filter[name]=$env:COMPUTERNAME" $ConfigRecord = Invoke-RestMethod -Uri $SearchUri -Method Get -Headers $Header if ($ConfigRecord.data) { $Payload = @{ data = @{ type = "configurations" attributes = @{ "custom-fields" = @{ "bitlocker-recovery-key" = $RecoveryKey } } } } | ConvertTo-Json -Depth 10 Invoke-RestMethod -Uri "$ITGBaseUrl/configurations/$($ConfigRecord.data[0].id)" -Method Patch -Headers $Header -Body $Payload }

May 3, 2026 · 1 min · Alfred van Ster

Infrastructure: Hyper-V Orphaned Snapshot Monitor

The Workflow The Implementation A common L3 infrastructure issue is technicians taking a VM checkpoint before an update and forgetting to delete it. This script scans for stale snapshots and fires an alert to a Microsoft Teams or Slack webhook. 1. The Workflow The script performs the following steps: Discovery: Scans the local Hyper-V host for all active checkpoints. Evaluation: Compares the creation date of the snapshot against a 7-day threshold. Alerting: If stale snapshots exist, it constructs a JSON payload and POSTs it to a designated webhook URL. 2. The Implementation $ThresholdDate = (Get-Date).AddDays(-7) $StaleSnapshots = Get-VM | Get-VMSnapshot | Where-Object { $_.CreationTime -lt $ThresholdDate } if ($StaleSnapshots) { $Payload = @{ text = "⚠️ Orphaned Snapshots Detected on $env:COMPUTERNAME" } | ConvertTo-Json Invoke-RestMethod -Uri "[https://your-webhook.url](https://your-webhook.url)" -Method Post -Body $Payload -ContentType "application/json" }

May 3, 2026 · 1 min · Alfred van Ster

Infrastructure: Windows Server DNS Stale Record Scavenger

The Workflow The Implementation In dynamic DHCP environments, DNS zones become polluted with stale A-records. This script provides a surgical, auditable way to identify and purge stale DNS records older than a defined threshold. 1. The Workflow The script performs the following steps: Targeting: Selects a specific internal DNS zone. Evaluation: Pulls all A records and compares the Timestamp against a 14-day threshold. Execution: Exports a CSV log of the stale records before actively removing them from the server. 2. The Implementation $ZoneName = "internal.avanster.tech" $ThresholdDate = (Get-Date).AddDays(-14) $Records = Get-DnsServerResourceRecord -ZoneName $ZoneName -RRType "A" foreach ($Record in $Records) { if ($Record.Timestamp -ne $null -and $Record.Timestamp -lt $ThresholdDate) { Remove-DnsServerResourceRecord -ZoneName $ZoneName -InputObject $Record -Force Write-Host "[-] Removed: $($Record.HostName)" } }

May 3, 2026 · 1 min · Alfred van Ster

M365 Security: Unauthorized Mailbox Forwarding Auditor

The Workflow The Implementation A classic BEC tactic involves configuring an inbox rule to forward emails to an external address. This script audits an entire Exchange Online tenant for any mailboxes with active forwarding rules to external domains. 1. The Workflow The script performs the following steps: Connection: Authenticates to Exchange Online via module parameters. Auditing: Iterates through all user mailboxes checking forwarding properties. Evaluation: Compares the forwarding destination against the tenant’s accepted domains. Alerting: Outputs a high-priority warning if external exfiltration is detected. 2. The Implementation Connect-ExchangeOnline -ShowBanner:$false $AcceptedDomains = (Get-AcceptedDomain).Name foreach ($Mailbox in (Get-Mailbox -ResultSize Unlimited)) { if ($Mailbox.ForwardingSmtpAddress) { $ForwardDestination = $Mailbox.ForwardingSmtpAddress.Replace("smtp:","") if ($ForwardDestination -notmatch ($AcceptedDomains -join "|")) { Write-Host "⚠️ EXTERNAL FORWARD: $($Mailbox.UserPrincipalName) -> $ForwardDestination" -ForegroundColor Red } } }

May 3, 2026 · 1 min · Alfred van Ster

Zero-Touch M365 Offboarding with n8n, Docker, and PowerShell

Overview In a Managed Service Provider (MSP) environment, manual offboarding is a massive liability. Missing a step when revoking access can lead to data breaches, compliance violations, and wasted licensing costs. This guide outlines an architectural approach to “Zero-Touch” offboarding, leveraging a self-hosted n8n instance running in Docker to trigger a robust PowerShell workflow that interacts directly with the Microsoft Graph API. The Architecture Relying on technicians to manually run scripts on their local machines creates bottlenecks. By containerizing the automation engine, we achieve predictable, auditable execution. ...

May 3, 2026 · 2 min · Alfred van Ster

SecOps: SentinelOne Global Threat Scraper

When a new 0-day vulnerability or a suspicious file hash is identified, waiting for a scheduled scan is not an option. This PowerShell tool utilizes the SentinelOne Management API to “scrape” the entire fleet for specific indicators of compromise (IOCs). 1. The Workflow The script performs the following steps: Authentication: Connects via API Token to the S1 Management Console. Query: Requests a list of all endpoints where a specific file hash or process has been detected in the last 24 hours. Reporting: Generates a CSV list of infected Hostnames, IP addresses, and the “Detection State” (Mitigated vs. Active). 2. The Implementation # S1 API Configuration $ApiToken = "YOUR_API_TOKEN" $BaseUrl = "[https://your-console.sentinelone.net/web/api/v2.1](https://your-console.sentinelone.net/web/api/v2.1)" $Header = @{ "Authorization" = "Token $ApiToken" } # Define the Threat Hash to hunt for $TargetHash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" # Search for the hash across the site $Response = Invoke-RestMethod -Uri "$BaseUrl/threats?contentHashes=$TargetHash" -Method Get -Headers $Header if ($Response.data) { Write-Host "ALERT: Threat detected on $($Response.data.count) endpoints!" -ForegroundColor Red $Response.data | Select-Object computerName, lastActiveDate, threatName | Export-Csv -Path "./ThreatReport.csv" } else { Write-Host "Clear: No matches found for the target hash." -ForegroundColor Green }

January 10, 2026 · 1 min · Alfred van Ster