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

# GCP

> Create a GCP secret to store Google Cloud service account credentials for authenticating with GCP services or pulling images from Artifact Registry.

GCP secrets store Google Cloud service account credentials, enabling your workloads to authenticate with Google Cloud services or pull images from Google Artifact Registry.

## Use Cases

* **Artifact Registry**: Pull container images from Google Artifact Registry
* **Cloud Storage**: Access files in Google Cloud Storage buckets
* **BigQuery**: Query data from BigQuery datasets
* **Pub/Sub**: Publish and subscribe to Pub/Sub topics
* **Any GCP Service**: Authenticate with any Google Cloud API

<Note>
  For Google Artifact Registry, you can also use a [Docker secret](/guides/create-secret/docker) with base64-encoded service account credentials. The GCP secret type is recommended for direct GCP API access.
</Note>

## Configuration Options

The GCP secret stores a complete service account JSON key file:

| Field            | Description                           |
| :--------------- | :------------------------------------ |
| `type`           | Always `service_account`              |
| `project_id`     | Your GCP project ID                   |
| `private_key_id` | Unique identifier for the private key |
| `private_key`    | RSA private key in PEM format         |
| `client_email`   | Service account email address         |
| `client_id`      | Numeric client ID                     |
| `auth_uri`       | OAuth2 authorization endpoint         |
| `token_uri`      | OAuth2 token endpoint                 |

***

## Create a GCP Secret

<Tabs>
  <Tab title="Console UI">
    <Steps>
      <Step title="Navigate to Secrets">
        In the Console, navigate to **Secrets** and click **New**, or use the **Create** dropdown in the top-right corner and select **Secret**.
      </Step>

      <Step title="Enter basic information">
        Enter a **Name** and optional **Description**.
      </Step>

      <Step title="Select secret type">
        Select **GCP** as the secret type.
      </Step>

      <Step title="Configure credentials">
        Click **Data** in the left pane. Drag and drop your service account JSON file, or click to import.
      </Step>

      <Step title="Create the secret">
        Click **Create**.
      </Step>
    </Steps>
  </Tab>

  <Tab title="CLI">
    Download your service account key from the Google Cloud Console, then create the secret:

    ```bash theme={null}
    cpln secret create-gcp \
      --name gcp-service-account \
      --file service-account.json \
      --org my-org
    ```

    <Tip>
      Generate service account keys from the [Google Cloud Console](https://console.cloud.google.com/iam-admin/serviceaccounts) under **IAM & Admin > Service Accounts > Keys**.
    </Tip>
  </Tab>

  <Tab title="Terraform">
    ```hcl theme={null}
    resource "cpln_secret" "gcp" {
      name        = "gcp-service-account"
      description = "GCP service account for Cloud Storage access"

      gcp = jsonencode({
        type                        = "service_account"
        project_id                  = "my-project-123"
        private_key_id              = "abc123def456"
        private_key                 = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
        client_email                = "my-service-account@my-project-123.iam.gserviceaccount.com"
        client_id                   = "123456789012345678901"
        auth_uri                    = "https://accounts.google.com/o/oauth2/auth"
        token_uri                   = "https://oauth2.googleapis.com/token"
        auth_provider_x509_cert_url = "https://www.googleapis.com/oauth2/v1/certs"
        client_x509_cert_url        = "https://www.googleapis.com/robot/v1/metadata/x509/my-service-account%40my-project-123.iam.gserviceaccount.com"
      })
    }
    ```

    <Warning>
      This example uses placeholder credentials for testing. In production, use `file("service-account.json")` or Terraform variables.
    </Warning>
  </Tab>

  <Tab title="Pulumi">
    <Tabs>
      <Tab title="TypeScript">
        ```typescript theme={null}
        import * as cpln from "@pulumiverse/cpln";

        const gcpSecret = new cpln.Secret("gcp-service-account", {
          name: "gcp-service-account",
          description: "GCP service account credentials",
          gcp: JSON.stringify({
            type: "service_account",
            project_id: "my-project-123",
            private_key_id: "abc123def456",
            private_key: "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
            client_email: "my-service-account@my-project-123.iam.gserviceaccount.com",
            client_id: "123456789012345678901",
            auth_uri: "https://accounts.google.com/o/oauth2/auth",
            token_uri: "https://oauth2.googleapis.com/token",
          }),
        });
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={null}
        import json
        import pulumiverse_cpln as cpln

        gcp_secret = cpln.Secret("gcp-service-account",
            name="gcp-service-account",
            description="GCP service account credentials",
            gcp=json.dumps({
                "type": "service_account",
                "project_id": "my-project-123",
                "private_key_id": "abc123def456",
                "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
                "client_email": "my-service-account@my-project-123.iam.gserviceaccount.com",
                "client_id": "123456789012345678901",
                "auth_uri": "https://accounts.google.com/o/oauth2/auth",
                "token_uri": "https://oauth2.googleapis.com/token",
            }))
        ```
      </Tab>

      <Tab title="Go">
        ```go theme={null}
        package main

        import (
            "encoding/json"
            "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
            "github.com/pulumiverse/pulumi-cpln/sdk/go/cpln"
        )

        func main() {
            pulumi.Run(func(ctx *pulumi.Context) error {
                gcpConfig, _ := json.Marshal(map[string]string{
                    "type":           "service_account",
                    "project_id":     "my-project-123",
                    "private_key_id": "abc123def456",
                    "private_key":    "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
                    "client_email":   "my-service-account@my-project-123.iam.gserviceaccount.com",
                    "client_id":      "123456789012345678901",
                    "auth_uri":       "https://accounts.google.com/o/oauth2/auth",
                    "token_uri":      "https://oauth2.googleapis.com/token",
                })

                _, err := cpln.NewSecret(ctx, "gcp-service-account", &cpln.SecretArgs{
                    Name:        pulumi.String("gcp-service-account"),
                    Description: pulumi.String("GCP service account credentials"),
                    Gcp:         pulumi.String(string(gcpConfig)),
                })
                return err
            })
        }
        ```
      </Tab>

      <Tab title="C#">
        ```csharp theme={null}
        using System.Text.Json;
        using Pulumi;
        using Pulumiverse.Cpln;
        using Pulumiverse.Cpln.Inputs;

        return await Deployment.RunAsync(() =>
        {
            var gcpConfig = JsonSerializer.Serialize(new
            {
                type = "service_account",
                project_id = "my-project-123",
                private_key_id = "abc123def456",
                private_key = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
                client_email = "my-service-account@my-project-123.iam.gserviceaccount.com",
                client_id = "123456789012345678901",
                auth_uri = "https://accounts.google.com/o/oauth2/auth",
                token_uri = "https://oauth2.googleapis.com/token",
            });

            var gcpSecret = new Secret("gcp-service-account", new SecretArgs
            {
                Name = "gcp-service-account",
                Description = "GCP service account credentials",
                Gcp = gcpConfig,
            });
        });
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

***

## Best Practices

<AccordionGroup>
  <Accordion title="Use least-privilege service accounts">
    Create dedicated service accounts with only the IAM roles your workload needs. Avoid using default service accounts or overly permissive roles.
  </Accordion>

  <Accordion title="Rotate keys regularly">
    Set up a key rotation schedule. Delete old keys after deploying new ones to Control Plane.
  </Accordion>

  <Accordion title="Use Workload Identity where possible">
    For GKE deployments, consider using [Workload Identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity) instead of service account keys.
  </Accordion>
</AccordionGroup>

***

## Using for Artifact Registry

To use a GCP secret for pulling images from Artifact Registry, add it as a **pull secret** to your GVC:

<Tabs>
  <Tab title="Console UI">
    <Steps>
      <Step title="Navigate to your GVC">
        Open your GVC in the Console.
      </Step>

      <Step title="Open Pull Secrets">
        Click **Pull Secrets** in the left pane.
      </Step>

      <Step title="Add the secret">
        Click **Add** and select your GCP secret.
      </Step>

      <Step title="Save changes">
        Click **Save**.
      </Step>
    </Steps>
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    cpln gvc update my-gvc \
      --set spec.pullSecretLinks+="gcp-service-account" \
      --org my-org
    ```
  </Tab>

  <Tab title="Terraform">
    ```hcl theme={null}
    resource "cpln_gvc" "my_gvc" {
      name = "my-gvc"

      pull_secrets = [
        cpln_secret.gcp.name
      ]
    }
    ```
  </Tab>

  <Tab title="Pulumi">
    <Tabs>
      <Tab title="TypeScript">
        ```typescript theme={null}
        import * as cpln from "@pulumiverse/cpln";

        const gvc = new cpln.Gvc("my-gvc", {
          name: "my-gvc",
          pullSecrets: [gcpSecret.name],
        });
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={null}
        import pulumiverse_cpln as cpln

        gvc = cpln.Gvc("my-gvc",
            name="my-gvc",
            pull_secrets=[gcp_secret.name])
        ```
      </Tab>

      <Tab title="Go">
        ```go theme={null}
        gvc, err := cpln.NewGvc(ctx, "my-gvc", &cpln.GvcArgs{
            Name:        pulumi.String("my-gvc"),
            PullSecrets: pulumi.StringArray{gcpSecret.Name},
        })
        ```
      </Tab>

      <Tab title="C#">
        ```csharp theme={null}
        var gvc = new Gvc("my-gvc", new GvcArgs
        {
            Name = "my-gvc",
            PullSecrets = new[] { gcpSecret.Name },
        });
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

<Note>
  The service account must have the `roles/artifactregistry.reader` role on the Artifact Registry repository.
</Note>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Using Secrets in Workloads" icon="cube" href="/guides/create-secret/overview#using-secrets-in-workloads">
    Learn how to grant access and inject secrets
  </Card>

  <Card title="GCP Cloud Account" icon="google" href="/reference/cloudaccount#gcp">
    Set up GCP cloud account integration
  </Card>
</CardGroup>
