Skip to content

Instantly share code, notes, and snippets.

@salrashid123
Last active March 7, 2025 14:35
Show Gist options
  • Save salrashid123/79de64a220aa3cecf04e4d757da35bc4 to your computer and use it in GitHub Desktop.
Save salrashid123/79de64a220aa3cecf04e4d757da35bc4 to your computer and use it in GitHub Desktop.
GCP x509 Workload Federation in pyhton using mTLS and TPM based private key

GCP x509 Workload Federation in python using TPM based authentication and openssl

assume you have a workload federation trusted cert and PEM key (workload3.crt, workload3.key), the following will embed the key into the tpm. Workload federation will use the tpm-based key for mtls.

you can ofcourse create the key inside the tpm or securely import it. those options are described here

Setup TPM tools

apt-get update
apt -y install   autoconf-archive   libcmocka0   libcmocka-dev   procps   iproute2   build-essential   git   pkg-config   gcc   libtool   automake   libssl-dev   uthash-dev   autoconf   doxygen  libcurl4-openssl-dev dbus-x11 libglib2.0-dev libjson-c-dev acl swtpm swtpm-tools python3-pip python3-requests python3-flask

cd
git clone https://github.com/tpm2-software/tpm2-tss.git
  cd tpm2-tss
  ./bootstrap
  ./configure --with-udevrulesdir=/etc/udev/rules.d
  make -j$(nproc)
  make install
  udevadm control --reload-rules && sudo udevadm trigger
  ldconfig

cd
git clone https://github.com/tpm2-software/tpm2-tools.git
  cd tpm2-tools
  ./bootstrap
  ./configure
  make install

cd
git clone https://github.com/tpm2-software/tpm2-openssl.git
cd tpm2-openssl
  ./bootstrap
  ./configure
  make install

Import the key

printf '\x00\x00' > /tmp/unique.dat
tpm2_createprimary -C o -G ecc  -g sha256 \
    -c primary.ctx \
    -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt" -u /tmp/unique.dat

tpm2_import -C primary.ctx -G ecc256:ecdsa -i workload3.key -u key.pub -r key.priv

tpm2_encodeobject -C primary.ctx -u key.pub -r key.priv -o workload3_tpm.key

Configure ADC

$ cat cert_config.json 
{
    "cert_configs": {
      "workload": {
        "cert_path": "/root/python_tls/workload3.crt",
        "key_path": "/root/python_tls/workload3_tpm.key"
      }
    }
  }

$ cat sts-creds-mtls.json 
    {
      "universe_domain": "googleapis.com",
      "type": "external_account",
      "audience": "//iam.googleapis.com/projects/995081019036/locations/global/workloadIdentityPools/cert-pool-1/providers/cert-provider-1",
      "subject_token_type": "urn:ietf:params:oauth:token-type:mtls",
      "token_url": "https://sts.mtls.googleapis.com/v1/token",
      "credential_source": {
        "certificate": {
          "certificate_config_location": "/root/python_tls/cert_config.json"
        }
      },
      "token_info_url": "https://sts.mtls.googleapis.com/v1/introspect"
    }

Configure openssl

create openssl.cnf:

$ cat openssl.cnf
openssl_conf = openssl_init

[openssl_init]
providers = provider_sect

[provider_sect]
default = default_sect
tpm2 = tpm2_sect

[default_sect]
activate = 1

[tpm2_sect]
activate = 1
export OPENSSL_CONF=`pwd`/openssl.cnf

$ openssl list --providers 
    Providers:
      default
        name: OpenSSL Default Provider
        version: 3.0.15
        status: active
      tpm2
        name: TPM 2.0 Provider
        version: 1.2.0-25-g87082a3
        status: active

Print the TPM based key details

cat  workload3_tpm.key 

-----BEGIN TSS2 PRIVATE KEY-----
MIIBEgYGZ4EFCgEDoAMBAf8CBEAAAAEEWgBYACMACwAEAEAAAAAQABgACwADABAA
IMzaHMjj+kYAU8ipJA5bgBHQgrxvP7Z1/izmUfvxYsrKACD4QFAH3thp8NOq+vba
kow82CcbRp5Tle+159cd0k3lrwSBoACeACAEwQLyGtSn/aqweqAM5mhMjRy6SbDE
kACG6pT52zOG7AAQW/YAj3eHwPNH9ny+bz9A4I8h9boqf5bIdzZ+wJJGBGSb3Edj
n1HiFZdzkDghmLLscoKZ1XrBU9FBKinNJOacprgJYhj6/lYUfPxpwTOgVCa7CUSi
yc5LN73ncZtSRVh+nuSJLI6DTQjO7IhY0DA0hOvprTZkRduiaa0=
-----END TSS2 PRIVATE KEY-----

$ openssl ec -provider tpm2  -provider default -in workload3_tpm.key  --text
   read EC key
   Private-Key: (EC P-256, TPM 2.0)
   Parent: 0x40000001
   pub:
       04:cc:da:1c:c8:e3:fa:46:00:53:c8:a9:24:0e:5b:
       80:11:d0:82:bc:6f:3f:b6:75:fe:2c:e6:51:fb:f1:
       62:ca:ca:f8:40:50:07:de:d8:69:f0:d3:aa:fa:f6:
       da:92:8c:3c:d8:27:1b:46:9e:53:95:ef:b5:e7:d7:
       1d:d2:4d:e5:af
   ASN1 OID: prime256v1
   Object Attributes:
     userWithAuth
     sign / encrypt
   writing EC key
   unable to write EC key

Create a gcp storage client

  • client.py
from google.cloud import storage

storage_client = storage.Client('your-project')
bucket_name = "your-bucket"
file_name = "foo.txt"

bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(file_name)
file_content = blob.download_as_string()
print(file_content)

Finally,

export GOOGLE_API_USE_CLIENT_CERTIFICATE=true
export GOOGLE_API_USE_MTLS_ENDPOINT=always
export GOOGLE_APPLICATION_CREDENTIALS=`pwd`/sts-creds-mtls.json

export OPENSSL_CONF=`pwd`/openssl.cnf

pip3 install pyOpenSSL google-cloud-storage

python3 client.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment