Skip to main content

Part 1: Google Workspace Data Ingestion

Set up a Google Cloud service account with domain-wide delegation so ConfigView can pull your Google Workspace data into the dashboard. ConfigView reads Workspace through the Admin SDK and a few related Admin APIs. A single service account, authorized once in your Workspace Admin Console, impersonates an admin and reads users, groups, org units, roles, devices, audit logs, and mailbox settings — all read-only. You’ll end up with two things in ConfigView: a secret GOOGLE_ADMIN_EMAIL (the admin to impersonate) and the service-account key file, uploaded as google_admin.json. The key is not a Secret Manager secret — like Google Cloud, it’s uploaded as a JSON file and referenced directly by the scripts.
Running more than one Google Workspace? Each instance gets its own JSON file and admin-email secret, suffixed by number: the first instance uses google_admin.json + GOOGLE_ADMIN_EMAIL, the second uses google_admin_2.json + GOOGLE_ADMIN_EMAIL_2, and so on. The steps below cover the first instance; for a second instance, just append _2 to the filename and the secret name.

Step 1: Create a Google Cloud project

The service account lives in a Google Cloud project. Any project works; API calls are quoted against it.
  1. Go to the Google Cloud Console.
  2. Click the project dropdown (top-left) → New Project.
  3. Name it configview-integration, choose your Organization, and click Create.
  4. Make sure the new project is selected in the dropdown before continuing.

Step 2: Enable the required APIs

On that project, enable the APIs ConfigView calls. On a fresh project these are off by default. Click each link (with your project selected) and press Enable, or run the one-liner below.
Note. The Admin SDK exposes both the Directory (directory_v1) and Reports (reports_v1) APIs under the single admin.googleapis.com service — enabling Admin SDK API covers both. You only need the others for the specific endpoints listed above; skip an API and just leave its scripts disabled.
Propagation. Right after enabling, you may see intermittent SERVICE_DISABLED 403s for ~10–15 minutes while the change rolls out. Wait it out before assuming a misconfiguration.

Step 3: Create the service account

  1. Open IAM & Admin → Service Accounts with your configview-integration project selected.
  2. Click Create Service Account.
  3. Name: configview (the email auto-fills, e.g. configview@configview-integration.iam.gserviceaccount.com).
  4. Click Create and Continue.
  5. Skip the optional “Grant this service account access to project” and “Grant users access” steps — this integration needs no project IAM roles; all access comes from domain-wide delegation in Step 5.
  6. Click Done.

Step 4: Create and download the JSON key

  1. From the service account list, click your configview service account.
  2. Open the Keys tab → Add KeyCreate new keyJSONCreate.
  3. The JSON key file downloads automatically. Keep it handy — you’ll upload it to ConfigView in Step 6.
  4. While you’re here, open the Details tab and copy the Unique ID (the numeric Client ID) — you’ll need it for delegation in Step 5.

Step 5: Authorize domain-wide delegation

This is what lets the service account read your Workspace data. You authorize its Client ID against a fixed list of read-only scopes in the Admin Console.
  1. Sign in to the Google Workspace Admin Console as a super admin.
  2. Go to SecurityAccess and data controlAPI controlsManage Domain Wide Delegation.
  3. Click Add new and paste:
    • Client ID: the numeric Unique ID from Step 4.4
    • OAuth scopes: the comma-separated list below
  4. Click Authorize.
Paste this full scope list (read-only — they grant visibility, never write access):
Each scope maps to a slice of the integration:
Seat utilization uses apps.licensing + admin.reports.usage.readonly. apps.licensing answers “how many seats are assigned” (one row per user per SKU). The purchased count comes from the Reports API customer usage report under admin.reports.usage.readonly, which exposes accounts:<edition>_total_licenses alongside _used_licenses. apps.order does not work for this and you can skip it. The Reseller API has the same numbers, but it authenticates the reseller — a customer super admin gets a flat 403 Forbidden on every method even with the scope granted, and buying through a reseller does not change that. It is listed above only because the scope name suggests otherwise. Note admin.reports.usage.readonly is a separate scope from admin.reports.audit.readonly — granting the audit one does not grant this one, and vice versa.
Adding scopes later. If you enable a new script that needs a scope you didn’t authorize, re-open Manage Domain Wide Delegation, click your client row, and add the missing scope. Delegation changes take a minute or two to propagate.
Trim if you like. You only need the scopes for the scripts you’ll actually run. The list above is the full set; dropping a scope just disables its endpoints (and its health check).

Step 6: Add the secret and upload the JSON key

6a. Add the admin-email secret.
  1. Go to your ConfigView dashboard: https://{companyname}.configview.com/admin/secret/
  2. Click Add Secret and create:
    • GOOGLE_ADMIN_EMAIL: a super-admin email address for the service account to impersonate (e.g. admin@yourdomain.com)
  3. Click Save.
6b. Upload the service-account JSON key.
  1. Go to the JSON upload board: https://{companyname}.configview.com/admin/external/
  2. Rename the key file you downloaded in Step 4 to google_admin.json before uploading — the scripts resolve it by that exact name.
  3. Upload it. It’s saved to <project_root>/json/google_admin.json on the satellite (the same directory that already holds secret-manager.json). It is not a Secret Manager secret — the key is referenced directly by all Google Workspace scripts.
Second instance. For a second Google Workspace, name the secret GOOGLE_ADMIN_EMAIL_2 and upload the key as google_admin_2.json (instance 3 → _3, and so on).

Step 7: Enable the Google Workspace app in ConfigView

  1. Go to: https://{companyname}.configview.com/admin/cron/
  2. You should see Google Workspace in the list of available apps.
  3. Select the scripts you want to run.
  4. Click Save.

Step 8: Verify

  1. Go to: https://{companyname}.configview.com/admin/status/
  2. Run the Google Workspace health check.
  3. All checks should pass.
If a check fails:
  • unauthorized_client / Client is unauthorized to retrieve access tokens — the Client ID isn’t authorized, or a required scope is missing. Re-do Step 5 and confirm the Unique ID matches. Note this failure happens when the token is issued, before any API call, so a script hitting it produces no 403 and no error rows — its table simply stays empty. Scopes are authorized individually: the rest of the integration can be working perfectly while one un-granted scope leaves its own endpoints silently at zero. If one table is empty and the others are fine, suspect its scope first.
  • access_denied / 403 on a specific endpoint — the matching scope wasn’t authorized, or GOOGLE_ADMIN_EMAIL isn’t a super admin.
  • SERVICE_DISABLED — the API for that endpoint isn’t enabled on the project. Re-check Step 2.
  • FileNotFoundError / google_admin.json — the key file wasn’t uploaded, or was uploaded under the wrong name. Re-do Step 6b and confirm it’s named exactly google_admin.json (or google_admin_2.json for a second instance).
  • Otherwise verify your GOOGLE_ADMIN_EMAIL secret and the uploaded JSON key are both in place.

Data Tables

Once the scripts run, the corresponding Google Workspace tables will be created in your database. All tables include a run_at column for historical tracking. The License Assignments script (google_get_licensesgoogle_licenses) records one row per user per SKU across Google Workspace, Gemini, Vault, Voice and AppSheet, so you can see how many seats of each SKU are actually assigned. It stores product_id and sku_id verbatim — the friendly product_name / sku_name come from a static catalog and are NULL for any SKU Google has added since, so filter and join on the ids, never the names. This is the assigned side. The License Totals script (google_get_license_totalsgoogle_license_totals) supplies the purchased side, from the Reports API customer usage report: one row per edition per day with total_licenses and used_licenses. Together they answer “are we at our seat limit” — the curated query google.license_utilization renders it directly as purchased / used / available / percent. Two things to know about it. The report is compiled daily and lags two to three days, so report_date is never today; asking for a newer date returns a 400 naming the newest one that exists, which the collector follows automatically. And its edition values are Google’s legacy gsuite_* names, which do not match the modern SKU names in google_licenses — compare the two tables’ numbers, don’t join them on the label. The Admin Audit Log script (google_admin_audit) pulls the Google Admin Console activity feed from the Reports API — user, group, role, and security-setting changes over a rolling 180-day window. Curated queries built on it (recent admin actions, role & privilege changes, security-setting changes, and per-user investigation lookups) ship in the saved-query catalog under the Audit category.