These steps require a browser or human judgment and cannot be fully automated. Claude Code will walk you through them and tell you when each is needed.
- Steps 1, 2, 6, 7 — You do these in a browser (Cloud Console, Slack). Claude will tell you what to click and what values to enter.
- Steps 3, 4, 5 — Claude runs these for you via
gcloudandterraformcommands. They're documented here so you can understand what's happening or run them manually if needed.
Everything beyond these steps is handled by terraform apply —
see terraform/.
Before starting, make sure you understand which identity to use. There are two options, and you should pick one and use it for all steps below unless a step explicitly says otherwise.
Log in with your LBL email (e.g. yourname@lbl.gov) via the browser
for Cloud Console steps, and via CLI for command-line steps:
gcloud auth login # For gcloud commands
gcloud auth application-default login # For Terraform
gcloud config set project YOUR_PROJECT_IDRequired role: Owner on the GCP project. If Science IT created the project for you, you should already be Owner. Verify with:
gcloud projects get-iam-policy YOUR_PROJECT_ID \
--format="table(bindings.role,bindings.members)" \
--flatten="bindings[].members" \
--filter="bindings.members:yourname@lbl.gov"You should see roles/owner in the output.
If you have an existing admin service account with a JSON key:
gcloud auth activate-service-account --key-file=PATH_TO_KEY.json
export GOOGLE_APPLICATION_CREDENTIALS=PATH_TO_KEY.json
gcloud config set project YOUR_PROJECT_IDRequired roles on the service account:
roles/editorroles/resourcemanager.projectIamAdminroles/iam.serviceAccountKeyAdminroles/run.admin
Common pitfall: The
roles/editorrole does NOT includerun.services.setIamPolicy. If you get a 403 error about this permission duringterraform apply, your service account also needsroles/resourcemanager.projectIamAdmin(which grants it indirectly). Alternatively, switch to your personal Owner account (Option A).
| Step | Who | Why |
|---|---|---|
| 1. Get GCP project | You (browser) | Request to Science IT |
| 2. Enable models | You (browser) | Model Garden is UI-only |
| 3. Consumer SA key | Same as step 5 | Needs iam.serviceAccountKeyAdmin |
| 4. Build container | Same as step 5 | Needs cloudbuild.builds.create |
| 5. Terraform apply | Owner or admin SA | Creates all resources |
| 6. Billing admins | You (browser) | Billing account access |
| 7. Slack webhook | You (browser) | Slack workspace access |
You do NOT need to switch identities between steps. If you authenticate as Owner (Option A), that single identity has all the permissions needed for every step. If you use a service account (Option B), it works for steps 3-5 but you'll still need your browser (as yourself) for steps 1, 2, 6, and 7.
Run as: yourself (browser)
- Contact your institution's IT / cloud admin group to provision a new GCP project under your organization's billing account. You'll typically need a project code or cost center to charge against — ask your group lead or grant administrator if you don't have one.
- They will attach the project to your account in GCP.
- Note the project ID (not the display name) — you'll need it for
terraform.tfvars.
Run as: yourself (browser, logged into Cloud Console)
This is UI-only — there is no API or Terraform resource for it.
- Go to console.cloud.google.com
- Select your project
- Search for "model garden"
- For each model you need (Haiku, Sonnet, Opus):
- Search for the model
- Click "Enable"
- If prompted, enable the Vertex AI API
- Fill out the purchase questionnaire:
- Business name: Lawrence Berkeley National Laboratory
- Business website: https://lbl.gov
- Contact email: yourusername@lbl.gov
- Headquartered: United States of America
- Industry: Government
- Intended users: Internal employees and external users
- Use cases: Scientific research
- Additional AUP requirements: No
- Select us-east5 for region
- Note the exact model IDs (e.g.
claude-sonnet-4-5@20250929)
Run as: Owner (Option A) or admin SA (Option B)
Before the first terraform apply, build and push the container:
cd /path/to/budget-enforcer
gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/budget-enforcer .Then set container_image in your terraform.tfvars.
Run as: Same identity as step 3. Do not switch.
cd terraform/
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars with your project details
terraform init
terraform plan # Review what will be created
terraform applyIf you see a 403 error about run.services.setIamPolicy, your service
account is missing roles/resourcemanager.projectIamAdmin. Either add
that role or switch to your personal Owner account (see Prerequisites).
Run as: Same identity as steps 3-4. Do not switch.
After terraform apply creates the service accounts, create a JSON
key for the consumer SA. This is intentionally kept out of Terraform
to avoid storing secrets in Terraform state.
# Get the consumer SA email from Terraform output
CONSUMER_EMAIL=$(cd terraform && terraform output -raw consumer_sa_email)
# Create a JSON key
gcloud iam service-accounts keys create consumer-key.json \
--iam-account="$CONSUMER_EMAIL"This JSON key is what you distribute to developers. Anyone with this key can make Vertex AI API calls (and incur costs). Distribute with care.
This key is gitignored (*.json in .gitignore). Never commit it.
Run as: yourself (browser, Cloud Console)
Budget alert emails (50%/75%/90%/95% thresholds) are sent by GCP to billing admins and project owners. Verify that the right people receive these early-warning emails — they're your first signal before enforcement.
- Go to Cloud Console > Billing > Account Management
- Look at the Permissions panel on the right
- Anyone with
Billing Account AdministratororBilling Account Userwill receive budget alert emails - Project owners also receive them
Or via CLI (requires billing account access):
gcloud billing accounts get-iam-policy BILLING_ACCOUNT_IDIf your team lead or PI should receive budget alerts:
- Go to Cloud Console > Billing > Account Management
- Click Add Principal in the Permissions panel
- Enter their email
- Assign role:
Billing Account User(for alerts only) orBilling Account Administrator(for full billing management)
Note: This controls who gets GCP's built-in email alerts for the sub-100% thresholds (50%, 75%, 90%, 95%). The budget-enforcer's own notifications (Slack) are separate — see step 7 below.
Run as: yourself (browser, Slack)
When the budget-enforcer disables keys, it can post a notification to a Slack channel so your team is immediately aware. This is optional — if not configured, the enforcer still works but only logs to Cloud Run.
Do not use the legacy "Incoming Webhooks" custom integration — it is deprecated by Slack and will be removed. Use a Slack app instead.
- Go to
https://api.slack.com/apps - Click Create New App > From scratch
- Name it (e.g.
Budget Enforcer) and select your workspace - Click Create App
- In the app settings, click Incoming Webhooks in the left sidebar
- Toggle Activate Incoming Webhooks to On
- Click Add New Webhook to Workspace
- Select the channel where alerts should go (e.g.
#infrastructureor#budget-alerts) - Click Allow
- Copy the Webhook URL (looks like:
https://hooks.slack.com/services/T.../B.../xxx)
Add it to your terraform.tfvars:
slack_webhook_url = "https://hooks.slack.com/services/T.../B.../xxx"Then apply (same identity as step 4):
cd terraform/
terraform applyThe webhook URL is sensitive — it's marked
sensitivein Terraform so it won't appear in plan output, andterraform.tfvarsis gitignored. Never commit it.
When keys are disabled, the Slack message includes:
- Which project was affected
- Which service account's keys were disabled
- Why (billing alert or flux estimate with dollar amounts)
- A pointer to the recovery docs