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

# Use Google Cloud Secret Manager

> Connect External Secrets Operator to Google Cloud Secret Manager with GKE Workload Identity.

* **Deployment model**: On-premises
* **Configuration reference**: The `external-secrets.io/v1` API.
* **Live validation**: ESO `0.16.2` on GKE, using an existing Workload Identity store and an isolated cloud marker Secret.

Use this page to create the `qodo-secrets` store consumed by the shared Qodo
Secret examples. Qodo application Pods continue to read Kubernetes Secrets.
For more information, see [Manage Qodo secrets with External Secrets Operator](https://docs.qodo.ai/on-prem/external-secrets.md).

## Before you begin

Complete the common ESO controller, webhook, CRD, namespace, and permission
checks first. For more information, see [Before you begin](https://docs.qodo.ai/on-prem/external-secrets.md#before-you-begin).

Prepare:

* A GKE cluster with Workload Identity enabled and the metadata server available to ESO.
* Secret Manager API enabled in the source project, with an enabled source Secret version.
* The project containing your source secrets, and the project, name, and location of the GKE cluster.
* A Google service account approved to read the required source secrets.
* ESO permission to request tokens for the referenced Kubernetes service account.
* Network access from ESO to Secret Manager and the identity services required by Workload Identity.

For a Standard cluster, verify the node pool running ESO also uses the GKE
metadata server. Enabling Workload Identity on the cluster does not by itself
configure an existing node pool. For more information, see [Authenticate to Google Cloud APIs from GKE workloads](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity).

This example links a Kubernetes service account to a Google service account.
If you already have an approved store, reuse it and update the shared
`ExternalSecret`'s `secretStoreRef` instead of creating another identity.
For more information, see [Google Cloud Secret Manager authentication](https://external-secrets.io/latest/provider/google-secrets-manager/#authentication).

## 1. Prepare the source Secret and permissions

Using your approved secret-management process, create `qodo-database` in
Secret Manager. Its JSON value must contain `POSTGRES_PASSWORD` with the
existing database password. Keep the value out of Git, Helm values, shell
arguments, and chat.

Configure these IAM bindings through your cloud administration process:

| Binding | Required relationship |
| - | - |
| Source access | Grant the Google service account `roles/secretmanager.secretAccessor` on the required source Secret |
| Service account impersonation | Grant `roles/iam.workloadIdentityUser` on the Google service account to `serviceAccount:CLUSTER_PROJECT_ID.svc.id.goog[qodo/qodo-secrets-reader]` |

Replace the cluster project ID in the IAM member. The cluster project and
secret project can differ; the store identifies them separately. Scope
source access to the required secrets. For more information, see [Authenticate to Google Cloud APIs from GKE workloads](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity).

## 2. Configure the service account and store

Replace every `REPLACE_WITH_*` value. `clusterLocation` is the Region for a
regional cluster or the zone for a zonal cluster. The annotation must name
the Google service account configured in the IAM bindings above.

```yaml google-cloud-secret-store.yaml theme={null}
apiVersion: v1
kind: ServiceAccount
metadata:
  name: qodo-secrets-reader
  namespace: qodo
  annotations:
    iam.gke.io/gcp-service-account: REPLACE_WITH_GOOGLE_SERVICE_ACCOUNT_EMAIL
---
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: qodo-secrets
  namespace: qodo
spec:
  provider:
    gcpsm:
      projectID: REPLACE_WITH_SECRET_PROJECT_ID
      auth:
        workloadIdentity:
          clusterProjectID: REPLACE_WITH_CLUSTER_PROJECT_ID
          clusterName: REPLACE_WITH_CLUSTER_NAME
          clusterLocation: REPLACE_WITH_CLUSTER_LOCATION
          serviceAccountRef:
            name: qodo-secrets-reader
```

The example uses a namespaced store. If your existing configuration uses a
`ClusterSecretStore`, its service account reference also needs the account's
namespace. Keep the store's approved name and access scope.

## 3. Reconcile and verify

Select the target context explicitly. These examples use namespace `qodo`:

```bash theme={null}
KUBE_CONTEXT="REPLACE_WITH_YOUR_CONTEXT"
NAMESPACE=qodo

kubectl --context "$KUBE_CONTEXT" apply \
  --dry-run=server -f google-cloud-secret-store.yaml
kubectl --context "$KUBE_CONTEXT" apply -f google-cloud-secret-store.yaml
kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" \
  wait secretstore/qodo-secrets --for=condition=Ready --timeout=120s
```

Apply the shared database `ExternalSecret`. It reads the JSON property from
`qodo-database` and writes the fixed `qodo-db-admin.POSTGRES_PASSWORD` target.
For more information, see [Manage Qodo secrets with External Secrets Operator](https://docs.qodo.ai/on-prem/external-secrets.md).

Verify the ready condition, refresh timestamp, target name, and key names.
After adding a new source version, confirm the target updates before rolling
out the affected consumer. Check that the provider accepts the credential
and the relevant Qodo flow still works.

Live validation exercised cloud source-version refresh, JSON property
extraction, missing-property failure/recovery, and target retention through
an existing store. A newly configured service account still needs its own
identity and application acceptance checks.

## Troubleshoot Google Cloud access

| Symptom | Check and recovery |
| - | - |
| Identity exchange fails | Check Workload Identity, the Kubernetes account annotation, the impersonation binding, and the cluster project/name/location |
| The wrong project is queried | Check `projectID` for the source secrets and `clusterProjectID` for the GKE identity pool |
| Access to the source is denied | Check Secret Accessor on the actual source Secret and whether the selected source version is enabled |
| The store is ready but synchronization fails | Check the Secret ID and case-sensitive JSON property, then inspect the ExternalSecret's conditions |
| Requests time out | Check DNS, egress, private access configuration, and access to Google identity and Secret Manager APIs |

## Next steps

* [Manage Qodo secrets with External Secrets Operator](https://docs.qodo.ai/on-prem/external-secrets.md): Apply the shared ownership, rotation, and recovery procedure.
* [Google Cloud Secret Manager provider](https://external-secrets.io/latest/provider/google-secrets-manager/): Review other authentication patterns and cross-project access.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.