Connect with a GCP account

Create a dedicated project and a read-only service account for Valkan, grant it access across your projects, then connect and scan. The same steps are given three ways — Cloud Console, Cloud Shell or bash, and PowerShell.

Before choosing Connect Google Cloud in Valkan, create a dedicated project with a service account, grant it read-only access, enable a few APIs, and generate a JSON key. Valkan only reads your Google Cloud resources; it never creates or modifies them.

A single connection covers every project the service account can access. To stop scanning one, untick it under Projects on the integration's page.

You need permission to:

  • create a project, and a service account in it (Service Account Admin, or Owner)
  • create a service account key (Service Account Key Admin, or Owner)
  • in each project you want scanned, define a custom role and grant it: Owner, or both Role Administrator (roles/iam.roleAdmin) and Project IAM Admin (roles/resourcemanager.projectIamAdmin)

Editor is not enough for the last one: it carries neither iam.roles.create nor resourcemanager.projects.setIamPolicy, so both commands in step 2 fail on a project where Editor is all you hold. That is easy to miss, because such a project still appears in the survey below.

Valkan only reads. Every call it makes to Google Cloud is a list or a get: it never creates, changes or deletes anything in your projects. It lists secret and bucket names, never secret values or bucket contents. The role below is read-only, so Google would refuse a write even if one were attempted. The commands in these steps are ones you run yourself; Valkan never runs them.

First, check what your account has

gcloud projects list --format="table(projectId,name,parent.type,parent.id)"

These are your existing projects, the ones holding the resources Valkan reports on. They are not candidates for holding the service account, which is always a new project created in step 1.

Decide now which of them Valkan should cover. Every route below configures only the projects you name, and two of the steps cost money in each one — enabling APIs and turning on DNS query logging are billable. Write the list down before you start: on an organization-wide login this survey can run to hundreds of projects, and there is no reason to touch the ones you are not onboarding.

A project you add later needs step 2 run again for it. Access is granted per project, so a new project is not picked up on its own. Valkan reports a project it can see referenced but not read — specifically, one named as the host of a Shared VPC network a covered project uses — as a coverage gap rather than leaving it absent. That is a floor, not a census: it catches only a project your covered infrastructure points at, so re-run step 2 whenever you add one instead of waiting to be told.

A project awaiting deletion does not appear in this list. In the console the same overview is IAM & Admin → Manage resources (console.cloud.google.com/cloud-resource-manager).

Showing the organization and folder names above your projects needs Organization Viewer and Folder Viewer, granted at the organization. They are optional: without them, projects are still scanned.

Choose one of the setup methods below. All perform the same steps, and the two terminal options differ only in shell syntax.

1. Create the project and service account

Create the project at console.cloud.google.com/projectcreate and name it valkan-discovery. Project IDs are globally unique, so the console may append digits; note the ID it settles on, because step 4 needs it. It needs no billing account.

Now open IAM & Admin → Service Accounts (console.cloud.google.com/iam-admin/serviceaccounts) with the new project selected in the top-left switcher. Click Create service account, name it valkan, and click Create and continue. When it offers to grant roles, click Done: the role comes from step 2, and it is granted in your other projects.

Copy the account's email address from the list. It looks like valkan@<project-id>.iam.gserviceaccount.com, and both later steps need it.

2. Create the read-only role and grant it

Valkan uses its own role definition rather than a broad predefined role. It contains 47 read permissions, every one of them a list or a get, and nothing that can create, change or delete. The nearest predefined role that would also work, Security Reviewer, carries more than two thousand.

{
  "title": "ValkanDiscovery Read-Only (single project)",
  "description": "Read-only Valkan Discovery for one project: identity inventory, IAM grants and deny policies, AI and compute workloads, Model Armor, data services, and audit metadata. No mutate permissions.",
  "stage": "GA",
  "includedPermissions": [
    "resourcemanager.projects.get",
    "resourcemanager.projects.getIamPolicy",
    "iam.serviceAccounts.list",
    "iam.serviceAccounts.getIamPolicy",
    "iam.serviceAccountKeys.list",
    "iam.denypolicies.list",
    "iam.denypolicies.get",
    "iam.roles.list",
    "iam.workloadIdentityPools.list",
    "iam.workloadIdentityPoolProviders.list",
    "run.services.list",
    "cloudfunctions.functions.list",
    "aiplatform.reasoningEngines.list",
    "aiplatform.endpoints.list",
    "discoveryengine.engines.list",
    "discoveryengine.dataStores.list",
    "dialogflow.agents.list",
    "dialogflow.agents.get",
    "dialogflow.webhooks.list",
    "dialogflow.fulfillments.get",
    "logging.logEntries.list",
    "logging.privateLogEntries.list",
    "monitoring.timeSeries.list",
    "compute.networks.list",
    "compute.instances.list",
    "compute.firewalls.list",
    "compute.subnetworks.list",
    "dns.policies.list",
    "secretmanager.secrets.list",
    "cloudsql.instances.list",
    "cloudsql.users.list",
    "cloudkms.locations.list",
    "cloudkms.keyRings.list",
    "cloudkms.cryptoKeys.list",
    "cloudkms.cryptoKeys.getIamPolicy",
    "modelarmor.floorSettings.get",
    "modelarmor.templates.list",
    "storage.buckets.list",
    "bigquery.datasets.get",
    "pubsub.topics.list",
    "pubsub.topics.getIamPolicy",
    "container.clusters.list",
    "container.clusters.get",
    "container.deployments.list",
    "container.statefulSets.list",
    "container.daemonSets.list",
    "container.cronJobs.list"
  ]
}

A custom role can only be granted inside the project that defines it, so create the role and grant it once in each project.

Choose the projects first

Work from the list you decided on in the survey above, not from everything the account can see. Steps 4 and 5 are billable in each project you configure, and on an organization-wide login the survey may list far more projects than you intend to onboard. Keep the list beside you: steps 2, 4, 5 and 6 each apply to it.

With the first of those projects selected in the top-left switcher, open IAM & Admin → Roles (console.cloud.google.com/iam-admin/roles) and click Create role:

  • Title — Valkan Discovery Read Only
  • ID — valkanDiscoveryReadOnly
  • Role launch stage — General Availability

Click Add permissions. That dialog filters a long list, so paste one permission name at a time into its filter box, tick the result, and repeat for all

  1. A permission whose API is not enabled yet (step 4) shows a "not supported" warning — add it anyway. The role keeps it, and it starts working when the API is on. Then click Create.

If valkanDiscoveryReadOnly already exists in this project from an earlier setup, edit it instead of creating a second role, and check all 47 permissions are present. A role made from an older version of this page keeps that version's permissions, and the ones added since never arrive — the scan then reports permission gaps and lists no virtual machines.

Still in that project, open IAM & Admin → IAM (console.cloud.google.com/iam-admin/iam), click Grant access, put the service account's email address in New principals, choose Valkan Discovery Read Only from the Custom group, and click Save.

Repeat both halves for each remaining project on your list, and no others. The two terminal methods loop over an explicit list instead, which is worth switching to if you have more than a handful.

You still add a single source in Valkan, however many projects it covers: the service account reports back every project it can read.

To undo this later, remove the service account's binding and delete the role in each project. Deleting the project that holds the service account does not remove grants made elsewhere.

3. Create a key

Open the service account, go to its Keys tab, then Add key → Create new key → JSON → Create. A file downloads. You paste its contents into Valkan in step 7, and it is the only copy Google gives you.

4. Enable the required APIs

Open APIs & Services → Library (console.cloud.google.com/apis/library), search each API by name, and click Enable.

Required — connecting fails without it:

  • Cloud Resource Manager API (cloudresourcemanager.googleapis.com). Valkan uses it to find out which projects the service account can read. Without it, Connect returns a permission error and no source is created.

Needed by the areas they cover. Leaving one off does not stop a scan; that area is reported as a coverage gap instead, so you can add them later:

  • Identity and Access Management API (iam.googleapis.com) — service accounts, their keys and their IAM policies. This is the core of what Valkan inventories on Google Cloud, so leaving it off produces a scan that finds almost nothing.
  • Compute Engine API (compute.googleapis.com) — virtual machines, their firewall exposure, and the check for networks without DNS logging
  • Cloud Logging API (logging.googleapis.com) — audit and activity evidence
  • Cloud DNS API (dns.googleapis.com) — DNS query evidence
  • Cloud Storage API (storage.googleapis.com) — storage buckets
  • Secret Manager API (secretmanager.googleapis.com) — secrets
  • Cloud Run Admin API (run.googleapis.com) — Cloud Run services
  • Cloud Functions API (cloudfunctions.googleapis.com) — Cloud Functions
  • Vertex AI API (aiplatform.googleapis.com) — Vertex endpoints and reasoning engines
  • Kubernetes Engine API (container.googleapis.com) — GKE clusters
  • Cloud SQL Admin API (sqladmin.googleapis.com) — Cloud SQL instances and their IAM database users
  • Cloud Key Management Service (KMS) API (cloudkms.googleapis.com) — KMS keys and who can use them
  • Model Armor API (modelarmor.googleapis.com) — whether a Model Armor floor setting covers Vertex AI agents
  • Cloud Monitoring API (monitoring.googleapis.com) — Vertex AI model usage counts
  • Discovery Engine API (discoveryengine.googleapis.com) — Vertex AI Agent Builder apps and their data stores
  • Dialogflow API (dialogflow.googleapis.com) — Dialogflow agents and their webhooks
  • BigQuery API (bigquery.googleapis.com) — datasets and who can read them
  • Cloud Pub/Sub API (pubsub.googleapis.com) — topics and who can publish to them

Enable these in each project on your list, switching project in the top-left switcher as you go. Granting access to a project does not enable its APIs. Enabling an API is a billable change to that project, so do not sweep projects you are not onboarding.

The project holding the service account needs only the Cloud Resource Manager API, because that is the one call Valkan makes without naming a project. Everything else is read from the project that owns the resource.

If that is more than a handful of projects, the two terminal methods loop over your list in one command.

5. Enable DNS query logging

Google Cloud leaves this off, and Valkan needs it for two things: the DNS tab, and attributing AI use to the machine making it. A VM resolving api.openai.com is how an agent nobody registered gets discovered, and without query logging there is nothing to read. Valkan reports a network with logging switched off as a finding, so skipping this step does not go unnoticed — it just leaves the gap open.

The policy costs nothing. The logs it produces are ingested by Cloud Logging, which is free up to a monthly allowance per project and charged by volume above it, so a large or chatty fleet can reach a bill. Step 6 is there for that case.

Logging attaches to a VPC network, not to a project, and a project can have several. You need Compute Network Admin or Owner on each project, which the person doing the rest of this setup may not have.

In the console this is Network Services → Cloud DNS → DNS server policies → Create policy, with Logs set to On and the network added under Networks. Repeat it for every network in each project on your list — the two terminal methods loop over that list, which is worth switching to here. This is the other billable step, so again, do not include projects you are not onboarding.

A network that already has a policy attached is reported and skipped rather than overwritten, because that policy may be someone else's. Turn logging on for it by editing the existing policy instead. Under a Shared VPC the network lives in the host project, so logging is set there and covers the service projects using it.

6. (Optional) Shorten DNS log retention to reduce storage cost

Skip this unless log volume is high enough for storage cost to matter, because logging already works at the default 30-day retention. This step is riskier than it appears: _Default is not DNS-only, so shortening its retention shortens retention for every log type routed there — data-access logs, application logs, anything else that project sends to it.

This is the one step with no loop at all. Reading is safe, so the check below reports your whole list at once; the change is deliberate and applies to one project, because a loop would quietly shorten retention estate-wide for logs other people rely on, and log data already aged out does not come back.

Per project, Logging → Logs storage shows _Default's retention, and Network Services → Cloud DNS → DNS server policies shows what is logging into it. The two terminal methods report every project in one pass.

Pick a project from that output only if it shows retention=30, the default, and logging-policies=0, meaning nothing has been logging to _Default yet. Anything else means the bucket is already carrying logs something depends on, and shortening it would cut their retention too.

In the console, open Logging → Logs storage, click _Default, choose Edit bucket and set the retention to 1 day.

(Optional) Record who calls Vertex AI models

Valkan counts Vertex AI model use per model from Cloud Monitoring with no extra setup. To see which service account or person made the calls, Google has to record them, and for Vertex AI it does not by default: those records are Data Access audit logs, which are off unless you turn them on. Until they are, Valkan shows the counts and says caller attribution is unavailable for that project, rather than showing no callers.

In each project you want attributed, open IAM & Admin → Audit Logs, find Vertex AI API, tick Data Read, and click Save. Data Access logs are billed as log storage, so turn them on where knowing the caller is worth it. The role you granted in step 2 already includes logging.privateLogEntries.list, which is what reading them requires.

The same switch on the Dialogflow API and Discovery Engine API lets Valkan see when each Dialogflow agent and Agent Builder app was last used. Without it, an agent is marked dormant only by its age, and Valkan says so.

(Optional) Sweep a whole organization with Cloud Asset Inventory

If you granted the role at the organization (or a folder), Valkan can also ask Cloud Asset Inventory for every project under it. Two things follow: every project the service account cannot read is reported by name — not only the ones it happens to find referenced — and roles granted on a folder count toward what each service account can reach in the projects beneath it.

It is off by default. To use it, enable the Cloud Asset API (cloudasset.googleapis.com) in the project that holds the service account, then ask your Valkan administrator to set the integration's asset inventory scope to organizations/<ORG_ID> or folders/<FOLDER_ID>. The organization role in step 2 already carries the two read-only search permissions this needs; the single-project role does not, because the search is only useful above a project.

(Optional) Read the workloads inside GKE clusters

Valkan lists your GKE clusters by default. To also see the Deployments, StatefulSets, DaemonSets and CronJobs running in them — and which Google service account each one runs as through Workload Identity — ask your Valkan administrator to turn on GKE workload reading for the integration. The role from step 2 already carries the four read-only container.*.list permissions this uses; GKE maps them to Kubernetes read access, so nothing is created inside the cluster.

Valkan reaches each cluster's public control-plane endpoint. A cluster with only a private endpoint is reported as not readable rather than left out silently. Environment variables are recorded by name only, and Kubernetes Secrets are never read.

7. Connect and scan in Valkan

Choose Integrations → Sources → Connect → Google Cloud, paste the contents of the JSON key and pick a region.

Test the connection

Before connecting, click Test connection. It tells you now what a first scan would otherwise report later:

  • Missing permissions: read-only permissions the service account lacks, per project when they differ.
  • Disabled APIs: APIs that are switched off. Enable them in the project.
  • Projects it couldn't check: each with the reason Google gave.
  • Could not confirm: APIs whose check got no answer. Test again.
  • Optional features that are off: organization-level and opt-in access, such as Cloud Asset Inventory and GKE workloads. These are not needed to connect.

It checks up to 5 projects, and your key is used for this request only: Valkan does not store it until you click Connect. The test is advice. Connect works whatever it says, and anything missing is reported by the first scan as a coverage gap.

Click Connect. The first scan starts automatically, and it reports what it could not reach rather than leaving it out.