Override Trust certificates for TLS for Google Cloud Client Libraries

2021-12-15

Overriding the TLS is not a common task as the built-in CA truststore is sufficient to access Google Cloud APIs.

However, there are certain cases where a developer may want to add or exclusively set the the CA certificates to trust.

This usecase is usually tied to the using a proxy server where the TLS traffic is intercepted (see Using proxy servers with Google Cloud Client Libraries). Another general usecase maybe to terminate TLS on a proxy like Envoy.


In most cases, you can override the system trust store directly and add you custom certificates.

in debian, the truststore is /etc/ssl/certs/ca-certificates.crt.

Simply append the custom CA and Subordinate chain in PEM mode to that file

Alternatively, you use update-ca-certificates binary to do that:

# note the destination file is saved with .crt extension
sudo cp myroot.crt /usr/local/share/ca-certificates/extra/myroot.crt
sudo cp mysub.crt /usr/local/share/ca-certificates/extra/mysub.crt
sudo update-ca-certificates -f 

For java, set the jvm truststore to include the custom CA

$ export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::")
$ echo $JAVA_HOME
   /usr/lib/jvm/java-11-openjdk-amd64/

the cacerts would then be at /usr/lib/jvm/java-11-openjdk-amd64/lib/security/cacerts

import the custom certificates for the proxy

keytool -import -trustcacerts -alias myRootCA -file root.crt -keystore "/tmp/cacerts" -storepass changeit

keytool -list -keystore "/tmp/cacerts" -storepass changeit

Invoke maven with the truststore

mvn -Djavax.net.ssl.trustStore=/tmp/cacerts \
   -Djavax.net.ssl.trustStorePassword=changeit \
  clean install exec:java -q

you can also ofcourse override the trust store in any language in code. This article is will not coverthat


import google.auth

import google.auth.transport.requests
from google.auth.transport.requests import AuthorizedSession

project='mineral-minutia-820'

## add custom cacerts to the following path (use full cert chain)
import certifi
print(certifi.where())  # env/lib/python3.9/site-packages/certifi/cacert.pem
ca_cert_bundle = certifi.where()


from google.cloud import storage
client = storage.Client(project=project, _http=authed_session)

for b in client.list_buckets():
   print(b.name)

import google.auth.transport.grpc
import grpc
from google.cloud import pubsub_v1
from google.pubsub_v1.services.publisher import transports 

regular_ssl_credentials = grpc.ssl_channel_credentials()
with open(ca_cert_bundle, 'rb') as f:
    trusted_certs = f.read()
custom_ssl_credential = grpc.ssl_channel_credentials(
            root_certificates=trusted_certs
)

channel = google.auth.transport.grpc.secure_authorized_channel(
    credentials=credentials, request=request, target='pubsub.googleapis.com:443',
    ssl_credentials=custom_ssl_credential)

transport = transports.PublisherGrpcTransport(
        credentials=credentials,
        channel=channel
)

publisher = pubsub_v1.PublisherClient(transport=transport)
project_path = f"projects/{project}"
for topic in publisher.list_topics(request={"project": project_path}):
  print(topic)

This site supports webmentions. Send me a mention via this form.