Skip to main content

Collecting Google Workspace

Reading the Admin SDK Reports API: which activity reports we pull, why the token report matters most, and what domain-wide delegation actually costs you.

Written for whoever runs IT7 min readUpdated

Google Workspace keeps a set of audit reports — who signed in, what administrators changed, which third-party applications were granted access to your users' data. The platform reads them through Google's Admin SDK Reports API. This article covers what is pulled, what setting it up costs you, and where this source stops.

Which activity reports are pulled

Google exposes its audit data as separate applications, each with its own report. Three are pulled unless you ask for something else, and the third is the one most people would not have chosen.

`login`
Sign-in successes and failures, including the address and whether a second factor was used, plus Google's own suspicious-login and account-disabled events. The equivalent of the Entra ID sign-in feed.
`admin`
Everything an administrator did in the admin console: users created and suspended, roles granted, settings changed, two-step verification enforcement turned on or off. This is where privilege change becomes visible.
`token`
OAuth grants to third-party applications. This one is in the default set on purpose: it is the Google analogue of an Entra consent grant, and it is the source of most Workspace account takeovers. A user who authorises a convincing-looking productivity add-on has just given a stranger persistent read access to their mail, and no password was involved at any point.

Other applications the Reports API offers — Drive, Calendar, Groups, mobile devices, SAML and the rest — can be added to the configuration by name. The application list is passed through to Google as given, so anything the Reports API accepts will be pulled. Be deliberate about Drive in particular: on an active tenancy it produces a very large volume of file-access records, and on a source that does not currently drive alerting the return on that volume is low.

What the configuration needs

Google requires domain-wide delegation to read reports for a whole customer, and domain-wide delegation is a heavier commitment than an API key. It is worth understanding what you are granting before you grant it.

  1. Create a service account and download its key

    In Google Cloud, create a service account for this purpose and nothing else, and download its JSON key. Authentication is the service-account JWT-bearer grant, which is what Google requires here — there is no interactive consent at poll time and no user session involved.

  2. Grant domain-wide delegation for one scope

    In the Workspace admin console, authorise the service account's client ID for exactly one scope: https://www.googleapis.com/auth/admin.reports.audit.readonly. That scope is read-only and limited to audit reports. Grant nothing else — a delegation is a standing capability, and the narrower it is, the less it is worth stealing.

  3. Nominate an administrator to impersonate

    Domain-wide delegation works by impersonation, so the service account acts as a named administrator when it reads. That address is the subject in the configuration. Use a dedicated administrator account rather than a person's, so the delegation does not break the day that person leaves.

  4. Find your customer ID

    The Workspace customer identifier for your tenancy. It is required — the literal my_customer shorthand some Google tooling accepts is not a substitute here, because the puller reads on behalf of a specific customer.

  5. Send us the details, with the key referenced rather than pasted

    In production the service account JSON is referenced by the name of an environment variable and resolved by the worker at runtime rather than stored in the configuration. An inline value is accepted so a local development stack works, and the worker logs a warning when it finds one outside development. This is a recorded stop-gap: there is no application-level secret store yet.

How the pull works

One request per application per window, paged. The bounds are deliberately conservative: at most a thousand records per page and twenty pages per cycle, an initial window of twenty-four hours on the first run, and a maximum look-back of thirty days. Default cadence is five minutes, adjustable per source.

The thirty-day bound is worth noting for a specific reason: it means this source cannot be used to backfill history from before it was configured beyond a month, regardless of how long Google retains the reports on their side. If you need the older records, export them from Google directly.

Incrementality uses the request's own start time plus a per-second set of already-seen record identifiers. That second half is not redundant. Google's start time parameter is inclusive, and several activities routinely share one timestamp to the second, so a naive resume from the last timestamp either loses events or duplicates them on every single poll. The identifier set removes the ambiguity, and a uniqueness constraint on the stored event catches anything that slips past it.

What failure looks like

Configuration problems are caught before scheduling, with a message naming what is wrong rather than a generic failure. Runtime problems back off exponentially with jitter, and Google's own Retry-After beats our guess. A failure on this source stops this source and nothing else — not the other sources for your organisation, and not any other tenant.

Messages worth recognising
workspace: service account JSON is required
workspace: impersonation subject (admin email) is required for domain-wide delegation
workspace: nil token source
workspace: token source returned an invalid token
workspace throttled: <detail>
workspace status=<code>: <detail>
workspace puller: missing <fields>
siem ingest: receiver skipped — invalid configuration

The second of those is the one you are most likely to hit, and it is the most common domain-wide delegation mistake: a service account key that is perfectly valid but with no administrator nominated to impersonate. Google will issue a token and then refuse the read, so the symptom appears at the wrong stage.

A note on an earlier defect, because it explains what you may have been told before. A previous implementation of this source issued the request and discarded the body, hard-coded the login report so administrator actions and OAuth grants were invisible, and took a caller-supplied bearer token with no refresh — which meant it worked for one hour after a deployment and then failed authentication indefinitely. All three are fixed. We name them because the connector exists is not the same statement as the connector returns your data, and the difference is the whole point of this knowledge base.

What to do about the alerting gap

  • Keep Google's own alert centre rules on. Google will email you about suspicious sign-ins and a handful of other conditions. Nothing here replaces that today.
  • Review your OAuth application access list in the admin console now, by hand. It takes twenty minutes, it is the single highest-value thing you can do in a Workspace tenancy without any product at all, and it does not depend on log collection working.
  • Collect anyway. Retained, searchable, normalised audit history is what makes an investigation possible weeks later and what an auditor asks to see. That value does not depend on alerting, and it means the history is already in place when the join lands.

What to read next

  1. Connecting your first log source — the per-source status table, and which source to prioritise.
  2. How your logs are normalised — what a Workspace activity record becomes once stored.
  3. Log retention — how long the collected history is kept.

Was this article wrong?

If a procedure here does not match what you see, or a limit we described has changed, tell us and we will fix the page. Email us about this article, or see how to get help if you need an answer rather than a correction.

Everything in logs and detection