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:
37
clients/bg-builders/scripts/bgb-assign-exo-role.ps1
Normal file
37
clients/bg-builders/scripts/bgb-assign-exo-role.ps1
Normal 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"
|
||||
81
clients/bg-builders/scripts/bgb-check-lesley-ownership.ps1
Normal file
81
clients/bg-builders/scripts/bgb-check-lesley-ownership.ps1
Normal 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
|
||||
11
clients/bg-builders/scripts/bgb-find-leslie.ps1
Normal file
11
clients/bg-builders/scripts/bgb-find-leslie.ps1
Normal 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
|
||||
102
clients/bg-builders/scripts/bgb-lesley-disable-wipe.ps1
Normal file
102
clients/bg-builders/scripts/bgb-lesley-disable-wipe.ps1
Normal 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
|
||||
33
clients/bg-builders/scripts/bgb-lesley-exchange.ps1
Normal file
33
clients/bg-builders/scripts/bgb-lesley-exchange.ps1
Normal 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"
|
||||
83
clients/bg-builders/scripts/bgb-lesley-fix-rules.ps1
Normal file
83
clients/bg-builders/scripts/bgb-lesley-fix-rules.ps1
Normal 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"
|
||||
@@ -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
|
||||
150
clients/bg-builders/scripts/bgb-lesley-mail-report.ps1
Normal file
150
clients/bg-builders/scripts/bgb-lesley-mail-report.ps1
Normal 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"
|
||||
193
clients/bg-builders/scripts/bgb-lesley-recover-review.ps1
Normal file
193
clients/bg-builders/scripts/bgb-lesley-recover-review.ps1
Normal 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 ""
|
||||
71
clients/bg-builders/scripts/bgb-lesley-verify-wipe.ps1
Normal file
71
clients/bg-builders/scripts/bgb-lesley-verify-wipe.ps1
Normal 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"
|
||||
119
clients/bg-builders/scripts/bgb-reenable-lesley.ps1
Normal file
119
clients/bg-builders/scripts/bgb-reenable-lesley.ps1
Normal 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
|
||||
166
clients/bg-builders/scripts/bgb-terminate-lesley.ps1
Normal file
166
clients/bg-builders/scripts/bgb-terminate-lesley.ps1
Normal 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
|
||||
2
clients/bg-builders/scripts/bgb-terminate-wrapper.cmd
Normal file
2
clients/bg-builders/scripts/bgb-terminate-wrapper.cmd
Normal 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
|
||||
16
clients/bg-builders/scripts/bgb-verify-users.ps1
Normal file
16
clients/bg-builders/scripts/bgb-verify-users.ps1
Normal 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
|
||||
Reference in New Issue
Block a user