Introduction
Terraform Enterprise (TFE) version 1.1.0 supports passwordless authentication to PostgreSQL when running on Google Cloud by leveraging Cloud SQL IAM authentication.
This removes the need to store or manage long-lived database passwords, improving overall security and operational simplicity.
This document walks through configuring TFE on OpenShift to connect to Cloud SQL PostgreSQL using GCP IAM–based authentication.
Prerequisites
1. Terraform Enterprise
- Deployed on Openshift
- Cloud Platform is GCP
-
External services:
1) Google Cloud Storage bucket
2) Cloud SQL PostgreSQL
3) Redis
2. Cloud SQL PostgreSQL
Enable IAM authentication on the Cloud SQL instance:
gcloud sql instances patch ${POSTGRESQL_NAME} \
--database-flags=cloudsql.iam_authentication=on \
--project=${PROJECT_ID}This allows Cloud SQL to accept IAM principals as database users.
3. IAM and Access
Create a dedicated service account that TFE will use for PostgreSQL authentication:
gcloud iam service-accounts create tfe-sql-sa \
--description="Service account for TFE PostgreSQL IAM auth" \
--display-name="TFE SQL SA"Capture the project ID:
PROJECT_ID=$(gcloud config get-value project)
echo $PROJECT_IDAssign the required IAM roles to the service account:
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:tfe-sql-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:tfe-sql-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/cloudsql.instanceUser"
These roles allow:
1) Connecting to Cloud SQL
2) Authenticating as a PostgreSQL IAM user
Associate the Service Account with TFE
OpenShift on GCP does not support native GCP Workload Identity like GKE.
Because of this limitation:
Pods cannot access the GCP metadata server
ADC is not available by default
Annotate the namespace and service account:
oc annotate namespace terraform-enterprise \
iam.gke.io/gcp-service-account=tfe-sql-sa@$PROJECT_ID.iam.gserviceaccount.com
oc annotate serviceaccount terraform-enterprise \
iam.gke.io/gcp-service-account=tfe-sql-sa@$PROJECT_ID.iam.gserviceaccount.com \
-n terraform-enterpriseVerify:
oc get serviceaccount terraform-enterprise -n terraform-enterprise -o yamlSolution
1. Create the IAM Database User in Cloud SQL
In Google Cloud Console:
Navigate to Cloud SQL → Select PostgreSQL → Users
Click Add user
-
Select:
Authentication method: Cloud IAM
-
IAM principal:
tfe-sql-sa@hc-0354a4ccd0274e1096dbc1bedc0.iam.gserviceaccount.com
Confirm creation:
gcloud sql users list \
--instance=${POSTGRESQL_NAME} \
--project=${PROJECT_ID}2. Create the database:
CREATE DATABASE openshift;3. Grant Database-Level Privileges
Cloud SQL truncates IAM usernames internally.
Always copy the exact role name shown by\du.
List roles:
\duGrant database access:
GRANT ALL PRIVILEGES ON DATABASE openshift
TO "tfe-sql-sa@hc-0354a4ccd0274e1096dbc1bedc0.iam";4. Grant Schema and Object Privileges
Connect to the database:
\c openshiftGrant schema access:
GRANT ALL PRIVILEGES ON SCHEMA public
TO "tfe-sql-sa@hc-0354a4ccd0274e1096dbc1bedc0.iam";This allows TFE to:
Create tables
Create indexes
Run migrations
5. Configure Default Privileges
Ensure future objects are accessible:
Tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT ALL ON TABLES
TO "tfe-sql-sa@hc-0354a4ccd0274e1096dbc1bedc0.iam";Sequences
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT ALL ON SEQUENCES
TO "tfe-sql-sa@hc-0354a4ccd0274e1096dbc1bedc0.iam";Functions
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT ALL ON FUNCTIONS
TO "tfe-sql-sa@hc-0354a4ccd0274e1096dbc1bedc0.iam";6. Create a Service Account Key (Required)
Because OpenShift does not provide native ADC:
gcloud iam service-accounts keys create tfe-sql-sa-key.json \
--iam-account=tfe-sql-sa@$PROJECT_ID.iam.gserviceaccount.com \
--project=$PROJECT_ID7. Create a Kubernetes Secret
oc create secret generic gcp-sql-sa-key \
--from-file=key.json=tfe-sql-sa-key.json \
-n terraform-enterpriseVerify:
oc get secret gcp-sql-sa-key -n terraform-enterprise8. Mount the Secret into the TFE Pod
In your Helm overrides.yaml:
extraVolumes:
- name: gcp-sa-key
secret:
secretName: gcp-sql-sa-key
extraVolumeMounts:
- name: gcp-sa-key
mountPath: /var/run/gcp
readOnly: trueThis creates:
/var/run/gcp/key.jsoninside the pod.
9. Configure TFE Environment Variables
Before: Password-Based Authentication
TFE_DATABASE_HOST: ${DB_HOSTNAME}
TFE_DATABASE_NAME: ${DB_NAME}
TFE_DATABASE_USER: ${DB_USER}
TFE_DATABASE_PARAMETERS: sslmode=requireIn this approach:
A static database password is stored in secrets
Credential rotation must be handled manually
After (IAM passwordless):
TFE_DATABASE_HOST: ${DB_HOSTNAME}
TFE_DATABASE_NAME: ${DB_NAME}
TFE_DATABASE_USER: ${DB_USER}
# Example: tfe-sql-sa@hc-0354a4ccd0274e1096dbc1bedc0.iam
TFE_DATABASE_PARAMETERS: "sslmode=require"
TFE_DATABASE_PASSWORDLESS_GOOGLE_USE_DEFAULT_CREDENTIALS: "true"
GOOGLE_APPLICATION_CREDENTIALS: "/var/run/gcp/key.json"In this approach:
TFE authenticates using Google Application Default Credentials (ADC)
No database password is required or stored
Authentication is enforced through IAM and PostgreSQL role mappings
TFE uses Google ADC to obtain short-lived OAuth 2.0 tokens
Token generation and refresh are handled automatically
Database access is governed by IAM roles and PostgreSQL privileges
Key Changes Summary
Enable passwordless authentication by setting
TFE_DATABASE_PASSWORDLESS_GOOGLE_USE_DEFAULT_CREDENTIALS: "true"Update
TFE_DATABASE_USERto the Cloud SQL IAM username formatRemove
TFE_DATABASE_PASSWORDfrom all Kubernetes secrets and Helm valuesProvide ADC explicitly via
GOOGLE_APPLICATION_CREDENTIALSwhen running on OpenShift
10. Restart Terraform Enterprise Pods
After applying the updated environment variables and volume mounts, restart the Terraform Enterprise deployment to apply the changes.
Restart the TFE Deployment
oc rollout restart deployment terraform-enterprise -n terraform-enterprise
Verify that the rollout completes successfully:
oc rollout status deployment terraform-enterprise -n terraform-enterprise
Check pods:
oc get pods -n terraform-enterprise
NAME READY STATUS RESTARTS AGE
terraform-enterprise-XXXXXX-XXXXX. 1/1 Running 0 5mMonitor Logs for Successful Authentication
Once the pods are running, monitor the logs to confirm that TFE connects to PostgreSQL using IAM-based authentication:
oc logs -n terraform-enterprise deploy/terraform-enterprise | grep -i databaseExpected logs:
{"component":"terraform-enterprise","log":"2026-01-12T04:56:36.947Z [INFO] database.pgmultiauth: getting initial db auth token"}
{"component":"terraform-enterprise","log":"2026-01-12T04:56:36.947Z [INFO] database.pgmultiauth: getting initial db auth token"}
{"component":"terraform-enterprise","log":"2026-01-12T04:56:37.204Z [INFO] terraform-enterprise: check passed: name=database duration=251.602798ms"}
{"component":"terraform-enterprise","log":"2026-01-12T04:56:37.204Z [INFO] terraform-enterprise.database.pgmultiauth: getting initial db auth token"}
{"component":"terraform-enterprise","log":"2026-01-12T04:56:37.403Z [INFO] terraform-enterprise: connected successfully to terraform_enterprise database"}
{"component":"terraform-enterprise","log":"2026-01-12T04:56:37.476Z [INFO] terraform-enterprise.database: running database migrations"}
{"component":"terraform-enterprise","log":"2026-01-12T04:56:37.552Z [INFO] terraform-enterprise.database: executed query to add 1.1.0 into application_versions table"}Common Troubleshooting
| Issue | What to Check |
|---|---|
| Authentication failed | Ensure the Cloud SQL IAM database user exactly matches the IAM principal name (including truncated .iam suffix as shown by \du). |
| Permission denied | Verify the service account has roles/cloudsql.client and roles/cloudsql.instanceUser assigned at the project level. |
| TFE stuck on startup | Confirm Google Application Default Credentials (ADC) are available and the service account key is correctly mounted inside the TFE pod. |
| Failed to fetch GCP token / connection refused to metadata server | TFE is attempting to access the GCP metadata server (169.254.169.254), which is not available in OpenShift. Ensure GOOGLE_APPLICATION_CREDENTIALS is set and points to a valid service account key file mounted in the pod. |
Conclusion
By enabling IAM-based authentication in Terraform Enterprise , organizations can securely connect TFE running on OpenShift to Cloud SQL PostgreSQL without managing database passwords. This approach replaces static credentials with identity-based access, leveraging Google Application Default Credentials and Cloud SQL IAM integration.