Account inventory

A worked example: from raw GAM output to a register with named owners

The walkthrough says "export, reconcile, assign owners." This page shows what that actually looks like, on a fictional 12-person tenant (example.dev) whose data is shaped like yours will be.

1 — What the user export looks like

gam print users … writes a CSV, one row per account. Opened in a spreadsheet it looks like this:

primaryEmail             name.fullName    suspended  isAdmin  lastLoginTime         creationTime          orgUnitPath
maya@example.dev         Maya Lindqvist   False      True     2026-07-23T08:14:02Z  2021-03-01T09:00:00Z  /
jonas@example.dev        Jonas Petit      False      False    2026-07-24T16:41:55Z  2022-11-14T10:22:00Z  /Staff
billing@example.dev      Billing Inbox    False      False    2026-07-21T07:03:11Z  2021-03-02T12:00:00Z  /Shared
svc-backup@example.dev   Backup Runner    False      False    Never                 2023-06-19T02:10:00Z  /Service
k.osei@example.dev       Kwame Osei       True       False    2024-01-30T11:47:23Z  2022-02-07T08:30:00Z  /Staff
mailer@example.dev       Newsletter Bot   False      False    2026-07-25T04:00:19Z  2024-09-12T15:45:00Z  /Service

Six rows, four different kinds of thing. maya and jonas are humans. billing@ is a shared mailbox several people read. svc-backup@ and mailer@ are service accounts driven by software. k.osei@ is suspended — a leaver. Every one of them can hold data, OAuth grants and group memberships, which is why every one of them goes in the register: suspended and robot accounts included.

2 — Groups and memberships

The two group exports are just as plain:

email                    name             adminCreated
staff@example.dev        All staff        True
finance@example.dev      Finance          True
partners@example.dev     Partner liaison  False

group                    member                    role     type
staff@example.dev        maya@example.dev          OWNER    USER
staff@example.dev        jonas@example.dev         MEMBER   USER
finance@example.dev      billing@example.dev       MEMBER   USER
partners@example.dev     anna@consultancy.example  MEMBER   USER

Two things to notice. partners@ was created by a user, not an admin (adminCreated = False) — nobody decided it should exist. And its member anna@consultancy.example is outside the domain. Neither is inventory's problem to fix — group hygiene is №34's audit — but the register records that partners@ exists and who answers for it.

3 — The identities with no user row

Domain-wide delegation clients live on their own console screen (Security → API controls → Manage Domain Wide Delegation) and look like this:

Name             Client ID              Scopes
Backup vendor    103846752019384756201  https://www.googleapis.com/auth/drive.readonly
(unnamed)        118293003847561029447  https://mail.google.com/

The second row is the interesting one: a client id with full Gmail scope and no name. Nothing in the user export points at it — DWD clients never appear as users, which is exactly why the walkthrough makes you visit this screen. In the register it becomes a row whose owner is "unknown", and an unknown owner on a Gmail-scope grant is a finding you chase this week, not a curiosity.

4 — Reconciliation, row by row

Reconciliation is a join: every exported account either matches a line in a source you already trust, or it doesn't. The trusted sources are the HR/people list for humans, and last cycle's register for everything else. Concretely:

maya@example.dev        → on the HR list                       ✓ human, owner = herself
jonas@example.dev       → on the HR list                       ✓ human, owner = himself
billing@example.dev     → in last cycle's register             ✓ shared, owner = Maya (finance lead)
svc-backup@example.dev  → in last cycle's register             ✓ service, owner = Jonas (runs backups)
k.osei@example.dev      → HR list says: left 2024-01           ✓ leaver — offboarding per №21
mailer@example.dev      → NOT on HR list, NOT in register      ✗ UNEXPLAINED → investigate

Five rows explain themselves in seconds. The sixth is the entire point of the exercise: mailer@ appeared between cycles, nobody recorded it, and "Newsletter Bot" is precisely the kind of plausible name an attacker gives a persistence account. Investigating usually takes one message — "who set up mailer@?" in the team channel — and ends in one of two ways: someone says "that's mine, for the October campaign" (record them as owner, done), or nobody claims it within a day and you treat it as an incident: suspend, pull its audit log, check its OAuth grants and filters.

5 — What "named owner" means

An owner is one human, by name, who can answer "what is this account for and can we turn it off?" Not a team, not a distribution list — a person (with a deputy if you like, but one name is accountable). For human accounts the owner is the human. For shared and service accounts, ownership is established the unglamorous way: you ask. Once. In writing. "You run the backups — are you the owner of svc-backup@?" The answer goes in the register, and from then on the monthly diff only ever asks about new rows, so the asking never repeats for settled accounts.

The register is also what makes the question cheap next year, when Maya has left: filter the register on owner = maya and you have the exact list of accounts needing a new owner — part of №21's offboarding.

6 — The register template

One sheet, one row per account, these columns. Paste the block below into a file and import it into Google Sheets (File → Import), or keep it as CSV next to the exports — the format matters less than the owner column never being empty.

email,kind,owner,purpose,created,status,reviewed,notes
maya@example.dev,human,maya,Founder / admin,2021-03-01,active,2026-07-26,
jonas@example.dev,human,jonas,Engineering,2022-11-14,active,2026-07-26,
billing@example.dev,shared,maya,Invoices in/out,2021-03-02,active,2026-07-26,3 readers via finance@
svc-backup@example.dev,service,jonas,Nightly Drive backup,2023-06-19,active,2026-07-26,DWD client 1038…6201
k.osei@example.dev,human,maya,Left 2024-01,2022-02-07,suspended,2026-07-26,data transfer pending (№21)
mailer@example.dev,service,UNKNOWN,under investigation,2024-09-12,active,2026-07-26,unclaimed — treating per §4
partners@example.dev,group,maya,Partner liaison list,—,active,2026-07-26,external member; audited by №34
118293…9447,dwd-client,UNKNOWN,Gmail scope grant,—,active,2026-07-26,unnamed client — finding

kind is one of human / shared / service / group / dwd-client; reviewed is the date a human last confirmed the row, which is what the monthly maintenance diff updates. The two UNKNOWN rows are not failures of the register — they are the register working.