G-Suite Migration: Automated Credential Distribution Using Python and GAM CLI

We recently migrated our organisation from G-Suite(Google Workspace) to Microsoft. While we used a third-party migration tool to shift the historical Google data across, we hit a practical roadblock: how do we securely distribute new Microsoft credentials to over 100 users?
The initial plan proposed by the team was entirely manual. We were going to create the Microsoft accounts with temporary passwords, divide the user list into batches, and have the engineering team manually share the credentials one by one via a password manager.
With a workload full of higher-priority tasks, spending a day manually distributing credentials felt like a poor use of time. The goal was to find a secure way to handle distribution without the manual overhead.
Scripting the Process with Python and GAM CLI
Instead of generating and distributing secure links, I used an environment users were already authenticated into: their existing Google Drive.
The approach was straightforward. Generate the credentials, write them to a per-user text file, and upload each file directly into the corresponding Google Drive account under the appropriate ownership.
Generating the Data
The first step was preparing a clean CSV mapping staff to their new email addresses and temporary passwords. Simple scripts often fail when dealing with multi-part surnames, so I used a small Python script to parse the names.txt file, normalise the formatting, and generate a 16-character temporary password for each user.
import csv
import random
import string
# Generate a normalised email using first initial + last name and a random domain
def generate_email(first_name, last_name):
domains = ["tech-journey.co.za", "example.com", "test.com", "company.com"]
username = f"{first_name[0].lower()}{last_name.lower()}"
username = ''.join(e for e in username if e.isalnum()) # sanitize username
return f"{username}@{random.choice(domains)}"
# Generate a 16-character password using letters and special characters
def generate_random_password():
characters = string.ascii_letters + "!@%^$&*#"
return ''.join(random.choices(characters, k=16))
# Read and clean input names
with open('names.txt', 'r') as file:
names = file.readlines()
data = []
for name in names:
name = name.strip()
if not name:
continue # skip empty lines
parts = name.split()
if len(parts) < 2:
print(f"Skipping invalid line: {name}") # enforce first + last name
continue
first_name = parts[0]
last_name = ' '.join(parts[1:]) # support multi-part surnames
data.append({
"email": generate_email(first_name, last_name),
"password": generate_random_password()
})
# Write results to CSV with fixed schema
with open('generated_email_password_pairs.csv', mode='w', newline='') as file:
writer = csv.DictWriter(file, fieldnames=["email", "password"])
writer.writeheader()
writer.writerows(data)
print("Email and password pairs added to generated_email_password_pairs.csv")
Example Output:
The script outputs a generated_email_password_pairs.csv file, which is then used in the next step.
Delivering the Credentials via GAM
With the CSV prepared, I used the GAM CLI (Google Apps Manager) to handle distribution.
GAM is an incredibly powerful command-line tool for managing G-Suite. If you haven't got it set up yet, you'll need to configure your API access and service accounts first. I highly recommend following the official GAM setup instructions to get that running.
By iterating through the CSV using a simple Bash loop, I used GAM to generate a text file containing each password and upload it directly into the user’s Google Drive root directory, assigning ownership to the corresponding account.
The Payoff
Writing and testing the script, along with the GAM commands , took a few hours. Rolling it out to 100+ users took around 15 minutes.
There was no manual copying into a password manager, no credentials passed through Slack or email, and no additional handling once the process was in place. Users signed into Google and retrieved their Microsoft credentials directly from their own drives.
The full Python script is available on GitHub here.






