Prerequisites
- Turnkey account with API credentials.
- Understanding of attestation verification.
Integration overview
Attestation verification
Every parse response carries an AWS Nitro attestation document. To trust the parsed output you must:- Verify the attestation’s certificate chain back to the AWS Nitro root CA.
- Check the document’s PCR values against an allowlist you control.
- Verify the parser’s ECDSA signature over the parsed payload using the public key from the attestation.
PCR allowlist values
The PCRs are determined by the qos enclave runtime version Turnkey has deployed (currently TVCv2026.2.6, qos commit d866f2c6cbc58cc08c24eab4828f0824ad16a226). You can reproduce them locally from that qos rev — never trust an externally supplied PCR file without verifying it.
Generating PCRs from source
Thescripts/extract-nitro-pcrs.sh tool in this repo clones tkhq/qos at the deployment rev declared in src/Cargo.toml, builds qos_enclave, and extracts /nitro.pcrs:
src/Cargo.toml:
rev = "..." on each qos_* crate in the same file, which pins the qos library code that parser_app compiles against and does not affect PCRs. To audit a prospective deployment bump before updating the marker, pass --rev explicitly:
Prerequisites
- Docker 26+
- Git and GNU Make
- ~8 GB of free RAM and ~15 GB of free disk (StageX base images, a clean cargo compile, and the qos OCI output).
Options
| Flag | Default | Purpose |
|---|---|---|
--cargo-toml PATH | src/Cargo.toml | Source of the deployment-rev marker. |
--qos-dir PATH | mktemp -d | qos checkout location. The default is ephemeral and removed on exit; pass an explicit path to keep cached cargo and docker layers between runs. The script verifies the directory’s origin URL matches tkhq/qos before mutating it. |
--output PATH | out/nitro.pcrs | Where to write the PCRs file. |
--skopeo-image REF | digest-pinned quay.io/skopeo/stable | Container image used to convert the OCI layout to a docker-loadable tar (no host skopeo install needed). |
--rev REV | (from Cargo.toml marker) | Override the rev. |
How it works
- Read the rev — the script extracts a 40-character hex from the
# qos-deployment-rev = ...line insrc/Cargo.toml. If--revis supplied it bypasses this step. - Check out qos — clones
tkhq/qosinto the work dir and checks out the rev. If--qos-dirpoints at an existing clone whoseoriginis the upstreamtkhq/qosURL and whoseHEADalready matches the rev, the script reuses it; if the origin differs the script refuses to touch the directory. - Build
qos_enclave— runsmake out/qos_enclave/index.jsoninside the qos checkout. This is qos’s deterministic StageX-based build: it produces anitro.eifandnitro.pcrsviaeif_buildand bakes them into the OCI image. The full pipeline lives in qos’sqos_enclaveContainerfile. - Extract
nitro.pcrs— runs the pinned skopeo image (as your host user, so the staging files clean up) to convert the OCI directory output to a docker-archive tar, loads it under a unique per-run tag, copies/nitro.pcrsout of a freshly created container, and removes both the container and the image on exit.
What the PCRs measure
PCR0 and PCR1 measure the Nitro EIF and kernel, and PCR2 measures the boot ramdisk that contains qos’sinit binary. The parser_app binary is loaded into qos at runtime over vsock and is not part of these PCR measurements — its integrity is established separately via the qos manifest, which is covered at Level 3 attestation. PCR3 in a live attestation measures the AWS IAM role and is intentionally absent from nitro.pcrs.
Cross-checking against a live prod attestation
You can confirm the locally built PCRs match what the production enclave actually serves by fetching a fresh attestation through visualsign-turnkeyclient.Reproducibility
The qos build is deterministic. Running the script twice should produce byte-identicalnitro.pcrs files. Pass --qos-dir to the second run so the cargo and docker layer caches are reused — the second build should be a no-op: