Connect GCP with Workload Identity Federation¶
Secruna can discover Vertex AI endpoints, Notebooks, and other AI
resources in your Google Cloud projects without storing any
long-lived secret on our side. The trust is rooted in a Workload
Identity Federation (WIF) binding that you create in your own GCP
project; revoking access is one gcloud command on your end.
This guide walks you through the five-command setup. It takes about 5 minutes.
What you'll do¶
- Open Cloud Shell in your GCP console.
- Run a single script that creates the WIF pool, provider, service account, and IAM bindings.
- Copy two values from the script's output (audience URI + SA email).
- Paste them into the Secruna Connect GCP dialog.
- Verify by running a discovery sweep.
What we never see¶
- Your
gcloudcredentials — the setup runs entirely inside your Cloud Shell. - Any service-account key file. WIF means we never need one.
- Your project data outside the read scopes you grant in step 1.
Step 1 — Run the setup script¶
Replace {tenant-id} with the Secruna tenant id shown in the
Connect GCP dialog (it's a UUID — we display it on screen so you
don't have to ask).
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe "$PROJECT_ID" \
--format="value(projectNumber)")
# 1. Workload Identity pool that trusts the Secruna OIDC issuer.
gcloud iam workload-identity-pools create secruna-discovery \
--location=global \
--display-name="Secruna AI Discovery"
gcloud iam workload-identity-pools providers create-oidc secruna-issuer \
--workload-identity-pool=secruna-discovery \
--location=global \
--issuer-uri="https://api.secruna.com/oidc" \
--attribute-mapping="google.subject=assertion.sub"
# 2. Read-only service account.
gcloud iam service-accounts create secruna-reader \
--display-name="Secruna read-only discovery"
# 3. Allow the Secruna federated identity to impersonate it.
gcloud iam service-accounts add-iam-policy-binding \
"secruna-reader@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/iam.workloadIdentityUser" \
--member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/secruna-discovery/subjects/secruna-discovery-{tenant-id}"
# 4. Grant the SA the read roles discovery needs. Read-only.
for role in roles/aiplatform.viewer roles/notebooks.viewer roles/browser; do
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
--member="serviceAccount:secruna-reader@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="$role"
done
# 5. Print the two values you'll paste into Secruna.
echo
echo "===== Paste these into Secruna's Connect GCP dialog ====="
echo
echo "Audience URI:"
echo "//iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/secruna-discovery/providers/secruna-issuer"
echo
echo "Service account email:"
echo "secruna-reader@${PROJECT_ID}.iam.gserviceaccount.com"
The script is idempotent — if you've already created the pool /
provider / SA, the gcloud ... create calls fail with ALREADY_EXISTS
(safe to ignore) and the policy bindings re-apply cleanly.
Step 2 — Paste the values¶
Back in the Secruna dashboard, in the Connect GCP dialog:
- Paste the Audience URI into the first field.
- Paste the Service account email into the second field.
- List the GCP project IDs you want Secruna to scan (one per line).
- Click Connect.
You'll land back on the Connections page with the new GCP row showing Workload Identity Federation as the auth method.
Step 3 — Verify¶
Click Run discovery on the new connection. Within ~30 seconds the run should land at Completed with a non-zero artifact count.
On your side, you can verify Secruna is using the WIF binding by checking Cloud Audit Logs:
gcloud logging read \
'protoPayload.serviceName="iamcredentials.googleapis.com"
AND protoPayload.methodName="GenerateAccessToken"
AND protoPayload.resourceName=~"secruna-reader@.*"' \
--limit=5 \
--format="table(timestamp,protoPayload.authenticationInfo.principalSubject)"
The principalSubject will read
principal://iam.googleapis.com/.../subjects/secruna-discovery-{your-tenant-id}.
Revoking access¶
To revoke Secruna's access at any time:
That single command tears down the federated binding. The next
discovery sweep will fail with a 401; Secruna marks the connection
auth_expired and you'll see a banner in the dashboard with a link
back to this guide.
Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
| Audience URI is rejected by the form | Wrong shape — should start //iam.googleapis.com/projects/... |
Re-copy the URI from the script's output (NOT the URL form). |
| Discovery returns "401: invalid_target" | --issuer-uri doesn't match https://api.secruna.com/oidc |
Re-run step 1's providers create-oidc with the exact URL. |
| Discovery returns "403: Permission denied" | The iam.workloadIdentityUser binding is missing |
Re-run step 3 of the script with the correct {tenant-id}. |
| Discovery returns 0 artifacts but no error | SA missing the aiplatform.viewer / notebooks.viewer roles |
Re-run step 4 of the script. |
Setup script reports ALREADY_EXISTS |
Pool / provider / SA already created | Safe to ignore — the policy bindings still update. |
If discovery still doesn't work after re-running the script, contact Secruna support with your project ID + tenant ID and we'll diff the expected vs. actual config against the operator runbook.
FAQ¶
Q: Does Secruna get a long-lived credential? No. Each discovery sweep mints a fresh 1-hour SA token through your WIF binding; nothing is persisted on our side beyond the audience URI and SA email (both public).
Q: What if I want to scan multiple projects?
Add them to the Project IDs field on the dialog. The SA needs the
read-only roles in each project — extend step 4 of the script to loop
over each PROJECT_ID.
Q: Can I rotate the SA without re-onboarding? Yes — as long as the SA email stays the same. If you create a new SA with a different name, paste the new email into the connection's Edit dialog.
Q: Will Secruna ever need write access?
No. The read-only roles (aiplatform.viewer, notebooks.viewer,
browser) cover every discovery and verdict-rendering path.