Автор: Ахилес Айт Мессауд, PhD, инженер по прикладному программному обеспечению, работающий в iExec.

Введение

Часть 1 этой серии заложила основу цепочки доверия Nox: проверку во время загрузки, которая не позволяет Confidential Virtual Machine (CVM) получать какие-либо секреты, если она не загрузила известный образ операционной системы и известный стек приложений на аттестованном аппаратном обеспечении Intel TDX. Однако это гарантия применяется внутренне платформой во время загрузки; сама по себе она не дает конечному пользователю или внешнему аудитору никакого прямого способа проверить в более поздний момент, что выполняющийся сервис Nox по-прежнему является ровно тем рабочим набором (workload), который был аттестован.

Этот документ является второй частью серии и закрывает этот пробел: runtime attestation — возможность любой стороне в любой момент жизненного цикла CVM проверить, что заданный компонент Nox действительно выполняет ожидаемый код внутри подлинного Intel TDX Trust Domain (TD). Мы описываем (i) как запрашивается свежая TDX-cитата у работающей CVM и что она содержит; (ii) какие компоненты развернуты вокруг флота TDX, чтобы обнаруживать запущенные CVM и предоставлять их цитаты; (iii) сквозную последовательность и интерфейс, видимый пользователю, где отображаются эти доказательства; и (iv) пошаговый протокол, по которому цитата верифицируется — от проверки подписи до docker-compose, который фактически выполнен.

Он напрямую строится на фундаменте TEE, описанном в Части 1, и намеренно ограничивает область только runtime attestation, представляемой через Runtime Attestation UI. Остальные звенья цепочки доверия — привязка к исходному коду и on-chain управление авторизованными измерениями — рассматриваются в более поздних частях.

Оставшаяся часть документа организована следующим образом. В разделе «Фон» напомним, что такое runtime attestation, как устроена TDX quote и какие три поля quote использует Nox. В «Архитектурное развертывание» описываем компоненты, развернутые вокруг TDX-серверов, и то, какие данные они обменивают. В «Справочная среда» фиксируем версии компонентов, на которых основана статья. В «Диаграмме последовательностей» прослеживаем сквозной поток, с помощью которого UI обнаруживает запущенные CVM и аттестует их. В «Презентации пользовательского интерфейса» представляем интерфейс и три уровня аттестации. В «Шаги аттестации компонента Nox» детализируем протокол верификации, применяемый к одной CVM. Наконец, в «Дальнейшая работа» описываем запланированные улучшения: происхождение образа, challenges от пользователя и дополнительные quote-верификаторы.

Фон

В этом разделе мы рассмотрим концепции, на которые опирается документ: что такое runtime attestation, как устроена TDX quote и какие три поля цитаты использует Nox — report_data, RTMRs и связанные с ними event logs.

Runtime Attestation

Runtime attestation — это механизм, позволяющий любому удаленному участнику проверять по требованию и в любой момент жизненного цикла CVM, что компонент Nox действительно работает внутри реального Intel TDX Trust Domain (TD) с ожидаемым кодом и конфигурацией. В то время как аттестация на момент загрузки (см. Часть 1) выстраивает цепочку доверия от аппаратуры до dstack-OS, runtime attestation раскрывает это доверие внешним верификаторам через простой протокол запрос-ответ по challenge.

TDX quote

TDX-quote — это криптографически подписанная структура, создаваемая Quoting Enclave платформы. Она несет доказательства, необходимые верификатору для доверия TD, и подписывается ключом аттестации, предоставленным Intel, так что любой может валидировать её подлинность, пройдя по цепочке сертификатов обратно к корню доверия Intel. Три поля, на которые полагается Nox для runtime attestation (report_data, RTMRs и их связанные event logs), описаны ниже.

report_data

report_data — это поле размером 64 байта, содержимое которого целиком выбирается нагрузкой. TDX копирует его дословно в подписанную quote, что позволяет приложению привязывать произвольные данные к аппаратной аттестации. Частые применения:

  • Свежесть / запрос-ответ: встраивание nonce, предоставленного верификатором, как делает Runtime Attestation UI, чтобы доказать, что цитата сгенерирована по требованию.

  • Привязка идентичности: встраивание хэша публичного ключа или TLS-сертификата (основа RA-TLS, см. Части 1), чтобы защищенный канал был доказуемо завершён внутри TD.

  • Другие доказательства, например адреса кошельков блокчейна или хэши состояния приложения.

В Nox UI генерирует случайный challenge и ожидает найти ровно это значение в report_data цитаты.

RTMRs

Регистры измерений времени выполнения (RTMR) — это эквивалент TPM PCR в TDX: регистры только для добавления (append-only), которые нельзя записать напрямую; можно только расширять через цепочку хэшей. TD раскрывает четыре таких регистра, и dstack назначает каждому чётко определенную роль:

  • RTMR0: виртуальная среда / прошивка.

  • RTMR1: ядро Linux.

  • RTMR2: командная строка ядра и initrd.

  • RTMR3: измерения, зависящие от приложения: app-id, os_image_hash, compose-hash, instance-id и key-provider.

Начальное содержимое памяти и конфигурация TD фиксируются отдельно в MRTD. Во время верификации RTMR0–RTMR2 (вместе с MRTD) аттестуют целостность цепочки загрузки, в то время как RTMR3 аттестует, что ожидаемый код приложения и конфигурация запущены. В Nox мы фокусируемся на RTMR3, поскольку он связывает quote с конкретным компонентом Nox и его docker-compose.

журналы событий

Значение RTMR — это непрозрачный хэш: он подтверждает, были ли включены ожидаемые измерения, но не то, какими они были. event log — это читаемая человеком запись отдельных событий измерений, которые были расширены в RTMR (на практике — RTMR3). Каждое событие — это измерение «ключ-значение», например app-id, compose-hash, instance-id или key-provider, и каждое событие включается в регистр по формуле расширения:

RTMR3_new = SHA384(RTMR3_old || SHA384(event_log))

Верификатор воспроизводит event log по этой формуле и сравнивает пересчитанный регистр со значением rt_mr3 внутри подписанной цитаты. Если они совпадают, отдельные значения event (в частности os_image_hash и compose_hash) можно считать достоверными представлениями образа ОС и docker-compose, которые реально были выполнены CVM.

Архитектурное развертывание

В этом разделе описаны компоненты, развернутые вокруг TDX-серверов, чтобы сделать возможной работу Runtime Attestation UI, и показана форма данных, которыми они обмениваются.

Чтобы Runtime Attestation UI работал, пять основных компонентов взаимодействуют:

  • Портал Runtime Attestation UI: Интерфейс, доступный пользователю для визуализации процесса Runtime Attestation. Он уже развернут на стороне iExec по адресу https://trust.noxprotocol.io/, но также может быть заново собран и развернут на персональных компьютерах с использованием своего исходного кода (https://github.com/iExec-Nox/nox-attestation-portal). UI запрашивает nox-cvms-exporter-aggregator чтобы получить список активных CVM, и для каждой из них — её только что полученную цитату и docker-compose. Сам агрегатор обращается к каждому CVM dstack-quote-service, поэтому UI никогда не взаимодействует с CVM напрямую.

  • nox-cvms-exporter: сервис-хост, который подключается к dstack hypervisor (dstack-vmm), чтобы собрать список активных CVM (их URL dstack-quote-service) на локальной TDX-машине, и отправляет его в nox-cvms-exporter-aggregator.

  • nox-cvms-exporter-aggregator: сервис, развернутый в Azure Kubernetes Service, который агрегирует список активных CVM, полученный от каждого отдельного nox-cvms-exporter. Для каждой перечисленной CVM он затем обращается к CVM dstack-quote-service, чтобы получить её свежую цитату (привязанную к challenge UI) и её docker-compose, и возвращает обогащенный список в портал Runtime Attestation UI.

  • Proof of Cloud Trust Server: сервер iExec для Proof of Cloud (http://github.com/proofofcloud/trust-server) для проверки того, что цитата выдана доверенной TDX-машиной из белого списка и не отозвана. Детали процесса белого списка Proof of Cloud описаны в Части I нашей серии статей.

  • Phala PCCS: локальный кэш Phala для хранения collateral (TCB Infos, сертификатов Intel PCK и списка отзыва сертификатов), чтобы верифицировать цитату.

Справочная среда

В этом разделе мы фиксируем точные версии компонентов, задействованных в Runtime Attestation UI, чтобы поведение, описанное в остальной части статьи, можно было воспроизвести; а по мере развития этих компонентов можно было сравнить результат с известной базовой версией.

Диаграмма последовательностей

В этом разделе мы прослеживаем сквозную последовательность, по которой Runtime Attestation UI обнаруживает запущенные CVM и аттестует их — от открытия портала до отображения результата.

Эта диаграмма описывает, как Runtime Attestation UI обнаруживает Confidential VMs (CVM), работающие в TDX-флоте, и аттестует их.

  1. Открыть портал: Пользователь открывает портал — либо напрямую через экземпляр, размещенный в iExec: https://trust.noxprotocol.io, либо собирает и запускает исходный репозиторий самостоятельно (https://githu b.com/iExec-Nox/nox-attestation-portal )При загрузке UI генерирует один случайный challenge (32 байта), который ожидается привязанным к собранным цитатам.

  2. Запрос на обнаружение: UI вызывает агрегатор GET /cvms endpoint, передавая свой challenge в качестве параметра запроса (?challenge=...). Этот параметр обязателен, поскольку challenge должен быть передан в CVM, чтобы привязать возвращаемые цитаты.

  3. Разветвление на экспортёры: Для каждой TDX-машины из настроенного списка экспортёров агрегатор вызывает GET {base_url}/cvms параллельно. На этом этапе challenge не пересылается; он используется только позже — при получении цитат.

  4. Листинг CVM на месте: Каждый экспортёр запрашивает у себя локальный dstack-vmm (POST /prpc/Status?json), чтобы перечислить ВМ, работающие на этой машине.

  5. Ответ VMM: dstack-vmm возвращает исходный список VM. Экспортёр фильтрует ВМ, чей статус остановлен/удален, и исключает системные CVM kms и dstack-gateway.

  6. Ответ экспортёра: Экспортёр формирует базовый URL для quote-service для каждой CVM и возвращает CVM, сгруппированные по app_id; для каждого экземпляра он переносит { instance_id, url, machine_id }.

  7. Запрос цитаты (обогащение): Агрегатор обогащает каждый экземпляр его свежей цитатой: для каждого экземпляра агрегатор вызывает CVM quote-service GET {url}/quote?data={challenge}, передавая challenge UI так, чтобы возвращаемая цитата была привязана к нему.

  8. Ответ цитаты: quote-service возвращает { quote, event_log }, поскольку UI нужно для проверки подписи сама цитата, а для replay RTMR3 — event log.

  9. Запрос манифеста: Параллельно с запросом цитаты агрегатор вызывает тот же CVM quote-service GET {url}/info, чтобы получить манифест развертывания.

  10. Ответ манифеста: quote-service возвращает полезную нагрузку своего /info; из неё агрегатор извлекает docker-compose манифест (tcb_info.app_compose).

  11. Объединить & ответить: Агрегатор перегруппирует обогащенные экземпляры по app_id и возвращает объединенный список в UI; теперь каждый экземпляр несёт { instance_id, machine_id, quote: { quote, event_log }, app_compose }. Поле url сохраняется внутренним для агрегатора и никогда не раскрывается UI, поэтому браузер не имеет способа напрямую обратиться к CVM. Приведенный ниже JSON-файл демонстрирует пример агрегированной записи, отправляемой nox-cvms-exporter-aggregator в UI аттестации.

{

"app_id": "a1b2c3...",

"name": "nox-component-cvm",

"instances": [

{

"instance_id": "i-0abc123",

"machine_id": "Node 1",

"quote": {

"quote": "0x0400...", # quote TDX (hex)

"event_log": [ ... ] # event_log RTMR3

},

"app_compose": "..." # docker-compose (YAML) манифест

},

{

"instance_id": "i-0def456",

"machine_id": "Node 2",

"quote": {

"quote": "0x0400...",

"event_log": [ ... ]

},

"app_compose": "..."

}

]

}

Проверка & отображение: Для каждой возвращенной CVM UI проверяет аттестацию локально и отображает CVM вместе с результатом. Этот протокол верификации подробно описан в разделе «Шаги аттестации компонента Nox».

Отображение через пользовательский интерфейс

В этом разделе представим Runtime Attestation UI и три уровня аттестации, которые он предоставляет пользователю.

Runtime Attestation UI как отображается в NOX · Цепочка доверия https://trust.noxprotocol.io

На скриншоте выше показан Runtime Attestation UI. После загрузки левая панель перечисляет компоненты Nox, запущенные на тестнет TDX-машинах, каждый с аннотацией своего числа реплик (например, 6 для nox-kms). Интерфейс предлагает три уровня аттестации компонентов Nox:

  1. Полная верификация: После нажатия на кнопку Verify all будут проверены все экземпляры CVM всех компонентов Nox
    .

  2. Верификация на уровне компонента: Этот уровень становится доступным после выбора компонента Nox в левой панели. После нажатия на Verify all будут проверены все экземпляры CVM выбранного компонента Nox независимо от лежащих в основе машин.

  3. Верификация на уровне экземпляра: Этот уровень также становится доступным после выбора компонента Nox в левой панели. После нажатия на Verify будет проверен только конкретный экземпляр выбранного компонента Nox.

Шаги аттестации компонента Nox

В этом разделе подробно описан пошаговый протокол верификации, применяемый к одной CVM компонента Nox, и объясняется, что отображает UI после прохождения каждой проверки.

Рабочий процесс runtime attestation для компонента Nox

Протокол верификации, применяемый к CVM компонента Nox, выполняется следующим образом:

  1. Получите свежую цитату: пользовательский интерфейс генерирует случайный challenge и получает, через агрегатор, свежую цитату, привязанную к этому challenge (см. Диаграмма последовательностей ). Ожидается, что challenge будет встроен в report_data отчета цитаты.

  2. Проверьте подпись цитаты и цепочку сертификатов: подпись цитаты и её цепочка сертификатов вплоть до Intel валидируются DCAP-верификатором. В текущей реализации это выполняется локально в браузере через встроенную Phala dcap-qvl (библиотека верификации quote: githubl ). QVL получает верификационные данные (информацию TCB и цепочку сертификатов, привязанную к корню Intel) из dstack PCCS (Сервис кэширования Provisioning Certificate, размещенный в Phala) и выполняет проверку самостоятельно. Параллельно цитата отправляется на Proof of Cloud Trust server — , который сообщает, принадлежит ли аттестованная машина доверенному (сертифицированному) облачному пулу из белого списка. Результат proof-of-cloud информативен и не блокирует: если сервер trust недоступен или истекает по времени ожидание, аттестация всё равно продолжается.

  3. Проверьте свежесть цитаты: свежесть цитаты подтверждается тем, что случайный challenge, сгенерированный UI, встраивается в report_data цитаты.

  4. Отображение значений RTMR: информативный шаг, который извлекает и показывает значения RTMR для цитаты.

  5. Повторный replay RTMR3: журналы событий, возвращаемые вместе с цитатой (в ответе агрегатора), используются для повторного воспроизведения RTMR3 по формуле Intel: RTMR3_new = SHA384(RTMR3_old || SHA384(event_log)). Если replayed RTMR3 совпадает с аттестованным (в цитате), то значения event-log os_image_hash и compose_hash можно считать достоверными представлениями выполненной ОС и docker-compose.

  6. Проверьте образ ОС: event-лог RTMR3 для os_image_hash извлекается, и предоставляется ссылка для скачивания, чтобы при необходимости можно было вручную проверить образ и его хэш. В iExec этот образ — dstackOS.

  7. Проверьте compose-hash: docker-compose (app_compose, предоставленный в ответе агрегатора) хэшируется, а результат сравнивается с compose_hash, встроенным как event log RTMR3.

После выполнения этих шагов верификации docker-compose, соответствующий compose-hash аттестованной CVM, отображается, как показано на изображении ниже.

Часть nox-kms docker-compose

docker-compose для CVM включает три сервиса:

  • nox-component: бизнес-сервис, выполняемый в CVM (например, nox-kms)

  • quote-service: сервис, используемый для получения quote и event logs, необходимых для аттестации CVM

  • fluent-bit: iExec log exporter service для внутренней наблюдаемости

Дальнейшая работа

В этом разделе описаны запланированные улучшения потока аттестации: происхождение образа, challenges от пользователя и дополнительные quote-верификаторы.

Происхождение образа

На данный момент аттестация прекращается, когда мы отображаем docker compose, который перечисляет образы, выполненные в аттестованной CVM. Следующий шаг — использовать инфраструктуру Sigstore для подписи GitHub Actions workflow, которая сгенерировала каждый образ, во время его сборки, и публиковать attestation уровня SLSA (Supply-chain Levels for Software Artifacts), идентифицируемую по sha256 checksum образа (subject-name) в GitHub и docker registry образа. Запись Rekor также будет естественным образом отправлена. Сделав это, мы сможем расширить шаги верификации, упомянутые в этой статье, аттестуя происхождение каждого образа Nox (то есть сборочный workflow и commit репозитория GitHub).

Challenge от пользователя

В настоящее время, чтобы проверить свежесть quote, мы используем автоматически сгенерированный challenge, который передается с UI агрегатору как параметр запроса; затем агрегатор пересылает его каждому quote-service. Мы усилим этот процесс, разрешив пользователям UI вводить свой собственный challenge, чтобы получить дополнительный уровень доверия к свежести quote.

Несколько верификаторов

В настоящее время мы используем Phala qvl как единственный метод верификации для проверки подписи Intel и цепочки сертификатов цитаты. Мы добавим дополнительные методы верификации — либо как резервные, либо как обязательные проверки, если они доступны, — чтобы повысить доверие к результату верификации. Потенциальные верификаторы, которые нужно добавить: dstack-verifier, размещаемый в iExec, и Intel Trust Authority.