Gsuite: Auto-deprovisioning with GAM
A GAM script to automate Gsuite account deprovisioning with logging.
GAM is a command line tool for Google Workspace admins to manage domain and user settings quickly and easily.
The goal of the sampling is to automate the deprovisioning process using a PowerShell script and a corresponding CSV, consisting of the following steps:
- Suspend the account.
- Remove 2FA information (both phone and email).
- Update the account's OU.
- Remove all data from user information fields.
- Turn off directory discovery.
- Disassociate all Google group memberships.
- Set a random, strong password.
- Re-enable the account in order for third-party tools to perform data backup.
- Save the output to a local log file.
Requirements
- GAM installed locally. API authorization is required for setting up a new project in Google Cloud Console for this.
- deprov.csv - this is a header-less CSV listing email addresses in column A, placed in the same folder as the PowerShell script.
- If an OU update is required, replace the OU with yours.
- Important: Do not run this script against active accounts!
Script
# Get today's date to include in the log file name
$logDate = Get-Date -Format "yyyy-MM-dd"
$logFileName = "deprov_log_$logDate.txt"
$logPath = Join-Path -Path $PSScriptRoot -ChildPath $logFileName
# Create or append to the log file
if (-not (Test-Path $logPath)) {
New-Item -Path $logPath -ItemType File | Out-Null
}
# Function to write log entries
function Write-Log {
param (
[string]$Message
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logEntry = "$timestamp - $Message"
Add-Content -Path $logPath -Value $logEntry
}
try {
# Read the CSV file and handle errors if the file doesn't exist or is inaccessible
$csvData = Import-Csv -Path $csvPath -ErrorAction Stop
} catch {
$errorMessage = "Error: $($_.Exception.Message)"
Write-Host $errorMessage
Write-Log $errorMessage
exit 1
}
foreach ($email in $csvData) {
# Trim whitespace and process each email address
$email = $email.Trim()
# Check if the $email variable contains a valid email address.
if ($email -match "^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$") {
try {
# Perform the GAM actions for each email address.
# Move the account to /Deprovisioned
gam update user $email ou /Deprovisioned
sleep 1
# Suspend the account for the cleanup
gam update user $email suspended on
sleep 1
# Remove 2FA email
gam update user $email recoveryemail `"`"
sleep 1
# Remove 2FA phone
gam update user $email recoveryphone `"`"
sleep 1
# Remove account data
gam update user $email organization clear
sleep 1
# Turn off directory discovery
gam update user $email gal false
sleep 1
# Remove the account's location
gam update user $email location type buildingid:terminated endlocation
sleep 1
# Remove the account's group memberships
gam user $email delete groups 2>$null
sleep 1
# Set a strong password, don't require password change
gam update user $email password random changepassword false
sleep 1
# Reactivate account
gam update user $email suspended off
sleep 1
$successMessage = "$email is prepared for backup!"
Write-Host $successMessage
Write-Log $successMessage
} catch {
$errorMessage = "Error processing $email: $($_.Exception.Message)"
Write-Host $errorMessage
Write-Log $errorMessage
}
} else {
# If the email address is not valid, throw a message
$invalidEmailMessage = "Invalid email address: $email"
Write-Host $invalidEmailMessage
Write-Log $invalidEmailMessage
}
}
$completionMessage = "All accounts have been processed."
Write-Host $completionMessage
Write-Log $completionMessage