From a47f17ef78908843e4f8267b16398270bcc2ec2d Mon Sep 17 00:00:00 2001 From: Jatin Agrawal Date: Wed, 11 Feb 2026 16:41:13 +0530 Subject: [PATCH 01/11] upload and download insertions for artifact audit --- cmd/gitness/wire_gen.go | 2 +- .../api/controller/pkg/generic/controller.go | 21 +++++++++++++++++-- .../app/api/controller/pkg/generic/wire.go | 3 +++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index 412baf1827..e320ec6420 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -653,7 +653,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro genericLocalRegistry := generic2.LocalRegistryProvider(localBase, fileManager, upstreamProxyConfigRepository, transactor, registryRepository, imageRepository, artifactRepository, provider) localRegistryHelper := generic2.LocalRegistryHelperProvider(genericLocalRegistry, localBase) proxy := generic2.ProxyProvider(upstreamProxyConfigRepository, registryRepository, imageRepository, artifactRepository, fileManager, transactor, provider, spaceFinder, secretService, localRegistryHelper) - genericController := generic.ControllerProvider(spaceStore, authorizer, fileManager, genericDBStore, transactor, spaceFinder, genericLocalRegistry, proxy, finder, dependencyFirewallChecker) + genericController := generic.ControllerProvider(spaceStore, authorizer, fileManager, genericDBStore, transactor, spaceFinder, genericLocalRegistry, proxy, finder, dependencyFirewallChecker, auditService) packagesHandler := api2.NewPackageHandlerProvider(registryRepository, downloadStatRepository, bandwidthStatRepository, spaceStore, tokenStore, controller, authenticator, provider, authorizer, spaceFinder, registryFinder, fileManager, finder, packageWrapper) genericHandler := api2.NewGenericHandlerProvider(spaceStore, genericController, tokenStore, controller, authenticator, provider, authorizer, packagesHandler, spaceFinder, registryFinder) handler3 := router.GenericHandlerProvider(genericHandler) diff --git a/registry/app/api/controller/pkg/generic/controller.go b/registry/app/api/controller/pkg/generic/controller.go index 54934ec68f..ff1c9c2d46 100644 --- a/registry/app/api/controller/pkg/generic/controller.go +++ b/registry/app/api/controller/pkg/generic/controller.go @@ -30,10 +30,12 @@ import ( "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/services/refcache" corestore "github.com/harness/gitness/app/store" + "github.com/harness/gitness/audit" "github.com/harness/gitness/registry/app/api/interfaces" "github.com/harness/gitness/registry/app/dist_temp/errcode" "github.com/harness/gitness/registry/app/metadata" "github.com/harness/gitness/registry/app/pkg" + registryaudit "github.com/harness/gitness/registry/app/pkg/audit" "github.com/harness/gitness/registry/app/pkg/commons" "github.com/harness/gitness/registry/app/pkg/filemanager" "github.com/harness/gitness/registry/app/pkg/generic" @@ -56,6 +58,7 @@ type Controller struct { proxy generic.Proxy quarantineFinder quarantine.Finder dependencyFirewallChecker interfaces.DependencyFirewallChecker + auditService audit.Service } type DBStore struct { @@ -78,6 +81,7 @@ func NewController( proxy generic.Proxy, quarantineFinder quarantine.Finder, dependencyFirewallChecker interfaces.DependencyFirewallChecker, + auditService audit.Service, ) *Controller { return &Controller{ SpaceStore: spaceStore, @@ -90,6 +94,7 @@ func NewController( proxy: proxy, quarantineFinder: quarantineFinder, dependencyFirewallChecker: dependencyFirewallChecker, + auditService: auditService, } } @@ -137,6 +142,8 @@ func (c Controller) UploadArtifact( if err != nil { return responseHeaders, "", errcode.ErrCodeUnknown.WithDetail(err) } + var imageUUID string + var artifactUUID string err = c.tx.WithTx( ctx, func(ctx context.Context) error { image := &types.Image{ @@ -149,6 +156,7 @@ func (c Controller) UploadArtifact( return fmt.Errorf("failed to create image for artifact : [%s] with "+ regNameFormat, info.Image, info.RegIdentifier) } + imageUUID = image.UUID dbArtifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version) @@ -173,21 +181,30 @@ func (c Controller) UploadArtifact( regNameFormat, info.Image, info.RegIdentifier) } - _, err = c.DBStore.ArtifactDao.CreateOrUpdate(ctx, &types.Artifact{ + newArtifact := &types.Artifact{ ImageID: image.ID, Version: info.Version, Metadata: metadataJSON, - }) + } + _, err = c.DBStore.ArtifactDao.CreateOrUpdate(ctx, newArtifact) if err != nil { return fmt.Errorf("failed to create artifact : [%s] with "+ regNameFormat, info.Image, info.RegIdentifier) } + artifactUUID = newArtifact.UUID return nil }) if err != nil { return responseHeaders, "", errcode.ErrCodeUnknown.WithDetail(err) } + + // Audit log for artifact push + registryaudit.LogArtifactPush( + ctx, c.auditService, c.spaceFinder, *info.ArtifactInfo, + info.Version, imageUUID, artifactUUID, + ) + responseHeaders.Code = http.StatusCreated return responseHeaders, fileInfo.Sha256, errcode.Error{} } diff --git a/registry/app/api/controller/pkg/generic/wire.go b/registry/app/api/controller/pkg/generic/wire.go index 81940773e8..cf5748ed46 100644 --- a/registry/app/api/controller/pkg/generic/wire.go +++ b/registry/app/api/controller/pkg/generic/wire.go @@ -18,6 +18,7 @@ import ( "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/services/refcache" gitnessstore "github.com/harness/gitness/app/store" + "github.com/harness/gitness/audit" "github.com/harness/gitness/registry/app/api/interfaces" "github.com/harness/gitness/registry/app/pkg/filemanager" "github.com/harness/gitness/registry/app/pkg/generic" @@ -49,6 +50,7 @@ func ControllerProvider( proxy generic.Proxy, quarantineFinder quarantine.Finder, dependencyFirewallChecker interfaces.DependencyFirewallChecker, + auditService audit.Service, ) *Controller { return NewController( spaceStore, @@ -61,6 +63,7 @@ func ControllerProvider( proxy, quarantineFinder, dependencyFirewallChecker, + auditService, ) } From c080f51dc8ad8ac2bb4be8ffed5593c05d153690 Mon Sep 17 00:00:00 2001 From: Jatin Agrawal Date: Wed, 11 Feb 2026 18:40:12 +0530 Subject: [PATCH 02/11] added changes --- cmd/gitness/wire_gen.go | 8 +- .../api/controller/pkg/generic/controller.go | 2 +- registry/app/api/handler/generic/base.go | 5 +- .../app/api/handler/huggingface/handler.go | 2 + registry/app/api/handler/maven/base.go | 5 +- registry/app/api/handler/oci/base.go | 4 + registry/app/api/handler/packages/handler.go | 35 +++++ registry/app/api/middleware/download_stats.go | 136 ++++++++++++++---- registry/app/api/wire.go | 13 +- registry/app/pkg/audit/artifact.go | 51 ++++++- registry/app/pkg/base/base.go | 3 +- registry/app/pkg/docker/manifest_service.go | 2 +- 12 files changed, 221 insertions(+), 45 deletions(-) diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index e320ec6420..1c2b072525 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -611,7 +611,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro evictor5 := publicaccess2.ProvideEvictorPublicAccess(pubSub) publicaccessCache := publicaccess2.ProvidePublicAccessCache(ctx, publicaccessService, evictor5) cacheService := publicaccess2.ProvideRegistryPublicAccess(publicaccessService, publicaccessCache, evictor5) - handler := api2.NewHandlerProvider(dockerController, spaceFinder, spaceStore, tokenStore, controller, authenticator, provider, authorizer, config, registryFinder, cacheService) + handler := api2.NewHandlerProvider(dockerController, spaceFinder, spaceStore, tokenStore, controller, authenticator, provider, authorizer, config, registryFinder, cacheService, auditService) registryOCIHandler := router.OCIHandlerProvider(handler) genericBlobRepository := database2.ProvideGenericBlobDao(db) nodesRepository := database2.ProvideNodeDao(db) @@ -647,15 +647,15 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro mavenRemoteRegistry := maven.RemoteRegistryProvider(mavenDBStore, transactor, mavenLocalRegistry, mavenController) dependencyFirewallChecker := helpers.NewNoopDependencyFirewallChecker() controller2 := maven.ControllerProvider(mavenLocalRegistry, mavenRemoteRegistry, authorizer, mavenDBStore, spaceFinder, finder, dependencyFirewallChecker) - mavenHandler := api2.NewMavenHandlerProvider(controller2, spaceStore, tokenStore, controller, authenticator, authorizer, spaceFinder, registryFinder, cacheService) + mavenHandler := api2.NewMavenHandlerProvider(controller2, spaceStore, tokenStore, controller, authenticator, authorizer, spaceFinder, registryFinder, cacheService, auditService) handler2 := router.MavenHandlerProvider(mavenHandler) genericDBStore := generic.DBStoreProvider(imageRepository, artifactRepository, bandwidthStatRepository, downloadStatRepository, registryRepository) genericLocalRegistry := generic2.LocalRegistryProvider(localBase, fileManager, upstreamProxyConfigRepository, transactor, registryRepository, imageRepository, artifactRepository, provider) localRegistryHelper := generic2.LocalRegistryHelperProvider(genericLocalRegistry, localBase) proxy := generic2.ProxyProvider(upstreamProxyConfigRepository, registryRepository, imageRepository, artifactRepository, fileManager, transactor, provider, spaceFinder, secretService, localRegistryHelper) genericController := generic.ControllerProvider(spaceStore, authorizer, fileManager, genericDBStore, transactor, spaceFinder, genericLocalRegistry, proxy, finder, dependencyFirewallChecker, auditService) - packagesHandler := api2.NewPackageHandlerProvider(registryRepository, downloadStatRepository, bandwidthStatRepository, spaceStore, tokenStore, controller, authenticator, provider, authorizer, spaceFinder, registryFinder, fileManager, finder, packageWrapper) - genericHandler := api2.NewGenericHandlerProvider(spaceStore, genericController, tokenStore, controller, authenticator, provider, authorizer, packagesHandler, spaceFinder, registryFinder) + packagesHandler := api2.NewPackageHandlerProvider(registryRepository, downloadStatRepository, bandwidthStatRepository, spaceStore, tokenStore, controller, authenticator, provider, authorizer, spaceFinder, registryFinder, fileManager, finder, packageWrapper, auditService, artifactRepository) + genericHandler := api2.NewGenericHandlerProvider(spaceStore, genericController, tokenStore, controller, authenticator, provider, authorizer, packagesHandler, spaceFinder, registryFinder, auditService) handler3 := router.GenericHandlerProvider(genericHandler) pythonLocalRegistry := python.LocalRegistryProvider(localBase, fileManager, upstreamProxyConfigRepository, transactor, registryRepository, registryFinder, imageRepository, artifactRepository, provider) pythonLocalRegistryHelper := python.LocalRegistryHelperProvider(pythonLocalRegistry, localBase) diff --git a/registry/app/api/controller/pkg/generic/controller.go b/registry/app/api/controller/pkg/generic/controller.go index ff1c9c2d46..a58bb3e03c 100644 --- a/registry/app/api/controller/pkg/generic/controller.go +++ b/registry/app/api/controller/pkg/generic/controller.go @@ -200,7 +200,7 @@ func (c Controller) UploadArtifact( } // Audit log for artifact push - registryaudit.LogArtifactPush( + registryaudit.LogArtifactUpload( ctx, c.auditService, c.spaceFinder, *info.ArtifactInfo, info.Version, imageUUID, artifactUUID, ) diff --git a/registry/app/api/handler/generic/base.go b/registry/app/api/handler/generic/base.go index 32702a47a2..82bc6def0d 100644 --- a/registry/app/api/handler/generic/base.go +++ b/registry/app/api/handler/generic/base.go @@ -30,6 +30,7 @@ import ( "github.com/harness/gitness/app/services/refcache" corestore "github.com/harness/gitness/app/store" urlprovider "github.com/harness/gitness/app/url" + "github.com/harness/gitness/audit" "github.com/harness/gitness/registry/app/api/controller/metadata" "github.com/harness/gitness/registry/app/api/controller/pkg/generic" "github.com/harness/gitness/registry/app/api/handler/packages" @@ -65,7 +66,7 @@ func NewGenericArtifactHandler( spaceStore corestore.SpaceStore, controller *generic.Controller, tokenStore corestore.TokenStore, userCtrl *usercontroller.Controller, authenticator authn.Authenticator, urlProvider urlprovider.Provider, authorizer authz.Authorizer, packageHandler packages.Handler, spaceFinder refcache.SpaceFinder, - registryFinder refcache2.RegistryFinder, + registryFinder refcache2.RegistryFinder, auditService audit.Service, ) *Handler { return &Handler{ Handler: packageHandler, @@ -78,6 +79,7 @@ func NewGenericArtifactHandler( Authorizer: authorizer, SpaceFinder: spaceFinder, RegistryFinder: registryFinder, + AuditService: auditService, } } @@ -92,6 +94,7 @@ type Handler struct { Authorizer authz.Authorizer SpaceFinder refcache.SpaceFinder RegistryFinder refcache2.RegistryFinder + AuditService audit.Service } //nolint:staticcheck diff --git a/registry/app/api/handler/huggingface/handler.go b/registry/app/api/handler/huggingface/handler.go index 5fd2b56848..331aa8eceb 100644 --- a/registry/app/api/handler/huggingface/handler.go +++ b/registry/app/api/handler/huggingface/handler.go @@ -109,6 +109,8 @@ func (h *handler) GetPackageArtifactInfo(r *http.Request) (pkg.PackageArtifactIn rev = "main" } info.Image = repo + // Set artifact type in the base ArtifactInfo for audit logging + info.ArtifactType = artifactType return &hftype.ArtifactInfo{ ArtifactInfo: info, diff --git a/registry/app/api/handler/maven/base.go b/registry/app/api/handler/maven/base.go index eaabc8c69c..ca8534508a 100644 --- a/registry/app/api/handler/maven/base.go +++ b/registry/app/api/handler/maven/base.go @@ -31,6 +31,7 @@ import ( "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/refcache" corestore "github.com/harness/gitness/app/store" + "github.com/harness/gitness/audit" "github.com/harness/gitness/registry/app/api/controller/metadata" "github.com/harness/gitness/registry/app/api/handler/utils" "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact" @@ -56,13 +57,14 @@ type Handler struct { SpaceFinder refcache.SpaceFinder RegistryFinder refcache2.RegistryFinder PublicAccessService publicaccess.Service + AuditService audit.Service } func NewHandler( controller *maven.Controller, spaceStore corestore.SpaceStore, tokenStore corestore.TokenStore, userCtrl *usercontroller.Controller, authenticator authn.Authenticator, authorizer authz.Authorizer, spaceFinder refcache.SpaceFinder, registryFinder refcache2.RegistryFinder, - publicAccessService publicaccess.Service, + publicAccessService publicaccess.Service, auditService audit.Service, ) *Handler { return &Handler{ Controller: controller, @@ -74,6 +76,7 @@ func NewHandler( SpaceFinder: spaceFinder, RegistryFinder: registryFinder, PublicAccessService: publicAccessService, + AuditService: auditService, } } diff --git a/registry/app/api/handler/oci/base.go b/registry/app/api/handler/oci/base.go index a140992ab7..beb6ca1042 100644 --- a/registry/app/api/handler/oci/base.go +++ b/registry/app/api/handler/oci/base.go @@ -27,6 +27,7 @@ import ( "github.com/harness/gitness/app/services/refcache" corestore "github.com/harness/gitness/app/store" urlprovider "github.com/harness/gitness/app/url" + "github.com/harness/gitness/audit" "github.com/harness/gitness/registry/app/api/handler/utils" "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact" "github.com/harness/gitness/registry/app/common" @@ -56,6 +57,7 @@ func NewHandler( registryFinder refcache2.RegistryFinder, publicAccessService publicaccess.Service, anonymousUserSecret string, + auditService audit.Service, ) *Handler { return &Handler{ Controller: controller, @@ -70,6 +72,7 @@ func NewHandler( OCIRelativeURL: ociRelativeURL, PublicAccessService: publicAccessService, AnonymousUserSecret: anonymousUserSecret, + AuditService: auditService, } } @@ -86,6 +89,7 @@ type Handler struct { OCIRelativeURL bool PublicAccessService publicaccess.Service AnonymousUserSecret string + AuditService audit.Service } type routeType string diff --git a/registry/app/api/handler/packages/handler.go b/registry/app/api/handler/packages/handler.go index 189653799d..a3e99ccdf0 100644 --- a/registry/app/api/handler/packages/handler.go +++ b/registry/app/api/handler/packages/handler.go @@ -31,10 +31,12 @@ import ( "github.com/harness/gitness/app/services/refcache" corestore "github.com/harness/gitness/app/store" urlprovider "github.com/harness/gitness/app/url" + "github.com/harness/gitness/audit" "github.com/harness/gitness/registry/app/api/interfaces" "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact" "github.com/harness/gitness/registry/app/dist_temp/errcode" "github.com/harness/gitness/registry/app/pkg" + pkgaudit "github.com/harness/gitness/registry/app/pkg/audit" "github.com/harness/gitness/registry/app/pkg/commons" "github.com/harness/gitness/registry/app/pkg/filemanager" "github.com/harness/gitness/registry/app/pkg/quarantine" @@ -58,6 +60,8 @@ func NewHandler( regFinder refcache2.RegistryFinder, fileManager filemanager.FileManager, quarantineFinder quarantine.Finder, packageWrapper interfaces.PackageWrapper, + auditService audit.Service, + artifactDao store.ArtifactRepository, ) Handler { return &handler{ RegistryDao: registryDao, @@ -74,6 +78,8 @@ func NewHandler( fileManager: fileManager, quarantineFinder: quarantineFinder, PackageWrapper: packageWrapper, + AuditService: auditService, + ArtifactDao: artifactDao, } } @@ -92,6 +98,8 @@ type handler struct { fileManager filemanager.FileManager quarantineFinder quarantine.Finder PackageWrapper interfaces.PackageWrapper + AuditService audit.Service + ArtifactDao store.ArtifactRepository } type Handler interface { @@ -156,9 +164,36 @@ func (h *handler) TrackDownloadStats( log.Ctx(ctx).Error().Msgf("failed to create download stat: %v", err.Error()) return usererror.ErrInternal } + + // Audit log for download operation + h.logArtifactDownloadAudit(r.Context(), info.BaseArtifactInfo(), info.GetVersion()) return nil } +func (h *handler) logArtifactDownloadAudit( + ctx context.Context, + info pkg.ArtifactInfo, + version string, +) { + var artifactUUID string + artifact, err := h.ArtifactDao.GetByRegistryImageAndVersion(ctx, info.RegistryID, info.Image, version) + if err != nil { + log.Ctx(ctx).Debug().Err(err).Msg("artifact not found for audit") + artifactUUID = "" + } else { + artifactUUID = artifact.UUID + } + + pkgaudit.LogArtifactDownload( + ctx, + h.AuditService, + h.SpaceFinder, + info, + version, + artifactUUID, + ) +} + func (h *handler) CheckQuarantineStatus( ctx context.Context, ) error { diff --git a/registry/app/api/middleware/download_stats.go b/registry/app/api/middleware/download_stats.go index f2c4e811f6..5b27295a82 100644 --- a/registry/app/api/middleware/download_stats.go +++ b/registry/app/api/middleware/download_stats.go @@ -19,6 +19,8 @@ import ( "errors" "net/http" + "github.com/harness/gitness/app/services/refcache" + "github.com/harness/gitness/audit" generic2 "github.com/harness/gitness/registry/app/api/controller/pkg/generic" "github.com/harness/gitness/registry/app/api/handler/generic" "github.com/harness/gitness/registry/app/api/handler/maven" @@ -27,6 +29,7 @@ import ( "github.com/harness/gitness/registry/app/api/router/utils" "github.com/harness/gitness/registry/app/dist_temp/errcode" "github.com/harness/gitness/registry/app/pkg" + pkgaudit "github.com/harness/gitness/registry/app/pkg/audit" "github.com/harness/gitness/registry/app/pkg/commons" "github.com/harness/gitness/registry/app/pkg/docker" gopackageutils "github.com/harness/gitness/registry/app/pkg/gopackage/utils" @@ -72,7 +75,7 @@ func TrackDownloadStat(h *oci.Handler) func(http.Handler) http.Handler { return } - err = dbDownloadStat(ctx, h.Controller, info) + err = dbDownloadStat(ctx, h.Controller, info, h.AuditService, h.SpaceFinder) if err != nil { log.Ctx(ctx).Error().Stack().Str("middleware", "TrackDownloadStat").Err(err).Msgf("error while putting download stat of artifact, %v", @@ -88,6 +91,8 @@ func dbDownloadStat( ctx context.Context, c *docker.Controller, info pkg.RegistryInfo, + auditService audit.Service, + spaceFinder refcache.SpaceFinder, ) error { registry := info.Registry @@ -104,18 +109,43 @@ func dbDownloadStat( return err } + // Try to get artifact - may not exist for upstream proxy first downloads + var artifactUUID string artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, dgst.String()) if err != nil { - return err + log.Ctx(ctx).Debug().Err(err).Msgf( + "artifact not yet cached in DB for download stats (upstream proxy first download): image=%s, digest=%s", + info.Image, dgst.String(), + ) + artifactUUID = "" + } else { + artifactUUID = artifact.UUID + + // Only create download stat if artifact exists in DB (preserves existing behavior) + downloadStat := &types.DownloadStat{ + ArtifactID: artifact.ID, + } + if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { + log.Ctx(ctx).Warn().Err(err).Msgf("failed to create download stat") + } } - downloadStat := &types.DownloadStat{ - ArtifactID: artifact.ID, + artifactInfo := pkg.ArtifactInfo{ + BaseInfo: &pkg.BaseInfo{ + ParentID: info.ParentID, + }, + RegistryID: registry.ID, + Image: info.Image, } + pkgaudit.LogArtifactDownload( + ctx, + auditService, + spaceFinder, + artifactInfo, + dgst.String(), + artifactUUID, + ) - if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { - return err - } return nil } @@ -146,7 +176,7 @@ func TrackDownloadStatForGenericArtifact(h *generic.Handler) func(http.Handler) return } - err = dbDownloadStatForGenericArtifact(ctx, h.Controller, info) + err = dbDownloadStatForGenericArtifact(ctx, h.Controller, info, h.AuditService, h.SpaceFinder) if !commons.IsEmptyError(err) { log.Ctx(ctx).Error().Stack().Str("middleware", "TrackDownloadStat").Err(err).Msgf("error while putting download stat of artifact, %v", @@ -189,7 +219,7 @@ func TrackDownloadStatForMavenArtifact(h *maven.Handler) func(http.Handler) http return } - err2 := dbDownloadStatForMavenArtifact(ctx, h.Controller, info) + err2 := dbDownloadStatForMavenArtifact(ctx, h.Controller, info, h.AuditService, h.SpaceFinder) if !commons.IsEmptyError(err2) { log.Ctx(ctx).Error().Stack().Str("middleware", "TrackDownloadStat").Err(err).Msgf("error while putting download stat of artifact, %v", @@ -205,29 +235,51 @@ func dbDownloadStatForGenericArtifact( ctx context.Context, c *generic2.Controller, info pkg.GenericArtifactInfo, + auditService audit.Service, + spaceFinder refcache.SpaceFinder, ) errcode.Error { registry, err := c.DBStore.RegistryDao.GetByParentIDAndName(ctx, info.ParentID, info.RegIdentifier) if err != nil { return errcode.ErrCodeInvalidRequest.WithDetail(err) } + var artifactUUID string image, err := c.DBStore.ImageDao.GetByName(ctx, registry.ID, info.Image) if err != nil { - return errcode.ErrCodeInvalidRequest.WithDetail(err) - } - - artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version) - if err != nil { - return errcode.ErrCodeInvalidRequest.WithDetail(err) + log.Ctx(ctx).Debug().Err(err).Msg("image not found for download stats") + artifactUUID = "" + } else { + artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version) + if err != nil { + log.Ctx(ctx).Debug().Err(err).Msg("artifact not found for download stats") + artifactUUID = "" + } else { + artifactUUID = artifact.UUID + downloadStat := &types.DownloadStat{ + ArtifactID: artifact.ID, + } + if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { + log.Ctx(ctx).Warn().Err(err).Msg("failed to create download stat") + } + } } - downloadStat := &types.DownloadStat{ - ArtifactID: artifact.ID, + artifactInfo := pkg.ArtifactInfo{ + BaseInfo: &pkg.BaseInfo{ + ParentID: info.ParentID, + }, + RegistryID: registry.ID, + Image: info.Image, } + pkgaudit.LogArtifactDownload( + ctx, + auditService, + spaceFinder, + artifactInfo, + info.Version, + artifactUUID, + ) - if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { - return errcode.ErrCodeNameUnknown.WithDetail(err) - } return errcode.Error{} } @@ -235,6 +287,8 @@ func dbDownloadStatForMavenArtifact( ctx context.Context, c *maven2.Controller, info pkg.MavenArtifactInfo, + auditService audit.Service, + spaceFinder refcache.SpaceFinder, ) errcode.Error { imageName := info.GroupID + ":" + info.ArtifactID registry, err := c.DBStore.RegistryDao.GetByParentIDAndName(ctx, info.ParentID, info.RegIdentifier) @@ -242,26 +296,46 @@ func dbDownloadStatForMavenArtifact( return errcode.ErrCodeInvalidRequest.WithDetail(err) } + var artifactUUID string image, err := c.DBStore.ImageDao.GetByName(ctx, registry.ID, imageName) if errors.Is(err, store.ErrResourceNotFound) { image, err = getMavenArtifactFromUpstreamProxy(ctx, c, info) } if err != nil { - return errcode.ErrCodeInvalidRequest.WithDetail(err) - } - - artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version) - if err != nil { - return errcode.ErrCodeInvalidRequest.WithDetail(err) + log.Ctx(ctx).Debug().Err(err).Msg("image not found for download stats") + artifactUUID = "" + } else { + artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version) + if err != nil { + log.Ctx(ctx).Debug().Err(err).Msg("artifact not found for download stats") + artifactUUID = "" + } else { + artifactUUID = artifact.UUID + downloadStat := &types.DownloadStat{ + ArtifactID: artifact.ID, + } + if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { + log.Ctx(ctx).Warn().Err(err).Msg("failed to create download stat") + } + } } - downloadStat := &types.DownloadStat{ - ArtifactID: artifact.ID, + artifactInfo := pkg.ArtifactInfo{ + BaseInfo: &pkg.BaseInfo{ + ParentID: info.ParentID, + }, + RegistryID: registry.ID, + Image: imageName, } + pkgaudit.LogArtifactDownload( + ctx, + auditService, + spaceFinder, + artifactInfo, + info.Version, + artifactUUID, + ) - if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { - return errcode.ErrCodeNameUnknown.WithDetail(err) - } return errcode.Error{} } diff --git a/registry/app/api/wire.go b/registry/app/api/wire.go index fd9946a8bc..679f1c017d 100644 --- a/registry/app/api/wire.go +++ b/registry/app/api/wire.go @@ -23,6 +23,7 @@ import ( "github.com/harness/gitness/app/services/refcache" corestore "github.com/harness/gitness/app/store" urlprovider "github.com/harness/gitness/app/url" + "github.com/harness/gitness/audit" cargo2 "github.com/harness/gitness/registry/app/api/controller/pkg/cargo" generic3 "github.com/harness/gitness/registry/app/api/controller/pkg/generic" gopackage2 "github.com/harness/gitness/registry/app/api/controller/pkg/gopackage" @@ -115,6 +116,7 @@ func NewHandlerProvider( config *types.Config, registryFinder refcache2.RegistryFinder, publicAccessService publicaccess2.CacheService, + auditService audit.Service, ) *ocihandler.Handler { return ocihandler.NewHandler( controller, @@ -129,6 +131,7 @@ func NewHandlerProvider( registryFinder, publicAccessService, config.Auth.AnonymousUserSecret, + auditService, ) } @@ -136,7 +139,7 @@ func NewMavenHandlerProvider( controller *maven.Controller, spaceStore corestore.SpaceStore, tokenStore corestore.TokenStore, userCtrl *usercontroller.Controller, authenticator authn.Authenticator, authorizer authz.Authorizer, spaceFinder refcache.SpaceFinder, registryFinder refcache2.RegistryFinder, - publicAccessService publicaccess2.CacheService, + publicAccessService publicaccess2.CacheService, auditService audit.Service, ) *mavenhandler.Handler { return mavenhandler.NewHandler( controller, @@ -148,6 +151,7 @@ func NewMavenHandlerProvider( spaceFinder, registryFinder, publicAccessService, + auditService, ) } @@ -160,6 +164,8 @@ func NewPackageHandlerProvider( regFinder refcache2.RegistryFinder, fileManager filemanager.FileManager, quarantineFinder quarantine.Finder, packageWrapper interfaces.PackageWrapper, + auditService audit.Service, + artifactDao store.ArtifactRepository, ) packages.Handler { return packages.NewHandler( registryDao, @@ -176,6 +182,8 @@ func NewPackageHandlerProvider( fileManager, quarantineFinder, packageWrapper, + auditService, + artifactDao, ) } @@ -211,7 +219,7 @@ func NewGenericHandlerProvider( spaceStore corestore.SpaceStore, controller *generic3.Controller, tokenStore corestore.TokenStore, userCtrl *usercontroller.Controller, authenticator authn.Authenticator, urlProvider urlprovider.Provider, authorizer authz.Authorizer, packageHandler packages.Handler, spaceFinder refcache.SpaceFinder, - registryFinder refcache2.RegistryFinder, + registryFinder refcache2.RegistryFinder, auditService audit.Service, ) *generic.Handler { return generic.NewGenericArtifactHandler( spaceStore, @@ -224,6 +232,7 @@ func NewGenericHandlerProvider( packageHandler, spaceFinder, registryFinder, + auditService, ) } diff --git a/registry/app/pkg/audit/artifact.go b/registry/app/pkg/audit/artifact.go index 63a34b86e2..bdfae4cd4f 100644 --- a/registry/app/pkg/audit/artifact.go +++ b/registry/app/pkg/audit/artifact.go @@ -33,9 +33,9 @@ const ( AuditKeyImageUUID = "imageUuid" ) -// LogArtifactPush logs audit trail for artifact push/upload operations. +// LogArtifactUpload logs audit trail for artifact push/upload operations. // This is a centralized audit utility that can be called from any package type handler. -func LogArtifactPush( +func LogArtifactUpload( ctx context.Context, auditService audit.Service, spaceFinder refcache.SpaceFinder, @@ -89,3 +89,50 @@ func LogArtifactPush( ) } } + +// LogArtifactDownload logs audit trail for artifact download/pull operations. +func LogArtifactDownload( + ctx context.Context, + auditService audit.Service, + spaceFinder refcache.SpaceFinder, + info pkg.ArtifactInfo, + version string, + artifactUUID string, +) { + session, ok := request.AuthSessionFrom(ctx) + if !ok { + log.Ctx(ctx).Debug().Msg("no auth session for audit log") + return + } + + parentSpace, err := spaceFinder.FindByID(ctx, info.ParentID) + if err != nil { + log.Ctx(ctx).Warn().Err(err).Msg("failed to get parent space for audit log") + return + } + + packageName := info.Image + artifactIdentifier := fmt.Sprintf("%s:%s", packageName, version) + if version == "" { + artifactIdentifier = packageName + } + + err = auditService.Log( + ctx, + session.Principal, + audit.NewResource( + audit.ResourceTypeRegistryArtifact, + artifactIdentifier, + AuditKeyResourceName, artifactIdentifier, + AuditKeyArtifactUUID, artifactUUID, + ), + audit.ActionDownloaded, + parentSpace.Path, + ) + if err != nil { + log.Ctx(ctx).Warn().Err(err).Msgf( + "failed to insert audit log for download artifact operation: %s", + artifactIdentifier, + ) + } +} diff --git a/registry/app/pkg/base/base.go b/registry/app/pkg/base/base.go index 2410486c7a..800d8a74b3 100644 --- a/registry/app/pkg/base/base.go +++ b/registry/app/pkg/base/base.go @@ -763,12 +763,11 @@ func (l *localBase) DeleteVersion(ctx context.Context, info pkg.PackageArtifactI return nil } -// AuditPush is a convenience wrapper for calling the centralized audit function from localBase. func (l *localBase) AuditPush( ctx context.Context, info pkg.ArtifactInfo, version string, imageUUID string, artifactUUID string, ) { - registryaudit.LogArtifactPush( + registryaudit.LogArtifactUpload( ctx, l.auditService, l.spaceFinder, info, version, imageUUID, artifactUUID, ) } diff --git a/registry/app/pkg/docker/manifest_service.go b/registry/app/pkg/docker/manifest_service.go index 49d5d894fd..a70553b3d0 100644 --- a/registry/app/pkg/docker/manifest_service.go +++ b/registry/app/pkg/docker/manifest_service.go @@ -519,7 +519,7 @@ func (l *manifestService) upsertImageAndArtifact(ctx context.Context, d digest.D } // Audit log for OCI/Docker/Helm artifact push - registryaudit.LogArtifactPush( + registryaudit.LogArtifactUpload( ctx, l.auditService, l.spaceFinder, *info.ArtifactInfo, dgst.String(), dbImage.UUID, dbArtifact.UUID, ) From fa895f3b8b6157f3e1df58f03a52a24d2166aac5 Mon Sep 17 00:00:00 2001 From: Jatin Agrawal Date: Tue, 17 Feb 2026 14:44:56 +0530 Subject: [PATCH 03/11] resolved the comments --- registry/app/api/handler/packages/handler.go | 12 +--- registry/app/api/middleware/download_stats.go | 67 +++++++------------ registry/app/pkg/audit/artifact.go | 32 +++++++-- 3 files changed, 54 insertions(+), 57 deletions(-) diff --git a/registry/app/api/handler/packages/handler.go b/registry/app/api/handler/packages/handler.go index a3e99ccdf0..a838735edd 100644 --- a/registry/app/api/handler/packages/handler.go +++ b/registry/app/api/handler/packages/handler.go @@ -166,7 +166,7 @@ func (h *handler) TrackDownloadStats( } // Audit log for download operation - h.logArtifactDownloadAudit(r.Context(), info.BaseArtifactInfo(), info.GetVersion()) + h.logArtifactDownloadAudit(ctx, info.BaseArtifactInfo(), info.GetVersion()) return nil } @@ -175,22 +175,12 @@ func (h *handler) logArtifactDownloadAudit( info pkg.ArtifactInfo, version string, ) { - var artifactUUID string - artifact, err := h.ArtifactDao.GetByRegistryImageAndVersion(ctx, info.RegistryID, info.Image, version) - if err != nil { - log.Ctx(ctx).Debug().Err(err).Msg("artifact not found for audit") - artifactUUID = "" - } else { - artifactUUID = artifact.UUID - } - pkgaudit.LogArtifactDownload( ctx, h.AuditService, h.SpaceFinder, info, version, - artifactUUID, ) } diff --git a/registry/app/api/middleware/download_stats.go b/registry/app/api/middleware/download_stats.go index 5b27295a82..e38884ba4a 100644 --- a/registry/app/api/middleware/download_stats.go +++ b/registry/app/api/middleware/download_stats.go @@ -110,17 +110,13 @@ func dbDownloadStat( } // Try to get artifact - may not exist for upstream proxy first downloads - var artifactUUID string artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, dgst.String()) if err != nil { log.Ctx(ctx).Debug().Err(err).Msgf( "artifact not yet cached in DB for download stats (upstream proxy first download): image=%s, digest=%s", info.Image, dgst.String(), ) - artifactUUID = "" } else { - artifactUUID = artifact.UUID - // Only create download stat if artifact exists in DB (preserves existing behavior) downloadStat := &types.DownloadStat{ ArtifactID: artifact.ID, @@ -134,8 +130,10 @@ func dbDownloadStat( BaseInfo: &pkg.BaseInfo{ ParentID: info.ParentID, }, - RegistryID: registry.ID, - Image: info.Image, + RegistryID: registry.ID, + RegIdentifier: registry.Name, + Image: info.Image, + ArtifactType: info.ArtifactType, } pkgaudit.LogArtifactDownload( ctx, @@ -143,7 +141,6 @@ func dbDownloadStat( spaceFinder, artifactInfo, dgst.String(), - artifactUUID, ) return nil @@ -243,24 +240,17 @@ func dbDownloadStatForGenericArtifact( return errcode.ErrCodeInvalidRequest.WithDetail(err) } - var artifactUUID string image, err := c.DBStore.ImageDao.GetByName(ctx, registry.ID, info.Image) if err != nil { log.Ctx(ctx).Debug().Err(err).Msg("image not found for download stats") - artifactUUID = "" + } else if artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version); err != nil { + log.Ctx(ctx).Debug().Err(err).Msg("artifact not found for download stats") } else { - artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version) - if err != nil { - log.Ctx(ctx).Debug().Err(err).Msg("artifact not found for download stats") - artifactUUID = "" - } else { - artifactUUID = artifact.UUID - downloadStat := &types.DownloadStat{ - ArtifactID: artifact.ID, - } - if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { - log.Ctx(ctx).Warn().Err(err).Msg("failed to create download stat") - } + downloadStat := &types.DownloadStat{ + ArtifactID: artifact.ID, + } + if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { + log.Ctx(ctx).Warn().Err(err).Msg("failed to create download stat") } } @@ -268,8 +258,10 @@ func dbDownloadStatForGenericArtifact( BaseInfo: &pkg.BaseInfo{ ParentID: info.ParentID, }, - RegistryID: registry.ID, - Image: info.Image, + RegistryID: registry.ID, + RegIdentifier: registry.Name, + Image: info.Image, + ArtifactType: info.ArtifactType, } pkgaudit.LogArtifactDownload( ctx, @@ -277,7 +269,6 @@ func dbDownloadStatForGenericArtifact( spaceFinder, artifactInfo, info.Version, - artifactUUID, ) return errcode.Error{} @@ -296,27 +287,20 @@ func dbDownloadStatForMavenArtifact( return errcode.ErrCodeInvalidRequest.WithDetail(err) } - var artifactUUID string image, err := c.DBStore.ImageDao.GetByName(ctx, registry.ID, imageName) if errors.Is(err, store.ErrResourceNotFound) { image, err = getMavenArtifactFromUpstreamProxy(ctx, c, info) } if err != nil { log.Ctx(ctx).Debug().Err(err).Msg("image not found for download stats") - artifactUUID = "" + } else if artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version); err != nil { + log.Ctx(ctx).Debug().Err(err).Msg("artifact not found for download stats") } else { - artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version) - if err != nil { - log.Ctx(ctx).Debug().Err(err).Msg("artifact not found for download stats") - artifactUUID = "" - } else { - artifactUUID = artifact.UUID - downloadStat := &types.DownloadStat{ - ArtifactID: artifact.ID, - } - if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { - log.Ctx(ctx).Warn().Err(err).Msg("failed to create download stat") - } + downloadStat := &types.DownloadStat{ + ArtifactID: artifact.ID, + } + if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { + log.Ctx(ctx).Warn().Err(err).Msg("failed to create download stat") } } @@ -324,8 +308,10 @@ func dbDownloadStatForMavenArtifact( BaseInfo: &pkg.BaseInfo{ ParentID: info.ParentID, }, - RegistryID: registry.ID, - Image: imageName, + RegistryID: registry.ID, + RegIdentifier: registry.Name, + Image: imageName, + ArtifactType: info.ArtifactType, } pkgaudit.LogArtifactDownload( ctx, @@ -333,7 +319,6 @@ func dbDownloadStatForMavenArtifact( spaceFinder, artifactInfo, info.Version, - artifactUUID, ) return errcode.Error{} diff --git a/registry/app/pkg/audit/artifact.go b/registry/app/pkg/audit/artifact.go index bdfae4cd4f..4a8e74455c 100644 --- a/registry/app/pkg/audit/artifact.go +++ b/registry/app/pkg/audit/artifact.go @@ -28,9 +28,13 @@ import ( const ( // Audit metadata keys. - AuditKeyResourceName = "resourceName" - AuditKeyArtifactUUID = "artifactId" - AuditKeyImageUUID = "imageUuid" + AuditKeyResourceName = "resourceName" + AuditKeyArtifactUUID = "artifactId" + AuditKeyImageUUID = "imageUuid" + AuditKeyRegistryName = "registryName" + AuditKeyPackageName = "packageName" + AuditKeyPackageType = "packageType" + AuditKeyVersionName = "versionName" ) // LogArtifactUpload logs audit trail for artifact push/upload operations. @@ -62,6 +66,12 @@ func LogArtifactUpload( artifactIdentifier = packageName } + // Get package type string + packageType := "" + if info.ArtifactType != nil { + packageType = string(*info.ArtifactType) + } + // Operational metadata auditData := []audit.Option{ audit.WithData( @@ -77,6 +87,10 @@ func LogArtifactUpload( artifactIdentifier, AuditKeyResourceName, artifactIdentifier, AuditKeyArtifactUUID, artifactUUID, + AuditKeyRegistryName, info.RegIdentifier, + AuditKeyPackageName, packageName, + AuditKeyPackageType, packageType, + AuditKeyVersionName, version, ), audit.ActionUploaded, parentSpace.Path, @@ -97,7 +111,6 @@ func LogArtifactDownload( spaceFinder refcache.SpaceFinder, info pkg.ArtifactInfo, version string, - artifactUUID string, ) { session, ok := request.AuthSessionFrom(ctx) if !ok { @@ -117,6 +130,12 @@ func LogArtifactDownload( artifactIdentifier = packageName } + // Get package type string + packageType := "" + if info.ArtifactType != nil { + packageType = string(*info.ArtifactType) + } + err = auditService.Log( ctx, session.Principal, @@ -124,7 +143,10 @@ func LogArtifactDownload( audit.ResourceTypeRegistryArtifact, artifactIdentifier, AuditKeyResourceName, artifactIdentifier, - AuditKeyArtifactUUID, artifactUUID, + AuditKeyRegistryName, info.RegIdentifier, + AuditKeyPackageName, packageName, + AuditKeyPackageType, packageType, + AuditKeyVersionName, version, ), audit.ActionDownloaded, parentSpace.Path, From 89111ded8115bec5f292f1f00a35c3ffeb1ad8fe Mon Sep 17 00:00:00 2001 From: Jatin Agrawal Date: Tue, 17 Feb 2026 14:47:00 +0530 Subject: [PATCH 04/11] resolved conflict --- registry/app/api/handler/huggingface/handler.go | 1 - 1 file changed, 1 deletion(-) diff --git a/registry/app/api/handler/huggingface/handler.go b/registry/app/api/handler/huggingface/handler.go index 331aa8eceb..b7638615f3 100644 --- a/registry/app/api/handler/huggingface/handler.go +++ b/registry/app/api/handler/huggingface/handler.go @@ -109,7 +109,6 @@ func (h *handler) GetPackageArtifactInfo(r *http.Request) (pkg.PackageArtifactIn rev = "main" } info.Image = repo - // Set artifact type in the base ArtifactInfo for audit logging info.ArtifactType = artifactType return &hftype.ArtifactInfo{ From ebc02e76f9840293217a4a546a231a8d527a1bef Mon Sep 17 00:00:00 2001 From: Jatin Agrawal Date: Tue, 17 Feb 2026 15:28:36 +0530 Subject: [PATCH 05/11] gci lint fixes --- registry/app/api/middleware/download_stats.go | 25 +++++++++---------- registry/app/pkg/audit/artifact.go | 15 ++++++----- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/registry/app/api/middleware/download_stats.go b/registry/app/api/middleware/download_stats.go index e38884ba4a..40353c19a2 100644 --- a/registry/app/api/middleware/download_stats.go +++ b/registry/app/api/middleware/download_stats.go @@ -39,7 +39,6 @@ import ( "github.com/harness/gitness/registry/request" "github.com/harness/gitness/registry/types" "github.com/harness/gitness/store" - "github.com/opencontainers/go-digest" "github.com/rs/zerolog/log" ) @@ -130,10 +129,10 @@ func dbDownloadStat( BaseInfo: &pkg.BaseInfo{ ParentID: info.ParentID, }, - RegistryID: registry.ID, - RegIdentifier: registry.Name, - Image: info.Image, - ArtifactType: info.ArtifactType, + RegistryID: registry.ID, + RegIdentifier: registry.Name, + Image: info.Image, + ArtifactType: info.ArtifactType, } pkgaudit.LogArtifactDownload( ctx, @@ -258,10 +257,10 @@ func dbDownloadStatForGenericArtifact( BaseInfo: &pkg.BaseInfo{ ParentID: info.ParentID, }, - RegistryID: registry.ID, - RegIdentifier: registry.Name, - Image: info.Image, - ArtifactType: info.ArtifactType, + RegistryID: registry.ID, + RegIdentifier: registry.Name, + Image: info.Image, + ArtifactType: info.ArtifactType, } pkgaudit.LogArtifactDownload( ctx, @@ -308,10 +307,10 @@ func dbDownloadStatForMavenArtifact( BaseInfo: &pkg.BaseInfo{ ParentID: info.ParentID, }, - RegistryID: registry.ID, - RegIdentifier: registry.Name, - Image: imageName, - ArtifactType: info.ArtifactType, + RegistryID: registry.ID, + RegIdentifier: registry.Name, + Image: imageName, + ArtifactType: info.ArtifactType, } pkgaudit.LogArtifactDownload( ctx, diff --git a/registry/app/pkg/audit/artifact.go b/registry/app/pkg/audit/artifact.go index 4a8e74455c..0d3f944319 100644 --- a/registry/app/pkg/audit/artifact.go +++ b/registry/app/pkg/audit/artifact.go @@ -22,19 +22,18 @@ import ( "github.com/harness/gitness/app/services/refcache" "github.com/harness/gitness/audit" "github.com/harness/gitness/registry/app/pkg" - "github.com/rs/zerolog/log" ) const ( // Audit metadata keys. - AuditKeyResourceName = "resourceName" - AuditKeyArtifactUUID = "artifactId" - AuditKeyImageUUID = "imageUuid" - AuditKeyRegistryName = "registryName" - AuditKeyPackageName = "packageName" - AuditKeyPackageType = "packageType" - AuditKeyVersionName = "versionName" + AuditKeyResourceName = "resourceName" + AuditKeyArtifactUUID = "artifactId" + AuditKeyImageUUID = "imageUuid" + AuditKeyRegistryName = "registryName" + AuditKeyPackageName = "packageName" + AuditKeyPackageType = "packageType" + AuditKeyVersionName = "versionName" ) // LogArtifactUpload logs audit trail for artifact push/upload operations. From 66d3a85a33cf0d8696390201e9dc72e622efb4c8 Mon Sep 17 00:00:00 2001 From: Jatin Agrawal Date: Tue, 17 Feb 2026 16:42:13 +0530 Subject: [PATCH 06/11] addressed comments --- registry/app/api/handler/packages/handler.go | 6 +- registry/app/api/middleware/download_stats.go | 121 +++++++++--------- registry/app/pkg/audit/artifact.go | 1 + 3 files changed, 68 insertions(+), 60 deletions(-) diff --git a/registry/app/api/handler/packages/handler.go b/registry/app/api/handler/packages/handler.go index a838735edd..db6442bcbc 100644 --- a/registry/app/api/handler/packages/handler.go +++ b/registry/app/api/handler/packages/handler.go @@ -159,14 +159,16 @@ func (h *handler) TrackDownloadStats( r *http.Request, ) error { info := request.ArtifactInfoFrom(r.Context()) //nolint:contextcheck + + // Audit log for download operation + h.logArtifactDownloadAudit(ctx, info.BaseArtifactInfo(), info.GetVersion()) + if err := h.DownloadStatDao.CreateByRegistryIDImageAndArtifactName(ctx, info.BaseArtifactInfo().RegistryID, info.BaseArtifactInfo().Image, info.GetVersion()); err != nil { log.Ctx(ctx).Error().Msgf("failed to create download stat: %v", err.Error()) return usererror.ErrInternal } - // Audit log for download operation - h.logArtifactDownloadAudit(ctx, info.BaseArtifactInfo(), info.GetVersion()) return nil } diff --git a/registry/app/api/middleware/download_stats.go b/registry/app/api/middleware/download_stats.go index 40353c19a2..d67da02494 100644 --- a/registry/app/api/middleware/download_stats.go +++ b/registry/app/api/middleware/download_stats.go @@ -39,6 +39,7 @@ import ( "github.com/harness/gitness/registry/request" "github.com/harness/gitness/registry/types" "github.com/harness/gitness/store" + "github.com/opencontainers/go-digest" "github.com/rs/zerolog/log" ) @@ -74,7 +75,7 @@ func TrackDownloadStat(h *oci.Handler) func(http.Handler) http.Handler { return } - err = dbDownloadStat(ctx, h.Controller, info, h.AuditService, h.SpaceFinder) + err = dbDownloadStatForDockerOrOCIArtifact(ctx, h.Controller, info, h.AuditService, h.SpaceFinder) if err != nil { log.Ctx(ctx).Error().Stack().Str("middleware", "TrackDownloadStat").Err(err).Msgf("error while putting download stat of artifact, %v", @@ -86,7 +87,7 @@ func TrackDownloadStat(h *oci.Handler) func(http.Handler) http.Handler { } } -func dbDownloadStat( +func dbDownloadStatForDockerOrOCIArtifact( ctx context.Context, c *docker.Controller, info pkg.RegistryInfo, @@ -95,36 +96,12 @@ func dbDownloadStat( ) error { registry := info.Registry - image, err := c.DBStore.ImageDao.GetByName(ctx, registry.ID, info.Image) - if errors.Is(err, store.ErrResourceNotFound) { - image, err = getImageFromUpstreamProxy(ctx, c, info) - } - if err != nil { - return err - } - dgst, err := types.NewDigest(digest.Digest(info.Digest)) if err != nil { return err } - // Try to get artifact - may not exist for upstream proxy first downloads - artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, dgst.String()) - if err != nil { - log.Ctx(ctx).Debug().Err(err).Msgf( - "artifact not yet cached in DB for download stats (upstream proxy first download): image=%s, digest=%s", - info.Image, dgst.String(), - ) - } else { - // Only create download stat if artifact exists in DB (preserves existing behavior) - downloadStat := &types.DownloadStat{ - ArtifactID: artifact.ID, - } - if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { - log.Ctx(ctx).Warn().Err(err).Msgf("failed to create download stat") - } - } - + // Log audit artifactInfo := pkg.ArtifactInfo{ BaseInfo: &pkg.BaseInfo{ ParentID: info.ParentID, @@ -142,6 +119,26 @@ func dbDownloadStat( dgst.String(), ) + image, err := c.DBStore.ImageDao.GetByName(ctx, registry.ID, info.Image) + if errors.Is(err, store.ErrResourceNotFound) { + image, err = getImageFromUpstreamProxy(ctx, c, info) + } + if err != nil { + return err + } + + artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, dgst.String()) + if err != nil { + return err + } + + downloadStat := &types.DownloadStat{ + ArtifactID: artifact.ID, + } + + if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { + return err + } return nil } @@ -239,20 +236,7 @@ func dbDownloadStatForGenericArtifact( return errcode.ErrCodeInvalidRequest.WithDetail(err) } - image, err := c.DBStore.ImageDao.GetByName(ctx, registry.ID, info.Image) - if err != nil { - log.Ctx(ctx).Debug().Err(err).Msg("image not found for download stats") - } else if artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version); err != nil { - log.Ctx(ctx).Debug().Err(err).Msg("artifact not found for download stats") - } else { - downloadStat := &types.DownloadStat{ - ArtifactID: artifact.ID, - } - if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { - log.Ctx(ctx).Warn().Err(err).Msg("failed to create download stat") - } - } - + // Log audit artifactInfo := pkg.ArtifactInfo{ BaseInfo: &pkg.BaseInfo{ ParentID: info.ParentID, @@ -270,6 +254,23 @@ func dbDownloadStatForGenericArtifact( info.Version, ) + image, err := c.DBStore.ImageDao.GetByName(ctx, registry.ID, info.Image) + if err != nil { + return errcode.ErrCodeInvalidRequest.WithDetail(err) + } + + artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version) + if err != nil { + return errcode.ErrCodeInvalidRequest.WithDetail(err) + } + + downloadStat := &types.DownloadStat{ + ArtifactID: artifact.ID, + } + + if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { + return errcode.ErrCodeNameUnknown.WithDetail(err) + } return errcode.Error{} } @@ -286,23 +287,7 @@ func dbDownloadStatForMavenArtifact( return errcode.ErrCodeInvalidRequest.WithDetail(err) } - image, err := c.DBStore.ImageDao.GetByName(ctx, registry.ID, imageName) - if errors.Is(err, store.ErrResourceNotFound) { - image, err = getMavenArtifactFromUpstreamProxy(ctx, c, info) - } - if err != nil { - log.Ctx(ctx).Debug().Err(err).Msg("image not found for download stats") - } else if artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version); err != nil { - log.Ctx(ctx).Debug().Err(err).Msg("artifact not found for download stats") - } else { - downloadStat := &types.DownloadStat{ - ArtifactID: artifact.ID, - } - if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { - log.Ctx(ctx).Warn().Err(err).Msg("failed to create download stat") - } - } - + // Log audit artifactInfo := pkg.ArtifactInfo{ BaseInfo: &pkg.BaseInfo{ ParentID: info.ParentID, @@ -320,6 +305,26 @@ func dbDownloadStatForMavenArtifact( info.Version, ) + image, err := c.DBStore.ImageDao.GetByName(ctx, registry.ID, imageName) + if errors.Is(err, store.ErrResourceNotFound) { + image, err = getMavenArtifactFromUpstreamProxy(ctx, c, info) + } + if err != nil { + return errcode.ErrCodeInvalidRequest.WithDetail(err) + } + + artifact, err := c.DBStore.ArtifactDao.GetByName(ctx, image.ID, info.Version) + if err != nil { + return errcode.ErrCodeInvalidRequest.WithDetail(err) + } + + downloadStat := &types.DownloadStat{ + ArtifactID: artifact.ID, + } + + if err := c.DBStore.DownloadStatDao.Create(ctx, downloadStat); err != nil { + return errcode.ErrCodeNameUnknown.WithDetail(err) + } return errcode.Error{} } diff --git a/registry/app/pkg/audit/artifact.go b/registry/app/pkg/audit/artifact.go index 0d3f944319..b6bf434592 100644 --- a/registry/app/pkg/audit/artifact.go +++ b/registry/app/pkg/audit/artifact.go @@ -22,6 +22,7 @@ import ( "github.com/harness/gitness/app/services/refcache" "github.com/harness/gitness/audit" "github.com/harness/gitness/registry/app/pkg" + "github.com/rs/zerolog/log" ) From 5f0573a27b45aedc0c4459cca8f7f43a4c1316fe Mon Sep 17 00:00:00 2001 From: Jatin Agrawal Date: Tue, 17 Feb 2026 17:02:43 +0530 Subject: [PATCH 07/11] lint removed --- registry/app/api/handler/packages/handler.go | 9 +++++++-- registry/app/api/middleware/download_stats.go | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/registry/app/api/handler/packages/handler.go b/registry/app/api/handler/packages/handler.go index 3f56fa901a..9a3cf1dbde 100644 --- a/registry/app/api/handler/packages/handler.go +++ b/registry/app/api/handler/packages/handler.go @@ -163,8 +163,13 @@ func (h *handler) TrackDownloadStats( // Audit log for download operation h.logArtifactDownloadAudit(ctx, info.BaseArtifactInfo(), info.GetVersion()) - if err := h.DownloadStatDao.CreateByRegistryIDImageAndArtifactName(ctx, - info.BaseArtifactInfo().RegistryID, info.BaseArtifactInfo().Image, info.GetVersion(), info.BaseArtifactInfo().ArtifactType); err != nil { + if err := h.DownloadStatDao.CreateByRegistryIDImageAndArtifactName( + ctx, + info.BaseArtifactInfo().RegistryID, + info.BaseArtifactInfo().Image, + info.GetVersion(), + info.BaseArtifactInfo().ArtifactType, + ); err != nil { log.Ctx(ctx).Error().Msgf("failed to create download stat: %v", err.Error()) return usererror.ErrInternal } diff --git a/registry/app/api/middleware/download_stats.go b/registry/app/api/middleware/download_stats.go index d67da02494..7eef711279 100644 --- a/registry/app/api/middleware/download_stats.go +++ b/registry/app/api/middleware/download_stats.go @@ -75,7 +75,7 @@ func TrackDownloadStat(h *oci.Handler) func(http.Handler) http.Handler { return } - err = dbDownloadStatForDockerOrOCIArtifact(ctx, h.Controller, info, h.AuditService, h.SpaceFinder) + err = dbDownloadStat(ctx, h.Controller, info, h.AuditService, h.SpaceFinder) if err != nil { log.Ctx(ctx).Error().Stack().Str("middleware", "TrackDownloadStat").Err(err).Msgf("error while putting download stat of artifact, %v", @@ -87,7 +87,7 @@ func TrackDownloadStat(h *oci.Handler) func(http.Handler) http.Handler { } } -func dbDownloadStatForDockerOrOCIArtifact( +func dbDownloadStat( ctx context.Context, c *docker.Controller, info pkg.RegistryInfo, From 77d779f598e9fb68cdb4bc06dd975baa88a68071 Mon Sep 17 00:00:00 2001 From: Jatin Agrawal Date: Tue, 17 Feb 2026 17:48:18 +0530 Subject: [PATCH 08/11] changed variable name --- registry/app/pkg/audit/artifact.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/registry/app/pkg/audit/artifact.go b/registry/app/pkg/audit/artifact.go index b6bf434592..a8e55f129e 100644 --- a/registry/app/pkg/audit/artifact.go +++ b/registry/app/pkg/audit/artifact.go @@ -66,10 +66,10 @@ func LogArtifactUpload( artifactIdentifier = packageName } - // Get package type string - packageType := "" + // Get package kind + packageKind := "" if info.ArtifactType != nil { - packageType = string(*info.ArtifactType) + packageKind = string(*info.ArtifactType) } // Operational metadata @@ -89,7 +89,7 @@ func LogArtifactUpload( AuditKeyArtifactUUID, artifactUUID, AuditKeyRegistryName, info.RegIdentifier, AuditKeyPackageName, packageName, - AuditKeyPackageType, packageType, + AuditKeyPackageType, packageKind, AuditKeyVersionName, version, ), audit.ActionUploaded, @@ -130,10 +130,10 @@ func LogArtifactDownload( artifactIdentifier = packageName } - // Get package type string - packageType := "" + // Get package kind + packageKind := "" if info.ArtifactType != nil { - packageType = string(*info.ArtifactType) + packageKind = string(*info.ArtifactType) } err = auditService.Log( @@ -145,7 +145,7 @@ func LogArtifactDownload( AuditKeyResourceName, artifactIdentifier, AuditKeyRegistryName, info.RegIdentifier, AuditKeyPackageName, packageName, - AuditKeyPackageType, packageType, + AuditKeyPackageType, packageKind, AuditKeyVersionName, version, ), audit.ActionDownloaded, From 42cc32b950a42558d49741b7547891b55ff7bd98 Mon Sep 17 00:00:00 2001 From: Jatin Agrawal Date: Tue, 17 Feb 2026 17:51:38 +0530 Subject: [PATCH 09/11] variable name change --- registry/app/pkg/audit/artifact.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/registry/app/pkg/audit/artifact.go b/registry/app/pkg/audit/artifact.go index a8e55f129e..0de9986580 100644 --- a/registry/app/pkg/audit/artifact.go +++ b/registry/app/pkg/audit/artifact.go @@ -33,7 +33,7 @@ const ( AuditKeyImageUUID = "imageUuid" AuditKeyRegistryName = "registryName" AuditKeyPackageName = "packageName" - AuditKeyPackageType = "packageType" + AuditKeyPackageKind = "packageKind" AuditKeyVersionName = "versionName" ) @@ -66,7 +66,7 @@ func LogArtifactUpload( artifactIdentifier = packageName } - // Get package kind + // Get package kind - packageKind := "" if info.ArtifactType != nil { packageKind = string(*info.ArtifactType) @@ -89,7 +89,7 @@ func LogArtifactUpload( AuditKeyArtifactUUID, artifactUUID, AuditKeyRegistryName, info.RegIdentifier, AuditKeyPackageName, packageName, - AuditKeyPackageType, packageKind, + AuditKeyPackageKind, packageKind, AuditKeyVersionName, version, ), audit.ActionUploaded, @@ -145,7 +145,7 @@ func LogArtifactDownload( AuditKeyResourceName, artifactIdentifier, AuditKeyRegistryName, info.RegIdentifier, AuditKeyPackageName, packageName, - AuditKeyPackageType, packageKind, + AuditKeyPackageKind, packageKind, AuditKeyVersionName, version, ), audit.ActionDownloaded, From d03de45c60138594d0a74cc1305695451400fa6c Mon Sep 17 00:00:00 2001 From: Arvind Choudhary Date: Tue, 17 Feb 2026 20:11:59 -0800 Subject: [PATCH 10/11] [AH-2826]: Fixed flows during read flows --- registry/app/pkg/docker/app.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/registry/app/pkg/docker/app.go b/registry/app/pkg/docker/app.go index 7d21d03c73..05c47ebc36 100644 --- a/registry/app/pkg/docker/app.go +++ b/registry/app/pkg/docker/app.go @@ -21,6 +21,7 @@ import ( "crypto/rand" "fmt" + "github.com/google/uuid" corestore "github.com/harness/gitness/app/store" "github.com/harness/gitness/registry/app/dist_temp/dcontext" "github.com/harness/gitness/registry/app/dist_temp/errcode" @@ -139,10 +140,12 @@ func (app *App) GetBlobsContext( OciBlobStore: nil, } - // For reads and lazy replication - if result := app.bucketService.GetBlobStore(c, info.RegIdentifier, info.RootIdentifier, blobLocator.BlobID, - digest.Digest(info.Digest).String()); result != nil { - ctx.OciBlobStore = result.OciStore + if blobLocator.BlobID != 0 || blobLocator.GenericBlobID != uuid.Nil { + // For reads and lazy replication + if result := app.bucketService.GetBlobStore(c, info.RegIdentifier, info.RootIdentifier, blobLocator.BlobID, + digest.Digest(info.Digest).String()); result != nil { + ctx.OciBlobStore = result.OciStore + } } // Default read/write From ce928ba1b51898a7f5d901e9bbb4b793d3e4d45c Mon Sep 17 00:00:00 2001 From: Arvind Choudhary Date: Tue, 17 Feb 2026 22:47:46 -0800 Subject: [PATCH 11/11] [AH-2826]: lint issues --- registry/app/pkg/docker/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/app/pkg/docker/app.go b/registry/app/pkg/docker/app.go index 05c47ebc36..d5548a2667 100644 --- a/registry/app/pkg/docker/app.go +++ b/registry/app/pkg/docker/app.go @@ -21,7 +21,6 @@ import ( "crypto/rand" "fmt" - "github.com/google/uuid" corestore "github.com/harness/gitness/app/store" "github.com/harness/gitness/registry/app/dist_temp/dcontext" "github.com/harness/gitness/registry/app/dist_temp/errcode" @@ -32,6 +31,7 @@ import ( registryTypes "github.com/harness/gitness/registry/types" "github.com/harness/gitness/types" + "github.com/google/uuid" "github.com/opencontainers/go-digest" "github.com/rs/zerolog/log" )