Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions central/image/service/service_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/stackrox/rox/generated/storage"
"github.com/stackrox/rox/pkg/auth/permissions"
"github.com/stackrox/rox/pkg/centralsensor"
"github.com/stackrox/rox/pkg/concurrency"
"github.com/stackrox/rox/pkg/env"
"github.com/stackrox/rox/pkg/errox"
"github.com/stackrox/rox/pkg/features"
Expand Down Expand Up @@ -635,6 +636,13 @@ func (s *serviceImpl) ScanImage(ctx context.Context, request *v1.ScanImageReques
if err := s.saveImageV2(imgV2); err != nil {
return nil, err
}
s.invalidateImageCacheOnSensors([]*central.InvalidateImageCache_ImageKey{
{
ImageId: imgV2.GetDigest(),
ImageIdV2: imgV2.GetId(),
ImageFullName: imgV2.GetName().GetFullName(),
},
})
}
if !request.GetIncludeSnoozed() {
utils.FilterSuppressedCVEsNoCloneV2(imgV2)
Expand Down Expand Up @@ -666,6 +674,12 @@ func (s *serviceImpl) ScanImage(ctx context.Context, request *v1.ScanImageReques
if err := s.saveImage(img); err != nil {
return nil, err
}
s.invalidateImageCacheOnSensors([]*central.InvalidateImageCache_ImageKey{
{
ImageId: img.GetId(),
ImageFullName: img.GetName().GetFullName(),
},
})
}
if !request.GetIncludeSnoozed() {
utils.FilterSuppressedCVEsNoClone(img)
Expand Down Expand Up @@ -1446,3 +1460,31 @@ func (s *serviceImpl) GetWatchedImages(ctx context.Context, _ *v1.Empty) (*v1.Ge
}
return &v1.GetWatchedImagesResponse{WatchedImages: watchedImgs}, nil
}

// invalidateImageCacheOnSensors sends targeted image cache invalidation to
// secured clusters that advertise TargetedImageCacheInvalidation. Old
// sensors are skipped — otherwise they would trigger a full admission
// controller cache purge for any InvalidateImageCache message.
func (s *serviceImpl) invalidateImageCacheOnSensors(keys []*central.InvalidateImageCache_ImageKey) {
if len(keys) == 0 {
return
}
msg := &central.MsgToSensor{
Msg: &central.MsgToSensor_InvalidateImageCache{
InvalidateImageCache: &central.InvalidateImageCache{
ImageKeys: keys,
},
},
}
for _, conn := range s.connManager.GetActiveConnections() {
if !conn.HasCapability(centralsensor.TargetedImageCacheInvalidation) {
continue
}
if err := conn.InjectMessage(concurrency.Never(), msg); err != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize we have concurrency.Never() for other broadcasts, but given ScanImage() is used heavily in CI/CD - breakage due to a misbehaving sensor may have large impact. Giving this a timeout may save us some future pain.

One misbehaving sensor has caused major issues in the past (inspiration for #15802)

log.Errorw("Failed to send image cache invalidation",
logging.String("cluster", conn.ClusterID()),
logging.Err(err),
)
}
}
}
Loading