GCP Secret Manager
This guide will show you how to set up automatic syncing of Doppler secrets to GCP Secret Manager.
Doppler supports two ways to authenticate to GCP Secret Manager. Workload identity federation is recommended, since it leaves no credential stored in Doppler. Follow whichever section applies, then continue to Configuration.
Throughout, a SECRET_PREFIX limits Doppler's access to only GCP secrets whose names start with that prefix.
- Adjust the
SECRET_PREFIXas desired, and use the same value when you set up the integration in Doppler. - The prefix may only contain alphanumeric characters, dashes, and underscores — a dash is recommended for the last character.
Prerequisites
- You have a GCP account and are familiar with GCP Secret Manager
- You have the gcloud CLI installed and authenticated
- You have enabled the Secret Manager API for your GCP project
Ensure gcloud is configured to use the correct project, e.g.
gcloud config set project yodaspeakbefore proceeding.
Keyless Authentication
Doppler can authenticate to this integration without you storing a long-lived credential. Instead of a service account key or client secret, Doppler acts as an OpenID Connect (OIDC) identity provider: whenever it needs access, it mints a short-lived signed token that your cloud verifies against Doppler's public keys and exchanges for its own temporary credentials.
Doppler's OIDC Issuer
| Issuer | https://api.doppler.com |
| Discovery document | https://api.doppler.com/.well-known/openid-configuration |
| JWKS | https://api.doppler.com/.well-known/jwks.json |
| Signing algorithm | RS256 |
| Token lifetime | 5 minutes |
Every connection gets its own identity. The sub claim of each token Doppler issues for a connection is:
workplace:<workplace-slug>:connection:<connection-id>
Tokens also carry workplace and connection claims holding those same two values. Tokens minted for a sync additionally carry sync, config, and project. Because the subject contains the connection ID, trust you grant to one connection never extends to another.
If you self-host Doppler, substitute your own API domain for
api.doppler.com. Keyless options only become selectable once an administrator has configured the OIDC issuer's signing keys. If the option is greyed out in the connection dialog, that hasn't been done yet.
Setup Takes Two Passes
A connection's identity contains its connection ID, and that ID doesn't exist until the connection has been created. Configuring keyless authentication is therefore a round trip between your cloud and Doppler:
- In your cloud, establish the trust relationship pointing at Doppler's issuer.
- In Doppler, create the connection. Doppler has no permissions yet, so it skips its usual credential check and the connection is created immediately.
- In your cloud, grant access to the identity Doppler displays on the connection page under Federation Identity.
Because step 2 can't verify anything, a keyless connection looks healthy even when step 3 is missing or wrong. The first sync, rotation, or lease is what proves the trust works. Confirm one succeeds before you consider setup finished.
Create a Workload Identity Pool and Provider
Create a pool to hold Doppler's identity, then a provider inside it that trusts Doppler's OIDC issuer. Do this before you create the connection in Doppler.
POOL_ID="doppler";
PROVIDER_ID="doppler";
# Get the current project's ID and number
PROJECT_ID="$(gcloud config get-value project --quiet)";
PROJECT_NUMBER="$(gcloud projects describe "$PROJECT_ID" --format='value(projectNumber)')";
# Create a workload identity pool for Doppler
gcloud iam workload-identity-pools create "$POOL_ID" \
--location="global" \
--display-name="Doppler";
# Create an OIDC provider in that pool which trusts Doppler's issuer
gcloud iam workload-identity-pools providers create-oidc "$PROVIDER_ID" \
--location="global" \
--workload-identity-pool="$POOL_ID" \
--issuer-uri="https://api.doppler.com" \
--attribute-mapping="google.subject=assertion.sub" \
--display-name="Doppler";
# Print the provider resource name to paste into Doppler
echo "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID";Doppler uses the provider's full resource name as the token audience, which is the audience GCP accepts by default. You don't need to set
--allowed-audiences.
Connect Doppler
In the connection dialog, choose Workload identity federation, then provide:
- Workload identity provider — the resource name printed by the last command above. It begins with
//iam.googleapis.com/and uses your numeric project number, not the project ID. - Project ID — your project's ID, the human-readable one (e.g.
my-gcp-project).
Doppler creates the connection without checking its access, since it has none yet.
Grant Access to the Doppler Principal
Open the connection in Doppler and copy the IAM principal shown under Federation Identity. It looks like this:
principal://iam.googleapis.com/projects/123456789012/locations/global/workloadIdentityPools/doppler/subject/workplace:my-workplace:connection:00000000-0000-0000-0000-000000000000
That principal is what you grant roles to below. Until you do, Doppler can authenticate but can't do anything.
To reach the connection dialog, navigate to the project you would like to integrate, click Integrations from the Projects menu, then select GCP Secret Manager. You can optionally set a Secret name prefix here as well.

Once the connection exists, grant its principal access to secrets carrying your prefix:
# This should match the prefix you entered in Doppler
SECRET_PREFIX="doppler-";
# Get current project
PROJECT_ID="$(gcloud config get-value project --quiet)";
# The IAM principal shown under "Federation Identity" on the Doppler connection page
PRINCIPAL="principal://iam.googleapis.com/projects/.../subject/workplace:...:connection:...";
# Attach SecretManagerAdmin policy to the Doppler principal, scoped to the prefix
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="$PRINCIPAL" \
--role="roles/secretmanager.admin" \
--condition="expression=resource.name.extract(\"secrets/{rest}\").startsWith(\"$SECRET_PREFIX\"),title=\"$SECRET_PREFIX*\"";IAM Service Account
Use this method if you'd rather give Doppler a service account key than set up federation.
We need to set up a Service Account so Doppler has the required permissions to sync secrets to GCP Secret Manager.
This is best done using the gcloud CLI:
# To narrow permission scope use this prefix for Doppler accessible secrets, adjust as desired
# This should match the prefix you enter in Doppler when setting up your integration
SECRET_PREFIX="doppler-";
# Get current project
PROJECT_ID="$(gcloud config get-value project --quiet)";
# Create a new Service Account
gcloud iam service-accounts create doppler-secret-manager \
--description="Service account for Doppler to sync secrets to Secret Manager" \
--display-name="Doppler Secret Manager";
# Attach SecretManagerAdmin policy to the new service account
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:doppler-secret-manager@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.admin" \
--condition="expression=resource.name.extract(\"secrets/{rest}\").startsWith(\"$SECRET_PREFIX\"),title=\"$SECRET_PREFIX*\"";Then we create a new key for the service account to generate the required credentials for Doppler:
# Generate a key for your new service account
gcloud iam service-accounts keys create iam-key.json \
--iam-account="doppler-secret-manager@$PROJECT_ID.iam.gserviceaccount.com";
# Print (and then remove) the JSON credentials
cat iam-key.json && rm iam-key.json;Copy the JSON credentials output in your shell as you'll need it for the next step.
Authorization
Navigate to the project you would like to integrate, click Integrations from the Projects menu, then select GCP Secret Manager to begin the authorization process.

Choose Service account key, enter the prefix used above (e.g., "doppler-"), paste the JSON from the shell into the credentials text field, then click Connect.

Configuration
Now chose the config to sync, the Region(s), and the enter a secret Name.
For region, Automatic replication is recommended, but you can instead specify which regions secrets should be replicated to. Learn more in the GCP Secret Manager replication docs.
Enter a Name (alphanumeric characters, dashes, and underscores) which will be concatenated to the prefix to display the Secret Manager Name (the GCP secret where Doppler will sync your secrets).

Click "Set Up Integration," and you're all set! Click the DESTINATION link in the table to see your secrets in the GCP console.

Doppler sync and secret versionsEvery time a secret is changed in Doppler, this will create a new version of the secret in GCP Secret Manager, so ensure sure your code always retrieves the latest version using
/versions/latest.
Import Secrets
The GCP Secret Manager integration doesn't currently support importing secrets. However, it's possible to import secrets programmatically using a script like this:
#!/bin/bash
# Check if jq is installed
if ! command -v jq &> /dev/null; then
echo "jq could not be found, please install jq to process JSON data."
exit 1
fi
# Check if gcloud is installed
if ! command -v gcloud &> /dev/null; then
echo "gcloud could not be found, please install the Google Cloud CLI."
exit 1
fi
# Check if doppler is installed
if ! command -v doppler &> /dev/null; then
echo "doppler could not be found, please install the doppler CLI."
exit 1
fi
# Configuration variables
gcp_project="${GCP_PROJECT}"
gcp_prefix="${GCP_PREFIX}"
doppler_project="${DOPPLER_PROJECT}"
doppler_config="${DOPPLER_CONFIG}"
date
echo "========================================"
echo "Initiating import from GCP to Doppler..."
echo "========================================"
echo "-------------- SOURCE ------------------"
echo " GCP Project: $gcp_project"
echo " GCP Secret Prefix: $gcp_prefix"
echo "------------ DESTINATION ---------------"
echo " Doppler Project: $doppler_project"
echo " Doppler Config: $doppler_config"
echo "----------------------------------------"
echo
# We're going to store all secrets in this variable in .env format. Note that we're not
# really doing any special character escaping with values, so be mindful of that if you
# have secrets that contain special characters or double-quotes.
secrets_to_import=""
# Iterate through all secrets in the specified GCP project that have the specified prefix in their name.
# Note that this filter is just looking for the prefix ANYWHERE in the name, it's not specifically limited
# to actually being a prefix.
for secret in $(gcloud secrets list --project $gcp_project --filter $gcp_prefix --format=json | jq -r '.[] | .name'); do
# Extract the secret name from the last portion of the fully specified secret name
secret_name=$(echo $secret | rev | cut -d'/' -f1 | rev)
# Remove the prefix from the secret name
secret_name=${secret_name//"$gcp_prefix"/}
echo "fetching ${secret_name}..."
# Fetch the secret value
secret_value=$(gcloud secrets versions access --project $gcp_project "${secret}/versions/latest")
# Append the secret to the result
secrets_to_import="${secrets_to_import}\\n${secret_name}=\"${secret_value}\""
done
# Upload the secrets to the specified Doppler project and config
doppler secrets upload -p $doppler_project -c $doppler_config --silent <(echo -e "$secrets_to_import")
echo
date
echo "Import complete."The script expects for arguments to be passed in as environment variables (you could also modify the script to accept them as arguments): the GCP project (GCP_PROJECT), the GCP secret prefix (GCP_PREFIX), the Doppler project (DOPPLER_PROJECT) and the Doppler config (DOPPLER_CONFIG). It functions by listing all secrets in the specified GCP project that contain the specified prefix in the name. It will then iterate through them, remove the prefix from the name and import them into the specified Doppler project and config.
Note that the script doesn't perform any special character escaping and simply wraps the secret values in double-quotes, so be mindful of this when using the script.
Amazing Work!You've successfully set up the Doppler GCP Secret Manager integration! Every time you update your secrets in Doppler, we will automatically sync them to GCP Secret Manager, creating a new version of that secret.
Updated 20 days ago

