Is your feature request related to a problem? Please describe.
I am building a SaaS platform / multi-tenant system on top of Zot and heavily rely on the events extension (specifically the http sink) to react to pushes, calculate billing, and write audit logs.
While the usage of the CloudEvents standard is fantastic, the event payload itself is missing critical context. Currently, events like zotregistry.image.updated only include name, reference, digest, mediaType, and manifest.
Crucially, it is impossible to know WHO triggered the event.
To maintain a proper audit trail or correlate actions to specific users/teams, downstream systems need to know the identity of the authenticated user (actor) and ideally metadata about the HTTP request (IP address, user-agent), similar to how distribution/distribution handles its webhook payloads.
Describe the solution you'd like
Looking at the codebase, this omission seems to be a side effect of where events are fired. The eventRecorder is tightly coupled to the storage layer (passed via storage.New(...)).
When a push happens, the api layer knows the actor via reqCtx.UserAcFromContext(request.Context()) in UpdateManifest (pkg/api/routes.go). However, this context is not passed down to imgStore.PutImageManifest(...). Thus, when the storage layer finally triggers ImageUpdated, the HTTP and Authentication context has been completely lost.
Interestingly, Zot already recognizes the importance of tracking the actor! Right after the storage operation completes in UpdateManifest, Zot calls meta.OnUpdateManifest(request.Context(), ...). By passing the HTTP context to the meta extension, the database layers (e.g., boltdb.go) are able to extract the user and successfully populate the PushedBy field in DescriptorStatistics. This data is just currently siloed in the MetaDB and never reaches the event system.
I would like the CloudEvents data payload to include information about the actor and the request. For example:
{
"name": "space/my-image",
"reference": "latest",
"actor": {
"name": "username_or_token_subject"
},
"request": {
"addr": "192.168.0.1",
"method": "PUT",
"useragent": "docker/24.0.5"
}
}
Describe alternatives you've considered
Querying the GraphQL API / MetaDB: Knowing that Zot already tracks the actor internally via the meta extension (populating the PushedBy field in DescriptorStatistics within the database), the natural alternative was to simply let the webhook trigger a synchronous GraphQL query back to Zot to ask for the actor. However, this is currently impossible, because the PushedBy field is not exposed in the ImageSummary GraphQL schema (pkg/extensions/search/schema.graphql). Therefore, I have no way to retrieve this internal data without parsing raw DB files.
Auth Token Correlation: Since my SaaS acts as the identity provider (issuing JWTs for Zot), I could temporarily cache whenever a user requests a push token for a specific repository. When the Zot webhook arrives a few seconds later, I correlate the webhook's name (repo) with the cached token intent. While this works as a band-aid, it adds stateful caching complexity, is susceptible to race conditions, and completely leaves out users relying on standard htpasswd or LDAP authentication.
Additional context
No response
Is your feature request related to a problem? Please describe.
I am building a SaaS platform / multi-tenant system on top of Zot and heavily rely on the
eventsextension (specifically thehttpsink) to react to pushes, calculate billing, and write audit logs.While the usage of the CloudEvents standard is fantastic, the event payload itself is missing critical context. Currently, events like
zotregistry.image.updatedonly includename,reference,digest,mediaType, andmanifest.Crucially, it is impossible to know WHO triggered the event.
To maintain a proper audit trail or correlate actions to specific users/teams, downstream systems need to know the identity of the authenticated user (
actor) and ideally metadata about the HTTP request (IP address, user-agent), similar to howdistribution/distributionhandles its webhook payloads.Describe the solution you'd like
Looking at the codebase, this omission seems to be a side effect of where events are fired. The
eventRecorderis tightly coupled to the storage layer (passed viastorage.New(...)).When a push happens, the api layer knows the actor via
reqCtx.UserAcFromContext(request.Context())in UpdateManifest (pkg/api/routes.go). However, this context is not passed down toimgStore.PutImageManifest(...). Thus, when the storage layer finally triggersImageUpdated, the HTTP and Authentication context has been completely lost.Interestingly, Zot already recognizes the importance of tracking the actor! Right after the storage operation completes in
UpdateManifest, Zot callsmeta.OnUpdateManifest(request.Context(), ...). By passing the HTTP context to themetaextension, the database layers (e.g., boltdb.go) are able to extract the user and successfully populate thePushedByfield inDescriptorStatistics. This data is just currently siloed in the MetaDB and never reaches the event system.I would like the CloudEvents data payload to include information about the actor and the request. For example:
{ "name": "space/my-image", "reference": "latest", "actor": { "name": "username_or_token_subject" }, "request": { "addr": "192.168.0.1", "method": "PUT", "useragent": "docker/24.0.5" } }Describe alternatives you've considered
Querying the GraphQL API / MetaDB: Knowing that Zot already tracks the actor internally via the
metaextension (populating thePushedByfield inDescriptorStatisticswithin the database), the natural alternative was to simply let the webhook trigger a synchronous GraphQL query back to Zot to ask for the actor. However, this is currently impossible, because thePushedByfield is not exposed in theImageSummaryGraphQL schema (pkg/extensions/search/schema.graphql). Therefore, I have no way to retrieve this internal data without parsing raw DB files.Auth Token Correlation: Since my SaaS acts as the identity provider (issuing JWTs for Zot), I could temporarily cache whenever a user requests a push token for a specific repository. When the Zot webhook arrives a few seconds later, I correlate the webhook's name (repo) with the cached token intent. While this works as a band-aid, it adds stateful caching complexity, is susceptible to race conditions, and completely leaves out users relying on standard htpasswd or LDAP authentication.
Additional context
No response