At a glance

VendorGoogle Workspace
Source typegoogle_workspace
Vendor ID (slug)google-workspace
Base URLhttps://admin.googleapis.com — fixed for every Workspace tenant
Auth methodoauth2Authorization: Bearer <access_token> minted per run from a domain-wide-delegated service account JWT
Schedule defaultdaily
AvailabilityStable — presentation refreshed 2026-04-18.

Required scopes & roles

Draxis authenticates as a GCP service account with domain-wide delegation, impersonating a read-only Workspace admin. The service account needs exactly these three read-only OAuth scopes — nothing more:

  • https://www.googleapis.com/auth/admin.directory.user.readonly — list users, 2SV enrollment state, admin flags, suspended/archived state. Backs the /admin/directory/v1/users call.
  • https://www.googleapis.com/auth/admin.reports.audit.readonly — read Admin, Token, and Drive audit logs. Backs the /admin/reports/v1/activity/users/all/applications/{admin,token,drive} calls.
  • https://www.googleapis.com/auth/admin.reports.usage.readonly — reserved for future usage-based KRIs; included now so you don’t need a second consent pass later.

On the Workspace side, the impersonated subject must be a user with a role that can read those APIs. The Google-provided “Services admin” predefined role works; for tighter least-privilege, create a custom admin role that grants only Admin API Privileges → Users → Read and Reports.

Do not grant the service account the Super Admin role — none of these scopes require it, and it would also grant write access.

Setup steps

  1. Create a GCP project and service account. In the Google Cloud Console, pick (or create) a project dedicated to third-party integrations, then go to IAM & Admin → Service Accounts → Create Service Account. Name it draxis-workspace-reader. Skip the “Grant this service account access to project” step — it needs zero GCP IAM roles.
  2. Enable the Admin SDK API on the project. APIs & Services → Library → Admin SDK API → Enable.
  3. Generate a JSON key. On the service account’s Keys tab, Add Key → Create new key → JSON. Save the file — you’ll paste the entire contents into Draxis in the final step. Treat it like a password.
  4. Enable domain-wide delegation. On the service account’s Details page, copy its Unique ID (OAuth 2.0 Client ID) — a numeric string. You’ll paste it in the next step.
  5. Authorize the scopes in the Workspace Admin Console. Go to admin.google.comSecurity → Access and data control → API controls → Manage Domain Wide Delegation → Add new. Paste the numeric Client ID from step 4, then paste these three scopes (comma-separated):
    https://www.googleapis.com/auth/admin.directory.user.readonly,https://www.googleapis.com/auth/admin.reports.audit.readonly,https://www.googleapis.com/auth/admin.reports.usage.readonly
    Click Authorize.
  6. Pick (or create) a read-only admin user to impersonate. In the Admin Console, Directory → Users → Add new user, e.g. draxis-reader@your-domain.com. Assign it the Services admin role (or the custom read-only role described above). This is the email you’ll put in the Draxis Client ID field — Draxis impersonates this user when calling Google.
  7. Verify the customer ID (optional). Most tenants can leave customer_id as my_customer. If you’re a Workspace reseller or manage multiple customers, find the real customer ID under Account → Account settings and put it in the Draxis Extra Config JSON as {"customer_id":"C01xxxxxx"}.

Wire it into Draxis

  1. Open Settings → Integrations in your tenant.
  2. Click Add integration and pick Google Workspace as the source type.
  3. The vendor dropdown auto-selects Google Workspace (Admin SDK + Reports), and Draxis auto-fills the base URL, the OAuth auth method, the daily schedule, and seeds extra_config_json with {"customer_id":"my_customer"}.
  4. In Client ID, paste the admin email from step 6 above (e.g. draxis-reader@your-domain.com). This is the user Draxis impersonates — not the service-account numeric ID.
  5. In Client Secret, paste the entire contents of the JSON key file from step 3 — every character including the enclosing { … }. Draxis encrypts it server-side with encryption.key before storage.
  6. Click Test. Green means Draxis minted a JWT, exchanged it for an access token, and hit the Directory API successfully.
  7. Under KRIs to import, tick the KRIs you want Draxis to manage. All seven gws_* KRIs are checked by default; uncheck any you don’t need. Selected rows are created on save with the seeded thresholds (tunable later in the KRIs tab). Unchecking a previously-imported KRI deletes it on save.
  8. Save. The connector runs daily by default; use Run now from run history to trigger the first sync immediately.

KRIs produced

SlugMeaningDerivation
gws_2sv_enrollment_pct % of active users enrolled in 2-Step Verification round(count(active[].isEnrolledIn2Sv) / count(active), 1) where active = users[!suspended && !archived]
gws_super_admin_count Count of users flagged isAdmin=true in the Directory API count(users[].isAdmin == true)
gws_ext_shared_sensitive_files Drive ACL changes that set visibility to an external audience, last 7 days count(drive_events where name in (change_user_access, change_acl_editors, change_document_visibility) and visibility in (people_with_link, public_on_the_web, public_in_the_domain_with_link, shared_externally))
gws_oauth_high_risk_apps Distinct OAuth client_ids authorized with high-risk scopes in the last 7 days distinct(token_events[authorize].client_id where any(scope matches mail.google.com | gmail.send|modify|insert | drive | admin.directory | admin.reports | cloud-platform | cloud_search))
gws_suspended_active_ratio_pct Suspended users as a % of active users round(count(suspended) / count(active) * 100, 1)
gws_admin_audit_anomalies_7d Count of privileged admin events in the last 7 days count(admin_events where name or type in (ASSIGN_ROLE, UNASSIGN_ROLE, CREATE_ROLE, DELETE_ROLE, UPDATE_ROLE, DELEGATED_ADMIN_SETTINGS, GRANT_ADMIN_PRIVILEGE, REVOKE_ADMIN_PRIVILEGE, TOGGLE_2SV_ENFORCEMENT, CHANGE_ALLOWED_TWO_STEP_VERIFICATION_METHODS, SSO_PROFILE_CREATED, SSO_PROFILE_DELETED))
gws_dlp_violations_7d Count of Drive DLP rule-violation events in the last 7 days count(drive_events where name startsWith 'dlp_' or type contains 'dlp')

Each row is a slug the connector writes to. Draxis creates the matching kri rows automatically when you check them in the KRIs to import section of the integration form — no manual API call or seed script needed. Thresholds shown in the table are the seeded defaults; you can edit them freely in the KRIs tab afterwards.

Vendor quirks

  • Domain-wide delegation is mandatory. Without it the JWT-bearer token exchange returns unauthorized_client. The scope list in Workspace must match exactly — a typo in one scope silently blocks access to that API.
  • Service-account impersonation is how Google Workspace does least-privilege. The service account itself has no powers; the impersonated subject’s Workspace role is what actually gates access. Keep that subject on a read-only custom role if you want the strictest least-privilege posture.
  • Reports API has a ~20-minute lag. Events appearing in the Admin Console may take up to ~20 minutes to surface through /admin/reports/v1/activity. Draxis’s 7-day window always trails real time, so this is invisible in practice.
  • customer_id=my_customer works for almost everyone. Only resellers or multi-customer setups need the real numeric customer ID. If Test returns HTTP 400 with “Invalid Input: customer”, replace it with your real ID from the Admin Console’s account settings.
  • Pagination is capped at 200 pages per endpoint. At 500 users/page that’s 100k users; at default Reports page sizes it’s well past any 7-day window we’ve seen. Very large tenants that hit the cap should open a support request — we’ll tune the window or paginate in chunks.
  • Service-account JSON keys are credentials. If a key is ever exposed, revoke it in the GCP console (Keys → Delete) and generate a new one — the old key stops working immediately, so do this only after you’re ready to update Draxis.

Troubleshooting

  • HTTP 401 unauthorized_client at the token exchange — domain-wide delegation isn’t set up, or the scope list in the Workspace Admin Console doesn’t match the three scopes above. Re-check the numeric Client ID and the exact scope strings.
  • HTTP 403 on Directory or Reports calls — the impersonated user’s Workspace role is too narrow. Grant them Services admin (or add Users → Read and Reports privileges to your custom role).
  • HTTP 400 “Invalid Input: customer” — you’re a reseller or multi-customer tenant and my_customer doesn’t resolve. Replace the customer_id in Extra Config with the real customer ID.
  • “Client Secret is not valid JSON” on Test — you pasted something other than the full service-account key file. Paste the entire JSON including the outer braces.
  • rowsSkipped > 0 and rowsWritten = 0 — your tenant hasn’t imported any KRIs for this integration yet. Open the integration in Settings → Integrations, tick the KRIs under KRIs to import, and save.
  • Still stuck? Open a support ticket with the run ID (from Run history) and we’ll dig in.