# 40 Scripted JIT admin elevation

> v0.1.3 · role: Prevent · [policy: #29 · #4, #32](https://docs.google.com/spreadsheets/d/1nOztaPd1Y7eNeRSR_hdovYy-ncpx-bAx/edit?usp=sharing&ouid=115159875779023172526&rtpof=true&sd=true)

Standing admin privilege is privilege an attacker can steal at any moment. JIT elevation strips the standing grant and hands the role out on request from a script that starts a timer and revokes unconditionally when it fires — a Directory API role assignment plus an Apps Script trigger or GAM under cron. What is handed out is a narrow custom role, never Super Admin, and any role assignment that did not come from the JIT service account is itself an alert.

Documentation: [Manage roles](https://developers.google.com/workspace/admin/directory/v1/guides/manage-roles)

## Caveats

- Google has no native TTL on role assignments — the timer is your code, and its failure mode is silent standing access, so a failed revoke must page loudly rather than retry quietly.
- An already-issued admin session survives role revocation until it expires — pair JIT with cloud and web session control (№38, №12) or the elevation window is longer than the timer claims.
- The JIT service account becomes the crown jewel — it holds the power to grant roles permanently, so it needs the same custody treatment as the break-glass credential.

## Setup steps

1. Create the narrow custom role the JIT script will hand out — never Super Admin. Grant only the privileges the task needs. — `Account › Admin roles`

   Custom role, e.g. 'JIT-UserMgmt' with Users > Update + Read only

   docs: [Create, edit, and delete custom admin roles](https://knowledge.workspace.google.com/admin/users/create-edit-and-delete-custom-admin-roles)

2. Strip the standing grant so there is nothing to steal between elevations.

   ```
   gam print admins user <admin>   # note the roleAssignmentId
   gam delete admin <roleAssignmentId>
   ```

   docs: [Remove Google Workspace administrator privileges](https://knowledge.workspace.google.com/admin/users/remove-google-workspace-administrator-privileges)

3. Script the elevation: grant the role, start a timer, revoke unconditionally when it fires (Apps Script time-based trigger, or GAM under cron).

   Directory API roleAssignments.insert → sleep(TTL) → roleAssignments.delete; TTL = 60 min, started only once the grant is confirmed active — a new role typically applies within minutes but can take up to 24 hours

   docs: [REST Resource: roleAssignments](https://developers.google.com/workspace/admin/directory/reference/rest/v1/roleAssignments) · [Installable Triggers](https://developers.google.com/apps-script/guides/triggers/installable)

4. Make the revoke fail-safe: if the revoke call errors, alert loudly rather than retrying quietly — a stuck grant is a standing grant.

   on revoke failure → page the security mailbox

5. Alert on any role assignment that did NOT come from the JIT service account — that is the signal that someone elevated out-of-band. — `Reporting › Audit and investigation › Admin log events`

   Filter: Event = Assign role; Actor ≠ jit-service-account (advanced/negative filter conditions in activity rules need Enterprise Standard+, Education Plus, Frontline Plus, Cloud Identity Premium or Chrome Enterprise Premium)

   docs: [Admin log events](https://knowledge.workspace.google.com/admin/reports/admin-log-events) · [Create and manage activity rules](https://knowledge.workspace.google.com/admin/security/create-and-manage-activity-rules)

## Ongoing maintenance

- **[automatable: AI agent]** Weekly: review the elevation log — every grant should map to a ticket.
- **[requires a human]** Quarterly: drill the elevation script end to end so it still works when needed.

## How to verify

1. Confirm no standing grants beyond the floor, then run one elevation cycle end to end (grant, use, auto-revoke) as a drill.

   ```
   gam print admins
   ```

## Settings screens

- Account > Admin roles (create the least-privilege role the script will grant)
  - console: https://admin.google.com/ac/list/roles
  - screenshot: ../screenshots/admin.google.com/ac/list/roles.png
- Directory > Users (confirm the elevated user holds no standing role)
  - console: https://admin.google.com/ac/users
  - screenshot: ../screenshots/admin.google.com/ac/users.png
- Reporting > Audit and investigation > Admin log events (verify grant + auto-revoke both landed)
  - console: https://admin.google.com/ac/sc/investigation
  - screenshot: ../screenshots/admin.google.com/ac/sc/investigation.png
