Enroll a collector¶
A collector runs on a confidential host, reports signed attestation evidence and a local host scan on a schedule, and only ever makes outbound HTTPS connections. Use it for hosts you run yourself (bare metal or VMs) and for continuous evidence that does not depend on a person running a scan.
Who: whoever administers the hosts. Installing the service needs root.
Requirements¶
- Linux with systemd. The service is a systemd unit, and
collector scanruns only on Linux. - Python 3.10 or later.
- Outbound HTTPS to your console origin; see Network.
- The evidence devices and tools for your platform; see Devices and tools.
1. Create a fleet¶
In the console, open Assets & environments › Environments › Hardware fleets and create a fleet for the platform:
- AMD SEV-SNP
- Intel TDX
- Intel SGX
- Arm CCA
- AWS Nitro Enclaves
- IBM Secure Execution
Creating a fleet, generating enrollment tokens, editing its policy and revoking collectors need an administrator. Other roles see the policy read-only.
The fleet shows a one-time enrollment token and the commands for that platform. The token works once and expires after 1 hour; untrust keeps only its hash. Choose New token to issue another, for example for each additional host. The fleet's policy holds the measurements and minimum firmware (TCB) levels its hosts must report; to compute the measurements, see Compute expected measurements.
2. Install the collector¶
Install the untrust wheel with the collector extra (see Install the CLI).
For production, install it into a root-owned virtual environment:
sudo python3 -m venv /opt/untrust
sudo /opt/untrust/bin/pip install "./untrust-<version>-py3-none-any.whl[collector]"
The service refuses to start from an executable that a non-root user could replace, so a
pip install --user or a virtual environment in a home directory is rejected.
Evidence tools such as nvattest (NVIDIA GPUs) and tpm2-tools (vTPM-based hosts) must be
installed from your distribution or vendor packages, root-owned, in /usr/bin or
/usr/local/bin. A tool that is not root-owned, or that sits in a writable directory, is
refused and that evidence is reported as skipped.
3. Enroll the host¶
untrust collector enroll --origin https://app.untrustsecurity.com --token <enrollment-token>
The CLI also reads the token from UNTRUST_ENROLL, which keeps it out of your shell
history.
The collector creates its own Ed25519 signing key on the host and registers the public key
with the fleet. The private key never leaves the host. Its state lives in
~/.untrust-collector by default, or in --state-dir or UNTRUST_COLLECTOR_STATE, in a
directory only its owner can read. --ca-file sets a CA bundle for a private origin.
4. Send one report¶
untrust collector run --once
This sends one signed report and exits. Check that the host appears in the fleet. Add
--no-scan to send attestation only, without the local host checks.
5. Keep it reporting¶
sudo untrust collector install-service
Enroll before you install the service. This installs and starts a systemd service,
untrust-collector, that reports every 15 minutes by default
(--interval, 60 to 86400 seconds). The service runs sandboxed: no capabilities, no new
privileges, a read-only system except its state directory and the TEE report interface,
access only to the evidence devices present at install time, and network access limited to
IP and vsock. If it stops, systemd restarts it after 30 seconds. Re-run install-service
after adding or removing an evidence device.
install-service takes --interval, --no-scan, --manifest, --collect-root-logins,
--state-dir and --ca-file, and writes them into the service definition. It refuses a
path that contains whitespace, quotes or %.
Devices and tools¶
The service can open only the evidence devices present when you ran install-service:
| Device | Used for |
|---|---|
/dev/sev-guest |
AMD SEV-SNP |
/dev/tdx_guest |
Intel TDX |
/dev/tpmrm0 |
vTPM or TPM |
/dev/sgx_enclave, /dev/sgx_provision |
Intel SGX |
/dev/uv |
IBM Secure Execution |
| NVIDIA GPU devices, and NVSwitch devices on HGX systems | NVIDIA GPUs |
/sys/kernel/config/tsm/report (configfs-tsm) |
SEV-SNP, TDX and Arm CCA reports |
Tools it runs:
| Tool | Needed for |
|---|---|
tpm2-tools |
Azure confidential VMs and other vTPM-based hosts, for example apt install tpm2-tools |
nvattest |
NVIDIA GPUs |
snphost |
Optional, for check CCHOST-02 on SEV-SNP hosts |
Tools are looked up in /usr/bin, then /usr/local/bin, or in the directories listed in
UNTRUST_COLLECTOR_TOOL_DIRS.
Network¶
The collector makes outbound HTTPS connections only, to your console origin. It refuses
plain http:// and refuses redirects, and each request times out after 30 seconds. It
identifies itself with the user agent untrust-collector/<version>.
| Connection | Purpose |
|---|---|
Console origin, /v1/collector-enroll |
Enrollment, once. |
| Console origin, collector challenge | A one-time challenge for each report, and a signed check-in every 60 seconds by default (30 to 600). The check-in is how a console re-attest request reaches the host. |
| Console origin, collector ingest | Signed reports. |
169.254.169.254 |
Azure confidential VMs only: the instance metadata service, for the AMD certificate. |
| vsock, port 5005 by default | Nitro Enclaves only: the agent inside the enclave. |
Allow outbound HTTPS to your console origin in your firewall or egress policy. Set
--ca-file if a private CA signs that origin.
Nitro Enclaves¶
On a Nitro Enclaves parent, run the agent inside the enclave and point the parent's collector at it:
# inside the enclave
untrust collector nitro-agent --port 5005
# on the parent instance
export UNTRUST_NITRO_ENCLAVE_CID=<enclave-cid>
untrust collector run --once
Optional inputs¶
| Option | Adds |
|---|---|
--manifest boot-inputs.json |
Declares what the workload loads at boot ("schema": "untrust.boot-inputs/v1"), adding checks BOOT-IN-01 (the destination is root-owned, not writable or executable by others, not a symlink) and BOOT-IN-02 (the source uses an authenticated transport). |
--collect-root-logins |
Reports successful root SSH logins (time, method, source address and key fingerprint, no command content) for root-login detection. |
UNTRUST_COLLECTOR_TPM_QUOTE=1 |
Adds a TPM 2.0 quote to fleet evidence on bare-metal SEV-SNP, TDX and SGX hosts. |
A one-off scan without enrolling¶
untrust collector scan --output host-report.json
Runs the host checks once on this machine and prints the result. It needs no enrollment, opens no listener and uploads nothing, so it suits air-gapped hosts. Linux only. Each check runs a fixed, read-only command compiled into untrust. If you import this report into the console, it is labelled as an uploaded host scan, not fleet evidence, and it never feeds a verdict history, drift baseline or release decision.
What the service does with a report¶
Each upload is signed by the host's enrolled key. The service checks that signature, then verifies the hardware evidence inside it against the vendor's trust roots and certificate revocation lists, and compares measurements and firmware levels with the fleet policy. The results appear under Attested TEEs and Platform & TCB. The fleet checks are listed in the check reference.
- A collector that has not reported for 1 hour (four missed 15-minute runs) becomes stale; its last result is never shown as current.
- Evidence that fails verification is shown as unverified, never as trusted.
- A fleet can require an administrator to approve each new host identity before its evidence counts. A quarantined host never receives a key through a release decision.
Re-attest a host¶
To get fresh evidence without waiting for the next scheduled run, choose Re-attest now on the host under Platform & TCB (analyst or administrator). The host reports at its next check-in, within about a minute by default.
Revoke a collector¶
If a host is retired, rebuilt or compromised, revoke its collector: open
Assets & environments › Environments › Hardware fleets, select the fleet and the
collector, and choose Revoke (administrator). The collector's key stops working on
its next upload, and the change is recorded in the audit log as collector.revoked. To add the
host again, enroll it with a new token.