Referenz der lokalen API¶
Wie Ihre eigene Software auf dem Gateway ihre Konfiguration vom
Bootstrap-Agent liest. Diese Seite ist eine Zusammenfassung; der vollständige
Vertrag ist local-api-v1.openapi.yaml im Release-Archiv (Vertragsversion 1.6,
interface_version 1).
Transport und Zugriff¶
- HTTP/1.1 über einen Unix-Socket,
/run/bootstrap-agent/api.sock. Der Agent öffnet keinen Netzwerk-Port. Der Host-Name in einer Anfrage wird ignoriert. - Der Zugriff ist die Dateiberechtigung des Sockets: Modus 0660, Gruppe
bootstrap-agent. Die Mitgliedschaft in dieser Gruppe ist die ganze Berechtigung. Nehmen Sie nur die Prozesse auf, die die Konfiguration brauchen: Sie enthält die Zugangsdaten für Ihre Zielplattform, und ein Aufruf der Lese-Endpunkte liefert sie. - Der Agent protokolliert bei jedem Aufruf, der etwas ändert, die Benutzer-ID des Aufrufers.
Der Agent antwortet mit einer Zeile JSON; | jq . rückt sie ein.
Beispielausgabe von cproto-v0.2.0-rc.2 (die Form ist echt, die Werte sind
ersetzt). Jeden Aufruf mit seiner echten Antwort zeigt
Beispiele der lokalen API.
{
"interface_version": 1,
"interface_minor_version": 6,
"agent_version": "cproto-v0.2.0-rc.2",
"state": "ready",
"attestation_mode": "tpm",
"profile_version": 42,
"last_checkin": "2026-01-01T12:00:00Z",
"tpm_transient_avail": 3,
"tpm_loaded_sessions": 0,
"tpm_transient_capacity": 3,
"tpm_transient_used": 0,
"identity_cert_state": "not_configured",
"auth_mode": "tpm",
"auth_mode_source": "server",
"activation": "listen",
"profile_ready_marker": "/etc/iot-config/profile-ready"
}
Endpunkte¶
| Aufruf | Antwort |
|---|---|
GET /v1/status |
Immer 200 mit dem Zustand des Agenten, siehe unten. Er schlägt nie fehl: Ein unbeantworteter Status sieht aus wie ein abgestürzter Agent. |
GET /v1/profile |
Die ganze aktuelle Konfiguration, genau so, wie die Plattform sie erzeugt hat. 404 mit NO_CONFIG, solange es keine gibt. If-None-Match mit dem ETag ergibt 304. |
GET /v1/profile/packages |
Die Liste der Pakete darin, mit Version und Hash. Gleiche Regeln für 404 und 304. |
GET /v1/profile/packages/{id} |
Der Inhalt eines Pakets, ohne Umschlag. 404, wenn es das Paket oder die Konfiguration nicht gibt. |
POST /v1/profile/packages/{id}/ack |
Meldet dem Agenten, dass Sie die Konfiguration angewendet haben. Body: {"profile_version": 42, "applied": true} (reason ist Freitext, wenn applied false ist; er wird angenommen, nicht gespeichert), siehe applied: false. 204, wenn vermerkt, 400 bei fehlerhaftem Body, 409, wenn die Version nicht die aktuelle ist, 404 bei unbekanntem Paket. Die Version wird zuerst geprüft: Ein unbekanntes Paket mit alter Version bekommt 409. Ein Body ohne applied gilt als applied: false. |
GET /v1/events |
Long Poll, siehe Ohne Polling. |
Das Profil kann Geheimnisse enthalten
GET /v1/profile und GET /v1/profile/packages/{id} liefern die
Konfiguration ungeschwärzt, einschließlich der Zugangsdaten für Ihre
Zielplattform samt privatem Schlüssel. Den Socket können nur der Benutzer
des Agenten, root und Mitglieder der Gruppe bootstrap-agent öffnen
(Modus 0660). Behandeln Sie alles, was diese Aufrufe liefern, als vertraulich:
nie in ein Log, ein Ticket, einen Chat oder einen Fehlerbericht schreiben und
nie vom Gateway kopieren. Um eine Konfiguration zu zeigen, nehmen Sie die
Paketliste (/v1/profile/packages); sie enthält nur Kennungen, Versionen und
Hashes. ?pretty=1 schützt nicht: Es ergänzt Zusammenfassungen der
Zertifikate und gibt den privaten Schlüssel trotzdem vollständig aus
(geprüft auf dem Labor-Gateway). Sichere Aufrufe zum Kopieren stehen unter
Beispiele der lokalen API; die Aufrufe, die
Geheimnisse ausgeben, stehen am Ende dieser Seite.
Beispiel für die Form von GET /v1/profile (alle Werte sind erfunden und
absichtlich nicht echt; die Struktur von content hängt von Ihrem Template ab):
{"profile_version":42,"packages":[{"id":"example-package","version":42,"sha256":"EXAMPLE-NOT-A-REAL-HASH","content":{"example_key":"EXAMPLE-VALUE-NOT-REAL"}}]}
?pretty=1 an den drei Lese-Aufrufen ergänzt jeden Hash in Hex-Form
(sha256_hex) und eine Zusammenfassung jedes Zertifikats (decoded_certs). Es
rückt nicht ein (dafür | jq .) und verbirgt nichts: Ein privater Schlüssel
wird vollständig ausgegeben, wie ohne den Parameter. sha256 selbst ist
Base64, so wie die Plattform es sendet.
Die Antwort wird neu zusammengesetzt; bilden oder vergleichen Sie Hashes einer
Konfiguration deshalb nur in der einfachen Form.
Zwei Wege zu bestätigen¶
Ihre Software meldet dem Agenten auf einem von zwei Wegen, dass die Konfiguration angewendet ist. Nehmen Sie die Markierungsdatei.
| Die Markierungsdatei (empfohlen) | ack über diese API |
|
|---|---|---|
| Was Ihre Software tut | Schreibt {"state":"connected"} nach /run/wlpc/target-confirmed, sobald sie mit ihrem Ziel verbunden ist, siehe Das Ziel bestätigen. |
POST /v1/profile/packages/{id}/ack mit {"profile_version": 42, "applied": true}, einmal für jedes Paket. |
| Was der Agent tut | Bestätigt jedes noch nicht bestätigte Paket mit applied: true. |
Vermerkt dieses eine Paket. |
| Was Ihre Software braucht | Die Gruppe wlpc. |
Die Gruppe bootstrap-agent, die Paket-IDs und die aktuelle profile_version. |
Die Datei ist ein Schreibvorgang und deckt jedes Paket jeder Konfiguration ab.
Rufen Sie ack nur selbst auf, wenn Ihre Software Pakete einzeln anwendet und
jedes einzeln bestätigen muss.
Was confirmed sendet. Keiner der beiden Wege sendet es direkt. Der Agent
sendet confirmed, sobald jedes Paket der aktuellen Konfiguration mit
applied: true bestätigt ist, gleich auf welchem Weg das letzte bestätigt
wurde. confirmed setzt das Gerät auf ACTIVE, und das erste confirmed
ist der einzige Schritt, der abgerechnet wird, einmal pro Gerät: nicht
complete, nicht Check-ins, und ein wiederholtes confirmed nie wieder (siehe
Bereit und bestätigt).
Ein Prozess des Agenten sendet sie einmal pro Konfiguration. Ein Paket, das auf
false zurückgesetzt und wieder bestätigt wird, lässt diesen Prozess sie nicht
noch einmal senden; nach einem Neustart sendet der neue Prozess sie für
dieselbe Konfiguration noch einmal, wenn ein Paket wieder bestätigt wird, mit
einem vorgezogenen Check-in (die letzten beiden Zeilen unten).
Wenn beide genutzt werden, gemessen mit dem Agenten von
cproto-v0.2.0-rc.2 gegen einen Testdienst (cproto/e2e/confirmpaths.sh),
jeder Fall auf einem frischen Gerät:
| Fall | Was geschah |
|---|---|
| Alle Pakete über die API bestätigt, keine Datei | confirmed wurde einmal gesendet. Eine danach geschriebene Datei änderte nichts: keine zweite Bestätigung. |
| Zwei von fünf Paketen über die API, dann die Datei | Nach den zweien keine Bestätigung. Die Datei bestätigte die übrigen drei, und confirmed wurde einmal gesendet. |
Vier mit applied: true, eines mit applied: false, dann die Datei |
Keine Bestätigung, und keine einzige Anfrage ging an die Plattform. Die Datei überschrieb danach das false mit true, und confirmed wurde einmal gesendet. |
applied: false nach der Bestätigung, die Datei noch da, dann ein Neustart |
Für das false wurde nichts gesendet. Beim Start las der Agent die Datei, bestätigte das Paket wieder mit true und sendete die Bestätigung mit einem vorgezogenen Check-in noch einmal. |
Ein Paket über die API auf false und zurück auf true, durch den Prozess, der bestätigt hatte |
Keine zweite Bestätigung. |
| Dasselbe nach einem Neustart | Die Bestätigung wurde noch einmal gesendet. |
Auf dem Labor-Gateway bestätigte die Datei alle sieben Pakete, und bei einem Agenten, der auf einer gespeicherten Konfiguration gestartet war, führte ein über die API wieder bestätigtes Paket zu einem vorgezogenen Check-in mit der Bestätigung.
Ein ack für eine ältere profile_version wird mit 409 abgelehnt, sodass
Software, die noch eine alte Konfiguration anwendet, die neue nicht als
geliefert markieren kann. Acks sind idempotent.
applied: false¶
- Auf dem Gerät: Das Paket gilt als nicht bestätigt (
"acked": falsein der Paketliste), und solange ein Paket nicht bestätigt ist, wird keinconfirmedgesendet. Der Wert wird gespeichert und übersteht einen Neustart. Einreasonwird angenommen, aber weder gespeichert noch gesendet. - Bei der Plattform: nichts. Der Agent sendet für ein ack keine Anfrage,
weder mit
truenoch mitfalse; er sendet nurconfirmed, sobald alletruesind. Die Plattform kann eine gescheiterte Konfiguration nicht von einer unterscheiden, die noch angewendet wird: Sie sieht nur, dassconfirmedausbleibt. Das ist eine bekannte Lücke, siehe Bekannte Lücken und Grenzen. - Die Datei gewinnt. Immer wenn der Agent eine Datei mit
connectedliest (wenn sie geschrieben wird, nach einer neuen Konfiguration und bei jedem Start), bestätigt er jedes nicht bestätigte Paket mitapplied: true, auch eines, das Ihre Software auffalsegesetzt hat. Software, die eine Konfiguration nicht anwenden kann, darf die Datei nicht schreiben und muss sie entfernen, falls sie da ist. - Fehlt
applied, gilt das alsfalse. Auf dem Labor-Gateway wurde ein ack nur mitprofile_versionmit204beantwortet, und das Paket stand als nicht bestätigt da.
Zustand¶
state in GET /v1/status ist einer von:
state |
Bedeutung |
|---|---|
no_config |
Es gibt (noch) keine Konfiguration. Das ist ein normaler Zustand, kein Fehler, und er kann Monate dauern: Ein Gerät im Regal, das niemand beansprucht hat, bleibt hier. Es ist auch der Zustand, nachdem die Plattform das Gerät abgewiesen hat (unbekannt, nicht beansprucht, gesperrt); den Grund nennt last_error_code. Ihre Software muss ihn beliebig lange aushalten, ohne abzustürzen, ihren Start zu blockieren oder Alarm zu schlagen. |
bootstrapping |
Eine Ersteinrichtung läuft. |
ready |
Eine Konfiguration ist gespeichert und wird ausgeliefert. |
error |
Ein lokaler Fehler: ein defektes TPM, Speicher, der nicht beschreibbar ist, eine fehlende Plattformadresse. Ein Bescheid der Plattform versetzt den Agenten nie hierher. |
Weitere Felder: profile_version (ein undurchsichtiger Wert, vergleichen Sie
nur mit == und !=; eine höhere Zahl heißt nicht neuer), last_checkin,
last_error_code (fehlt, solange es keinen gibt), tpm_transient_avail und
tpm_transient_capacity (freie und gesamte transiente TPM-Plätze),
tpm_transient_used, tpm_loaded_sessions, identity_cert_state,
auth_mode, auth_mode_source, activation (in diesem Agenten immer
listen) und profile_ready_marker (der Pfad der Markerdatei). Ob es ein
neueres Feld gibt, erkennen Sie an interface_minor_version.
last_error_code trägt den öffentlichen Fehlercode der Plattform unverändert
oder einen der eigenen TPM-Fehlercodes des Agenten, zum Beispiel
TPM_STUCK_POWER_CYCLE_REQUIRED, siehe TPM-Slots.
Eine Ablehnung, die die Plattform bei einem späteren Check-in schickt, setzt
ihn ebenfalls, und ein Gerät, das eine Konfiguration hält, bleibt ready. Die
Konsole zeigt einen solchen abgewiesenen Kontakt nicht, siehe
Bekannte Lücken und Grenzen; lesen Sie ihn hier oder im
Log des Agenten ab.
Fehler¶
Eine Fehlerantwort ist {"code": "..."} mit einem von NO_CONFIG,
NOT_FOUND, MALFORMED_REQUEST, STALE_PROFILE_VERSION oder INTERNAL. Ein
unbekannter Pfad bekommt 404 mit NOT_FOUND. Ebenso eine Methode, die ein
Pfad nicht annimmt (zum Beispiel POST oder DELETE auf /v1/status, GET
auf .../ack): 404, nicht 405. Was
zu tun ist, wenn ein Gerät in no_config bleibt, steht unter
Fehlerbehebung.
Ohne Polling¶
Sie müssen GET /v1/status nicht jede Sekunde oder alle zwei Sekunden
abfragen, um von einer neuen Konfiguration zu erfahren. Stattdessen zwei Wege:
- Long Poll.
GET /v1/events?profile_version=PROFILE_VERSIONwartet, bis sich die Version ändert (Antwort200mit der neuenprofile_version) oder 60 Sekunden vergehen (204). Ist die übergebene Version schon veraltet, antwortet er sofort, sodass eine Änderung zwischen zwei Abfragen nicht verloren geht. Eine geschlossene Keep-alive-Verbindung ist normal; verbinden Sie sich neu. - Eine Markerdatei. Nach jeder neu gespeicherten Konfiguration, und erst
wenn sie sicher geschrieben ist, ersetzt der Agent die Datei
/etc/iot-config/profile-ready. Eine systemd-Path-Unit reagiert darauf, siehe Software starten und bestätigen. Ein unveränderter Check-in berührt die Datei nicht.