PostgreSQL uses application-level protocol negotation for SSL connection. Istio Proxy currently uses TCP-level protocol negotation, so Istio Proxy sidecar errors out during SSL handshake when it tries to auto encryt connection with PostgreSQL. Please follow the steps in PostgreSQL Auto SSL Connection Problem Using Istio Sidecar to see the details of this issue.
Because ASM Istio Proxy sidecar doesn't work with PostgreSQL SSL auto encryption, we demostrate how to use Cloud SQL Proxy to auto encrypt SSL connection with Cloud SQL PostgreSQL database in this article.
- Enforce SSL connection on Cloud SQL PostgreSQL instance.
- We don't need certificates for Cloud SQL Proxy connection. However, we will create client certificate and download client certificate, client key and server certificate for the purpose of initial SSL connection without sidecar auto-encryption. Instructions for downloading Cloud SQL for PostreSQL certificates is on this page: Configuring SSL/TLS certificates
- Add K8s node IPs to the Authorized Networks of PostgreSQL instance. Or, we can add "0.0.0.0/0" to allow client connection from any IP address for testing purpose.
-
Download the
client-cert.pem
,client-key.pem
andserver-ca.pem
certificates, using the instructions on Configuring SSL/TLS certificatesNOTE: These certificates are not needed for connecting via the Cloud SQL Proxy
-
Use the Dockerfile to build a test PostgreSQL client container image.
The certificates are packaged into the Docker image just for initial connection testing.
-
Deploy a PostgreSQL client without any sidecar.
kubectl apply -f postgres-plain.yaml -n sample
-
Run the follow command to make sure the SSL connection works.
# Enter into postgres-plain Pod kubectl exec -it deploy/postgres-plain -n sample -- /bin/bash # Once in the Pod, run this psql command with SSL mode psql "sslmode=verify-ca sslrootcert=server-ca.pem \ sslcert=client-cert.pem sslkey=client-key.pem \ hostaddr=YOUR_POSTGRESQL_IP \ port=5432 \ user=YOUR_USERNAME dbname=YOUR_DB_NAME" # Enter your password when it is prompted
You should see something like this:
psql (12.5, server 12.4) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help.
-
Now, run
psql
command in Non-SSL modepsql "hostaddr=YOUR_POSTGRESQL_IP port=5432 user=YOUR_USERNAME dbname=YOUR_DB_NAME"
You should see the below error message. This proves that a Non-SSL connection doesn't work.
psql: error: FATAL: connection requires a valid client certificate FATAL: pg_hba.conf rejects connection for host "35.235.65.143", user "postgres", database "postgres", SSL off
-
Create a Kubernetes Service Account
-
We have already deployed our GKE cluster with Workload Identity enabled.
-
We will use a Kubernetes Service Account (KSA) binding to a Google Cloud Service Account (GSA) to simplify our Cloud Proxy sidecar deployment.
-
Create a KSA named "ksa-sqlproxy"
kubectl apply -f service-account.yaml -n sample
-
-
Set up a Google Cloud Service Account
- Set up a Google Cloud Service Account (or use an existing GSA).
- Make sure that Cloud SQL Client predefined role (roles/cloudsql.client) is granted to this GSA.
- In the next step, we will create a new GSA
sql-client@${PROJECT_ID}.iam.gserviceaccount.com
.
-
Bind KSA to GSA
export PROJECT_ID="$(gcloud config get-value project || ${GOOGLE_CLOUD_PROJECT})" gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[YOUR_NAMESPACE/ksa-sqlproxy]" \ sql-client@${PROJECT_ID}.iam.gserviceaccount.com
-
Add annotation to the service account
kubectl annotate serviceaccount \ ksa-sqlproxy \ iam.gke.io/gcp-service-account="sql-client@${PROJECT_ID}.iam.gserviceaccount.com" \ -n YOUR_NAMESPACE
-
Deploy PostgreSQL client with Cloud SQL Proxy sidecar
Take a look at the deployment YAML file, postgres-cloudproxy.yaml. Please note the following two items:
i. The "serviceAccountName: ksa-sqlproxy" entry for pod.
- This pod will use this KSA to authenticate itself through Google Cloud IAM.
- Remember that we don't need the certificate files.
ii. The container entry for Cloud SQL Proxy.
kubectl apply -f postgres-cloudproxy.yaml -n sample
-
Test out Cloud SQL Proxy sidecar
-
Run the following command to get into Postgres client container
kubectl exec -it deploy/postgres-check -c postgres-check -n sample -- /bin/bash
-
Run
psql
command in Non-SSL modepsql "hostaddr=YOUR_POSTGRESQL_IP port=5432 user=YOUR_USERNAME dbname=YOUR_DB_NAME"
You should be prompted for password, then you should be connected to your PostgreSQL database.
-