InfrastructureService accountVerified August 25, 2026
Lutril needs one service account carrying one organization-level custom role to inventory every Google Cloud service account and key, tell you when each was last used, and let you disable the dormant ones. No stack of predefined roles: the custom role below is the complete permission list, verified by creating it. Lutril never deletes service accounts, never creates, rotates or deletes keys, and never edits IAM policies.
Remediation (optional): iam.serviceAccounts.disable, iam.serviceAccounts.enable. Without them the inventory still works and the Disable button reports a permission error.
Just-in-time grants (optional): resourcemanager.projects.setIamPolicy. Used only to add and remove one time-boxed binding per approved access request.
Last used values come from Policy Analyzer, which aggregates authentications per day (Pacific time). Google states results may not include very recent authentication events; a lag of several days is common. Google also does not track requests authenticated with bound API keys, Cloud Storage HMAC keys, or Google APIs outside Cloud (for example Workspace domain-wide delegation, as used by GAM): such accounts can show as never used while active. This is why Lutril treats no observed authentication as a warning signal, never as proof of non-use.
Setup steps
1
Create a service account for Lutril in a dedicated project. That project becomes the quota project for Policy Analyzer calls, so keep it separate from your workloads. Open the account, go to Keys, choose Add key, then Create new key with the JSON type. The file downloads once and cannot be downloaded again; you will paste it into Lutril in step 5.
Enable four APIs in that project only: Cloud Asset, IAM, Cloud Resource Manager and Policy Analyzer. Lutril attributes every call to the service account's own project, so Policy Analyzer never needs enabling in the projects being analyzed.
Replace <LUTRIL_PROJECT_ID> with the ID of the project you created the service account in.
3
Create the custom role at organization level from Cloud Shell. ORG_ID is the numeric organization ID shown in the organization picker, or by gcloud organizations list. Prefer the console? Open IAM & Admin, then Roles with the organization selected, click Create role and add the same permissions.
The role is read-only apart from the last two permissions. Drop iam.serviceAccounts.disable and iam.serviceAccounts.enable if you want Lutril to observe without ever remediating.Open Roles
4
Bind the role to the Lutril service account on the organization. One binding covers every folder and project, including the ones created after today.
<LUTRIL_SA_EMAIL> is the address of the account from step 1, ending in .iam.gserviceaccount.com.
5
Optional, for just-in-time access. When an access request for a project is approved, Lutril grants the person a time-boxed IAM role on that project (an IAM condition on request.time) and removes it at the deadline. This needs one write permission on the same role.
Shell
gcloud iam roles update lutrilNhiGovernance \
--organization=<ORG_ID> \
--add-permissions=resourcemanager.projects.setIamPolicy
Bound at the organization, setIamPolicy lets the Lutril service account grant any role on any project. Mitigations: bind the role only on the folder that holds requestable projects, or add an IAM deny policy that blocks resourcemanager.projects.setIamPolicy for roles/owner, roles/editor, roles/iam.securityAdmin and roles/resourcemanager.projectIamAdmin when the principal is the Lutril service account. Lutril itself refuses to grant Owner, Editor or Viewer (they cannot carry a time condition).
6
In Lutril, open Settings, then Integrations, then Google Cloud. Paste the Service Account JSON. Set the Organization ID for an organization-wide scan (recommended) or a Project ID to scan a single project. Keep the stale key threshold at 90 days unless your policy says otherwise. Turn the Impersonation lens on to list who can impersonate each service account; it costs one extra IAM read per account.
7
Open Non-Human Identities and click Refresh. The sync runs in the background and takes a few minutes on large organizations; the page reports any missing API or permission as a warning. Last used showing Unknown everywhere means Policy Analyzer is not enabled in the Lutril project or its permissions are missing. Projects marked Not synced lack the resourcemanager permissions. Disable failing with a permission error means the role lacks iam.serviceAccounts.disable. Rate limits (429) are retried automatically and previously known data is kept.