> For the complete documentation index, see [llms.txt](https://docs.firefly.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.firefly.ai/detailed-guides/oidc-provider/google-cloud.md).

# Google Cloud

Firefly runners can authenticate to Google Cloud using Workload Identity Federation (WIF) instead of a stored service account key. At execution time, Firefly issues a short-lived OIDC token, Google Cloud exchanges it for temporary credentials, and the runner impersonates a service account in your project. No static Google Cloud key is ever stored by Firefly.

Setting this up takes two parts:

* **Part 1** — in your Google Cloud project: create a workload identity pool, add Firefly as an OIDC provider, and grant access to a service account.
* **Part 2** — in Firefly: enable OIDC on the project or workspace and paste in two values from Part 1.

Then check your Terraform code against [Required Terraform configuration](#required-terraform-configuration) below — there's little to add, but one setting will silently bypass federation if it's present.

Plan for about 15 minutes, plus whatever time it takes to get the permissions listed below if you don't already have them.

***

## Before you start

### Enable the required APIs

On a new Google Cloud project, some of these may be off. Enable all four:

| API                                   | Why it's needed                                     |
| ------------------------------------- | --------------------------------------------------- |
| `iam.googleapis.com`                  | Workload identity pools and providers               |
| `sts.googleapis.com`                  | Exchanging the Firefly token for Google credentials |
| `iamcredentials.googleapis.com`       | Service account impersonation                       |
| `cloudresourcemanager.googleapis.com` | Project-level IAM changes                           |

`iamcredentials.googleapis.com` is the one most often missed. Without it, everything appears configured correctly and impersonation fails at run time.

### Check your permissions

You'll need the following roles. If you don't have all of them, note that the project-level grant in Step 5 typically requires a different administrator than the rest of the flow:

| Steps | Role required                                                                                                           |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| 1–3   | Workload Identity Pool Admin (`roles/iam.workloadIdentityPoolAdmin`)                                                    |
| 4     | Service Account Admin (`roles/iam.serviceAccountAdmin`), or the ability to edit the target service account's IAM policy |
| 5     | Project IAM Admin (`roles/resourcemanager.projectIamAdmin`)                                                             |

### Check for organization policy restrictions

If your organization enforces `constraints/iam.workloadIdentityPoolProviders`, only allow-listed issuer URIs can be registered. Provider creation in Step 2 will be rejected regardless of your project permissions. If that happens, ask your platform or security team to add the Firefly issuer URL for your environment to the allow-list.

### Collect the values Firefly shows you

Two of the values you'll enter in Google Cloud come from Firefly and are specific to your account.

1. In Firefly, open the workspace you want to configure (**Workspaces → + Workspace**, or open an existing workspace and choose **Edit workspace**).
2. Go to **Workspace Configuration → Runner Configuration**.
3. Check **Enable OIDC authentication**, then select **Google Cloud** under **Cloud provider**.
4. Copy the **attribute condition** and the **principal attribute value** from the panel. Both are shown ready to paste — you don't need to substitute anything into them.

Leave this tab open. You'll come back to it in Part 2.

> **Configuring at the project level instead?** The same panel appears in the project creation and project settings screens, and the two values are identical — they're derived from your Firefly account, not from the workspace. Collect them from wherever you plan to configure OIDC.

***

## Part 1 — Google Cloud setup

Navigate to **IAM & Admin → Workload Identity Federation**. If you have no pools yet, choose **Create pool**; otherwise choose **Add provider** on an existing pool.

### Step 1 — Create an identity pool

* **Name** — for example, `firefly pool`.
* **Description** — optional.
* Leave **Enabled pool** checked.

Then click **Continue**.

> **The pool ID is permanent.** It's derived automatically from the name you enter (`firefly pool` becomes `firefly-pool`) and cannot be changed afterwards. Deleted pool IDs are soft-deleted for 30 days and cannot be reused during that window, so a typo means either living with it or picking a different name. Check the derived ID before saving.

### Step 2 — Add an OIDC provider to the pool

* **Select a provider** — choose **OpenID Connect (OIDC)**. Not AWS, not SAML.
* **Provider name** — for example, `firefly-runner`.
* **Issuer (URL)** — use the value matching your Firefly environment:

| Firefly environment | Issuer URL                     |
| ------------------- | ------------------------------ |
| Production          | `https://api.gofirefly.io/v2`  |
| Production (EU)     | `https://api.eu.firefly.ai/v2` |

> **Include the `/v2` suffix.** This is the exact `iss` claim Firefly puts in the token, not just the domain. Entering the bare domain causes an issuer mismatch that only surfaces when a run fails.

* **JWK file (JSON)** — leave this blank. Firefly's issuer is publicly reachable, so Google Cloud fetches `/.well-known/openid-configuration` and `/.well-known/jwks.json` automatically. A JWK file is only needed for issuers that aren't publicly accessible.
* **Audiences** — select **Allowed audiences**, not **Default audience**, and add exactly one entry:

  ```
  https://runners.firefly.ai
  ```

  This audience is fixed. It's the same for every Firefly environment and region, so unlike the issuer URL it never changes and you only ever configure it once.

Then click **Continue**.

### Step 3 — Configure provider attributes

* **Attribute mapping** — map `google.subject` to `assertion.sub`.
* **Attribute condition (CEL)** — paste the attribute condition you copied from the Firefly panel. It takes this form:

  ```
  assertion.sub == "account:<FIREFLY_ACCOUNT_ID>"
  ```

Click **Save**. You'll land on the pool's details page, which has **Providers** and **Connected service accounts** tabs.

### Step 4 — Allow the Firefly identity to impersonate a service account

Create or choose the service account your runs will act as, for example `firefly-runner@example-project.iam.gserviceaccount.com`.

From the pool's details page, go to **Connected service accounts → Grant Access**. Google Cloud offers two options here:

* **Grant access using service account impersonation** — choose this one.
* **Grant access using federated identities** — do *not* choose this. It issues an Application Default Credentials file intended for direct client-library use. Firefly's runner writes an `external_account` credential config containing a `service_account_impersonation_url`, which requires the impersonation grant instead.

Then:

* **Select service account** — the service account above.
* **Select principals** — set **Attribute name** to `subject`. This is the `google.subject` attribute you mapped in Step 3; the dropdown only offers attributes present in the provider's mapping. For **Attribute value**, paste the **principal attribute value** from the Firefly panel, which takes the form `account:<FIREFLY_ACCOUNT_ID>`.

Click **Save**.

This produces the same IAM binding as running:

```bash
gcloud iam service-accounts add-iam-policy-binding <SA_EMAIL> \
  --role=roles/iam.workloadIdentityUser \
  --member="principal://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<POOL_ID>/subject/account:<FIREFLY_ACCOUNT_ID>"
```

You can also make the grant from the service account's own **Permissions** tab, using the same `principal://` string as the principal and **Workload Identity User** as the role. All three routes are equivalent — use whichever is most convenient.

#### Why the account ID appears twice

Steps 3 and 4 both reference `account:<FIREFLY_ACCOUNT_ID>`, and it can look like duplication. They're two independent gates, and both are required:

* The **attribute condition** in Step 3 controls *which Firefly accounts the pool will accept a token from at all*. It's enforced at the pool provider.
* The **principal binding** in Step 4 controls *which subject is allowed to impersonate this particular service account*. It's enforced on the service account.

Removing either one either opens the pool to any Firefly account or breaks impersonation. Keep both.

### Step 5 — Grant the service account a role on your project

> **This step is required and is the most common way to misconfigure the integration.** Step 4 and Step 5 modify IAM policies on two different resources, and no wizard prompts you for Step 5. Skip it and Workload Identity Federation will work perfectly while every run still fails with an error like `the user does not have permission to access Project '<PROJECT_ID>' or it may not exist`.
>
> The distinction: **Step 4 determines who may impersonate the service account. Step 5 determines what the service account is actually allowed to do.**

1. Go to **IAM & Admin → IAM** at the project level. This is not the service account's own permissions page.
2. Click **Grant Access**.
3. **Principal** — the service account's email address.
4. **Role** — whatever your infrastructure code actually needs. Start with **Viewer** to confirm access works end to end, then broaden to specific service roles, or to **Editor**, as required.

Firefly doesn't manage or prescribe this role. Scoping it is your IAM decision, based on what your configuration touches.

### Values to carry into Firefly

Two values from Part 1 go into Firefly:

* **Workload identity provider** — the full resource path, shown on the pool's **Providers** tab:

  ```
  //iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<POOL_ID>/providers/<PROVIDER_ID>
  ```

  The `iam.googleapis.com/` host is part of the value and must be included — a bare `projects/...` path is rejected. Only the leading `//` is optional; Firefly adds it if omitted. Note that this path uses the project *number*, not the project ID.
* **Service account email** — the service account from Step 4.

***

## Part 2 — Firefly configuration

You can enable OIDC at either the project level or the workspace level. Both take the same two values from Part 1.

### Option 1: Configure OIDC in Projects

> **Note:** OIDC Authentication configured at the project level is an inherited attribute. This means all sub-projects and workspaces within the project will automatically be configured with this authentication method.

Whether you're creating a new project or editing an existing one:

1. Navigate to the project creation screen, or to your project settings.
2. Enable **OIDC Authentication**, and select **Google Cloud** under **Cloud provider**.
3. Enter the **Workload identity provider** resource path.
4. Enter the **Service account to impersonate**.
5. Save the project.

### Option 2: Configure OIDC in Workspaces

Back in the workspace panel you left open in *Before you start*:

1. Confirm **Enable OIDC authentication** is checked and **Cloud provider** is set to **Google Cloud**.
2. Enter the **Workload identity provider** resource path.
3. Enter the **Service account to impersonate**.
4. Save the workspace.

Runs now federate to Google Cloud through Workload Identity Federation. This applies to Terraform, OpenTofu, and Terragrunt runs alike.

***

## Required Terraform configuration

Firefly writes an `external_account` credential file on the runner and points Application Default Credentials at it. The `google` provider resolves credentials through ADC, which understands that file natively, so you do **not** need a `credentials` attribute in your provider block. Federation happens without it.

You do still need to tell the provider which project to operate on. Firefly doesn't set this — it's yours to declare, either in the provider block or through the `GOOGLE_PROJECT` environment variable:

```hcl
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = ">= 4.0"
    }
  }
}

provider "google" {
  project = "example-project"
  region  = "us-central1"
}
```

The absence of a `credentials` attribute above is deliberate, not an omission.

### Don't override the credentials

> **This is the one way to configure the provider incorrectly, and it fails quietly.** Setting `credentials` in the provider block to your own service account key, or setting `GOOGLE_CREDENTIALS` as a workspace variable, overrides Application Default Credentials and bypasses OIDC entirely. The run will still succeed, using whichever credentials you supplied, so there's no error to alert you. Federation simply isn't being used.
>
> If you're migrating a workspace from a static service account key, removing those values is part of the migration.

### Provider version

Workload Identity Federation support was added in `hashicorp/google` 3.61.0, so that's the minimum. Version 4.0 or later is recommended.

***

## Working across multiple Google Cloud projects

The pool, provider, and impersonation grant from Steps 1–4 live in one project, but the service account can be granted roles in others. If your configuration provisions resources across several projects, Step 5 must be repeated in each of them — grant the same service account an appropriate role on every project it touches, or grant it once at the folder or organization level if the scope justifies that.

Steps 1–4 do not need to be repeated. One pool and provider can serve any number of projects.

***

## Troubleshooting

| Symptom                                                                                  | Likely cause                                                                                                                                                                          |
| ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `the user does not have permission to access Project '<PROJECT_ID>' or it may not exist` | Step 5 was skipped. The service account can be impersonated but has no role on the project.                                                                                           |
| Provider creation is rejected outright                                                   | An organization policy restricts allowed issuer URIs. Ask your platform team to allow-list the Firefly issuer.                                                                        |
| Token exchange fails with an audience error                                              | The audience was entered under **Default audience** instead of **Allowed audiences**, or doesn't exactly match `https://runners.firefly.ai`.                                          |
| Issuer or `iss` claim mismatch                                                           | The `/v2` suffix is missing from the issuer URL, or the URL is for a different Firefly environment.                                                                                   |
| Impersonation fails despite a valid token                                                | `iamcredentials.googleapis.com` isn't enabled, or **Grant access using federated identities** was chosen in Step 4 instead of service account impersonation.                          |
| Provider path is rejected as invalid                                                     | The path contains the project ID instead of the project number, or the `iam.googleapis.com/` host is missing from the front of the value.                                             |
| Runs succeed, but federation clearly isn't being used                                    | `credentials` is set in the provider block to a service account key, or `GOOGLE_CREDENTIALS` is set as a workspace variable. Either overrides ADC and bypasses OIDC without erroring. |
| `google` provider can't use the credential file                                          | The provider version predates 3.61.0, which is where Workload Identity Federation support was added.                                                                                  |
| Terraform errors that no project was specified                                           | `project` isn't set in the provider block and `GOOGLE_PROJECT` isn't defined. Firefly doesn't set this for you.                                                                       |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.firefly.ai/detailed-guides/oidc-provider/google-cloud.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
