Zugriffsprotokoll der Registry
Das Audit-Log erfasst administrative Aktionen. Das
Zugriffsprotokoll der Registry erfasst etwas anderes: jede Anfrage, die ein Client an
die Paket- und Container-Registry deiner Organisation stellt. Dazu gehören jeder
Download, jeder Metadaten-Abruf (ein npm-Packument, ein PyPI-Simple-Index, eine Maven-
maven-metadata.xml), jeder Upload und jedes Löschen, auch Anfragen,
die eine Richtlinie blockiert hat. Es wird nichts stichprobenartig erfasst, mit zwei Ausnahmen für routinemäßigen CI-
Verkehr über den Dependency-Proxy.
Beide gelten nur für eine Anfrage, die ein Forgejo-Actions-Job gestellt hat, die der Proxy
zugelassen und ohne Fehler beantwortet hat:
- Metadaten-Abrufe aus CI werden nicht erfasst (seit 2026-10-12). Ein Paketindex
oder eine Versionsliste (ein npm-Packument, ein PyPI-Simple-Index, eine Maven-
maven-metadata.xml), die ein Job abruft, wird nicht gespeichert. Eine einzige Paketinstallation erzeugt Hunderte solcher Abrufe, und sie sagen nichts, was der anschließende Download nicht auch sagt. - CI-Downloads aus dem Proxy-Cache werden gezählt, nicht einzeln protokolliert (seit 2026-10-13). Lädt ein Job eine Paketdatei herunter, die der Proxy bereits vorhält, wird der Download dem Pull-Zensus hinzugefügt, statt als Ereignis gespeichert zu werden: ein Zählwert pro UTC-Tag, Paketversion und Repository, mit den IDs der Actions-Läufe, die es geladen haben. So siehst du im Zensus weiterhin, welche Version welches Pakets in welchen Build gelangt ist, aufgeschlüsselt nach Lauf.
Alles andere bleibt ein Ereignis, CI eingeschlossen:
- jeder Download, den der Proxy aus der Upstream-Registry geholt hat (ein Cache- Miss), und jeder Download aus deiner eigenen Registry
- jede Anfrage, die eine Richtlinie abgewiesen, blockiert oder blockiert hätte
- jede Anfrage, die fehlgeschlagen ist (Status 400 oder höher)
- jede Anfrage von einer Person, einem Bot, einem Registry-Robot oder anonym, einschließlich Metadaten-Abrufen und Cache-Treffern
Ein CI-Download, der im Zensus gezählt wird, behält Paket, Version, Tag,
Repository und Lauf sowie die Anzahl der Pulls. Was ein Ereignis darüber hinaus enthält, behält er nicht:
den Dateinamen, die Größe, den genauen Zeitpunkt jedes Pulls (der
Zensus hat den ersten und den letzten des Tages), die Client-Adresse, den User-Agent
und die Request-ID. Er wird nicht an einen SIEM-Endpunkt geliefert und steht nicht in
access-log.ndjson; er steht in der Zensus-API und in
metadata/pulled-versions.ndjson im Datenexport. Ereignisse, die vor
diesen Daten gespeichert wurden, werden für ihre normale Aufbewahrungsdauer behalten.
Was ein Ereignis enthält
| Feld | Bedeutung |
|---|---|
occurred_at | Wann fremforge die Anfrage beantwortet hat (UTC). |
origin | Welche Komponente die Anfrage gesehen hat: registry für die Paket-Registry. Der Dependency-Proxy schreibt proxy. |
surface | api (/api/packages/…), oci (/v2/…, die Container-Registry) oder web (eine über die Weboberfläche heruntergeladene Datei). |
org, package.type, package.name, package.version, package.file | Was angefragt wurde. |
repo | Bei einer Anfrage mit dem Job-Token eines Forgejo-Actions-Jobs: das Repository des Jobs, <owner>/<repo>. Sonst leer. |
actions | Bei einer Anfrage mit dem Job-Token eines Forgejo-Actions-Jobs: der Lauf, aus dem sie kam, {repo_id, run_id, run_number, job_id}. run_number ist die Seite des Laufs, /<owner>/<repo>/actions/runs/<run_number>; run_id ist GITHUB_RUN_ID. null bei jeder anderen Anfrage und bei Anfragen, die vor 2026-10-08 erfasst wurden. |
package.digest | sha256:<hex> der Datei oder des Manifests, die ausgeliefert oder gespeichert wurden, sofern die Registry ihn genannt hat. |
action | download, metadata, upload, delete oder other. |
actor | Wen die Registry authentifiziert hat: {type: "user" | "bot" | "anonymous", id, login}. Ein Token oder eine Sitzung wird dem Benutzer zugeordnet, dem sie gehört, und Forgejo-Actions-Jobs erscheinen als Bot. |
client_ip | Die Client-Adresse, wie der Edge von fremforge sie gesehen hat. Leer, wenn fremforge die Adresse nicht verifizieren konnte, zum Beispiel bei einer Anfrage, die nicht über den Edge kam. |
user_agent | Der User-Agent des Clients, nach 256 Zeichen abgeschnitten. |
http.method, http.status, http.bytes | Die Request-Methode, die Antwort und die Größe, soweit bekannt. Bei einem Download, der auf den Objektspeicher umgeleitet wird, ist die Größe unbekannt. Eine HEAD-Anfrage erscheint als GET, weil das CDN HEAD-Anfragen als GET an die Registry weiterleitet. |
decision, decision_reason | allowed; blocked; would_block (eine Richtlinie im Schattenmodus oder deine Image-Scan-Sperraktion warn hätte sie abgewiesen, und die Anfrage ging durch); oder pending_refused (deine Paketrichtlinie weist Dateien ab, deren Scan noch nicht abgeschlossen ist, und der Scan dieser Datei war es nicht; der Client bekam 503 mit Retry-After, und ein erneuter Versuch nach Abschluss des Scans gelingt). decision_reason nennt die Regel, die entschieden hat, zum Beispiel malware, image_malware, image_cve, registry_scan:<reason> oder immutable_retired (siehe unveränderliche Paketversionen). |
Nie erfasst: ein Access Token, ein Authorization-Header, ein Cookie oder ein
Query-String. Eine vorsignierte Speicher-URL zum Beispiel erscheint nie in einem
Ereignis.
Auslesen
Mit einem Token, das audit:read trägt:
curl -sS -H "Authorization: Bearer $FFP_TOKEN" \
"https://frem.sh/_app/api/v1/orgs/acme/access-log?action=download&type=npm&since=2026-10-01"Die Ergebnisse kommen mit dem neuesten zuerst. Übergib den Wert next einer Seite als cursor, um
die nächste Seite zu erhalten, und hör auf, wenn next null ist. Der Cursor ist ein Keyset, sodass
Ereignisse, die während des Blätterns eintreffen, nie eine Zeile verschieben oder wiederholen. Filter:
since, until, origin, action, decision, type, name, version,
actor (ein Login oder anonymous) und ip. Eine Seite enthält bis zu 500 Ereignisse.
Die vollständige Struktur steht in der API-Referenz.
Welche verwundbaren Versionen geladen werden
Der Pull-Zensus zählt die erfolgreichen Downloads in
diesem Protokoll pro Paketversion und Konsument, zusammen mit den CI-Cache-Treffern,
die dort gezählt statt protokolliert werden, und verknüpft sie mit den Advisories,
die deine Paketrichtlinie verwendet. Er beantwortet „Welche verwundbaren Versionen wurden in
den letzten 30 Tagen geladen, und von wem", ohne dass du durch die Rohereignisse blättern musst, und
run_id beantwortet „Welche Versionen hat dieser Build geladen".
Weiterleitung an dein SIEM
Zugriffsereignisse können an einen SIEM-Endpunkt geliefert werden, im
selben signierten Umschlag wie Audit-Ereignisse. Die Aktion ist
registry.access.<action> (zum Beispiel registry.access.download), und
hash_chain ist null, weil Zugriffsereignisse nicht Teil der Audit-Hash-Kette
sind. Die Zustellung ist standardmäßig aus, weil der Download-Verkehr weit
größer ist als der Audit-Verkehr. Schalte sie pro Endpunkt mit include_access_log ein:
curl -sS -X PATCH -H "Authorization: Bearer $FFP_TOKEN" -H 'Content-Type: application/json' \
-d '{"include_access_log": true}' \
https://frem.sh/_app/api/v1/orgs/acme/siem/endpoints/$ENDPOINT_IDDie Aktionspräfixe eines Endpunkts gelten auch für Zugriffsereignisse. Zum Beispiel
leitet registry.access.upload nur Uploads weiter. Der CI-Verkehr, der nicht
als Ereignis gespeichert wird (siehe oben), wird auch nicht geliefert.
Im Datenexport
Ein Datenexport enthält access-log.ndjson mit jedem
Zugriffsereignis, das fremforge für die Organisation noch vorhält, ein JSON-Objekt pro
Zeile in derselben Struktur, die die API liefert, und metadata/pulled-versions.ndjson
mit dem Pull-Zensus, in dem CI-Cache-Treffer gezählt werden. Beide Dateien sind
durch das signierte Manifest des Exports abgedeckt.
Wie lange es aufbewahrt wird
Zugriffsereignisse werden gemäß der Einstellung access_log der
Aufbewahrung von Nachweisen deiner Organisation aufbewahrt: 30 bis 730 Tage. Ist sie nicht gesetzt,
folgt sie der Aufbewahrung des Audit-Logs (90, 180, 365 oder 730 Tage, eingestellt unter
Authentifizierungsrichtlinie → Aufbewahrung des Audit-Logs; Standard 90). Ältere Ereignisse werden
einmal täglich gelöscht. Solange ein Legal Hold besteht, wird nichts gelöscht.
Wer die Adressen sehen kann
Das Zugriffsprotokoll enthält personenbezogene Daten: die Logins und IP-Adressen deiner Nutzer. Die API, die SIEM-Zustellung und der Export zeigen beides so, wie es erfasst wurde, denn dies ist der eigene Datensatz deiner Organisation. Die Werkzeuge der fremforge-Mitarbeitenden sehen beides nur als schlüsselbasierte Pseudonyme. Protokollzeilen, die die Plattform für ihren eigenen Betrieb schreibt, enthalten keines von beiden.
Grenzen
- Git-Clone und -Fetch sowie Abrufe über die REST-API (
/api/v1) sind keine Registry-Anfragen und stehen noch nicht in diesem Protokoll. - Das Löschen einer Paketversion über die REST-API
(
DELETE /api/v1/packages/...) oder die Weboberfläche wird hier nicht erfasst. Das Löschen durch einen Registry-Client unter/api/packageswird erfasst. - Eine Anfrage, die die Plattform abgewiesen hat, bevor die Registry geantwortet hat, etwa ein
Upload, den der Malware-Scanner zurückgewiesen hat, hat keinen authentifizierten Akteur und
erscheint als
anonymous. - Die Zustellung von der Registry an das Protokoll erfolgt gebündelt alle 2 Sekunden oder alle 500 Ereignisse. Wird die Plattform mitten in einem Bündel neu gestartet, können die Ereignisse der letzten Sekunden verloren gehen. Bewusste Verwerfungen werden auf unserer Seite protokolliert und lösen einen Alarm aus.