Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.teesql.com/llms.txt

Use this file to discover all available pages before exploring further.

Remote attestation is the cryptographic proof that the program you are talking to is the program you expect, running on hardware you trust. Every TeeSQL connection completes one before any SQL flows. The mechanism is RA-TLS: the database’s TLS certificate is self-signed and embeds an Intel TDX attestation quote in a custom X.509 extension. Your client extracts the quote, verifies it against Intel’s signing chain, and only then unblocks the underlying Postgres driver.

Prerequisites

The attestation flow

1

The CVM mints an RA-TLS certificate at boot

On startup the TeeSQL sidecar calls GetTlsKey(usage_ra_tls=true, usage_server_auth=true) on the dstack guest agent over /var/run/dstack.sock. The guest agent:
  1. Generates a fresh keypair
  2. Asks the Intel TDX module for an attestation quote with REPORTDATA = SHA-256(public key bytes)
  3. Builds a self-signed X.509 leaf certificate whose Subject Public Key Info matches that public key
  4. Embeds the attestation in a custom certificate extension (Phala RA-TLS OID 1.3.6.1.4.1.62397.1.8 for the current SCALE-encoded VersionedAttestation; legacy raw-quote bytes also published at OID 1.3.6.1.4.1.62397.1.1 for backward compatibility)
  5. Returns the leaf, intermediates, and the dstack KMS root certificate as a PEM chain
Binding the public key into REPORTDATA is what prevents a man-in-the-middle: any substitute certificate would have a different public key, and the quote would no longer match.
2

The sidecar serves the cert on :5433

The sidecar parses the chain and private key into rustls types, configures a TLS acceptor that requires client certificates by default in production (TEESQL_REQUIRE_CLIENT_ATTESTATION=true), and listens on 0.0.0.0:5433. Plain Postgres on 127.0.0.1:5432 is reachable only from inside the CVM.The same RA-TLS pattern is also exposed over HTTP at :8080GET /attestation returns the live attestation report described below.
3

The client connects and extracts the quote

During the TLS handshake the client receives the server’s self-signed leaf and chain. A standard CA-based check would reject the leaf — RA-TLS clients deliberately disable the default chain check (e.g. node-postgres rejectUnauthorized: false) and switch to attestation-based trust:
  1. Take the DER bytes of the leaf certificate
  2. Walk the X.509 extensions for OID 1.3.6.1.4.1.62397.1.8 (current SCALE-encoded attestation), falling back to OID 1.3.6.1.4.1.62397.1.1 (legacy raw quote) for backward compatibility
  3. Strip the DER OCTET STRING wrapper and decode if needed
  4. The remaining bytes are the raw TDX quote
4

The client verifies the quote

Verification has two paths, and TeeSQL client libraries implement both:Intel Trust Authority (hosted, REST). The client POSTs the base64-encoded quote to https://api.trustauthority.intel.com/appraisal/v2/attest with an API key, receives a signed JWT, fetches Intel’s JWKS at the URL named in the JWT header (jku), and verifies the JWT signature with PS384/RS256. Used by IntelApiVerifier in prisma-ra-tls, psycopg-ra-tls, and sqlx-ra-tls.Local DCAP. The client uses dcap-qvl (a Rust quote-verification library) with Intel’s public PCS or a self-hosted PCCS for platform collateral. No external API call required. Used by DcapVerifier in sqlx-ra-tls (default).Either path produces the same trust decision. Pick ITA when you want a managed verifier and don’t mind a third-party dependency on the connection path; pick DCAP when you want self-contained verification or air-gapped operation.
5

The client checks specific claims

The verifier returns a structured result; the client library then enforces:
CheckDefaultWhat it means
tdx_is_debuggable is falserequiredReject debug TDs — they have no confidentiality
tcb_status is acceptablerequiredAccept only OK, SWHardeningNeeded, ConfigurationNeeded, ConfigurationAndSWHardeningNeeded
tdx_mrtd is in the configured allowlistoptionalPin the expected CVM image; mismatch indicates an image swap
tdx_rtmr0tdx_rtmr3 available for inspectionalways returnedLower-level measurement registers — see below
A failure at any step is a hard refusal: the client library does not pass any bytes to the underlying Postgres driver. From the application’s point of view, a verification failure surfaces as an ordinary connection error.
6

The result is cached, then bytes flow

On success the verification result is cached (default 1 hour in prisma-ra-tls; configurable via cacheTtlMs) so subsequent connections in the same process don’t hit Intel Trust Authority again. The client library then bridges the now-attested TLS channel to the application’s Postgres driver, and SQL can flow normally.

What is in an attestation report

The sidecar’s GET /attestation endpoint returns a JSON document with the following fields:
FieldTypeSource
app_idhex stringdstack application identity
compose_hashhex stringSHA-256 of the normalized docker-compose file
instance_idstringUnique identifier for this CVM instance
quotehex stringRaw TDX attestation quote bytes
tcb_info.mrtdhex stringInitial CVM image measurement
tcb_info.rtmr0hex stringPlatform configuration
tcb_info.rtmr1hex stringGuest kernel image
tcb_info.rtmr2hex stringBoot parameters and initramfs
tcb_info.rtmr3hex stringApplication layer (compose + runtime)
postgres_state.wal_lsnstringCurrent WAL log sequence number
postgres_state.controldata_hashhex stringSHA-256 of pg_controldata output
postgres_state.pg_versionstringServer version string
timestampunix secondsWhen the report was produced
The quote itself binds the request to the database’s current state: REPORTDATA for /attestation is SHA-256(wal_lsn || controldata_hash || timestamp). So the same endpoint produces a fresh quote on every call, and the quote attests not just the CVM identity but a snapshot of Postgres’s live state at that moment. For the TLS handshake quote (different from /attestation), REPORTDATA is SHA-256(public key), which binds the TLS session to the attested identity but does not commit to Postgres state.

Where expected measurements come from

To pin a measurement (allowedMrTd, etc.), you need a known-good value to compare against. There are three production-relevant sources:
  • MRTD is determined by the CVM image. When the operator cuts a new image, they republish the expected MRTD; clients update their allowlist together with their deployment.
  • RTMR1 and RTMR2 are determined by the guest kernel and boot parameters. They change when the kernel image or boot configuration changes.
  • RTMR3 is determined by the application layer — most importantly the compose_hash. It changes whenever the compose definition changes, which in practice means whenever the sidecar or Postgres image is upgraded.
For the hands-on procedure — how to read the values from a running cluster, how to pin them in client code, what to do on rotation — see Verify attestation.
Last modified on May 1, 2026