> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formal.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# GCP

> Connect a Google Cloud project for autodiscovery and Cloud Storage log delivery

The GCP Cloud Account connects a Google Cloud project to Formal using [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation). Formal presents its AWS identity, which your project trusts through a workload identity pool, then impersonates a dedicated service account. No service account keys are created; access is entirely federated.

## What Formal Discovers

<AccordionGroup>
  <Accordion title="Cloud SQL Autodiscovery" icon="database">
    Discover Cloud SQL for PostgreSQL and MySQL instances and add them as Formal
    resources.
  </Accordion>

  <Accordion title="GKE Autodiscovery" icon="dharmachakra">
    Discover GKE clusters for Kubernetes access control. Clusters need a public
    endpoint to be discovered.
  </Accordion>

  <Accordion title="Compute Engine Autodiscovery" icon="server">
    Discover Compute Engine instances for SSH access.
  </Accordion>

  <Accordion title="Cloud Storage Log Delivery" icon="bucket">
    Forward Formal Connector logs to GCS buckets for long-term storage and
    compliance.
  </Accordion>
</AccordionGroup>

Autodiscovery for all three resource types is on by default. See [Resource Autodiscovery](/docs/guides/integrations/clouds/introduction#resource-autodiscovery) for how discovered resources behave.

## Architecture

The [`terraform-formal-gcp`](https://github.com/formalco/terraform-formal-gcp) module enables the required APIs (IAM, STS, IAM Credentials, Cloud Resource Manager) and creates:

1. **Workload Identity Pool**: a pool with an AWS-type provider that trusts Formal's AWS account
2. **Attribute Condition**: pins Formal's per-integration role ARN, so only that exact role can exchange a token
3. **Service Account**: the identity Formal impersonates in your project
4. **IAM Bindings**: grant the service account only the roles for the capabilities you enable, such as `compute.viewer`, `container.viewer`, and `cloudsql.viewer` for discovery, and `storage.objectCreator` for log delivery

Formal derives the exact roles from the capabilities you enable and returns them for the module to grant.

## Setup

<Tabs>
  <Tab title="Web Console">
    <Steps>
      <Step title="Navigate to Cloud Accounts">
        Go to [Cloud Accounts](https://app.formal.ai/cloud-accounts)
      </Step>

      <Step title="Add Integration">
        Click **Add Integration** and choose **GCP**
      </Step>

      <Step title="Enter Details">
        Enter a name and the Google Cloud **project ID** to connect
      </Step>

      <Step title="Choose Discovery">
        Toggle autodiscovery for **Compute Engine**, **GKE**, and **Cloud SQL**. All are on by default.
      </Step>

      <Step title="Configure GCS Access">
        To deliver logs to Cloud Storage, enable **GCS log writes**. Leave the bucket list empty to allow every bucket in the project, or name specific buckets to scope access.
      </Step>

      <Step title="Run the Setup Command">
        Formal shows a command with your integration ID and security key filled in. Paste it into an authenticated [Cloud Shell](https://cloud.google.com/shell) for that project:

        ```bash theme={null}
        bash <(curl -sSL https://formal.ai/gcp.sh) <INTEGRATION_ID> <SECURITY_KEY>
        ```

        It fetches the setup parameters from Formal, runs `terraform apply`, then reports the service account and workload identity pool provider back to Formal, which activates the integration.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Terraform">
    Register the integration, provision the GCP resources with the [`terraform-formal-gcp`](https://github.com/formalco/terraform-formal-gcp) module, then report them back to activate it.

    ```hcl theme={null}
    # 1. Register the GCP Cloud Account. Autodiscovery is on by default. allow_gcs_access
    #    with an empty gcs_buckets list grants log delivery to any bucket in the project;
    #    set gcs_buckets to scope it.
    resource "formal_integration_cloud" "gcp" {
      name = "production-gcp"

      gcp {
        project_id                              = "my-gcp-project"
        enable_compute_instances_autodiscovery  = true
        enable_gke_clusters_autodiscovery       = true
        enable_cloudsql_instances_autodiscovery = true
        allow_gcs_access                        = true
      }
    }

    # 2. Provision the GCP-side resources with the Formal-maintained module, driven by the
    #    roles and buckets Formal derives from the capabilities enabled above.
    module "formal_gcp" {
      source = "github.com/formalco/terraform-formal-gcp"

      integration_id  = formal_integration_cloud.gcp.id
      formal_role_arn = formal_integration_cloud.gcp.aws_formal_role_arn
      project_id      = "my-gcp-project"
      roles           = formal_integration_cloud.gcp.gcp_roles
      gcs_buckets     = formal_integration_cloud.gcp.gcp_gcs_buckets
    }

    # 3. Report the created resources back to Formal to activate the integration.
    resource "formal_integration_cloud_gcp_activation" "gcp" {
      integration_id                  = formal_integration_cloud.gcp.id
      service_account_email           = module.formal_gcp.service_account_email
      workload_identity_pool_provider = module.formal_gcp.workload_identity_pool_provider
    }
    ```

    <Note>
      The activation resource is separate from `formal_integration_cloud` on purpose. That resource feeds the module its ID and role ARN, so reading the module outputs back into it would create a dependency cycle.
    </Note>

    Each discovery flag defaults to `true`; set any to `false` to skip that resource type.
  </Tab>
</Tabs>

## Cloud Storage Log Delivery

To forward logs to GCS, the integration needs Cloud Storage access. Enable it when creating the integration with two settings:

| Setting            | Description                                                                    |
| ------------------ | ------------------------------------------------------------------------------ |
| `allow_gcs_access` | Grants Formal's service account permission to write log objects.               |
| `gcs_buckets`      | Buckets Formal may write to. Leave empty to allow every bucket in the project. |

Formal grants matching IAM: a project-level `roles/storage.objectCreator` when the bucket list is empty, or per-bucket IAM bindings when you restrict it.

Once access is granted, create a [Log Integration](/docs/guides/integrations/log) pointing at a bucket to start forwarding logs.

## Security

* **Federated, keyless**: no service account keys are created or stored.
* **Pinned role**: the pool's attribute condition trusts only Formal's exact per-integration role ARN.
* **Least privilege**: the service account gets only the roles for the capabilities you enable; disabling every capability connects the project with no access.
* **Bucket scoping**: restrict `gcs_buckets` so Formal can write only to the buckets you name.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Setup command fails">
    **Possible causes:**

    * The Cloud Shell is not authenticated to the target project
    * The account lacks permission to enable APIs or create IAM resources
    * The integration ID or security key is wrong

    **Solution:**

    1. Run `gcloud config set project <PROJECT_ID>` in the Cloud Shell
    2. Ensure the account has `roles/owner` or an equivalent set of IAM and Service Usage roles
    3. Copy the exact command Formal shows when you create the integration
  </Accordion>

  <Accordion title="Resources not discovered">
    **Possible causes:**

    * Autodiscovery disabled for that resource type
    * GKE cluster has no public endpoint
    * Cloud SQL instance is neither PostgreSQL nor MySQL
    * Service account missing the viewer role

    **Solution:**

    1. Verify the discovery toggle is enabled on the Cloud Account
    2. Confirm the cluster exposes a public endpoint
    3. Re-run the setup command so the module grants the viewer roles
    4. Wait a few minutes for the initial scan
  </Accordion>

  <Accordion title="GCS log forwarding not working">
    **Possible causes:**

    * Cloud Storage access not enabled on the integration
    * The target bucket is not in the `gcs_buckets` allowlist
    * Log integration not configured

    **Solution:**

    1. Confirm `allow_gcs_access` is enabled on the Cloud Account
    2. Add the bucket to `gcs_buckets`, or leave the list empty to allow all buckets
    3. Create a [Log Integration](/docs/guides/integrations/log) pointing to this cloud integration
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Log Integration" icon="pipe" href="/docs/guides/integrations/log">
    Forward logs to Cloud Storage
  </Card>

  <Card title="Add Resources" icon="database" href="/docs/guides/core-concepts/resources/introduction">
    Manually configure discovered resources
  </Card>

  <Card title="Terraform" icon="code" href="/docs/guides/configuration/terraform">
    Manage integrations as code
  </Card>

  <Card title="View Resources" icon="list" href="https://app.formal.ai/resources">
    See all autodiscovered resources
  </Card>
</CardGroup>
