seal
Blog

Turn on your cloud's TPM

A copied cloud credential works from anywhere. With your machine's TPM on, Seal's proofs only work from that machine. Here's how to turn it on.

Your app proves who it is to Seal with its cloud identity: an AWS role, an Azure managed identity, a Google service account. That proof comes from credentials, and credentials can be copied. Someone who reads them off your machine can prove to be your app from anywhere, until they expire.

A TPM closes that gap. It's a chip, real or virtual, that holds a key no one can copy off the machine, root included. With it, each proof says both "this is my role" and "this request comes from this machine". A copied credential then works nowhere else.

The Seal SDK finds the TPM on its own. You don't change any code. If it can't use the TPM, it says why and links to the section below that fixes it.

Seal uses the TPM on AWS first. Azure and Google Cloud are next, and their sections are here so you can turn it on now.

AWS

AWS calls it NitroTPM. It's off unless the AMI turns it on:

Check an AMI:

aws ec2 describe-images --image-ids ami-0123456789abcdef0 \
  --query 'Images[].[BootMode,TpmSupport]' --output text

You need uefi and v2.0. None means it's off.

Turn it on for an AMI

You can't change an existing AMI. Register a new one from its snapshot, with UEFI boot and TPM support. If the AMI isn't yours (Amazon Linux, Ubuntu), copy it into your account first, so the snapshot is yours:

aws ec2 copy-image --source-image-id ami-0123456789abcdef0 \
  --source-region us-east-1 --name my-app-base
aws ec2 describe-images --image-ids ami-<copy> \
  --query 'Images[].BlockDeviceMappings[0].Ebs.SnapshotId' --output text

aws ec2 register-image --name my-app-tpm \
  --architecture x86_64 --virtualization-type hvm --ena-support \
  --root-device-name /dev/xvda \
  --boot-mode uefi --tpm-support v2.0 \
  --block-device-mappings 'DeviceName=/dev/xvda,Ebs={SnapshotId=snap-<id>,VolumeType=gp3}'

If you build images with Packer, set it on the amazon-ebs builder:

boot_mode   = "uefi"
tpm_support = "v2.0"

With Terraform, set it on aws_ami:

boot_mode   = "uefi"
tpm_support = "v2.0"

Where it runs

Azure

Azure's TPM comes with Trusted Launch.

To set it yourself with the CLI:

az vm create ... --security-type TrustedLaunch \
  --enable-vtpm true --enable-secure-boot true

With Terraform, on azurerm_linux_virtual_machine:

vtpm_enabled        = true
secure_boot_enabled = true

AKS

AKS node pools have it off unless you ask for it:

az aks nodepool add ... --enable-vtpm --enable-secure-boot

Pods on AKS should still prove who they are with a Kubernetes service account token.

Google Cloud

Google's TPM comes with Shielded VM. It's on by default for Google's public images. Check a VM:

gcloud compute instances describe my-vm \
  --format='value(shieldedInstanceConfig)'

You need enableVtpm=True. To create a VM with it:

gcloud compute instances create my-vm ... \
  --shielded-vtpm --shielded-secure-boot --shielded-integrity-monitoring

Let your app open the TPM

On a Linux VM the TPM is a device file, and your app's user needs read and write access to it. On AWS the SDK opens /dev/tpm0 itself, not the shared /dev/tpmrm0, because AWS's attestation command only goes through the device itself. So:

Containers and Kubernetes

Check that it works

The console's Apps page shows, for every app, whether its last connection used the TPM. If it didn't, the page says why and links back here.

Once every machine running an app connects with its TPM, turn on Require cloud TPM for that app. From then on, a proof without one is refused.