Connect projects
LevelFour connects to Google Cloud in two parts. First you grant read-only access to the projects you want analyzed by running a short command in your own Cloud Shell. Then you connect your Cloud Billing data so LevelFour can attribute spend to individual resources.
Different people can own each part. Connecting projects needs someone who can grant IAM roles; connecting billing data needs a finance or billing admin. Do them in that order, because billing export on its own produces nothing: LevelFour only reads costs for projects you have already connected.
Prerequisites
- Ask your LevelFour contact to turn on Google Cloud for your organization. Until they do, the connect commands cannot be generated.
- LevelFour admin rights, to generate the connect commands.
- Someone who can grant IAM roles on the target project, typically an Owner or a user with
roles/resourcemanager.projectIamAdmin. For organization mode, the same rights at the organization level, for exampleroles/resourcemanager.organizationAdmin. - The connect command from the Connect Google Cloud page in the dashboard.
Connecting billing data needs a finance identity as well, with its own roles. Cloud Billing export lists them.
Connect
Choose single project or organization
Open the Connect Google Cloud page in the dashboard (Connect Accounts > Google Cloud). A toggle sets the scope of the connection. Pick one:
- Single Project grants read access to one project. LevelFour builds a resource inventory and reads utilization metrics for that project.
- Organization discovers every project under your Google Cloud organization and connects them in one pass, so existing projects and projects that join later are all covered.
The two paths do not combine, so follow the one you picked start to finish.
A single-project connection ingests only that project's share of the bill, never the whole billing account.
A single-project connection cannot use the Committed Use Discounts export, which requires an organization connection. If you hold committed use discounts, connect at the organization level.
Point Cloud Shell at the right scope
The connect script reads the scope from your Cloud Shell session, not from the dashboard. Set it before you run the command.
Run the commands for the mode you picked above, not both.
Set the active project to the one you want to connect:
gcloud config set project YOUR_PROJECT_ID
gcloud config get-value project # confirmThe script binds roles to the first organization your identity can see. If you belong to more than one, check which one that is before you run the command:
gcloud organizations listThe first row is the one that gets connected. If it is the wrong organization, connect from an identity that only sees the one you want, or contact LevelFour support.
Run the connect command in Cloud Shell
Click Generate connect command. LevelFour builds the command, embeds a one-time token tied to your organization, and shows it with a Copy button.
Open Cloud Shell in the Google Cloud console (the terminal icon in the top bar), paste the command, and run it. Copy it exactly as shown; there is nothing in it for you to fill in or edit. Read What the connect command does first if you want to see the script before you run it.
The script prints the service-account address, the identity it will grant as, and the list of roles, then asks Continue? [y/N]. Answer y. Anything else stops the script without changing your account.
Copy the service-account address the script prints. It looks like tenant-42@levelfour-prod.iam.gserviceaccount.com. The optional steps further down this page need it, and no dashboard screen shows it. If you lose it, see Finding your service-account address.
The roles it grants are read-only:
| Role | What it allows |
|---|---|
roles/browser | Read the resource hierarchy (projects, folders, organization) so LevelFour can enumerate what exists |
roles/monitoring.viewer | Read Cloud Monitoring metrics, used to detect idle resources from real usage |
roles/compute.viewer | Read Compute Engine resources: instances, disks, addresses, snapshots |
roles/cloudasset.viewer | Read the Cloud Asset Inventory, a normalized snapshot of resources across the connected scope |
roles/serviceusage.serviceUsageConsumer | Call the read-only Google Cloud APIs above against your project |
roles/recommender.computeViewer | Read Google's own recommendation data for Compute Engine |
roles/recommender.cloudsqlViewer | Read Google's own recommendation data for Cloud SQL |
roles/recommender.projectCudViewer | Read committed use discount recommendations at the project level |
roles/cloudsql.viewer | List Cloud SQL instances, so LevelFour can spot idle databases |
roles/logging.viewer | Read Cloud Audit Admin Activity logs, so an applied change is attributed to whoever made it |
The script grants each role separately and keeps going if one fails, so a partial grant is normal. LevelFour does not take the script's word for it: it verifies the connection by checking what the service account can see. A run where every role succeeded still fails verification if the service account sees no projects.
If your organization restricts Data Access logs, grant roles/logging.privateLogViewer on top of what the script applied. Without it, applied savings show an unknown actor.
Billing data is not covered by these roles. You connect it separately, in Connect your billing data.
If your organization enforces Domain Restricted Sharing (the iam.allowedPolicyMemberDomains org policy), IAM bindings to an outside identity are blocked by default and the grant will fail. Ask your LevelFour contact for the Cloud Identity customer ID to allowlist, add it to the allowed domains (or add an exception for the LevelFour service account), then re-run the command.
Your connect command stays valid for 20 minutes. Within that window you can re-run it as often as you need. After it expires, click Generate connect command again for a fresh one.
Check what connected
Within about a minute of the command finishing, the Connect Google Cloud page moves through Waiting for grant, then Verifying access, then Connected, and what you connected appears in the Projects table below it. A project LevelFour can read shows Connected.
If it stalls on Waiting for grant for more than 90 seconds, the page offers to cancel and generate a fresh command.
The Projects table lists what LevelFour found, one row per project:
| Status | Meaning |
|---|---|
| Connected | LevelFour can read this project |
| Awaiting grant | The binding has not landed yet |
| Error | LevelFour could not read this project |
| Revoked | Access was removed |
In organization mode LevelFour re-discovers projects daily, so projects that join your organization later are picked up on their own.
Enable the APIs LevelFour reads
LevelFour analyzes a project only where the APIs it reads are enabled. Enable these on each project you want covered:
compute.googleapis.com(Compute Engine)monitoring.googleapis.com(Cloud Monitoring)cloudresourcemanager.googleapis.com(Cloud Resource Manager)sqladmin.googleapis.com(Cloud SQL Admin), if you run Cloud SQLbigquery.googleapis.com(BigQuery), on the project that holds your billing export
Connect your billing data
LevelFour reads your Cloud Billing data from a BigQuery billing export.
LevelFour prices every finding against your bill and drops any it cannot price, so until the export lands you get no Google Cloud recommendations.
Follow Cloud Billing export. That page walks through turning on the Detailed usage cost export, choosing a dataset, and running a second command that grants LevelFour read access to the export.
Confirming it worked
The project side confirms in about a minute. See Check what connected.
The billing side takes about two days end to end: Google takes 24 to 48 hours to deliver the first export rows, and LevelFour reads the export on a schedule after that. Once that data lands, resource-level cost breakdowns appear in your cost views. The export page covers what the Billing data (BigQuery export) panel shows: Confirming it worked.
Cost anomalies need about two weeks of cost history before the first one can appear, and LevelFour only raises anomalies above a $50 impact.
What the connect command does
You grant access to a service account that belongs only to your organization.
The command downloads a script to levelfour_connect.sh rather than piping it into a shell, so you can read it before it runs:
less levelfour_connect.shLevelFour never asks for a service-account key, and no credentials leave your environment. The script adds the read-only bindings listed under Run the connect command in Cloud Shell, reports back to LevelFour, and stops there.
The one-time token travels in the Authorization header, not the URL. The downloaded file contains that token, so delete it when you are done.
Finding your service-account address
The connect script prints the address it grants to, and that is the only place it appears. If you no longer have the output, read it back from the bindings the script created:
gcloud projects get-iam-policy YOUR_PROJECT_ID \
--flatten="bindings[].members" \
--filter="bindings.members:levelfour-prod.iam.gserviceaccount.com" \
--format="value(bindings.members)" | sort -uIf you connected an organization, swap projects get-iam-policy YOUR_PROJECT_ID for organizations get-iam-policy YOUR_ORG_ID. Generating a fresh connect command and running it again also reprints the address.
Removing access
Revoking has two parts, one for each connect command.
Project or organization roles. From Cloud Shell, for a single project:
SA="PASTE_THE_ADDRESS_THE_SCRIPT_PRINTED"
for ROLE in roles/browser roles/monitoring.viewer roles/compute.viewer \
roles/cloudasset.viewer roles/serviceusage.serviceUsageConsumer \
roles/recommender.computeViewer roles/recommender.cloudsqlViewer \
roles/recommender.projectCudViewer roles/cloudsql.viewer \
roles/logging.viewer; do
gcloud projects remove-iam-policy-binding "YOUR_PROJECT_ID" \
--member="serviceAccount:$SA" --role="$ROLE"
doneIf you connected an organization, swap projects remove-iam-policy-binding "YOUR_PROJECT_ID" for organizations remove-iam-policy-binding "YOUR_ORG_ID". Add roles/logging.privateLogViewer if you granted it.
Billing access. Remove the billing-account roles and the BigQuery dataset binding. See Removing billing access.
LevelFour stops being able to read as soon as the bindings are gone. To also have your Google Cloud records removed from LevelFour, contact your LevelFour representative.
Troubleshooting
gcloud is required. Open this in a Cloud Shell.
The script ran somewhere other than Cloud Shell. Open Cloud Shell from the terminal icon in the Google Cloud console and paste the command there.
The command fails with a policy or permission error on the IAM binding. Your organization likely enforces Domain Restricted Sharing. Ask your LevelFour contact for the Cloud Identity customer ID to allowlist, add it, then re-run the command.
The command reports success but the page never leaves Waiting for grant. The script finished but its report to LevelFour did not arrive. Re-run the command; it is safe to run twice. If your command has expired, reopen the Connect Google Cloud page for a fresh one.
Verification fails with no projects visible.
The roles were bound somewhere the service account cannot see any projects. In single-project mode, confirm gcloud config get-value project returned the project you meant. In organization mode, confirm the first row of gcloud organizations list is the organization you meant.
Organization mode connected fewer projects than you expected. LevelFour lists the projects your organization exposes to the service account, so projects pending deletion are skipped. If a project you expect is missing, confirm it sits under the organization you connected and re-check after the next daily discovery.
Recommendations are missing entirely. Cost lives in the billing export. Until it lands, LevelFour has nothing to price findings against. See Connect your billing data.
Applied savings show an unknown actor.
Attribution reads your Cloud Audit Admin Activity logs through roles/logging.viewer. Check the connect command's output to see whether that grant succeeded, and re-run the command if it did not. If your organization restricts Data Access logs, grant roles/logging.privateLogViewer as well.
Next
- Billing export turns on the Detailed usage cost export, which is what prices every recommendation against your real bill
- Committed use discounts fills in the commitment term, start and end dates, and status alongside coverage
Automated Savings
Add the empty LevelFourSavingsExec role that Automated Savings needs, in an account onboarded before the role existed: AWS Console, Terraform, or an AWS Organization.
Billing export
Turn on the Detailed usage cost export in Cloud Billing so LevelFour can analyze resource-level Google Cloud cost data.