Skip to content

jessesomerville/tpm_bound_sa_key

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TPM Bound GCP Service Account Credentials

Credit to salrashid123!

This repo demonstrates how you can embed a service account's private key into a Shielded VMs vTPM then use it to sign JWTs that can be used to authenticate to Google Cloud APIs. Assuming that the key pair only exists within the TPM (barring exfiltration), valid JWTs can only be signed while on the Compute VM effectively "binding" the credentials.

NOTE: The content in this repo is very experimental and for demonstration purposes only. You should take proper precautions before using this method in an active environment.

Create Compute Shielded VM

Create a VM with a Shielded vTPM

gcloud compute instances create example-vtpm-compute-vm \
  --zone=us-central1-a --machine-type=n1-standard-1 \
  --subnet=default --network-tier=PREMIUM --no-service-account \
  --no-scopes --image=ubuntu-2010-groovy-v20210130 \
  --image-project=ubuntu-os-cloud --no-shielded-secure-boot \
  --shielded-vtpm --shielded-integrity-monitoring

Remote into the instance

gcloud compute ssh example-vtpm-compute-vm --zone=us-central1-a

Install Dependencies

NOTE: The following commands assume you are running as root sudo su -

Verify that the TPM is correctly recognized

dmesg | grep tpm

Install tpm2-tss dependencies

apt 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 \
  libjson-c-dev \
  libcjson1 \
  libcjson-dev \
  libini-config-dev \
  libcurl4-openssl-dev

Install tpm2-tss

git clone --depth=1 https://github.com/tpm2-software/tpm2-tss.git
cd tmp2-tss
./bootstrap
./configure
make -j$(nproc)
make install
udevadm control --reload-rules && udevadm trigger
ldconfig

Install tpm2-tss-engine

git clone --depth=1 https://github.com/tpm2-software/tpm2-tss-engine.git
cd tpm2-tss-engine
./bootstrap
./configure
make -j$(nproc)
make install
ldconfig

Install tpm2-tools

apt install tpm2-tools

Generate the key for delivery to the TPM

The script in seal_sa_jwt/main.go generates a 2048-bit RSA private key and associates the key with a user-supplied service account. It then fetches a target VM's Endorsement Key and seals the encrypted blob.

Alternatively, a user can implement this flow with the following steps on a Shielded Compute Instance. The repository scripts assume that the instance which uploads the private key and signs it with a Compute VM's endorsement key is distinct from the instance which actually unseals the key and uses it to authenticate to Google APIs.

This method generates the primary key in the TPM; however, you could also download a P12 key file for a service account. The method shown below is recommended to reduce exposure of the private key.

Create a primary object under the TPM_RH_ENDORSEMENT hierarchy and save it to primary.ctx

tpm2_createprimary -C e -g sha256 -G rsa -c primary.ctx

Generate the private key as a child object of the primary context that was just created

tpm2_create -G rsa -u key.pub -r key.priv -C primary.ctx

Load the private and public keys into the TPM and save the resulting context object to key.ctx

tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx

Make the key persistent in the TPM at the handle 0x81010002. This handle value is arbitrary. If leave it blank and the key will be persisted at the first available handle.

tpm2_evictcontrol -C o -c key.ctx 0x81010002

Generate the x509 cert and upload it to the service account

Generate the cert and write it to public.crt

openssl req -new -x509 -engine tpm2tss \
  -key 0x81010002 -keyform engine -out public.crt \
  -subj "/CN=example.com"

Upload the certificate to the service account

gcloud iam service-accounts keys upload public.crt \
  --iam-account=example-sa@project_id.iam.gserviceaccount.com

Confirm the key was successfully uploaded

gcloud iam service-accounts keys list \
  --iam-account=example-sa@project_id.iam.gserviceaccount.com

Create and Sign a JWT to Authenticate to Google APIs

Service account JWT format

You can use sign_sa_jwt included in this repo to accomplish this.

NOTE: You will probably want to update the claim values to for your use case

cd sign_sa_jwt
GOOS=linux GOARCH=amd64 go build -v main.go

# Move the binary to the VM
gcloud compute scp ./main example-vtpm-compute-vm:~ --zone=us-central1-a

On the VM, run the main binary and a JWT will be printed

# ./main
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiAiamVzc2UtdHBtLX...

Confirm everything is working by requesting an access token

curl https://oauth2.googleapis.com/token \
  -d "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=$SA_JWT"

About

Example showing how you can generate a GCP service account private key within a Shielded VMs vTPM

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages