From 077762aa335de0cf99e190bd5afb5b77f5403a89 Mon Sep 17 00:00:00 2001 From: Anderson Toshiyuki Sasaki Date: Tue, 17 Feb 2026 16:43:04 +0100 Subject: [PATCH] Document agent-driven (push) attestation Co-Authored-By: Claude Opus 4.6 Signed-off-by: Anderson Toshiyuki Sasaki --- docs/assets/push-model-architecture.svg | 86 ++++ docs/assets/push-model-sequence.svg | 122 +++++ docs/conf.py | 1 + docs/design.rst | 1 + docs/design/overview.rst | 11 +- docs/design/push_model.rst | 226 +++++++++ docs/index.rst | 1 + docs/installation.rst | 11 + docs/man/keylime_push_model_agent.8.rst | 226 +++++++++ docs/man/keylime_verifier.8.rst | 3 +- docs/rest_apis.rst | 30 ++ docs/rest_apis/3_0/3_0.rst | 21 + docs/rest_apis/3_0/verifier.rst | 608 ++++++++++++++++++++++++ docs/user_guide.rst | 1 + docs/user_guide/configuration.rst | 7 + docs/user_guide/push_model.rst | 370 ++++++++++++++ 16 files changed, 1721 insertions(+), 4 deletions(-) create mode 100644 docs/assets/push-model-architecture.svg create mode 100644 docs/assets/push-model-sequence.svg create mode 100644 docs/design/push_model.rst create mode 100644 docs/man/keylime_push_model_agent.8.rst create mode 100644 docs/rest_apis/3_0/3_0.rst create mode 100644 docs/rest_apis/3_0/verifier.rst create mode 100644 docs/user_guide/push_model.rst diff --git a/docs/assets/push-model-architecture.svg b/docs/assets/push-model-architecture.svg new file mode 100644 index 000000000..82a5672f4 --- /dev/null +++ b/docs/assets/push-model-architecture.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + Push-Model Architecture + + + Pull Model (traditional) + + + + Agent + (server, port 9002) + + + + Registrar + + + + Verifier + + + + register + + + + poll quotes + + + + + + Push Model (new) + + + + Agent + (client, no ports) + + + + Registrar + + + + Verifier + + + + register + + + + push evidence + + + + Protocol Flow (Push Model) + + 1. Agent registers with Registrar (same as pull model) + 2. Agent authenticates with Verifier via PoP (POST /v3/sessions) + 3. Agent sends capabilities to Verifier (POST /v3/agents/{agent_id}/attestations) — receives challenge nonce + 4. Agent sends evidence to Verifier (PATCH /v3/agents/{agent_id}/attestations/latest) — receives 202 Accepted + 5. Agent waits for configured interval, then repeats from step 3 + diff --git a/docs/assets/push-model-sequence.svg b/docs/assets/push-model-sequence.svg new file mode 100644 index 000000000..d9affe1c9 --- /dev/null +++ b/docs/assets/push-model-sequence.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + Push-Model Agent State Machine + + + + Unregistered + Initial state + + + + Registered + Ready for attestation + + + + Negotiating + Phase 1: capabilities + + + + Attesting + Phase 2: evidence + + + + Reg. Failed + Will retry + + + + Attest. Failed + Will retry + + + + registration OK + + + + failed + + + + retry + + + + start negotiation + + + + 201 Created + + + + error + + + + 202 Accepted + (wait interval) + + + + rejected + + + + retry + + + + Legend + + + Success transition + + + Error transition + + + Retry (with exponential backoff) + + Phase 1: Agent POSTs capabilities, receives challenge nonce + Phase 2: Agent PATCHes evidence, receives 202 Accepted + The Negotiating/Attesting cycle repeats continuously + diff --git a/docs/conf.py b/docs/conf.py index 5543afa86..00d9735de 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -154,6 +154,7 @@ ("man/keylime_registrar.8", "keylime_registrar", "Keylime registrar service", [author], 8), ("man/keylime_verifier.8", "keylime_verifier", "Keylime verifier service", [author], 8), ("man/keylime_agent.8", "keylime_agent", "Keylime agent service", [author], 8), + ("man/keylime_push_model_agent.8", "keylime_push_model_agent", "Keylime push-model agent service", [author], 8), ] diff --git a/docs/design.rst b/docs/design.rst index 522ade113..dd72fd4e7 100644 --- a/docs/design.rst +++ b/docs/design.rst @@ -7,6 +7,7 @@ Design of Keylime :caption: Contents: design/overview.rst + design/push_model.rst design/security.rst diff --git a/docs/design/overview.rst b/docs/design/overview.rst index 4c7b52227..985cbc94b 100644 --- a/docs/design/overview.rst +++ b/docs/design/overview.rst @@ -51,9 +51,14 @@ Verifier The verifier implements the actual attestation of an agent and sends revocation messages if an agent leaves the trusted state. -Once an agent is registered for attestation (using the tenant or the API directly) the verifier continuously pulls -the required attestation data from the agent. This can include: a quote over the PCRs, the PCR values, NK public key, -IMA log and UEFI event log. After that the quote is validated additional validation of the data can be configured. +In the default **pull model**, once an agent is registered for attestation (using the tenant or the API directly) +the verifier continuously pulls the required attestation data from the agent. This can include: a quote over the +PCRs, the PCR values, NK public key, IMA log and UEFI event log. After that the quote is validated additional +validation of the data can be configured. + +Keylime also supports a **push model** where the agent initiates connections to the verifier and proactively +submits attestation evidence. This is useful for environments where the verifier cannot directly reach the +agent (e.g. behind firewalls or NAT). See :doc:`push_model` for details. Static PCR values """"""""""""""""" diff --git a/docs/design/push_model.rst b/docs/design/push_model.rst new file mode 100644 index 000000000..29f9061e0 --- /dev/null +++ b/docs/design/push_model.rst @@ -0,0 +1,226 @@ +======================== +Push-Model Attestation +======================== + +.. warning:: + Push-model attestation is currently experimental. The feature is functional + but the API and configuration options may change in future releases. + Please report issues at https://github.com/keylime/keylime/issues/?q=label:push-mode + +Introduction +------------ + +Traditional Keylime attestation uses a **pull model** where the verifier continuously +polls agents for attestation data. The agent acts as a server and the verifier initiates +connections to it. This model requires that the verifier can reach the agent over the +network. + +The **push model** reverses this communication direction: the agent initiates connections +to the verifier and proactively sends attestation data. The verifier never connects to +the agent. This makes push-model attestation suitable for environments where the +verifier cannot directly reach the agent, such as: + +* **Edge and IoT devices** behind firewalls or NAT +* **Hybrid cloud environments** with restricted network policies +* **Air-gapped networks** where inbound connections to agents are not permitted +* **Dynamic environments** where agent IP addresses change frequently + +In push mode, the agent is a separate binary (``keylime-push-model-agent``) that +implements the push attestation protocol using API version 3.0. + +Architectural Overview +---------------------- + +In pull-model attestation, the verifier runs a polling loop that periodically contacts +each registered agent to request a TPM quote and associated evidence. The agent exposes +an HTTPS server that responds to these requests. + +In push-model attestation, this relationship is inverted: + +* The **agent initiates** all connections to the verifier +* The agent does **not expose any HTTP endpoints** (no listening ports) +* The verifier accepts incoming attestation data from agents +* Verification is performed **asynchronously** after evidence is received +* An **event-driven timeout** system replaces the polling loop for monitoring agent + liveness + +The registrar interaction is unchanged: in both models, the agent registers itself +with the registrar during startup. + +.. figure:: ../assets/push-model-architecture.svg + :width: 600 + :align: center + :alt: Diagram showing the push-model architecture where the agent initiates + connections to both the registrar and the verifier, contrasted with the pull + model where the verifier connects to the agent. + + **Figure 1:** Push-Model Architecture + +The Two-Phase Attestation Protocol +----------------------------------- + +Push-model attestation uses a two-phase protocol for each attestation cycle. + +Phase 1: Capabilities Negotiation +"""""""""""""""""""""""""""""""""" + +The agent begins an attestation cycle by sending its capabilities to the verifier. +This tells the verifier what types of evidence the agent can produce and what +cryptographic algorithms it supports. + +1. The agent sends a ``POST /v3/agents/{agent_id}/attestations`` request to the + verifier containing its supported evidence types (TPM quote parameters, IMA log + capabilities, UEFI log capabilities) and the public attestation key (AK). + +2. The verifier creates an attestation resource, selects cryptographic parameters + (signature scheme, hash algorithm, PCRs to quote), generates a random challenge + nonce, and returns a ``201 Created`` response with: + + * The challenge nonce for TPM quote generation + * The chosen cryptographic parameters + * The evidence types requested + * A deadline (``challenges_expire_at``) by which evidence must be submitted + +Phase 2: Evidence Submission +""""""""""""""""""""""""""""" + +The agent collects the requested evidence and submits it to the verifier. + +1. The agent generates a TPM quote using the challenge nonce from Phase 1, + collects IMA and/or UEFI event logs as requested, and sends a + ``PATCH /v3/agents/{agent_id}/attestations/latest`` request with the evidence. + +2. The verifier returns a ``202 Accepted`` response immediately. The evidence is + then verified asynchronously in a background worker process. + +3. If verification succeeds, the attestation is marked as ``pass``. If it fails, + the attestation is marked as ``fail`` with a failure reason + (``broken_evidence_chain`` or ``policy_violation``). + +4. The response includes a ``seconds_to_next_attestation`` value in the ``meta`` + field, indicating when the agent should start its next attestation cycle. + +After a configurable interval, the agent begins a new cycle from Phase 1. + +Agent State Machine +""""""""""""""""""" + +The push-model agent operates as a state machine with the following states: + +.. figure:: ../assets/push-model-sequence.svg + :width: 600 + :align: center + :alt: Sequence diagram showing the push-model agent state machine transitions + from Unregistered through Registered, Negotiating, and Attesting states. + + **Figure 2:** Push-Model Agent State Machine + +* **Unregistered**: Initial state. The agent registers with the registrar. +* **Registered**: Registration succeeded. The agent begins negotiation with the + verifier. +* **Negotiating**: The agent sends capabilities to the verifier (Phase 1) and waits + for the challenge response. +* **Attesting**: The agent generates and sends evidence to the verifier (Phase 2). + On success, the agent waits for the configured interval and transitions back to + Negotiating. +* **RegistrationFailed**: Registration with the registrar failed. The agent waits + and retries. +* **AttestationFailed**: An attestation attempt failed (network error or verifier + rejection). The agent waits and retries from Negotiating. + +The agent uses exponential backoff when retrying failed operations. + +Authentication +-------------- + +Push-model attestation uses **Proof of Possession (PoP)** authentication instead of +the mTLS client certificates used in pull mode. This is necessary because the agent +acts as a client (not a server) and does not have certificates signed by the verifier's +trusted CA. + +The PoP authentication flow: + +1. The agent creates a session by sending ``POST /v3/sessions`` with its agent ID + and supported authentication methods. +2. The verifier responds with a challenge nonce. +3. The agent proves possession of its AK by signing the challenge using the TPM + (``TPM2_Certify``) and sends the result via ``PATCH /v3/sessions/{session_id}``. +4. If the signature is valid, the verifier issues a bearer token. +5. The agent includes this token in the ``Authorization`` header of all subsequent + requests. +6. Tokens have a configurable expiration time and can be refreshed. + +The TLS connection uses **server verification only**: the agent verifies the verifier's +server certificate but does not present a client certificate. The agent needs the +verifier's CA certificate for this verification. + +For full details on the authorization framework, including the separation between +agent and admin authentication, see :doc:`../user_guide/authentication`. + +Timeout Monitoring +------------------ + +In pull mode, the verifier detects unresponsive agents through its polling loop. In +push mode, an event-driven timeout system serves this purpose. + +The verifier monitors push-mode agents as follows: + +1. When the verifier receives an attestation from an agent, it schedules a timeout + for that agent. The timeout duration is ``quote_interval * 5`` seconds (where + ``quote_interval`` is the verifier's configured quote interval). + +2. If the agent does not submit a new attestation before the timeout fires, the + verifier sets the agent's ``accept_attestations`` flag to ``False``. + +3. Once ``accept_attestations`` is ``False``, the verifier rejects new attestation + requests from that agent with a ``403 Forbidden`` response. + +4. The agent can recover by re-registering or by administrator intervention + (reactivation). + +Comparison with Pull Model +--------------------------- + +.. list-table:: + :header-rows: 1 + :widths: 30 35 35 + + * - Aspect + - Pull Model + - Push Model + * - Connection direction + - Verifier connects to agent + - Agent connects to verifier + * - Agent binary + - ``keylime_agent`` + - ``keylime_push_model_agent`` + * - Agent network requirements + - Must expose HTTP port (default 9002) + - No listening ports required + * - Firewall requirements + - Inbound to agent from verifier + - Outbound from agent to verifier + * - Authentication method + - mTLS (agent as server) + - PoP bearer tokens (agent as client) + * - API version + - v2.x + - v3.0 + * - Verification trigger + - Verifier polls on ``quote_interval`` + - Agent pushes on ``attestation_interval_seconds`` + * - Liveness detection + - Polling loop state machine + - Event-driven timeout (``quote_interval * 5``) + * - Verifier configuration + - ``mode = pull`` (default) + - ``mode = push`` + * - Suitable for + - Controlled networks, data centers + - Edge, IoT, NAT, firewalled environments + * - Maturity + - Stable + - Experimental + +For deployment and configuration instructions, see :doc:`../user_guide/push_model`. +For the v3.0 API reference, see :doc:`../rest_apis/3_0/3_0`. diff --git a/docs/index.rst b/docs/index.rst index 8234217fd..fd5f08bed 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -43,6 +43,7 @@ what the goals of Keylime are and how they are implemented. man/keylime_verifier.8 man/keylime_registrar.8 man/keylime_agent.8 + man/keylime_push_model_agent.8 man/keylime_policy.1 Indices and tables diff --git a/docs/installation.rst b/docs/installation.rst index 21d35a793..b96574137 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -62,6 +62,17 @@ Rust agent Installation instructions can be found in the `README.md `_ for the Rust agent. +Push-model agent +~~~~~~~~~~~~~~~~ +.. note:: + The push-model agent (``keylime-push-model-agent``) is a separate binary from + the standard Rust agent. It implements the push attestation protocol where the + agent initiates connections to the verifier. This feature is currently experimental. + + Installation instructions are the same as for the Rust agent. The push-model + agent binary is built from the same repository. For configuration and deployment + details, see the :doc:`user_guide/push_model` user guide. + Keylime Bash installer ---------------------- diff --git a/docs/man/keylime_push_model_agent.8.rst b/docs/man/keylime_push_model_agent.8.rst new file mode 100644 index 000000000..b033db801 --- /dev/null +++ b/docs/man/keylime_push_model_agent.8.rst @@ -0,0 +1,226 @@ +========================== +keylime_push_model_agent +========================== + +------------------------------------------------------------ +Keylime push-model agent for TPM-based remote attestation +------------------------------------------------------------ + +:Manual section: 8 +:Author: Keylime Developers +:Date: February 2026 + +SYNOPSIS +======== + +**keylime_push_model_agent** [*OPTIONS*] + +(Most operations require root privileges, use with sudo) + +DESCRIPTION +=========== + +The push-model agent is a long-running service that runs on systems to be attested. +Unlike the standard Keylime agent which acts as a server and waits for the verifier +to poll it, the push-model agent initiates connections to the verifier and proactively +submits attestation evidence. + +The agent registers with the registrar, authenticates with the verifier using Proof of +Possession (PoP), and performs periodic attestation cycles consisting of capabilities +negotiation and evidence submission. + +This agent uses API version 3.0 and requires the verifier to be configured in push +mode (``mode = push``). + +OPTIONS +======= + +**--verifier-url** *URL* + URL of the verifier (must use HTTPS). Default: ``https://localhost:8881`` + +**--registrar-url** *URL* + URL of the registrar. Default: ``http://127.0.0.1:8888`` + +**--agent-identifier** *ID* + Agent UUID. Overrides the ``uuid`` configuration option. + +**--attestation-interval-seconds** *SECONDS* + Interval between attestation cycles. Default: ``60`` + +**--ca-certificate** *PATH* + CA certificate file for verifying the verifier's TLS certificate. Overrides + ``verifier_tls_ca_cert``. + +**--api-version** *VERSION* + API version to use. Default: ``v3.0`` + +**--timeout** *MILLISECONDS* + HTTP request timeout. Default: ``5000`` + +**--insecure** + Accept invalid TLS certificates. For testing only. + +**--avoid-tpm** + Use a mock TPM instead of hardware TPM. For testing only. + +**--json-file** *FILE* + JSON file for payload data. + +**--attestation-index** *INDEX* + Attestation index value. Default: ``1`` + +**--session-index** *INDEX* + Session index value. Default: ``1`` + +**--message-type** *TYPE* + Message type (Attestation, EvidenceHandling, Session). Default: ``Attestation`` + +**--method** *METHOD* + HTTP method. Default: ``POST`` + +CONFIGURATION +============= + +Primary configuration is read from ``/etc/keylime/agent.conf`` (TOML format). +All options are under the ``[agent]`` section. Command-line arguments override +configuration file values. + +Drop-in overrides: files in ``/etc/keylime/agent.conf.d/`` are applied in +lexicographic order. + +Push-model specific options: + +**verifier_url** + URL of the verifier. Must use HTTPS. Default: ``https://localhost:8881`` + +**verifier_tls_ca_cert** + Path to CA certificate for verifying the verifier's TLS certificate. + Relative paths are resolved from ``keylime_dir``. Default: ``cv_ca/cacert.crt`` + +**attestation_interval_seconds** + Interval in seconds between attestation cycles. Default: ``60`` + +**api_versions** + API versions to use. Default: ``3.0`` + +**certification_keys_server_identifier** + Server identifier for attestation key certification. Default: ``ak`` + +**uefi_logs_evidence_version** + UEFI logs evidence format version. Default: ``2.1`` + +**exponential_backoff_initial_delay** + Initial retry delay in milliseconds. Default: ``10000`` + +**exponential_backoff_max_retries** + Maximum number of retry attempts. Default: ``5`` + +**exponential_backoff_max_delay** + Maximum retry delay in milliseconds. Default: ``300000`` + +Shared options (same as standard agent): + +**uuid** + Agent identifier. Default: auto-generated UUID. + +**registrar_ip**, **registrar_port** + Registrar endpoint. Default: ``127.0.0.1:8890`` + +**registrar_tls_enabled** + Enable TLS for registrar communication. Default: ``false`` + +**registrar_tls_ca_cert** + CA certificate for registrar TLS verification. Default: ``cv_ca/cacert.crt`` + +**tpm_hash_alg**, **tpm_encryption_alg**, **tpm_signing_alg** + TPM algorithms. Defaults: ``sha256``, ``rsa``, ``rsassa`` + +**keylime_dir** + Working directory. Default: ``/var/lib/keylime`` + +**run_as** + User:group to drop privileges to. Default: ``keylime:tss`` + +**enable_iak_idevid** + Enable IAK/IDevID usage. Default: ``false`` + +ENVIRONMENT +=========== + +**KEYLIME_AGENT_CONFIG** + Path to agent.conf (highest priority) + +**KEYLIME_DIR** + Working directory (default: ``/var/lib/keylime``) + +**RUST_LOG** + Log level configuration. Default in systemd service: + ``keylime_push_model_agent=info,keylime=info`` + +All configuration options can be overridden via environment variables in the form +``KEYLIME_AGENT_`` (e.g. ``KEYLIME_AGENT_VERIFIER_URL``). + +FILES +===== + +``/etc/keylime/agent.conf`` + TOML format configuration file (shared with standard agent) + +``/etc/keylime/agent.conf.d/`` + Drop-in configuration snippets + +``/var/lib/keylime/cv_ca/cacert.crt`` + Default CA certificate for verifier TLS verification + +``/var/lib/keylime/agent_data.json`` + Persisted agent TPM data + +RUNTIME +======= + +Start directly: + +.. code-block:: bash + + sudo keylime_push_model_agent --verifier-url https://verifier.example.com:8881 + +Start as a systemd service: + +.. code-block:: bash + + sudo systemctl enable --now keylime_push_model_agent + +Check service status: + +.. code-block:: bash + + sudo systemctl status keylime_push_model_agent + sudo journalctl -u keylime_push_model_agent -f + +PREREQUISITES +============= + +- Root privileges (use sudo) +- TPM 2.0 available (verify with ``tpm2_pcrread``) +- Verifier configured with ``mode = push`` +- Network connectivity from agent to verifier and registrar +- Verifier CA certificate available on agent machine + +NOTES +===== + +- This service conflicts with ``keylime_agent.service``. Only one agent type can + run on a machine at a time. +- The push-model agent does not expose any listening ports. +- Push-model attestation is currently experimental. +- Authentication uses PoP bearer tokens, not mTLS client certificates. + +SEE ALSO +======== + +**keylime_agent**\(8), **keylime_verifier**\(8), **keylime_registrar**\(8), **keylime_tenant**\(1) + +BUGS +==== + +Report bugs at https://github.com/keylime/rust-keylime/issues diff --git a/docs/man/keylime_verifier.8.rst b/docs/man/keylime_verifier.8.rst index fd7cfb941..5303a5f06 100644 --- a/docs/man/keylime_verifier.8.rst +++ b/docs/man/keylime_verifier.8.rst @@ -32,6 +32,7 @@ Primary configuration is read from ``/etc/keylime/verifier.conf`` (or an overrid All options are under the ``[verifier]`` section. Essentials: +- **mode**: Attestation mode (``pull`` or ``push``). Default: ``pull`` - **uuid**: Unique identifier for this verifier instance - **ip**, **port**: Bind address and HTTP port - **registrar_ip**, **registrar_port**: Registrar endpoint @@ -108,7 +109,7 @@ NOTES SEE ALSO ======== -**keylime_registrar**\(8), **keylime_tenant**\(1), **keylime_agent**\(8) +**keylime_registrar**\(8), **keylime_tenant**\(1), **keylime_agent**\(8), **keylime_push_model_agent**\(8) BUGS ==== diff --git a/docs/rest_apis.rst b/docs/rest_apis.rst index edfe8be1c..aba64c338 100644 --- a/docs/rest_apis.rst +++ b/docs/rest_apis.rst @@ -14,10 +14,40 @@ Check the :ref:`Changelog` section for the differences between versions rest_apis/2_3/2_3.rst rest_apis/2_4/2_4.rst rest_apis/2_5/2_5.rst + rest_apis/3_0/3_0.rst Changelog _________ +Changes from v2.5 to v3.0 +~~~~~~~~~~~~~~~~~~~~~~~~~ + +API version 3.0 introduces push-model attestation. Unlike previous versions where +the verifier polls agents, in v3.0 agents initiate connections and submit +attestation evidence to the verifier. The v3.0 endpoints are served by the +verifier only; the push-model agent does not expose HTTP endpoints. + +* Added `POST /v3/agents/{agent_id}/attestations` endpoint to the verifier: + * Allows agents to submit attestation capabilities (Phase 1 of push protocol) + * Returns challenge nonce for TPM quote generation +* Added `PATCH /v3/agents/{agent_id}/attestations/latest` endpoint: + * Allows agents to submit attestation evidence (Phase 2 of push protocol) + * Returns `202 Accepted` for asynchronous verification +* Added `PATCH /v3/agents/{agent_id}/attestations/{index}` endpoint: + * Submit evidence for a specific attestation by index +* Added `GET /v3/agents/{agent_id}/attestations` endpoint: + * Lists all attestation records for an agent +* Added `GET /v3/agents/{agent_id}/attestations/latest` endpoint: + * Returns the most recent attestation for an agent, including verification status +* Added `GET /v3/agents/{agent_id}/attestations/{index}` endpoint: + * Returns a specific attestation by its index +* Added `POST /v3/sessions` endpoint: + * Creates a PoP authentication session and returns a challenge nonce for the agent +* Added `PATCH /v3/sessions/{session_id}` endpoint: + * Completes PoP authentication by submitting the TPM-signed challenge response +* Introduced PoP (Proof of Possession) bearer token authentication for + agent-to-verifier communication + Changes from v2.4 to v2.5 ~~~~~~~~~~~~~~~~~~~~~~~~~ API version 2.5 was first implemented in Keylime 7.14.0. diff --git a/docs/rest_apis/3_0/3_0.rst b/docs/rest_apis/3_0/3_0.rst new file mode 100644 index 000000000..d6cac705d --- /dev/null +++ b/docs/rest_apis/3_0/3_0.rst @@ -0,0 +1,21 @@ +RESTful API for Keylime (v3.0) +------------------------------ + +API version 3.0 introduces push-model attestation, where agents initiate +connections to the verifier and proactively submit attestation evidence. + +Unlike previous API versions where the agent exposed HTTP endpoints for the +verifier to poll, in v3.0 the agent acts as a client. The v3.0 endpoints are +served by the **verifier only**. The push-model agent does not expose an API. + +For a conceptual overview of push-model attestation, see +:doc:`../../design/push_model`. + +.. warning:: + Push-model attestation is currently experimental. The API may change in + future releases. + +.. toctree:: + :maxdepth: 2 + + verifier.rst diff --git a/docs/rest_apis/3_0/verifier.rst b/docs/rest_apis/3_0/verifier.rst new file mode 100644 index 000000000..3476cc7a3 --- /dev/null +++ b/docs/rest_apis/3_0/verifier.rst @@ -0,0 +1,608 @@ +Verifier +~~~~~~~~ + +Push-Model Attestation Endpoints +""""""""""""""""""""""""""""""""" + +These endpoints implement the two-phase push-model attestation protocol. Agents +use these endpoints to submit attestation capabilities and evidence. Administrators +can use the GET endpoints to view attestation results. + +For details on authentication requirements, see :doc:`../../user_guide/authentication`. + +.. http:post:: /v3/agents/{agent_id}/attestations + + Phase 1: Submit attestation capabilities and receive a challenge. + + The agent sends its supported evidence types, cryptographic algorithms, and + attestation key. The verifier selects parameters and returns a challenge nonce + for TPM quote generation. + + :param agent_id: UUID of the agent + :type agent_id: string + + **Authentication**: PoP bearer token (agent-only) + + **Example request**: + + .. sourcecode:: json + + { + "data": { + "type": "attestation", + "attributes": { + "evidence_supported": [ + { + "evidence_class": "certification", + "evidence_type": "tpm_quote", + "capabilities": { + "signature_schemes": ["rsassa"], + "hash_algorithms": ["sha256", "sha384", "sha512"], + "available_subjects": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], + "certification_keys": [ + { + "key_class": "asymmetric", + "key_algorithm": "rsa", + "key_size": 2048, + "server_identifier": "ak", + "allowable_signature_schemes": ["rsassa"], + "allowable_hash_algorithms": ["sha256", "sha384", "sha512"], + "public": "" + } + ], + "component_version": "2.0", + "evidence_version": "1.0" + } + }, + { + "evidence_class": "log", + "evidence_type": "ima_log", + "capabilities": { + "entry_count": 1024, + "supports_partial_access": true, + "appendable": true, + "formats": ["text/plain"], + "component_version": "1.0", + "evidence_version": "1.0" + } + } + ], + "system_info": { + "boot_time": "2024-01-15T10:30:00Z" + } + } + } + } + + **Example response** (201 Created): + + .. sourcecode:: json + + { + "data": { + "type": "attestation", + "id": "0", + "attributes": { + "stage": "awaiting_evidence", + "evidence_requested": [ + { + "evidence_class": "certification", + "evidence_type": "tpm_quote", + "chosen_parameters": { + "challenge": "", + "signature_scheme": "rsassa", + "hash_algorithm": "sha256", + "selected_subjects": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], + "certification_key": { + "key_class": "asymmetric", + "key_algorithm": "rsa", + "key_size": 2048, + "server_identifier": "ak" + } + } + }, + { + "evidence_class": "log", + "evidence_type": "ima_log", + "chosen_parameters": { + "starting_offset": 0, + "entry_count": 1024, + "format": "text/plain" + } + } + ], + "system_info": { + "boot_time": "2024-01-15T10:30:00Z" + }, + "capabilities_received_at": "2024-01-15T10:30:00.123456Z", + "challenges_expire_at": "2024-01-15T10:35:00.123456Z" + }, + "links": { + "self": "/v3/agents/{agent_id}/attestations/0" + } + } + } + + :json string data.id: Attestation index (auto-incremented per agent) + :>json string data.attributes.stage: ``"awaiting_evidence"`` + :>json array data.attributes.evidence_requested: Evidence the verifier wants the agent to provide + :>json string evidence_requested[].chosen_parameters.challenge: Base64-encoded challenge nonce for TPM quote + :>json string data.attributes.capabilities_received_at: ISO 8601 timestamp + :>json string data.attributes.challenges_expire_at: Deadline for evidence submission + :>json string data.links.self: URL to this attestation resource + + :statuscode 201: Attestation created, challenge issued + :statuscode 400: Invalid request body + :statuscode 403: Attestations disabled for this agent (timeout or previous failure) + :statuscode 404: Agent not found + :statuscode 409: Concurrent attestation creation attempt + :statuscode 422: Invalid capabilities data + :statuscode 429: Rate limited (attestation interval not elapsed). Includes ``Retry-After`` header + :statuscode 503: Previous attestation still being verified. Includes ``Retry-After`` header + + +.. http:patch:: /v3/agents/{agent_id}/attestations/latest + + Phase 2: Submit attestation evidence for the latest attestation. + + The agent sends the TPM quote, PCR values, and event logs generated using the + challenge nonce from Phase 1. The verifier accepts the evidence and verifies it + asynchronously. + + :param agent_id: UUID of the agent + :type agent_id: string + + **Authentication**: PoP bearer token (agent-only) + + **Example request**: + + .. sourcecode:: json + + { + "data": { + "type": "attestation", + "attributes": { + "evidence_collected": [ + { + "evidence_class": "certification", + "evidence_type": "tpm_quote", + "data": { + "subject_data": { + "0": "", + "1": "" + }, + "message": "", + "signature": "" + } + }, + { + "evidence_class": "log", + "evidence_type": "ima_log", + "data": { + "entry_count": 512, + "entries": "" + } + } + ] + } + } + } + + **Example response** (202 Accepted): + + .. sourcecode:: json + + { + "data": { + "type": "attestation", + "id": "0", + "attributes": { + "stage": "evaluating_evidence", + "evidence": [ + { + "evidence_class": "certification", + "evidence_type": "tpm_quote", + "capabilities": {}, + "chosen_parameters": {}, + "data": { + "message": "", + "signature": "", + "subject_data": {} + } + } + ], + "system_info": { + "boot_time": "2024-01-15T10:30:00Z" + }, + "capabilities_received_at": "2024-01-15T10:30:00.123456Z", + "challenges_expire_at": "2024-01-15T10:35:00.123456Z", + "evidence_received_at": "2024-01-15T10:31:00.123456Z" + }, + "links": { + "self": "/v3/agents/{agent_id}/attestations/0" + } + }, + "meta": { + "seconds_to_next_attestation": 45 + } + } + + :json string data.attributes.stage: ``"evaluating_evidence"`` (verification in progress) + :>json array data.attributes.evidence: Evidence items with capabilities, parameters, and data + :>json string data.attributes.evidence_received_at: ISO 8601 timestamp when evidence was received + :>json int meta.seconds_to_next_attestation: Suggested wait before starting the next attestation cycle + + :statuscode 202: Evidence accepted, verification in progress + :statuscode 400: Invalid evidence format + :statuscode 403: Evidence already submitted, attestation is not the latest, or challenges expired + :statuscode 404: Agent or attestation not found + :statuscode 410: Attestation no longer exists + :statuscode 503: No available worker processes. Includes ``Retry-After`` header + + +.. http:patch:: /v3/agents/{agent_id}/attestations/{index} + + Submit attestation evidence for a specific attestation by index. + + Behaves identically to ``PATCH /v3/agents/{agent_id}/attestations/latest`` + but targets a specific attestation index. Evidence can only be submitted for + the latest attestation. + + :param agent_id: UUID of the agent + :type agent_id: string + :param index: Attestation index + :type index: integer + + **Authentication**: PoP bearer token (agent-only) + + :statuscode 202: Evidence accepted + :statuscode 403: Not the latest attestation, evidence already submitted, or challenges expired + :statuscode 404: Agent or attestation not found + + +.. http:get:: /v3/agents/{agent_id}/attestations + + List all attestations for an agent. + + :param agent_id: UUID of the agent + :type agent_id: string + + **Authentication**: mTLS (admin) or PoP bearer token (own agent only) + + **Example response**: + + .. sourcecode:: json + + { + "data": [ + { + "type": "attestation", + "id": "1", + "attributes": { + "stage": "verification_complete", + "evaluation": "pass", + "evidence": [], + "system_info": { + "boot_time": "2024-01-15T10:30:00Z" + }, + "capabilities_received_at": "2024-01-15T10:30:00.123456Z", + "challenges_expire_at": "2024-01-15T10:35:00.123456Z", + "evidence_received_at": "2024-01-15T10:31:00.123456Z", + "verification_completed_at": "2024-01-15T10:32:00.123456Z" + }, + "links": { + "self": "/v3/agents/{agent_id}/attestations/1" + } + }, + { + "type": "attestation", + "id": "0", + "attributes": { + "stage": "verification_complete", + "evaluation": "pass", + "evidence": [], + "system_info": {}, + "capabilities_received_at": "2024-01-15T10:25:00.123456Z", + "challenges_expire_at": "2024-01-15T10:30:00.123456Z", + "evidence_received_at": "2024-01-15T10:26:00.123456Z", + "verification_completed_at": "2024-01-15T10:27:00.123456Z" + }, + "links": { + "self": "/v3/agents/{agent_id}/attestations/0" + } + } + ] + } + + :>json array data: List of attestation resources + :>json string data[].id: Attestation index + :>json string data[].attributes.stage: ``"awaiting_evidence"``, ``"evaluating_evidence"``, or ``"verification_complete"`` + :>json string data[].attributes.evaluation: ``"pending"``, ``"pass"``, or ``"fail"`` + :>json string data[].attributes.failure_reason: ``"broken_evidence_chain"`` or ``"policy_violation"`` (only when evaluation is ``"fail"``) + + :statuscode 200: Success + :statuscode 404: Agent not found + + +.. http:get:: /v3/agents/{agent_id}/attestations/latest + + Get the latest attestation for an agent. + + :param agent_id: UUID of the agent + :type agent_id: string + + **Authentication**: mTLS (admin) or PoP bearer token (own agent only) + + **Example response**: + + .. sourcecode:: json + + { + "data": { + "type": "attestation", + "id": "1", + "attributes": { + "stage": "verification_complete", + "evaluation": "pass", + "failure_reason": null, + "evidence": [ + { + "evidence_class": "certification", + "evidence_type": "tpm_quote", + "capabilities": {}, + "chosen_parameters": {}, + "data": { + "message": "", + "signature": "", + "subject_data": {} + } + } + ], + "system_info": { + "boot_time": "2024-01-15T10:30:00Z" + }, + "capabilities_received_at": "2024-01-15T10:30:00.123456Z", + "challenges_expire_at": "2024-01-15T10:35:00.123456Z", + "evidence_received_at": "2024-01-15T10:31:00.123456Z", + "verification_completed_at": "2024-01-15T10:32:00.123456Z" + }, + "links": { + "self": "/v3/agents/{agent_id}/attestations/1" + } + } + } + + :>json string data.attributes.stage: Current stage of the attestation + :>json string data.attributes.evaluation: ``"pending"``, ``"pass"``, or ``"fail"`` + :>json string data.attributes.failure_reason: ``null``, ``"broken_evidence_chain"``, or ``"policy_violation"`` + :>json array data.attributes.evidence: Evidence items with full data + :>json string data.attributes.capabilities_received_at: When capabilities were received + :>json string data.attributes.challenges_expire_at: When challenges expire + :>json string data.attributes.evidence_received_at: When evidence was received (``null`` if still awaiting) + :>json string data.attributes.verification_completed_at: When verification completed (``null`` if still in progress) + + :statuscode 200: Success + :statuscode 404: Agent not found or no attestations exist + + +.. http:get:: /v3/agents/{agent_id}/attestations/{index} + + Get a specific attestation by index. + + :param agent_id: UUID of the agent + :type agent_id: string + :param index: Attestation index + :type index: integer + + **Authentication**: mTLS (admin) or PoP bearer token (own agent only) + + Response format is identical to ``GET /v3/agents/{agent_id}/attestations/latest``. + + :statuscode 200: Success + :statuscode 404: Agent or attestation not found + + +Session Endpoints +""""""""""""""""" + +These endpoints manage PoP (Proof of Possession) authentication sessions for +push-model agents. Sessions are required before an agent can submit attestations. + +.. http:post:: /v3/sessions + + Create a new authentication session. + + The verifier generates a challenge nonce that the agent must sign using its + TPM attestation key to prove possession. + + **Authentication**: None (public endpoint) + + **Example request**: + + .. sourcecode:: json + + { + "data": { + "type": "session", + "attributes": { + "agent_id": "d432fbb3-d2f1-4a97-9ef7-75bd81c00000", + "authentication_supported": [ + { + "authentication_class": "pop", + "authentication_type": "tpm_pop" + } + ] + } + } + } + + **Example response** (200 OK): + + .. sourcecode:: json + + { + "data": { + "type": "session", + "id": "550e8400-e29b-41d4-a716-446655440000", + "attributes": { + "agent_id": "d432fbb3-d2f1-4a97-9ef7-75bd81c00000", + "authentication_requested": [ + { + "authentication_class": "pop", + "authentication_type": "tpm_pop", + "chosen_parameters": { + "challenge": "" + } + } + ], + "created_at": "2024-01-15T10:30:00.123456Z", + "challenges_expire_at": "2024-01-15T10:31:00.123456Z" + } + } + } + + :json string data.id: Session UUID + :>json string data.attributes.challenges_expire_at: Deadline for submitting the PoP response + + :statuscode 200: Session created + :statuscode 400: Missing or invalid agent_id + :statuscode 429: Rate limited. Includes ``Retry-After`` header + + +.. http:patch:: /v3/sessions/{session_id} + + Submit Proof of Possession response to complete authentication. + + The agent signs the challenge nonce from the session creation response using + ``TPM2_Certify`` and submits the result. If valid, the verifier issues a bearer + token for subsequent API calls. + + :param session_id: UUID of the session + :type session_id: string + + **Authentication**: None (public endpoint; validates PoP internally) + + **Example request**: + + .. sourcecode:: json + + { + "data": { + "type": "session", + "attributes": { + "agent_id": "d432fbb3-d2f1-4a97-9ef7-75bd81c00000", + "authentication_provided": [ + { + "authentication_class": "pop", + "authentication_type": "tpm_pop", + "data": { + "message": "", + "signature": "" + } + } + ] + } + } + } + + **Example response** (200 OK, authentication passed): + + .. sourcecode:: json + + { + "data": { + "type": "session", + "id": "550e8400-e29b-41d4-a716-446655440000", + "attributes": { + "agent_id": "d432fbb3-d2f1-4a97-9ef7-75bd81c00000", + "evaluation": "pass", + "token": "550e8400-e29b-41d4-a716-446655440000.", + "authentication": [ + { + "authentication_class": "pop", + "authentication_type": "tpm_pop", + "chosen_parameters": { + "challenge": "" + }, + "data": { + "message": "", + "signature": "" + } + } + ], + "created_at": "2024-01-15T10:30:00.123456Z", + "challenges_expire_at": "2024-01-15T10:31:00.123456Z", + "response_received_at": "2024-01-15T10:30:30.123456Z", + "token_expires_at": "2024-01-15T11:30:00.123456Z" + } + } + } + + :>json string data.attributes.evaluation: ``"pass"`` or ``"fail"`` + :>json string data.attributes.token: Bearer token for subsequent requests (only on ``"pass"``) + :>json string data.attributes.token_expires_at: Token expiration time (only on ``"pass"``) + + :statuscode 200: PoP response processed (check ``evaluation`` field for result) + :statuscode 400: Missing or invalid request body + :statuscode 401: PoP verification failed + :statuscode 404: Session not found + + +Attestation Stages and Evaluations +""""""""""""""""""""""""""""""""""" + +Each attestation progresses through the following stages: + +.. list-table:: + :header-rows: 1 + :widths: 25 75 + + * - Stage + - Description + * - ``awaiting_evidence`` + - Capabilities received, challenge issued, waiting for evidence + * - ``evaluating_evidence`` + - Evidence received, verification in progress + * - ``verification_complete`` + - Verification finished, see ``evaluation`` for result + +The ``evaluation`` field indicates the verification result: + +.. list-table:: + :header-rows: 1 + :widths: 20 80 + + * - Evaluation + - Description + * - ``pending`` + - Verification not yet complete + * - ``pass`` + - Evidence verified successfully + * - ``fail`` + - Evidence verification failed (see ``failure_reason``) + +When an attestation fails, the ``failure_reason`` field provides the cause: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Failure Reason + - Description + * - ``broken_evidence_chain`` + - TPM quote signature invalid or evidence integrity check failed + * - ``policy_violation`` + - Evidence is valid but violates the configured attestation policy diff --git a/docs/user_guide.rst b/docs/user_guide.rst index 9bd44c512..ed052c175 100644 --- a/docs/user_guide.rst +++ b/docs/user_guide.rst @@ -8,6 +8,7 @@ User Guide user_guide/authentication.rst user_guide/configuration.rst + user_guide/push_model.rst user_guide/runtime_ima.rst user_guide/user_selected_pcr_monitoring.rst user_guide/use_measured_boot.rst diff --git a/docs/user_guide/configuration.rst b/docs/user_guide/configuration.rst index 6d8f35c88..2e50757df 100644 --- a/docs/user_guide/configuration.rst +++ b/docs/user_guide/configuration.rst @@ -40,6 +40,13 @@ The following components can be configured: - ``/etc/keylime/logging.conf`` - ``/etc/keylime/logging.conf.d`` +.. note:: + For push-model attestation, the verifier must be configured with ``mode = push`` + in the ``[verifier]`` section. The push-model agent uses the same + ``/etc/keylime/agent.conf`` file (TOML format) but with additional options such + as ``verifier_url`` and ``attestation_interval_seconds``. See + :doc:`push_model` for details. + The next sections contain details of the configuration files Configuration file processing order diff --git a/docs/user_guide/push_model.rst b/docs/user_guide/push_model.rst new file mode 100644 index 000000000..773d2aaaa --- /dev/null +++ b/docs/user_guide/push_model.rst @@ -0,0 +1,370 @@ +======================== +Push-Model Attestation +======================== + +.. warning:: + Push-model attestation is currently experimental. The feature is functional + but the API and configuration options may change in future releases. + +Introduction +------------ + +In the default pull model, the Keylime verifier continuously polls agents for +attestation data. This requires the verifier to reach the agent over the network. + +The push model reverses this: the agent initiates connections to the verifier and +proactively sends attestation evidence. This is useful when the verifier cannot +directly reach the agent, for example behind firewalls, NAT, or in edge/IoT +deployments. + +For a detailed description of how push-model attestation works, see +:doc:`../design/push_model`. + +Prerequisites +------------- + +* Keylime verifier and registrar installed and running +* The ``keylime-push-model-agent`` binary installed on the target machine +* A TPM 2.0 device (hardware or emulated for development) +* Network connectivity **from the agent to the verifier and registrar** (the + reverse is not required) +* The verifier's CA certificate available on the agent machine + +Configuring the Verifier for Push Mode +-------------------------------------- + +Set the verifier's attestation mode to ``push`` in ``/etc/keylime/verifier.conf``: + +.. code-block:: ini + + [verifier] + mode = push + +Or use a configuration snippet in ``/etc/keylime/verifier.conf.d/``: + +.. code-block:: ini + + # /etc/keylime/verifier.conf.d/001-push-mode.conf + [verifier] + mode = push + +The verifier can also be configured via environment variable: + +.. code-block:: bash + + export KEYLIME_VERIFIER_MODE=push + +.. note:: + The ``mode`` setting affects all agents on this verifier. A verifier in push + mode expects agents to submit attestation data; it does not poll agents. A + single verifier cannot operate in both modes simultaneously. + +Additional verifier settings relevant to push mode: + +* ``quote_interval``: Used to calculate the agent timeout threshold + (``quote_interval * 5``). Default: ``2`` seconds. +* ``challenge_lifetime``: How long a challenge nonce remains valid for evidence + submission. +* ``verification_timeout``: Maximum time allowed for evidence verification. + +After changing the configuration, restart the verifier: + +.. code-block:: bash + + sudo systemctl restart keylime_verifier + +Configuring the Push-Model Agent +--------------------------------- + +The push-model agent is a separate binary from the standard Keylime agent. It is +installed as ``keylime_push_model_agent`` (or ``keylime-push-model-agent``). + +The agent is configured through ``/etc/keylime/agent.conf`` (TOML format), command-line +arguments, or environment variables. + +Key Configuration Options +""""""""""""""""""""""""" + +The following options are specific to or particularly important for push-model +operation: + +.. list-table:: + :header-rows: 1 + :widths: 30 15 55 + + * - Option + - Default + - Description + * - ``verifier_url`` + - ``https://localhost:8881`` + - URL of the verifier. Must use HTTPS. + * - ``verifier_tls_ca_cert`` + - ``cv_ca/cacert.crt`` + - Path to the CA certificate for verifying the verifier's TLS certificate. + Relative paths are resolved from ``keylime_dir``. + * - ``attestation_interval_seconds`` + - ``60`` + - Interval in seconds between attestation cycles. + * - ``registrar_ip`` + - ``127.0.0.1`` + - IP address of the registrar. + * - ``registrar_port`` + - ``8890`` + - Port of the registrar. + * - ``registrar_tls_enabled`` + - ``false`` + - Enable TLS for registrar communication. + * - ``registrar_tls_ca_cert`` + - ``cv_ca/cacert.crt`` + - CA certificate for registrar TLS verification. + * - ``uuid`` + - (generated) + - Agent UUID. Can be a specific UUID, ``generate`` (random), or + ``hash_ek`` (derived from the EK). + * - ``api_versions`` + - ``3.0`` + - API versions supported by the agent. Defaults to ``3.0`` for push model. + * - ``tpm_hash_alg`` + - ``sha256`` + - TPM hash algorithm (``sha256``, ``sha384``, ``sha512``). + * - ``tpm_signing_alg`` + - ``rsassa`` + - TPM signing algorithm (``rsassa``, ``ecdsa``). + * - ``keylime_dir`` + - ``/var/lib/keylime`` + - Working directory for certificates and data files. + +Example Minimal Configuration +"""""""""""""""""""""""""""""" + +.. code-block:: toml + + # /etc/keylime/agent.conf (push-model agent) + [agent] + uuid = "d432fbb3-d2f1-4a97-9ef7-75bd81c00000" + verifier_url = "https://verifier.example.com:8881" + verifier_tls_ca_cert = "/var/lib/keylime/cv_ca/cacert.crt" + attestation_interval_seconds = 60 + registrar_ip = "registrar.example.com" + registrar_port = 8890 + tpm_hash_alg = "sha256" + tpm_signing_alg = "rsassa" + +Command-Line Arguments +"""""""""""""""""""""" + +The push-model agent accepts the following command-line arguments, which override +configuration file values: + +.. code-block:: text + + --verifier-url Verifier URL (required) + --registrar-url Registrar URL (default: http://127.0.0.1:8888) + --agent-identifier Agent UUID + --attestation-interval-seconds Attestation interval (default: 60) + --ca-certificate CA certificate for TLS verification + --api-version API version (default: v3.0) + --timeout Request timeout in milliseconds (default: 5000) + --insecure Accept invalid TLS certificates (testing only) + --avoid-tpm Use mock TPM (testing only) + +Exponential Backoff +""""""""""""""""""" + +When the agent encounters errors (network failures, verifier unavailable), it uses +exponential backoff for retries: + +.. list-table:: + :header-rows: 1 + :widths: 35 15 50 + + * - Option + - Default + - Description + * - ``exponential_backoff_initial_delay`` + - ``10000`` + - Initial delay in milliseconds (10 seconds) + * - ``exponential_backoff_max_retries`` + - ``5`` + - Maximum number of retry attempts + * - ``exponential_backoff_max_delay`` + - ``300000`` + - Maximum delay in milliseconds (5 minutes) + +Systemd Service Management +--------------------------- + +The push-model agent is managed as a systemd service: + +.. code-block:: bash + + # Enable the service to start on boot + sudo systemctl enable keylime_push_model_agent + + # Start the service + sudo systemctl start keylime_push_model_agent + + # Check service status + sudo systemctl status keylime_push_model_agent + + # View logs + sudo journalctl -u keylime_push_model_agent -f + +.. warning:: + The push-model agent service (``keylime_push_model_agent.service``) conflicts + with the standard pull-model agent service (``keylime_agent.service``). Only one + can run at a time on the same machine. Starting one will stop the other. + +The service is configured to restart on failure with a 120-second delay between +restart attempts. + +Enrolling an Agent for Push-Model Attestation +--------------------------------------------- + +Use the ``keylime_tenant`` tool with the ``--push-model`` flag to enroll an agent +for push-model attestation: + +.. code-block:: bash + + # Add an agent in push mode + sudo keylime_tenant -c add --push-model -u + + # Add with a runtime IMA policy + sudo keylime_tenant -c add --push-model -u \ + --runtime-policy-name + + # Add with a measured boot policy + sudo keylime_tenant -c add --push-model -u \ + --mb-policy-name + +.. note:: + In push mode, the ``-t`` / ``--targethost`` option is not required because the + verifier does not need to connect to the agent. The agent's IP and port are set + to ``None`` in the verifier's database. + +To check the status of a push-model agent: + +.. code-block:: bash + + sudo keylime_tenant -c cvstatus -u + +To remove an agent: + +.. code-block:: bash + + sudo keylime_tenant -c delete -u + +TLS Configuration for Push Model +--------------------------------- + +The push model uses TLS differently from the pull model: + +**Agent-to-verifier connection:** + +* The agent connects to the verifier over HTTPS +* The agent verifies the verifier's server certificate using the configured CA + certificate (``verifier_tls_ca_cert``) +* The agent does **not** present a client certificate (no mTLS) +* Authentication is done via PoP bearer tokens (see :doc:`authentication`) + +**Agent-to-registrar connection:** + +* The agent connects to the registrar to register itself +* TLS can be enabled with ``registrar_tls_enabled = true`` +* The registrar CA certificate is configured with ``registrar_tls_ca_cert`` + +**Firewall considerations:** + +* No inbound ports need to be opened on the agent machine +* The agent needs outbound access to the verifier port (default: 8881) +* The agent needs outbound access to the registrar port (default: 8890) + +To set up TLS, copy the verifier's CA certificate to the agent machine: + +.. code-block:: bash + + # On the verifier machine, the CA cert is typically at: + # /var/lib/keylime/cv_ca/cacert.crt + + # Copy to the agent machine: + scp verifier:/var/lib/keylime/cv_ca/cacert.crt /var/lib/keylime/cv_ca/cacert.crt + +Verifying the Deployment +------------------------- + +After starting both the verifier (in push mode) and the push-model agent: + +1. **Check agent registration** in the registrar: + + .. code-block:: bash + + sudo keylime_tenant -c regstatus -u + +2. **Check attestation status** in the verifier: + + .. code-block:: bash + + sudo keylime_tenant -c cvstatus -u + +3. **View verifier logs** for attestation activity: + + .. code-block:: bash + + sudo journalctl -u keylime_verifier -f + + Successful attestations will show evidence receipt and verification completion + messages. + +4. **View agent logs** for attestation cycles: + + .. code-block:: bash + + sudo journalctl -u keylime_push_model_agent -f + + The agent logs will show transitions through the state machine: + registration, negotiation, and attestation phases. + +Troubleshooting +---------------- + +Agent cannot connect to verifier +""""""""""""""""""""""""""""""""" + +* Verify the ``verifier_url`` is correct and uses HTTPS +* Check that the verifier is running and listening on the configured port +* Verify network connectivity from the agent to the verifier +* Check that the CA certificate (``verifier_tls_ca_cert``) matches the verifier's + server certificate + +Agent shows timeout failures +""""""""""""""""""""""""""""" + +The verifier marks an agent as failed if it does not receive an attestation within +``quote_interval * 5`` seconds. + +* Verify the ``attestation_interval_seconds`` on the agent is less than the + verifier's timeout threshold +* Check for network instability between agent and verifier +* Review agent logs for errors during attestation cycles + +PoP authentication errors +"""""""""""""""""""""""""" + +* Ensure the agent is properly registered in the registrar (the AK must be known) +* Check that the TPM is accessible and functioning +* Verify the agent UUID matches between agent configuration and verifier enrollment + +Agent state stuck in Negotiating +""""""""""""""""""""""""""""""""" + +* The verifier may be rejecting capabilities. Check verifier logs for error details +* Ensure the TPM algorithms configured on the agent are accepted by the verifier +* Check that the ``api_versions`` setting includes ``3.0`` + +Service fails to start +"""""""""""""""""""""" + +* Check that the pull-model agent service is not running + (``systemctl status keylime_agent``) +* Verify the configuration file syntax (TOML format) +* Check file permissions on TLS certificates and TPM device