Reorganize repo: compartmentalize scripts by client/project

Move 150+ scripts from root and scripts/ into client/project directories:
- clients/dataforth/scripts/ (110 files: AD2, sync, SSH, DB, DOS scripts)
- clients/bg-builders/scripts/ (14 files: Lesley mgmt, Exchange, termination)
- clients/internal-infrastructure/scripts/ (10 files: GDAP, Gitea, backups)
- projects/msp-tools/scripts/ (9 files: CIPP, MSP onboarding, Datto)
- projects/gururmm-agent/scripts/ (3 files: API test, JWT, record counts)
- clients/glaztech/scripts/ (1 file: CentraStage removal)

Also reorganized:
- VPN scripts → infrastructure/vpn-configs/
- Retrieved API/JS files → api/
- Forum posts → projects/community-forum/forum-posts/
- SSH docs → clients/internal-infrastructure/docs/
- NWTOC/CTONW docs → projects/wrightstown-smarthome/docs/
- ACG website files → projects/internal/acg-website-2025/
- Dataforth docs → clients/dataforth/docs/
- schema-retrieved.sql → docs/database/

Deleted 24 tmp_*.ps1 one-off debug scripts (preserved in git history).
Root reduced from 220+ files to 62 items (docs + directories only).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-20 17:15:07 -07:00
parent 98ea867d2c
commit 5cbd49ce24
207 changed files with 49 additions and 547 deletions

View File

@@ -0,0 +1,37 @@
# BG Builders - Assign Exchange Administrator role to Claude-MSP-Access service principal
# Required for Exchange Online app-only auth (Set-Mailbox, litigation hold, etc.)
# Run from interactive PowerShell as sysadmin@bgbuildersllc.com
$tenantId = "ededa4fb-f6eb-4398-851d-5eb3e11fab27"
$spId = "9c04bb74-c2d0-4d83-ab54-9c43a9daaa23" # Claude-MSP-Access SP in BG Builders
$exoRoleId = "87706939-e519-4028-a73e-a6a7f04b4a20" # Exchange Administrator
Write-Output "Connecting to Graph..."
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Identity.DirectoryManagement
Connect-MgGraph -TenantId $tenantId -Scopes 'RoleManagement.ReadWrite.Directory' -NoWelcome
Write-Output "[OK] Connected"
Write-Output "Assigning Exchange Administrator to Claude-MSP-Access..."
$body = @{
"@odata.id" = "https://graph.microsoft.com/v1.0/servicePrincipals/$spId"
}
New-MgDirectoryRoleMemberByRef -DirectoryRoleId $exoRoleId -BodyParameter $body
Write-Output "[OK] Exchange Administrator role assigned"
# Now set litigation hold on Lesley
Write-Output "`nConnecting to Exchange Online..."
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName "sysadmin@bgbuildersllc.com" -ShowBanner:$false
Write-Output "[OK] Connected"
Write-Output "Setting litigation hold on Lesley's mailbox..."
Set-Mailbox -Identity "lesley@bgbuildersllc.com" -LitigationHoldEnabled $true -LitigationHoldDuration Unlimited
Write-Output "[OK] Litigation hold enabled"
Write-Output "`nVerifying..."
Get-Mailbox -Identity "lesley@bgbuildersllc.com" | Format-List DisplayName,LitigationHoldEnabled,LitigationHoldDuration
Disconnect-ExchangeOnline -Confirm:$false
Disconnect-MgGraph
Write-Output "[OK] Done"

View File

@@ -0,0 +1,81 @@
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Users
Import-Module Microsoft.Graph.Groups
Import-Module Microsoft.Graph.Sites
$tenantId = "ededa4fb-f6eb-4398-851d-5eb3e11fab27"
$lesleyUPN = "lesley@bgbuildersllc.com"
Write-Output "========================================="
Write-Output " BG Builders - Lesley Roth Ownership Audit"
Write-Output " $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Output "========================================="
Connect-MgGraph -TenantId $tenantId -Scopes 'User.Read.All','Group.Read.All','Sites.Read.All','TeamSettings.Read.All' -NoWelcome
$lesley = Get-MgUser -UserId $lesleyUPN -Property Id,DisplayName
Write-Output "[OK] Lesley ID: $($lesley.Id)"
# --- Check Teams/M365 Group ownership ---
Write-Output "`n--- Teams / M365 Group Ownership ---"
$ownedGroups = Get-MgUserOwnedObject -UserId $lesley.Id -All
if ($ownedGroups) {
foreach ($obj in $ownedGroups) {
$group = Get-MgGroup -GroupId $obj.Id -Property DisplayName,GroupTypes,Mail -ErrorAction SilentlyContinue
if ($group) {
$isTeam = $group.GroupTypes -contains "Unified"
$type = if ($isTeam) { "M365 Group/Team" } else { "Group" }
Write-Output " [OWNER] $type : $($group.DisplayName) ($($group.Mail))"
# Check if sole owner
$owners = Get-MgGroupOwner -GroupId $obj.Id -All
if ($owners.Count -le 1) {
Write-Output " [WARNING] SOLE OWNER - needs transfer before termination"
} else {
Write-Output " [OK] Has $($owners.Count) owners total"
}
}
}
} else {
Write-Output " [INFO] Lesley does not own any groups or teams"
}
# --- Check group memberships ---
Write-Output "`n--- Group / Team Memberships ---"
$memberships = Get-MgUserMemberOf -UserId $lesley.Id -All
foreach ($mem in $memberships) {
$group = Get-MgGroup -GroupId $mem.Id -Property DisplayName,GroupTypes,Mail -ErrorAction SilentlyContinue
if ($group) {
$isTeam = $group.GroupTypes -contains "Unified"
$type = if ($isTeam) { "M365 Group/Team" } else { "Security/DL Group" }
Write-Output " [MEMBER] $type : $($group.DisplayName) ($($group.Mail))"
}
}
# --- Check SharePoint site ownership ---
Write-Output "`n--- SharePoint Sites ---"
try {
$sites = Get-MgSite -Search "*" -All -Property DisplayName,WebUrl 2>$null
if ($sites) {
foreach ($site in $sites) {
try {
$sitePermissions = Get-MgSitePermission -SiteId $site.Id -ErrorAction SilentlyContinue 2>$null
} catch {
# Fall through - permissions API may not be available on all sites
}
Write-Output " [SITE] $($site.DisplayName) - $($site.WebUrl)"
}
}
} catch {
Write-Output " [INFO] Could not enumerate SharePoint sites (may need SharePoint admin role)"
}
# --- Check distribution group membership via Exchange ---
Write-Output "`n--- Distribution List Memberships (requires Exchange connection) ---"
Write-Output " [INFO] Run separately via Exchange Online to check DL memberships"
Write-Output "`n========================================="
Write-Output " Audit Complete"
Write-Output "========================================="
Disconnect-MgGraph

View File

@@ -0,0 +1,11 @@
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Users
Connect-MgGraph -TenantId 'ededa4fb-f6eb-4398-851d-5eb3e11fab27' -Scopes 'User.Read.All' -NoWelcome
# List all users to find Leslie
$allUsers = Get-MgUser -All -Property DisplayName,Mail,UserPrincipalName,AccountEnabled,Id
Write-Output "--- All Users in Tenant ---"
$allUsers | Format-Table DisplayName,Mail,UserPrincipalName,AccountEnabled -AutoSize
Disconnect-MgGraph

View File

@@ -0,0 +1,102 @@
# BG Builders - Disable Lesley Roth + Wipe Email from Device
# Employee: Lesley Roth (lesley@bgbuildersllc.com)
# Date: 2026-03-09
# Actions:
# 1. Block sign-in
# 2. Revoke all sessions
# 3. Reset password
# 4. Wipe email data from mobile devices (selective wipe + EAS wipe)
$ErrorActionPreference = "Stop"
$tenantId = "ededa4fb-f6eb-4398-851d-5eb3e11fab27"
$lesleyUPN = "lesley@bgbuildersllc.com"
Write-Output "========================================="
Write-Output " BG Builders - Disable Lesley Roth"
Write-Output " $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Output "========================================="
# --- STEP 1: Connect to Microsoft Graph ---
Write-Output "`n[STEP 1] Connecting to Microsoft Graph..."
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Users
Import-Module Microsoft.Graph.Users.Actions
Connect-MgGraph -TenantId $tenantId -Scopes 'User.ReadWrite.All','Directory.ReadWrite.All','DeviceManagementManagedDevices.ReadWrite.All','DeviceManagementManagedDevices.PrivilegedOperations.All' -NoWelcome
Write-Output "[OK] Connected to Graph"
$lesley = Get-MgUser -UserId $lesleyUPN -Property Id,DisplayName,AccountEnabled,AssignedLicenses
Write-Output "[INFO] Current state: AccountEnabled=$($lesley.AccountEnabled)"
# --- STEP 2: Block sign-in ---
Write-Output "`n[STEP 2] Blocking sign-in..."
Update-MgUser -UserId $lesley.Id -AccountEnabled:$false
Write-Output "[OK] Sign-in blocked"
# --- STEP 3: Revoke all sessions ---
Write-Output "`n[STEP 3] Revoking all active sessions..."
Revoke-MgUserSignInSession -UserId $lesley.Id
Write-Output "[OK] All sessions revoked"
# --- STEP 4: Reset password ---
Write-Output "`n[STEP 4] Resetting password..."
$newPassword = -join ((65..90) + (97..122) + (48..57) + (33,35,36,37,38) | Get-Random -Count 24 | ForEach-Object {[char]$_})
$params = @{
passwordProfile = @{
forceChangePasswordNextSignIn = $true
password = $newPassword
}
}
Update-MgUser -UserId $lesley.Id -BodyParameter $params
Write-Output "[OK] Password reset to random value"
# --- STEP 5: Wipe email from devices (Intune managed) ---
Write-Output "`n[STEP 5] Checking for Intune-managed devices..."
Import-Module Microsoft.Graph.DeviceManagement
$devices = Get-MgDeviceManagementManagedDevice -Filter "userPrincipalName eq '$lesleyUPN'" 2>$null
if ($devices) {
foreach ($device in $devices) {
Write-Output " Found: $($device.DeviceName) ($($device.OperatingSystem)) - ID: $($device.Id)"
Write-Output " Initiating selective wipe (company data only)..."
Invoke-MgRetireDeviceManagementManagedDevice -ManagedDeviceId $device.Id
Write-Output " [OK] Selective wipe queued for $($device.DeviceName)"
}
} else {
Write-Output "[INFO] No Intune-managed devices found"
}
# --- STEP 6: Wipe email from devices (Exchange ActiveSync) ---
Write-Output "`n[STEP 6] Connecting to Exchange Online..."
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName "sysadmin@bgbuildersllc.com" -ShowBanner:$false
Write-Output "[OK] Connected to Exchange Online"
Write-Output "Checking for ActiveSync devices..."
$easDevices = Get-MobileDevice -Mailbox $lesleyUPN 2>$null
if ($easDevices) {
foreach ($eas in $easDevices) {
Write-Output " Found EAS device: $($eas.FriendlyName) ($($eas.DeviceOS))"
Clear-MobileDevice -Identity $eas.Identity -AccountOnly -Confirm:$false
Write-Output " [OK] Account-only wipe initiated for $($eas.FriendlyName)"
}
Write-Output "[OK] All EAS devices queued for account wipe"
} else {
Write-Output "[INFO] No EAS mobile devices found"
}
# --- DONE ---
Write-Output "`n========================================="
Write-Output " DISABLE + DEVICE WIPE COMPLETE"
Write-Output " $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Output "========================================="
Write-Output ""
Write-Output "Summary:"
Write-Output " [OK] Sign-in blocked"
Write-Output " [OK] Sessions revoked"
Write-Output " [OK] Password reset"
Write-Output " [OK] Device email wipe initiated (Intune + EAS)"
Write-Output ""
Write-Output "[INFO] Mailbox is still accessible - run full termination script"
Write-Output " when ready to convert to shared, remove license, etc."
Disconnect-ExchangeOnline -Confirm:$false
Disconnect-MgGraph

View File

@@ -0,0 +1,33 @@
# BG Builders - Lesley Exchange steps (run from interactive PowerShell)
# Adds Shelly as delegate + enables litigation hold
$lesleyUPN = "lesley@bgbuildersllc.com"
$shellyUPN = "Shelly@bgbuildersllc.com"
Write-Output "Connecting to Exchange Online..."
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName "sysadmin@bgbuildersllc.com" -ShowBanner:$false
Write-Output "[OK] Connected"
# Add Shelly as delegate
Write-Output "`nAdding Shelly as delegate..."
Add-MailboxPermission -Identity $lesleyUPN -User $shellyUPN -AccessRights FullAccess -AutoMapping $true
Write-Output "[OK] Shelly granted FullAccess"
Add-RecipientPermission -Identity $lesleyUPN -Trustee $shellyUPN -AccessRights SendAs -Confirm:$false
Write-Output "[OK] Shelly granted SendAs"
# Enable litigation hold
Write-Output "`nEnabling litigation hold..."
Set-Mailbox -Identity $lesleyUPN -LitigationHoldEnabled $true -LitigationHoldDuration Unlimited
Write-Output "[OK] Litigation hold enabled"
# Verify
Write-Output "`nVerifying permissions..."
Get-MailboxPermission -Identity $lesleyUPN | Where-Object { $_.User -notlike "NT AUTHORITY*" -and $_.User -notlike "S-1-*" } | Format-Table User,AccessRights -AutoSize
Write-Output "`nVerifying litigation hold..."
Get-Mailbox -Identity $lesleyUPN | Format-List LitigationHoldEnabled,LitigationHoldDuration
Disconnect-ExchangeOnline -Confirm:$false
Write-Output "[OK] Done"

View File

@@ -0,0 +1,83 @@
# BG Builders - Check and fix inbox rules on lesley shared mailbox
# Run from interactive PowerShell
$lesleyUPN = "lesley@bgbuildersllc.com"
Write-Output "Connecting to Exchange Online..."
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName "sysadmin@bgbuildersllc.com" -ShowBanner:$false
Write-Output "[OK] Connected"
# Check inbox rules
Write-Output "`n=== INBOX RULES ==="
$rules = Get-InboxRule -Mailbox $lesleyUPN -IncludeHidden
if ($rules) {
foreach ($rule in $rules) {
Write-Output " Rule: $($rule.Name) | Enabled: $($rule.Enabled) | Priority: $($rule.Priority)"
Write-Output " Description: $($rule.Description)"
Write-Output " MoveToFolder: $($rule.MoveToFolder)"
Write-Output " DeleteMessage: $($rule.DeleteMessage)"
Write-Output " SoftDeleteMessage: $($rule.SoftDeleteMessage)"
Write-Output ""
}
# Disable any rules that delete messages
foreach ($rule in $rules) {
if ($rule.DeleteMessage -or $rule.SoftDeleteMessage -or $rule.MoveToFolder -match "Deleted") {
Write-Output "[ALERT] Removing problematic rule: $($rule.Name)"
Remove-InboxRule -Mailbox $lesleyUPN -Identity $rule.Identity -Confirm:$false
Write-Output "[OK] Removed"
}
}
} else {
Write-Output " [OK] No inbox rules found"
}
# Check sweep rules
Write-Output "`n=== SWEEP RULES ==="
try {
$sweep = Get-SweepRule -Mailbox $lesleyUPN
if ($sweep) {
foreach ($s in $sweep) {
Write-Output " Rule: $($s.Name) | Enabled: $($s.Enabled)"
Write-Output " SourceFolder: $($s.SourceFolder)"
Write-Output " DestFolder: $($s.DestFolder)"
Write-Output " KeepLatest: $($s.KeepLatest)"
Write-Output ""
}
# Remove sweep rules
foreach ($s in $sweep) {
Write-Output "[ALERT] Removing sweep rule: $($s.Name)"
Remove-SweepRule -Identity $s.Identity -Mailbox $lesleyUPN -Confirm:$false
Write-Output "[OK] Removed"
}
} else {
Write-Output " [OK] No sweep rules found"
}
} catch {
Write-Output " [INFO] Sweep rules not available: $_"
}
# Check mailbox type and forwarding
Write-Output "`n=== MAILBOX STATUS ==="
$mb = Get-Mailbox -Identity $lesleyUPN
Write-Output " Type: $($mb.RecipientTypeDetails)"
Write-Output " Forwarding: $($mb.ForwardingAddress)"
Write-Output " ForwardingSMTP: $($mb.ForwardingSmtpAddress)"
Write-Output " DeliverToMailboxAndForward: $($mb.DeliverToMailboxAndForward)"
Write-Output " HiddenFromGAL: $($mb.HiddenFromAddressListsEnabled)"
Write-Output " LitigationHold: $($mb.LitigationHoldEnabled)"
# Check transport rules affecting this mailbox
Write-Output "`n=== TRANSPORT RULES ==="
$transport = Get-TransportRule | Where-Object { $_.State -eq "Enabled" }
if ($transport) {
foreach ($t in $transport) {
Write-Output " Rule: $($t.Name) | Priority: $($t.Priority)"
}
} else {
Write-Output " [OK] No transport rules"
}
Disconnect-ExchangeOnline -Confirm:$false
Write-Output "`n[OK] Done"

View File

@@ -0,0 +1,62 @@
=========================================
LESLEY ROTH - 72-HOUR MAIL ACTIVITY REPORT
Generated: 2026-03-09 09:30:46
Window: 2026-03-06 09:30 to 2026-03-09 09:30
=========================================
=========================================
SENT MESSAGES (0 total)
=========================================
[NONE] No sent messages in the last 72 hours
=========================================
RECEIVED MESSAGES (5 total)
=========================================
Date: 2026-03-09 09:53:49
From: Gallagher.NoReply@Vertafore.com
Subject: Coyote Landing - 23-09001.Coyote - Enrollment Status Report From AJG - 03/09/2026 - By Contractor Name (All Tier)
Status: Delivered
---
Date: 2026-03-09 09:22:52
From: Gallagher.NoReply@Vertafore.com
Subject: Coyote Landing - 23-09001.Coyote - Enrollment Status Report From AJG - 03/09/2026 - By Contractor Name (First Tier)
Status: Delivered
---
Date: 2026-03-09 08:32:29
From: Gallagher.NoReply@Vertafore.com
Subject: Coyote Landing / EmpirePaving-BGBuild-23-09001.Coyote / Missing/Incomplete Insurance Cost Worksheet
Status: Delivered
---
Date: 2026-03-09 08:17:05
From: Gallagher.NoReply@Vertafore.com
Subject: Coyote Landing / EmpirePaving-BGBuild-23-09001.Coyote / Enrollment Incomplete
Status: Delivered
---
Date: 2026-03-06 22:09:29
From: notifications@s.usa.experian.com
Subject: Lesley, your Experian account info recently changed.
Status: Delivered
---
=========================================
DELETED ITEMS (0 total)
=========================================
[NONE] No deleted items in the last 72 hours
=========================================
INBOX RULES
=========================================
[NONE] No inbox rules configured
=========================================
FORWARDING CONFIGURATION
=========================================
ForwardingAddress:
ForwardingSmtpAddress:
DeliverToMailboxAndForward: False
[OK] No forwarding configured

View File

@@ -0,0 +1,150 @@
# BG Builders - Lesley Roth 72-Hour Mail Activity Report
# Pulls sent mail (message trace) and deleted items (mailbox audit log)
# Date: 2026-03-09
$ErrorActionPreference = "Stop"
$lesleyUPN = "lesley@bgbuildersllc.com"
$startDate = (Get-Date).AddHours(-72)
$endDate = Get-Date
$reportPath = "D:\ClaudeTools\scripts\bgb-lesley-mail-report-$(Get-Date -Format 'yyyyMMdd').txt"
Write-Output "========================================="
Write-Output " BG Builders - Lesley Roth Mail Report"
Write-Output " 72-Hour Window: $($startDate.ToString('yyyy-MM-dd HH:mm')) to $($endDate.ToString('yyyy-MM-dd HH:mm'))"
Write-Output "========================================="
# --- Connect to Exchange Online ---
Write-Output "`n[STEP 1] Connecting to Exchange Online..."
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName "sysadmin@bgbuildersllc.com" -ShowBanner:$false
Write-Output "[OK] Connected"
# Start building report
$report = @()
$report += "========================================="
$report += " LESLEY ROTH - 72-HOUR MAIL ACTIVITY REPORT"
$report += " Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
$report += " Window: $($startDate.ToString('yyyy-MM-dd HH:mm')) to $($endDate.ToString('yyyy-MM-dd HH:mm'))"
$report += "========================================="
# --- SENT MAIL (Message Trace) ---
Write-Output "`n[STEP 2] Pulling sent mail via message trace..."
$sentMessages = Get-MessageTraceV2 -SenderAddress $lesleyUPN -StartDate $startDate -EndDate $endDate
$report += ""
$report += "=========================================`n SENT MESSAGES ($($sentMessages.Count) total)`n========================================="
if ($sentMessages.Count -gt 0) {
$sentMessages | Sort-Object Received -Descending | ForEach-Object {
$report += ""
$report += " Date: $($_.Received.ToString('yyyy-MM-dd HH:mm:ss'))"
$report += " To: $($_.RecipientAddress)"
$report += " Subject: $($_.Subject)"
$report += " Status: $($_.Status)"
$report += " Size: $([math]::Round($_.Size / 1KB, 1)) KB"
$report += " MsgID: $($_.MessageId)"
$report += " ---"
}
} else {
$report += " [NONE] No sent messages in the last 72 hours"
}
Write-Output "[OK] Found $($sentMessages.Count) sent messages"
# --- RECEIVED MAIL (Message Trace) ---
Write-Output "`n[STEP 3] Pulling received mail via message trace..."
$receivedMessages = Get-MessageTraceV2 -RecipientAddress $lesleyUPN -StartDate $startDate -EndDate $endDate
$report += ""
$report += "=========================================`n RECEIVED MESSAGES ($($receivedMessages.Count) total)`n========================================="
if ($receivedMessages.Count -gt 0) {
$receivedMessages | Sort-Object Received -Descending | ForEach-Object {
$report += ""
$report += " Date: $($_.Received.ToString('yyyy-MM-dd HH:mm:ss'))"
$report += " From: $($_.SenderAddress)"
$report += " Subject: $($_.Subject)"
$report += " Status: $($_.Status)"
$report += " ---"
}
} else {
$report += " [NONE] No received messages in the last 72 hours"
}
Write-Output "[OK] Found $($receivedMessages.Count) received messages"
# --- DELETED ITEMS (Mailbox Audit Log) ---
Write-Output "`n[STEP 4] Pulling deleted items via mailbox audit log..."
# Use Search-UnifiedAuditLog (Search-MailboxAuditLog deprecated Jan 2026)
$deleteOps = "SoftDelete","HardDelete","MoveToDeletedItems"
$deletedItems = Search-UnifiedAuditLog -UserIds $lesleyUPN -Operations ($deleteOps -join ",") -StartDate $startDate -EndDate $endDate -ResultSize 5000
$report += ""
$report += "=========================================`n DELETED ITEMS ($($deletedItems.Count) total)`n========================================="
if ($deletedItems.Count -gt 0) {
$deletedItems | Sort-Object CreationDate -Descending | ForEach-Object {
$auditData = $_.AuditData | ConvertFrom-Json
$report += ""
$report += " Date: $($_.CreationDate)"
$report += " Operation: $($_.Operations)"
$report += " User: $($_.UserIds)"
$report += " Subject: $($auditData.AffectedItems.Subject -join '; ')"
$report += " Folder: $($auditData.Folder.Path)"
$report += " Client: $($auditData.ClientInfoString)"
$report += " ---"
}
} else {
$report += " [NONE] No deleted items in the last 72 hours"
}
Write-Output "[OK] Found $($deletedItems.Count) deleted items"
# --- INBOX RULES (check for forwarding/auto-delete) ---
Write-Output "`n[STEP 5] Checking inbox rules..."
$rules = Get-InboxRule -Mailbox $lesleyUPN 2>$null
$report += ""
$report += "=========================================`n INBOX RULES`n========================================="
if ($rules) {
foreach ($rule in $rules) {
$report += ""
$report += " Name: $($rule.Name)"
$report += " Enabled: $($rule.Enabled)"
$report += " Priority: $($rule.Priority)"
if ($rule.ForwardTo) { $report += " ForwardTo: $($rule.ForwardTo -join '; ')" }
if ($rule.RedirectTo) { $report += " RedirectTo: $($rule.RedirectTo -join '; ')" }
if ($rule.DeleteMessage) { $report += " [WARNING] Auto-delete enabled" }
$report += " ---"
}
} else {
$report += " [NONE] No inbox rules configured"
}
Write-Output "[OK] Rules checked"
# --- FORWARDING CONFIG ---
Write-Output "`n[STEP 6] Checking forwarding configuration..."
$mbx = Get-Mailbox -Identity $lesleyUPN | Select-Object ForwardingAddress,ForwardingSmtpAddress,DeliverToMailboxAndForward
$report += ""
$report += "=========================================`n FORWARDING CONFIGURATION`n========================================="
$report += " ForwardingAddress: $($mbx.ForwardingAddress)"
$report += " ForwardingSmtpAddress: $($mbx.ForwardingSmtpAddress)"
$report += " DeliverToMailboxAndForward: $($mbx.DeliverToMailboxAndForward)"
if ($mbx.ForwardingAddress -or $mbx.ForwardingSmtpAddress) {
$report += " [WARNING] Active forwarding detected!"
} else {
$report += " [OK] No forwarding configured"
}
# --- Write report to file ---
$report | Out-File -FilePath $reportPath -Encoding UTF8
Write-Output "`n========================================="
Write-Output " REPORT SAVED"
Write-Output " $reportPath"
Write-Output "========================================="
# Also output to console
Write-Output "`n--- REPORT CONTENTS ---"
$report | ForEach-Object { Write-Output $_ }
Disconnect-ExchangeOnline -Confirm:$false
Write-Output "`n[OK] Done"

View File

@@ -0,0 +1,193 @@
#Requires -Modules ExchangeOnlineManagement
<#
.SYNOPSIS
BG Builders - Lesley Roth: Recover deleted items (last 10 days) and review inbox rules
.DESCRIPTION
1. Connects to Exchange Online as sysadmin@bgbuildersllc.com
2. Recovers all soft-deleted items from Lesley's mailbox (last 10 days)
3. Lists all inbox rules on the account
.NOTES
Run in PowerShell 7 (pwsh) for best compatibility
Tenant: bgbuildersllc.com / sonorangreenllc.onmicrosoft.com
Target: lesley@bgbuildersllc.com
#>
$ErrorActionPreference = 'Stop'
$targetUser = 'lesley@bgbuildersllc.com'
# ── Connect to Exchange Online ──────────────────────────────────────
Write-Host "`n=== Connecting to Exchange Online ===" -ForegroundColor Cyan
try {
$session = Get-ConnectionInformation -ErrorAction SilentlyContinue
if (-not $session -or $session.State -ne 'Connected') {
Connect-ExchangeOnline -UserPrincipalName sysadmin@bgbuildersllc.com -ShowBanner:$false
} else {
Write-Host "Already connected to Exchange Online" -ForegroundColor Green
}
} catch {
Write-Host "Connecting fresh..." -ForegroundColor Yellow
Connect-ExchangeOnline -UserPrincipalName sysadmin@bgbuildersllc.com -ShowBanner:$false
}
# ── Part 1: Review Inbox Rules ──────────────────────────────────────
Write-Host "`n=== INBOX RULES for $targetUser ===" -ForegroundColor Cyan
try {
$rules = Get-InboxRule -Mailbox $targetUser -IncludeHidden
if ($rules) {
Write-Host "`nFound $($rules.Count) rule(s):" -ForegroundColor Yellow
foreach ($rule in $rules) {
Write-Host "`n--- Rule: $($rule.Name) ---" -ForegroundColor White
Write-Host " Enabled: $($rule.Enabled)"
Write-Host " Priority: $($rule.Priority)"
Write-Host " Description: $($rule.Description)"
if ($rule.ForwardTo) {
Write-Host " ** FORWARD TO: $($rule.ForwardTo)" -ForegroundColor Red
}
if ($rule.ForwardAsAttachmentTo) {
Write-Host " ** FWD ATTACH: $($rule.ForwardAsAttachmentTo)" -ForegroundColor Red
}
if ($rule.RedirectTo) {
Write-Host " ** REDIRECT TO: $($rule.RedirectTo)" -ForegroundColor Red
}
if ($rule.DeleteMessage) {
Write-Host " ** DELETE MSG: True" -ForegroundColor Red
}
if ($rule.MoveToFolder) {
Write-Host " Move To: $($rule.MoveToFolder)"
}
if ($rule.From) {
Write-Host " From: $($rule.From)"
}
if ($rule.SubjectContainsWords) {
Write-Host " Subject Words: $($rule.SubjectContainsWords -join ', ')"
}
if ($rule.BodyContainsWords) {
Write-Host " Body Words: $($rule.BodyContainsWords -join ', ')"
}
}
} else {
Write-Host "No inbox rules found." -ForegroundColor Green
}
} catch {
Write-Host "Error getting inbox rules: $_" -ForegroundColor Red
}
# ── Check forwarding configuration ──────────────────────────────────
Write-Host "`n=== FORWARDING CONFIG for $targetUser ===" -ForegroundColor Cyan
try {
$mbx = Get-Mailbox -Identity $targetUser
if ($mbx.ForwardingAddress) {
Write-Host " ForwardingAddress: $($mbx.ForwardingAddress)" -ForegroundColor Red
} else {
Write-Host " ForwardingAddress: (none)" -ForegroundColor Green
}
if ($mbx.ForwardingSmtpAddress) {
Write-Host " ForwardingSmtpAddress: $($mbx.ForwardingSmtpAddress)" -ForegroundColor Red
} else {
Write-Host " ForwardingSmtpAddress: (none)" -ForegroundColor Green
}
Write-Host " DeliverToMailboxAndForward: $($mbx.DeliverToMailboxAndForward)"
} catch {
Write-Host "Error getting forwarding config: $_" -ForegroundColor Red
}
# ── Part 2: Recover Deleted Items (last 10 days) ───────────────────
Write-Host "`n=== RECOVERING DELETED ITEMS (last 10 days) ===" -ForegroundColor Cyan
Write-Host "Target: $targetUser" -ForegroundColor White
$startDate = (Get-Date).AddDays(-10)
$endDate = Get-Date
$dateRange = "$($startDate.ToString('yyyy-MM-dd'))..$($endDate.ToString('yyyy-MM-dd'))"
# Step 1: Try Get-RecoverableItems (requires Mailbox Import Export role)
Write-Host "`n--- Method 1: Get-RecoverableItems ---" -ForegroundColor White
try {
Write-Host "Scanning recoverable items from $dateRange..."
$preview = Get-RecoverableItems -Identity $targetUser -FilterStartTime $startDate -FilterEndTime $endDate -FilterItemType All
if ($preview) {
Write-Host "Found $($preview.Count) recoverable item(s):" -ForegroundColor Yellow
$preview | Group-Object ItemClass | ForEach-Object { Write-Host " $($_.Name): $($_.Count) items" }
$preview | Select-Object -First 20 | ForEach-Object {
$subj = if ($_.Subject) { $_.Subject } else { "(no subject)" }
Write-Host " [$($_.LastModifiedTime.ToString('MM/dd HH:mm'))] $subj"
}
Write-Host "`nRestoring all $($preview.Count) items..." -ForegroundColor Yellow
Restore-RecoverableItems -Identity $targetUser -FilterStartTime $startDate -FilterEndTime $endDate -FilterItemType All -Confirm:$false
Write-Host "Recovery complete!" -ForegroundColor Green
} else {
Write-Host "No recoverable items found." -ForegroundColor Green
}
} catch {
Write-Host "Get-RecoverableItems not available (needs Mailbox Import Export role)." -ForegroundColor Yellow
Write-Host "Falling back to Compliance Search..." -ForegroundColor Yellow
# Step 2: Connect to Security & Compliance and run a content search
Write-Host "`n--- Method 2: Compliance Search (eDiscovery) ---" -ForegroundColor White
try {
Connect-IPPSSession -UserPrincipalName sysadmin@bgbuildersllc.com -ShowBanner:$false
Write-Host "Connected to Security & Compliance Center." -ForegroundColor Green
$searchName = "LesleyRecovery_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
$kql = "received>=$($startDate.ToString('yyyy-MM-dd')) AND received<=$($endDate.ToString('yyyy-MM-dd'))"
Write-Host "Creating compliance search: $searchName"
Write-Host " KQL: $kql"
Write-Host " Mailbox: $targetUser"
New-ComplianceSearch -Name $searchName `
-ExchangeLocation $targetUser `
-ContentMatchQuery $kql `
-Description "Recover deleted items for Lesley Roth - last 10 days" |
Out-Null
Write-Host "Starting search..." -ForegroundColor Yellow
Start-ComplianceSearch -Identity $searchName
# Poll for completion (max 5 minutes)
$maxWait = 300
$elapsed = 0
do {
Start-Sleep -Seconds 10
$elapsed += 10
$status = (Get-ComplianceSearch -Identity $searchName).Status
Write-Host " Status: $status ($elapsed sec)"
} while ($status -ne 'Completed' -and $elapsed -lt $maxWait)
$result = Get-ComplianceSearch -Identity $searchName
Write-Host "`nSearch Results:" -ForegroundColor Cyan
Write-Host " Status: $($result.Status)"
Write-Host " Items Found: $($result.Items)"
Write-Host " Size: $($result.Size)"
Write-Host " Success Results: $($result.SuccessResults)"
if ($result.Items -gt 0) {
Write-Host "`nItems found! To restore them:" -ForegroundColor Yellow
Write-Host " Option A: Use the Microsoft Purview portal > Content Search > '$searchName' > Export/Restore"
Write-Host " Option B: Run New-ComplianceSearchAction -SearchName '$searchName' -Purge -PurgeType SoftDelete"
Write-Host " (This moves items - for restore, use the Purview portal export instead)"
Write-Host "`n Purview URL: https://compliance.microsoft.com/contentsearchv2" -ForegroundColor Cyan
} else {
Write-Host "`nNo deleted items found in date range." -ForegroundColor Green
Write-Host "(Litigation hold preserves items in-place - they may still be in the mailbox)"
}
} catch {
Write-Host "Compliance search also failed: $_" -ForegroundColor Red
Write-Host "`nManual recovery options:" -ForegroundColor Yellow
Write-Host " 1. Outlook > Deleted Items > 'Recover items recently removed from this folder'"
Write-Host " (Log in as Barry/Shelly who have FullAccess)"
Write-Host " 2. CIPP > Mailbox Restore"
Write-Host " 3. Microsoft Purview portal > eDiscovery > Content Search"
Write-Host " URL: https://compliance.microsoft.com/contentsearchv2"
}
}
Write-Host "`n=== DONE ===" -ForegroundColor Cyan
Write-Host "Summary:"
Write-Host " - Inbox rules reviewed"
Write-Host " - Forwarding config checked"
Write-Host " - Deleted item recovery attempted"
Write-Host ""

View File

@@ -0,0 +1,71 @@
# BG Builders - Verify Lesley Device Wipe Status
$ErrorActionPreference = "Stop"
$tenantId = "ededa4fb-f6eb-4398-851d-5eb3e11fab27"
$lesleyUPN = "lesley@bgbuildersllc.com"
Write-Output "========================================="
Write-Output " Verify Device Wipe - Lesley Roth"
Write-Output " $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Output "========================================="
# --- Check Intune Managed Devices ---
Write-Output "`n[CHECK 1] Intune Managed Devices..."
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.DeviceManagement
Connect-MgGraph -TenantId $tenantId -Scopes 'DeviceManagementManagedDevices.Read.All' -NoWelcome
Write-Output "[OK] Connected to Graph"
$devices = Get-MgDeviceManagementManagedDevice -Filter "userPrincipalName eq '$lesleyUPN'" 2>$null
if ($devices) {
foreach ($d in $devices) {
Write-Output ""
Write-Output " Device: $($d.DeviceName)"
Write-Output " OS: $($d.OperatingSystem) $($d.OsVersion)"
Write-Output " Compliance: $($d.ComplianceState)"
Write-Output " Management State: $($d.ManagementState)"
Write-Output " Last Sync: $($d.LastSyncDateTime)"
Write-Output " Device Action: $($d.DeviceActionResults | ForEach-Object { "$($_.ActionName): $($_.ActionState)" })"
}
} else {
Write-Output " [INFO] No Intune-managed devices found for $lesleyUPN"
}
Disconnect-MgGraph
# --- Check EAS Devices ---
Write-Output "`n[CHECK 2] Exchange ActiveSync Devices..."
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName "sysadmin@bgbuildersllc.com" -ShowBanner:$false
Write-Output "[OK] Connected to Exchange Online"
$easDevices = Get-MobileDevice -Mailbox $lesleyUPN 2>$null
if ($easDevices) {
foreach ($eas in $easDevices) {
$stats = Get-MobileDeviceStatistics -Identity $eas.Identity 2>$null
Write-Output ""
Write-Output " Device: $($eas.FriendlyName)"
Write-Output " Type: $($eas.DeviceType)"
Write-Output " OS: $($eas.DeviceOS)"
Write-Output " Access State: $($eas.DeviceAccessState)"
Write-Output " First Sync: $($eas.FirstSyncTime)"
if ($stats) {
Write-Output " Last Sync: $($stats.LastSuccessSync)"
Write-Output " Wipe Status: $($stats.DeviceWipeSentTime)"
Write-Output " Wipe Ack: $($stats.DeviceWipeAckTime)"
Write-Output " Status: $($stats.Status)"
}
}
} else {
Write-Output " [INFO] No EAS devices found for $lesleyUPN"
}
# --- Check account status ---
Write-Output "`n[CHECK 3] Account Status..."
$mbx = Get-Mailbox -Identity $lesleyUPN -ErrorAction SilentlyContinue
if ($mbx) {
Write-Output " Mailbox Type: $($mbx.RecipientTypeDetails)"
Write-Output " Litigation Hold: $($mbx.LitigationHoldEnabled)"
}
Disconnect-ExchangeOnline -Confirm:$false
Write-Output "`n[OK] Verification complete"

View File

@@ -0,0 +1,119 @@
# BG Builders - Re-enable Lesley Roth + Add Shelly Delegate
# lesley@bgbuildersllc.com - was terminated 2026-02-27
# Actions:
# 1. Unblock sign-in
# 2. Reassign license
# 3. Add Shelly@bgbuildersllc.com as delegate (FullAccess + SendAs)
# 4. Enable litigation hold (prevent email deletion)
$ErrorActionPreference = "Stop"
$tenantId = "ededa4fb-f6eb-4398-851d-5eb3e11fab27"
$lesleyUPN = "lesley@bgbuildersllc.com"
$shellyUPN = "Shelly@bgbuildersllc.com"
Write-Output "========================================="
Write-Output " BG Builders - Re-enable Lesley Roth"
Write-Output " $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Output "========================================="
# --- STEP 1: Connect to Microsoft Graph ---
Write-Output "`n[STEP 1] Connecting to Microsoft Graph..."
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Users
Connect-MgGraph -TenantId $tenantId -Scopes 'User.ReadWrite.All','Organization.Read.All' -NoWelcome
Write-Output "[OK] Connected to Graph"
$lesley = Get-MgUser -UserId $lesleyUPN -Property Id,DisplayName,AccountEnabled,AssignedLicenses
Write-Output "[INFO] Lesley current state: AccountEnabled=$($lesley.AccountEnabled)"
# --- STEP 2: Unblock sign-in ---
Write-Output "`n[STEP 2] Unblocking sign-in..."
Update-MgUser -UserId $lesley.Id -AccountEnabled:$true
Write-Output "[OK] Sign-in unblocked for Lesley Roth"
# --- STEP 3: Reassign license ---
Write-Output "`n[STEP 3] Reassigning license..."
# List available SKUs to find the right one
$skus = Get-MgSubscribedSku -All
Write-Output "Available licenses:"
foreach ($sku in $skus) {
$available = $sku.PrepaidUnits.Enabled - $sku.ConsumedUnits
Write-Output " $($sku.SkuPartNumber) - $available available of $($sku.PrepaidUnits.Enabled) total"
}
# Assign Exchange Online Plan 1 (EXCHANGESTANDARD) - cheapest option for mailbox access
$exoPlan = $skus | Where-Object { $_.SkuPartNumber -eq "EXCHANGESTANDARD" }
if ($exoPlan) {
$availableCount = $exoPlan.PrepaidUnits.Enabled - $exoPlan.ConsumedUnits
if ($availableCount -gt 0) {
Set-MgUserLicense -UserId $lesley.Id -AddLicenses @(@{SkuId = $exoPlan.SkuId}) -RemoveLicenses @()
Write-Output "[OK] Assigned Exchange Online Plan 1 ($availableCount were available)"
} else {
Write-Output "[WARNING] No Exchange Online Plan 1 licenses available, trying Business Standard..."
$bizStd = $skus | Where-Object { $_.SkuPartNumber -eq "O365_BUSINESS_PREMIUM" }
if ($bizStd) {
$availableCount = $bizStd.PrepaidUnits.Enabled - $bizStd.ConsumedUnits
if ($availableCount -gt 0) {
Set-MgUserLicense -UserId $lesley.Id -AddLicenses @(@{SkuId = $bizStd.SkuId}) -RemoveLicenses @()
Write-Output "[OK] Assigned M365 Business Standard ($availableCount were available)"
} else {
Write-Output "[ERROR] No available licenses of either type - assign manually"
}
}
}
} else {
Write-Output "[WARNING] EXCHANGESTANDARD SKU not found, trying Business Standard..."
$bizStd = $skus | Where-Object { $_.SkuPartNumber -eq "O365_BUSINESS_PREMIUM" }
if ($bizStd) {
$availableCount = $bizStd.PrepaidUnits.Enabled - $bizStd.ConsumedUnits
if ($availableCount -gt 0) {
Set-MgUserLicense -UserId $lesley.Id -AddLicenses @(@{SkuId = $bizStd.SkuId}) -RemoveLicenses @()
Write-Output "[OK] Assigned M365 Business Standard ($availableCount were available)"
} else {
Write-Output "[ERROR] No available licenses - assign manually"
}
}
}
# --- STEP 4: Connect to Exchange Online ---
Write-Output "`n[STEP 4] Connecting to Exchange Online..."
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName "sysadmin@bgbuildersllc.com" -ShowBanner:$false
Write-Output "[OK] Connected to Exchange Online"
# --- STEP 5: Add Shelly as delegate ---
Write-Output "`n[STEP 5] Adding Shelly as delegate on Lesley's mailbox..."
Add-MailboxPermission -Identity $lesleyUPN -User $shellyUPN -AccessRights FullAccess -AutoMapping $true
Write-Output "[OK] Shelly granted FullAccess (auto-mapped)"
Add-RecipientPermission -Identity $lesleyUPN -Trustee $shellyUPN -AccessRights SendAs -Confirm:$false
Write-Output "[OK] Shelly granted SendAs"
# --- STEP 6: Enable litigation hold ---
Write-Output "`n[STEP 6] Enabling litigation hold (prevent email deletion)..."
Set-Mailbox -Identity $lesleyUPN -LitigationHoldEnabled $true -LitigationHoldDuration Unlimited
Write-Output "[OK] Litigation hold enabled - emails cannot be permanently deleted"
# --- STEP 7: Verify ---
Write-Output "`n[STEP 7] Verifying permissions..."
$perms = Get-MailboxPermission -Identity $lesleyUPN | Where-Object { $_.User -notlike "NT AUTHORITY*" -and $_.User -notlike "S-1-*" }
Write-Output "Current mailbox permissions:"
foreach ($p in $perms) {
Write-Output " $($p.User) - $($p.AccessRights -join ', ')"
}
# --- DONE ---
Write-Output "`n========================================="
Write-Output " COMPLETE"
Write-Output " $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Output "========================================="
Write-Output ""
Write-Output "Summary:"
Write-Output " [OK] Lesley sign-in re-enabled"
Write-Output " [OK] License reassigned"
Write-Output " [OK] Shelly has FullAccess + SendAs on Lesley's mailbox"
Write-Output " [OK] Litigation hold enabled - no email can be permanently deleted"
Write-Output " [INFO] Barry still has access from termination script"
Disconnect-ExchangeOnline -Confirm:$false
Disconnect-MgGraph

View File

@@ -0,0 +1,166 @@
# BG Builders - Employee Termination Script
# Employee: Lesley Roth (lesley@bgbuildersllc.com)
# Scheduled: 2026-02-27 12:00 PM MST
# Actions:
# 1. Block sign-in
# 2. Revoke all sessions
# 3. Reset password
# 4. Selective wipe company data from mobile devices
# 5. Convert mailbox to shared
# 6. Grant Barry full access + send-as on shared mailbox
# 7. Remove from Employees group
# 8. Hide from GAL
# 9. Grant Barry OneDrive access
# 10. Remove license
$ErrorActionPreference = "Stop"
$tenantId = "ededa4fb-f6eb-4398-851d-5eb3e11fab27"
$lesleyUPN = "lesley@bgbuildersllc.com"
$barryUPN = "barry@bgbuildersllc.com"
Write-Output "========================================="
Write-Output " BG Builders - Lesley Roth Termination"
Write-Output " $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Output "========================================="
# --- STEP 1: Connect to Microsoft Graph ---
Write-Output "`n[STEP 1] Connecting to Microsoft Graph..."
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Users
Import-Module Microsoft.Graph.Users.Actions
Import-Module Microsoft.Graph.Identity.DirectoryManagement
Connect-MgGraph -TenantId $tenantId -Scopes 'User.ReadWrite.All','Directory.ReadWrite.All','Group.ReadWrite.All','DeviceManagementManagedDevices.ReadWrite.All','DeviceManagementManagedDevices.PrivilegedOperations.All' -NoWelcome
Write-Output "[OK] Connected to Graph"
# Get user IDs
$lesley = Get-MgUser -UserId $lesleyUPN -Property Id,DisplayName,AccountEnabled,AssignedLicenses
$barry = Get-MgUser -UserId $barryUPN -Property Id,DisplayName
Write-Output "[OK] Lesley ID: $($lesley.Id)"
Write-Output "[OK] Barry ID: $($barry.Id)"
# --- STEP 2: Block sign-in ---
Write-Output "`n[STEP 2] Blocking sign-in..."
Update-MgUser -UserId $lesley.Id -AccountEnabled:$false
Write-Output "[OK] Sign-in blocked"
# --- STEP 3: Revoke all sessions ---
Write-Output "`n[STEP 3] Revoking all active sessions..."
Revoke-MgUserSignInSession -UserId $lesley.Id
Write-Output "[OK] All sessions revoked"
# --- STEP 4: Reset password ---
Write-Output "`n[STEP 4] Resetting password..."
$newPassword = -join ((65..90) + (97..122) + (48..57) + (33,35,36,37,38) | Get-Random -Count 24 | ForEach-Object {[char]$_})
$params = @{
passwordProfile = @{
forceChangePasswordNextSignIn = $true
password = $newPassword
}
}
Update-MgUser -UserId $lesley.Id -BodyParameter $params
Write-Output "[OK] Password reset (stored securely - not displayed)"
# --- STEP 5: Selective wipe company data from mobile devices ---
Write-Output "`n[STEP 5] Checking for managed mobile devices..."
Import-Module Microsoft.Graph.DeviceManagement
$devices = Get-MgDeviceManagementManagedDevice -Filter "userPrincipalName eq '$lesleyUPN'" 2>$null
if ($devices) {
foreach ($device in $devices) {
Write-Output " Found device: $($device.DeviceName) ($($device.OperatingSystem)) - ID: $($device.Id)"
Write-Output " Initiating selective wipe (company data only)..."
# Retire = selective wipe (removes company data, leaves personal data)
Invoke-MgRetireDeviceManagementManagedDevice -ManagedDeviceId $device.Id
Write-Output " [OK] Selective wipe initiated for $($device.DeviceName)"
}
Write-Output "[OK] All managed devices queued for selective wipe"
} else {
Write-Output "[INFO] No Intune-managed devices found"
Write-Output "[INFO] Checking for EAS (Exchange ActiveSync) devices..."
}
# --- STEP 6: Connect to Exchange Online and convert mailbox ---
Write-Output "`n[STEP 6] Connecting to Exchange Online..."
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName "sysadmin@bgbuildersllc.com" -ShowBanner:$false
Write-Output "[OK] Connected to Exchange Online"
# Check for ActiveSync devices and wipe company data
$easDevices = Get-MobileDevice -Mailbox $lesleyUPN 2>$null
if ($easDevices) {
foreach ($eas in $easDevices) {
Write-Output " Found EAS device: $($eas.FriendlyName) ($($eas.DeviceOS))"
# AccountOnly wipe - removes only the M365 account, not personal data
Clear-MobileDevice -Identity $eas.Identity -AccountOnly -Confirm:$false
Write-Output " [OK] Account-only wipe initiated for $($eas.FriendlyName)"
}
Write-Output "[OK] All EAS devices queued for account wipe"
} else {
Write-Output "[INFO] No EAS mobile devices found"
}
Write-Output "`n[STEP 6a] Converting mailbox to shared..."
Set-Mailbox -Identity $lesleyUPN -Type Shared
Write-Output "[OK] Mailbox converted to shared"
# --- STEP 7: Grant Barry full access and send-as ---
Write-Output "`n[STEP 7] Granting Barry full access to shared mailbox..."
Add-MailboxPermission -Identity $lesleyUPN -User $barryUPN -AccessRights FullAccess -AutoMapping $true
Write-Output "[OK] Full access granted"
Write-Output "Granting Barry send-as permission..."
Add-RecipientPermission -Identity $lesleyUPN -Trustee $barryUPN -AccessRights SendAs -Confirm:$false
Write-Output "[OK] Send-as granted"
# --- STEP 8: Remove from Employees group ---
Write-Output "`n[STEP 8] Removing from Employees group..."
$employeesGroup = Get-MgGroup -Filter "displayName eq 'Employees'" | Select-Object -First 1
if ($employeesGroup) {
Remove-MgGroupMemberByRef -GroupId $employeesGroup.Id -DirectoryObjectId $lesley.Id -ErrorAction SilentlyContinue
Write-Output "[OK] Removed from Employees group ($($employeesGroup.Id))"
} else {
Write-Output "[WARNING] Employees group not found"
}
# --- STEP 9: Hide from GAL ---
Write-Output "`n[STEP 9] Hiding shared mailbox from Global Address List..."
Set-Mailbox -Identity $lesleyUPN -HiddenFromAddressListsEnabled $true
Write-Output "[OK] Hidden from GAL"
# --- STEP 10: Remove license ---
Write-Output "`n[STEP 10] Removing licenses..."
$licenses = $lesley.AssignedLicenses
if ($licenses.Count -gt 0) {
$licenseIds = $licenses | ForEach-Object { $_.SkuId }
Set-MgUserLicense -UserId $lesley.Id -AddLicenses @() -RemoveLicenses $licenseIds
Write-Output "[OK] Removed $($licenseIds.Count) license(s)"
} else {
Write-Output "[INFO] No licenses assigned"
}
# --- STEP 11: Grant Barry OneDrive access ---
Write-Output "`n[STEP 11] Granting Barry access to Lesley's OneDrive..."
# Note: OneDrive access delegation requires SharePoint admin or may need manual step
Write-Output "[WARNING] OneDrive access must be granted via M365 Admin Center:"
Write-Output " Admin Center > Users > Lesley Roth > OneDrive tab > Create link to files"
Write-Output " Or: SharePoint Admin > User Profiles > Manage User Profiles > Lesley Roth > Manage site collection owners > Add Barry"
# --- DONE ---
Write-Output "`n========================================="
Write-Output " TERMINATION COMPLETE"
Write-Output " $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Output "========================================="
Write-Output ""
Write-Output "Summary:"
Write-Output " [OK] Sign-in blocked"
Write-Output " [OK] Sessions revoked"
Write-Output " [OK] Password reset"
Write-Output " [OK] Mobile devices - selective wipe initiated"
Write-Output " [OK] Mailbox converted to shared"
Write-Output " [OK] Barry has full access + send-as"
Write-Output " [OK] Removed from Employees group"
Write-Output " [OK] Hidden from GAL"
Write-Output " [OK] Licenses removed"
Write-Output " [WARNING] OneDrive access - manual step required"
Disconnect-ExchangeOnline -Confirm:$false
Disconnect-MgGraph

View File

@@ -0,0 +1,2 @@
@echo off
powershell.exe -ExecutionPolicy Bypass -File "D:\ClaudeTools\scripts\bgb-terminate-lesley.ps1" > "D:\ClaudeTools\scripts\bgb-terminate-lesley.log" 2>&1

View File

@@ -0,0 +1,16 @@
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Users
# Connect with interactive browser auth
Connect-MgGraph -TenantId 'ededa4fb-f6eb-4398-851d-5eb3e11fab27' -Scopes 'User.Read.All','User.ReadWrite.All','Directory.ReadWrite.All' -NoWelcome
# Find both users
$leslie = Get-MgUser -Filter "startsWith(displayName,'Leslie') or startsWith(mail,'leslie')" -Property DisplayName,Mail,UserPrincipalName,AccountEnabled,Id
$barry = Get-MgUser -Filter "startsWith(displayName,'Barry') or startsWith(mail,'barry')" -Property DisplayName,Mail,UserPrincipalName,AccountEnabled,Id
Write-Output '--- Leslie ---'
$leslie | Format-List DisplayName,Mail,UserPrincipalName,AccountEnabled,Id
Write-Output '--- Barry ---'
$barry | Format-List DisplayName,Mail,UserPrincipalName,AccountEnabled,Id
Disconnect-MgGraph