SDKs & Integrations
Google Cloud Functions
Load KeyEnv secrets in Google Cloud Functions.
Google Cloud Functions Integration
Load secrets from KeyEnv in your Google Cloud Functions.
Prerequisites
- Google Cloud project with Cloud Functions enabled
- gcloud CLI installed
- KeyEnv service token with read access
Quick Sync
Deploy with secrets as environment variables:
export KEYENV_TOKEN=your-service-token
FUNCTION_NAME="my-function"
REGION="us-central1"
# Export to .env file
keyenv export -p YOUR_PROJECT_ID -e production --format dotenv > .env.production
# Deploy with env vars
gcloud functions deploy "$FUNCTION_NAME" \
--region="$REGION" \
--runtime=nodejs20 \
--trigger-http \
--env-vars-file=.env.productionSync Script
Create a reusable deployment script:
#!/bin/bash
# deploy-function.sh
set -euo pipefail
: "${KEYENV_TOKEN:?KEYENV_TOKEN is required}"
PROJECT_ID="${KEYENV_PROJECT:-YOUR_PROJECT_ID}"
ENVIRONMENT="${KEYENV_ENV:-production}"
FUNCTION_NAME="${FUNCTION_NAME:-my-function}"
REGION="${REGION:-us-central1}"
RUNTIME="${RUNTIME:-nodejs20}"
echo "Exporting secrets from KeyEnv ($ENVIRONMENT)..."
keyenv export -p "$PROJECT_ID" -e "$ENVIRONMENT" --format dotenv > .env.deploy
echo "Deploying $FUNCTION_NAME to Cloud Functions..."
gcloud functions deploy "$FUNCTION_NAME" \
--region="$REGION" \
--runtime="$RUNTIME" \
--trigger-http \
--allow-unauthenticated \
--env-vars-file=.env.deploy
# Cleanup
rm .env.deploy
echo "Done!"Using SDK at Runtime
For dynamic secret loading, use the Node.js or Python SDK.
Node.js Function
// index.js
const { KeyEnv } = require('keyenv');
const functions = require('@google-cloud/functions-framework');
const keyenv = new KeyEnv({
token: process.env.KEYENV_TOKEN,
cacheTtl: 300, // Cache for 5 minutes
});
let secretsLoaded = false;
functions.http('helloWorld', async (req, res) => {
// Load secrets on first invocation (cached)
if (!secretsLoaded) {
await keyenv.loadEnv(process.env.KEYENV_PROJECT, 'production');
secretsLoaded = true;
}
// Use secrets
const apiKey = process.env.API_KEY;
res.send('Hello World!');
});Python Function
# main.py
import functions_framework
import os
from keyenv import KeyEnv
keyenv = KeyEnv(
token=os.environ["KEYENV_TOKEN"],
cache_ttl=300,
)
secrets_loaded = False
@functions_framework.http
def hello_world(request):
global secrets_loaded
if not secrets_loaded:
keyenv.load_env(os.environ["KEYENV_PROJECT"], "production")
secrets_loaded = True
api_key = os.environ.get("API_KEY")
return "Hello World!"Using Secret Manager (Recommended)
For production, store secrets in Google Secret Manager.
1. Sync to Secret Manager
#!/bin/bash
# sync-to-secret-manager.sh
GCP_PROJECT="your-gcp-project"
keyenv export -p YOUR_PROJECT_ID -e production --format json | \
jq -r '.secrets[] | "\(.key)=\(.value)"' | while IFS='=' read -r key value; do
if gcloud secrets describe "$key" --project="$GCP_PROJECT" &>/dev/null; then
echo -n "$value" | gcloud secrets versions add "$key" --data-file=- --project="$GCP_PROJECT"
echo "Updated: $key"
else
echo -n "$value" | gcloud secrets create "$key" --data-file=- --project="$GCP_PROJECT"
echo "Created: $key"
fi
done2. Access in Function
// index.js
const { SecretManagerServiceClient } = require('@google-cloud/secret-manager');
const functions = require('@google-cloud/functions-framework');
const secretClient = new SecretManagerServiceClient();
const secrets = {};
async function loadSecret(name) {
if (!secrets[name]) {
const [version] = await secretClient.accessSecretVersion({
name: `projects/${process.env.GCP_PROJECT}/secrets/${name}/versions/latest`,
});
secrets[name] = version.payload.data.toString();
}
return secrets[name];
}
functions.http('helloWorld', async (req, res) => {
const apiKey = await loadSecret('API_KEY');
res.send('Hello!');
});3. Reference via Environment
Or reference secrets directly in deployment:
gcloud functions deploy my-function \
--region=us-central1 \
--runtime=nodejs20 \
--trigger-http \
--set-secrets="DATABASE_URL=DATABASE_URL:latest,API_KEY=API_KEY:latest"CI/CD Integration
GitHub Actions
name: Deploy Cloud Function
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- name: Install KeyEnv CLI
run: curl -fsSL https://keyenv.dev/install.sh | bash
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
workload_identity_provider: ${{ vars.WIF_PROVIDER }}
service_account: ${{ vars.WIF_SERVICE_ACCOUNT }}
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v2
- name: Sync secrets
run: |
export PATH="$HOME/.keyenv/bin:$PATH"
keyenv export -p ${{ vars.KEYENV_PROJECT }} -e production --format json | \
jq -r '.secrets[] | "\(.key)=\(.value)"' | while IFS='=' read -r key value; do
gcloud secrets versions add "$key" --data-file=- <<< "$value" 2>/dev/null || \
gcloud secrets create "$key" --data-file=- <<< "$value"
done
env:
KEYENV_TOKEN: ${{ secrets.KEYENV_TOKEN }}
- name: Deploy function
run: |
gcloud functions deploy my-function \
--region=us-central1 \
--runtime=nodejs20 \
--trigger-http \
--set-secrets="DATABASE_URL=DATABASE_URL:latest,API_KEY=API_KEY:latest"Cloud Build
# cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/curl'
args: ['-fsSL', 'https://keyenv.dev/install.sh', '-o', 'install.sh']
- name: 'ubuntu'
entrypoint: 'bash'
args: ['install.sh']
- name: 'ubuntu'
entrypoint: 'bash'
args:
- '-c'
- |
export PATH="$$HOME/.keyenv/bin:$$PATH"
keyenv export -p $$KEYENV_PROJECT -e production --format dotenv > .env.deploy
secretEnv: ['KEYENV_TOKEN']
env:
- 'KEYENV_PROJECT=your-project-id'
- name: 'gcr.io/cloud-builders/gcloud'
args:
- 'functions'
- 'deploy'
- 'my-function'
- '--region=us-central1'
- '--runtime=nodejs20'
- '--trigger-http'
- '--env-vars-file=.env.deploy'
availableSecrets:
secretManager:
- versionName: projects/$PROJECT_ID/secrets/KEYENV_TOKEN/versions/latest
env: 'KEYENV_TOKEN'Gen 2 Functions
For Cloud Functions (2nd gen):
gcloud functions deploy my-function \
--gen2 \
--region=us-central1 \
--runtime=nodejs20 \
--trigger-http \
--entry-point=helloWorld \
--set-secrets="DATABASE_URL=DATABASE_URL:latest"Multiple Functions
Deploy multiple functions with shared secrets:
#!/bin/bash
FUNCTIONS=("api" "auth" "webhook")
REGION="us-central1"
# Export once
keyenv export -p YOUR_PROJECT_ID -e production --format dotenv > .env.deploy
for func in "${FUNCTIONS[@]}"; do
echo "Deploying $func..."
gcloud functions deploy "$func" \
--region="$REGION" \
--runtime=nodejs20 \
--trigger-http \
--env-vars-file=.env.deploy
done
rm .env.deployBest Practices
- Use Secret Manager - Better security and automatic rotation
- Cache secrets - Use SDK caching for warm function reuse
- Grant minimal permissions - Service accounts should only access needed secrets
- Use IAM bindings - Control who can invoke functions
Troubleshooting
Secret Access Denied
Grant the function's service account access:
gcloud secrets add-iam-policy-binding SECRET_NAME \
--member="serviceAccount:[email protected]" \
--role="roles/secretmanager.secretAccessor"Function Not Seeing New Secrets
Redeploy the function:
gcloud functions deploy my-function --region=us-central1 ...Environment Variables Not Loading
Check current configuration:
gcloud functions describe my-function --region=us-central1