> For the complete documentation index, see [llms.txt](https://docs.upriverdata.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.upriverdata.com/integrations/gcp/bigquery/bigquery-permissions.md).

# BigQuery Permissions

The complete list of IAM roles the Upriver GCP setup grants, where each one is granted, and what it is used for.

## 1. Overview

Upriver reaches BigQuery through a **service account created in your own Google Cloud project**, by the Terraform file you download from the BigQuery or Cloud Composer connector and run yourself. Nothing else is provisioned, and no credential ever leaves your project:

* **There is no service account key.** Upriver's platform service account is granted `roles/iam.serviceAccountTokenCreator` **on the created service account** and impersonates it with short-lived tokens. Upriver never holds, receives, or stores a key — there is no key upload anywhere in the product.
* **Everything Upriver can do is bounded by the roles below.** All of them are read-only predefined Google roles.
* **Revoking is one-sided and instant.** Remove the `serviceAccountTokenCreator` binding, or run `terraform destroy`, and access stops.

This page is the reference for a security review: the roles listed here are **exactly** what the generated Terraform grants, so `terraform plan` should match it line for line. Setup instructions live on the [BigQuery](/integrations/gcp/bigquery.md) and [Cloud Composer](/integrations/gcp/cloud-composer.md) pages.

***

## 2. What the setup grants

### 2.1 On every project you listed under "BigQuery projects"

Every role below is granted at **project** level, on each of those projects — and on no others. Projects you listed only under "Cloud Composer projects" do not receive any of them.

| Role                             | Granted                                                              | Used for                                                                                                                     |
| -------------------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `roles/bigquery.jobUser`         | Always, when BigQuery is included                                    | Create BigQuery jobs — the read-only `SELECT` and `INFORMATION_SCHEMA` queries behind freshness, volume and profiling checks |
| `roles/bigquery.metadataViewer`  | Always, when BigQuery is included                                    | List and read datasets, tables and schemas — discovery and cataloging                                                        |
| `roles/bigquery.resourceViewer`  | Always, when BigQuery is included                                    | Read job history and job metadata                                                                                            |
| `roles/bigquery.readSessionUser` | Always, when BigQuery is included                                    | Open read sessions on the BigQuery Storage Read API, which is how table data is streamed for profiling                       |
| `roles/datacatalog.viewer`       | Always, when BigQuery is included                                    | Read Data Catalog entries and tags for the assets in scope                                                                   |
| `roles/logging.privateLogViewer` | Always, when BigQuery is included                                    | Read Cloud Logging **Data Access audit logs** — the source Upriver derives BigQuery lineage from (see §3)                    |
| `roles/logging.viewAccessor`     | Always, when BigQuery is included                                    | Read log entries through the log views on the project's log buckets — the access path to the logs above                      |
| `roles/bigquery.dataViewer`      | Only if you chose **"Every dataset in the BigQuery projects above"** | Read table data anywhere in the project                                                                                      |

### 2.2 On every project you listed under "Cloud Composer projects"

| Role                  | Granted                              | Used for                                                                   |
| --------------------- | ------------------------------------ | -------------------------------------------------------------------------- |
| `roles/composer.user` | Only when Cloud Composer is included | Call the Cloud Composer API and reach the environment's Airflow web server |

This is the only role those projects receive. None of the BigQuery roles in §2.1 are granted there.

### 2.3 On the datasets and tables you listed

If you chose **"Only the datasets and tables I list below"**, `roles/bigquery.dataViewer` is **not** granted at project level. Instead it is granted on each dataset and each table you listed, and nowhere else. Table data outside that list is not readable.

### 2.4 On the service account the setup creates

| Role                                   | Granted to                         | Used for                                                                                                                       |
| -------------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `roles/iam.serviceAccountTokenCreator` | Upriver's platform service account | Minting short-lived tokens for the created service account — this is how Upriver authenticates instead of using a key (see §3) |

The binding is on the created service account only. It does not let Upriver impersonate anything else in your project.

{% hint style="info" %}
If your organization enforces the **Domain restricted sharing** org policy (`iam.allowedPolicyMemberDomains`), this is the grant it will block, because Upriver's platform service account is external to your domain. Allowing Upriver's Google customer ID in that policy is a prerequisite — see "Before you start" on the [BigQuery](/integrations/gcp/bigquery.md) or [Cloud Composer](/integrations/gcp/cloud-composer.md) page.
{% endhint %}

***

## 3. The two grants a reviewer should look at closely

**`roles/logging.privateLogViewer` — audit logs, including query text.** BigQuery lineage is derived from Cloud Logging Data Access audit logs: they record which job read which table and wrote which table, which is the only complete source for column- and table-level lineage. This role lets Upriver read those entries, and **those entries can contain the text of queries run in your project, including queries run by your own users and services**. It is granted on every monitored project whenever BigQuery is included, and it is the one role on this page that reads something other than your BigQuery metadata and data. If that is not acceptable in your environment, raise it with Upriver before you run the setup.

**`roles/iam.serviceAccountTokenCreator` — impersonation instead of a key.** This is what replaces a downloaded JSON key. Upriver's platform service account calls `generateAccessToken` on the service account your Terraform created and receives a short-lived token; there is no long-lived credential to leak or rotate. Every call Upriver then makes appears in your Cloud Audit Logs under the created service account's identity, with the impersonating principal recorded in the entry's service-account delegation info — so you can attribute Upriver's activity precisely.

***

## 4. What the setup does **not** grant

Stated explicitly, so a review does not have to infer it from absence:

* **No service account keys.** None are created, and the product has no key upload path.
* **No write, delete or admin roles** — anywhere, on any resource. `bigquery.admin` and `bigquery.dataOwner` are not used.
* **No billing, quota or slot roles.** `roles/billing.viewer` and `roles/serviceusage.serviceUsageConsumer` are not granted, and Upriver does not surface cost, slot or quota insights.
* **No Cloud Storage roles.** BigQuery external tables backed by Cloud Storage are therefore not readable through this service account; if you want those profiled, that access has to be granted separately.
* **No project or organization Viewer.** Upriver reads only the projects you listed on the Connect step — there is no project enumeration across your organization.
* **No IAM or org-policy administration.**

***

## 5. Scope: which projects get which roles

One run can cover several projects, and BigQuery and Cloud Composer may live in different ones.

| Project                                          | What it receives                                                                |
| ------------------------------------------------ | ------------------------------------------------------------------------------- |
| **Project for the service account**              | The service account itself, plus the `serviceAccountTokenCreator` binding on it |
| **Each project under "BigQuery projects"**       | The project-level roles in §2.1, and nothing else                               |
| **Each project under "Cloud Composer projects"** | `roles/composer.user` only — none of the BigQuery roles in §2.1                 |
| **Each dataset / table you listed**              | `roles/bigquery.dataViewer` on that dataset or table only (§2.3)                |

There is no requirement for the service account to live in the same project as the data or as Composer — all three may be separate projects. A common pattern is one dedicated project for the service account, one or more data projects, and a separate project for Composer.

***

## 6. Custom roles

The generated Terraform uses **predefined** Google roles only, so the plan is easy to audit and stays correct as Google evolves the roles. The exact permission set behind each role is documented by Google under [BigQuery IAM roles](https://cloud.google.com/bigquery/docs/access-control), [Data Catalog IAM](https://cloud.google.com/data-catalog/docs/concepts/iam), [Cloud Logging access control](https://cloud.google.com/logging/docs/access-control) and [Cloud Composer access control](https://cloud.google.com/composer/docs/composer-2/access-control).

If your policy requires custom roles instead of predefined ones, talk to Upriver before running the setup rather than hand-assembling a permission list — a missing permission usually surfaces later as a partial scan rather than a clean failure.

***

## 7. Verifying what was granted

After `terraform apply`, the grants can be read back straight from GCP:

```bash
# project-level bindings for the created service account
gcloud projects get-iam-policy <monitored-project> \
  --flatten="bindings[].members" \
  --filter="bindings.members:<terraform-email-output>" \
  --format="table(bindings.role)"

# who may impersonate the created service account
gcloud iam service-accounts get-iam-policy <terraform-email-output>

# dataset-level grants, if you scoped access to specific datasets
bq show --format=prettyjson <project>:<dataset> | jq '.access'
```

The first command should return the §2.1 list and nothing else. The second should return exactly one `serviceAccountTokenCreator` member: Upriver's platform service account.

***

## 8. Security notes

* **Dedicated identity.** The setup creates its own service account. Do not point Upriver at a service account that your applications or people already use — it destroys the attribution described in §3.
* **Scope data access deliberately.** Listing datasets and tables is the tighter option and is the recommended default; whole-project `dataViewer` is a convenience, not a requirement.
* **Audit it.** Filter your Cloud Audit Logs on the created service account's email to see everything Upriver has done, including the queries it ran.
* **Revoke on your terms.** `terraform destroy` removes the service account and every role in this page. Removing only the `serviceAccountTokenCreator` binding cuts Upriver off while leaving the account and its grants in place.
* **No key rotation to manage.** There is no key, so there is nothing to rotate or expire.
