Skip to content
Merged
Show file tree
Hide file tree
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
4 changes: 2 additions & 2 deletions central/detection/service/service_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func (s *serviceImpl) DetectBuildTime(ctx context.Context, req *apiV1.BuildDetec
return nil, err
}
if enrichResult.ImageUpdated {
img.Id = utils.GetImageID(img)
img.Id = utils.GetSHA(img)
if img.GetId() != "" {
if err := s.riskManager.CalculateRiskAndUpsertImage(img); err != nil {
return nil, err
Expand Down Expand Up @@ -176,7 +176,7 @@ func (s *serviceImpl) enrichAndDetect(ctx context.Context, enrichmentContext enr
}
for _, idx := range updatedIndices {
img := images[idx]
img.Id = utils.GetImageID(img)
img.Id = utils.GetSHA(img)
if err := s.riskManager.CalculateRiskAndUpsertImage(images[idx]); err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions central/image/service/service_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ func (s *serviceImpl) ScanImage(ctx context.Context, request *v1.ScanImageReques
}

// Save the image
img.Id = utils.GetImageID(img)
img.Id = utils.GetSHA(img)
if img.GetId() != "" {
if err := s.saveImage(img); err != nil {
return nil, err
Expand Down Expand Up @@ -505,7 +505,7 @@ func (s *serviceImpl) WatchImage(ctx context.Context, request *v1.WatchImageRequ
}

// Save the image
img.Id = utils.GetImageID(img)
img.Id = utils.GetSHA(img)
if img.GetId() == "" {
return &v1.WatchImageResponse{
ErrorType: v1.WatchImageResponse_SCAN_FAILED,
Expand Down
2 changes: 1 addition & 1 deletion central/reprocessor/reprocessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ func (l *loopImpl) reprocessWatchedImage(name string) bool {
return false
}
// Save the image
img.Id = utils.GetImageID(img)
img.Id = utils.GetSHA(img)
if img.GetId() == "" {
return false
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/images/enricher/enricher_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ func (e *enricherImpl) fetchFromDatabase(ctx context.Context, img *storage.Image
return img, false
}
// See if the image exists in the DB with a scan, if it does, then use that instead of fetching
id := utils.GetImageID(img)
id := utils.GetSHA(img)
if id == "" {
return img, false
}
Expand Down
8 changes: 7 additions & 1 deletion pkg/images/types/digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ type Digest struct {
}

// NewDigest returns an internal representation of a SHA.
// If an algorithm cannot be determined, it is set to sha256
// for legacy purposes.
func NewDigest(sha string) *Digest {
if sha == "" {
return nil
Expand All @@ -32,7 +34,7 @@ func (d *Digest) Algorithm() string {
if d == nil {
return ""
}
return d.algorithm + ":" + d.hash
return d.algorithm
}

// Digest returns the entire Digest
Expand All @@ -50,3 +52,7 @@ func (d *Digest) Hash() string {
}
return d.hash
}

func (d *Digest) String() string {
return d.Digest()
}
64 changes: 63 additions & 1 deletion pkg/images/types/digest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
)

func TestNewDigest(t *testing.T) {
func TestDigest_Digest(t *testing.T) {
cases := []struct {
sha string
expected string
Expand All @@ -23,10 +23,72 @@ func TestNewDigest(t *testing.T) {
sha: "",
expected: "",
},
{
sha: "sha512:267eebcd42de25e467db55ca95284244f95390c3c02da7b35c17ef3460aec60dc3a1a25e3ce00a9b18cf686ca4fef4429e88d1ac364e06cbd635381f489a9185",
expected: "sha512:267eebcd42de25e467db55ca95284244f95390c3c02da7b35c17ef3460aec60dc3a1a25e3ce00a9b18cf686ca4fef4429e88d1ac364e06cbd635381f489a9185",
},
}
for _, c := range cases {
t.Run(c.sha, func(t *testing.T) {
assert.Equal(t, c.expected, NewDigest(c.sha).Digest())
})
}
}

func TestDigest_Algorithm(t *testing.T) {
cases := []struct {
sha string
expected string
}{
{
sha: "sha256:adea4f68096fded167603ba6663ed615a80e090da68eb3c9e2508c15c8368401",
expected: "sha256",
},
{
sha: "adea4f68096fded167603ba6663ed615a80e090da68eb3c9e2508c15c8368401",
expected: "sha256",
},
{
sha: "",
expected: "",
},
{
sha: "sha512:267eebcd42de25e467db55ca95284244f95390c3c02da7b35c17ef3460aec60dc3a1a25e3ce00a9b18cf686ca4fef4429e88d1ac364e06cbd635381f489a9185",
expected: "sha512",
},
}
for _, c := range cases {
t.Run(c.sha, func(t *testing.T) {
assert.Equal(t, c.expected, NewDigest(c.sha).Algorithm())
})
}
}

func TestDigest_Hash(t *testing.T) {
cases := []struct {
sha string
expected string
}{
{
sha: "sha256:adea4f68096fded167603ba6663ed615a80e090da68eb3c9e2508c15c8368401",
expected: "adea4f68096fded167603ba6663ed615a80e090da68eb3c9e2508c15c8368401",
},
{
sha: "adea4f68096fded167603ba6663ed615a80e090da68eb3c9e2508c15c8368401",
expected: "adea4f68096fded167603ba6663ed615a80e090da68eb3c9e2508c15c8368401",
},
{
sha: "",
expected: "",
},
{
sha: "sha512:267eebcd42de25e467db55ca95284244f95390c3c02da7b35c17ef3460aec60dc3a1a25e3ce00a9b18cf686ca4fef4429e88d1ac364e06cbd635381f489a9185",
expected: "267eebcd42de25e467db55ca95284244f95390c3c02da7b35c17ef3460aec60dc3a1a25e3ce00a9b18cf686ca4fef4429e88d1ac364e06cbd635381f489a9185",
},
}
for _, c := range cases {
t.Run(c.sha, func(t *testing.T) {
assert.Equal(t, c.expected, NewDigest(c.sha).Hash())
})
}
}
39 changes: 16 additions & 23 deletions pkg/images/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ const (

var (
log = logging.LoggerForModule()

// digestPrefixes lists the prefixes for valid, OCI-compliant image digests.
// Please see https://github.com/opencontainers/image-spec/blob/main/descriptor.md#registered-algorithms
// for more information.
digestPrefixes = []string{"sha256:", "sha512:"}
)

// GenerateImageFromStringWithDefaultTag generates an image type from a common string format and returns an error if
Expand Down Expand Up @@ -121,21 +126,11 @@ func GenerateImageFromStringWithOverride(imageStr, registryOverride string) (*st

// GetSHA returns the SHA of the image, if it exists.
func GetSHA(img *storage.Image) string {
return GetSHAFromIDAndMetadata(img.GetId(), img.GetMetadata())
}

// GetSHAFromIDAndMetadata returns the SHA of the image based on the given ID and metadata, if it exists.
func GetSHAFromIDAndMetadata(id string, metadata *storage.ImageMetadata) string {
if id != "" {
return id
}
if d := metadata.GetV2().GetDigest(); d != "" {
return d
}
if d := metadata.GetV1().GetDigest(); d != "" {
return d
}
return ""
return stringutils.FirstNonEmpty(
img.GetId(),
img.GetMetadata().GetV2().GetDigest(),
img.GetMetadata().GetV1().GetDigest(),
)
}

// Reference returns what to use as the reference when talking to registries
Expand Down Expand Up @@ -171,10 +166,13 @@ func IsValidImageString(imageStr string) error {
return err
}

// ExtractImageDigest returns the image sha if it exists within the string.
// ExtractImageDigest returns the image sha, if it exists, within the string.
// Otherwise, the empty string is returned.
func ExtractImageDigest(imageStr string) string {
if idx := strings.Index(imageStr, "sha256:"); idx != -1 {
return imageStr[idx:]
for _, prefix := range digestPrefixes {
if idx := strings.Index(imageStr, prefix); idx != -1 {
return imageStr[idx:]
}
}

return ""
Expand Down Expand Up @@ -203,11 +201,6 @@ func GetFullyQualifiedFullName(holder nameHolder) string {
return fmt.Sprintf("%s@%s", holder.GetName().GetFullName(), holder.GetId())
}

// GetImageID returns the id of the image based on the currently set values
func GetImageID(img *storage.Image) string {
return stringutils.FirstNonEmpty(img.GetId(), img.GetMetadata().GetV2().GetDigest(), img.GetMetadata().GetV1().GetDigest())
}

// StripCVEDescriptions takes in an image and returns a stripped down version without the descriptions of CVEs
func StripCVEDescriptions(img *storage.Image) *storage.Image {
newImage := img.Clone()
Expand Down
8 changes: 8 additions & 0 deletions pkg/images/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ func TestExtractImageSha(t *testing.T) {
input: "docker://sha256:041b6144416e6e9c540d1fb4883ebc1b6fe4baf09d066d8311c0109755baae96",
output: "sha256:041b6144416e6e9c540d1fb4883ebc1b6fe4baf09d066d8311c0109755baae96",
},
{
input: "docker-pullable://k8s.gcr.io/etcd-amd64@sha512:4cc8f2b59644e88f744c5d889a9082b9c3e6c03c549c703d1ec5613ecb308beae9b0d0c268ef6c5efdc1606d0e918a211276c3ae5d5fa7c7e903b6f2237f2383",
output: "sha512:4cc8f2b59644e88f744c5d889a9082b9c3e6c03c549c703d1ec5613ecb308beae9b0d0c268ef6c5efdc1606d0e918a211276c3ae5d5fa7c7e903b6f2237f2383",
},
{
input: "docker://sha512:36fb26cde46557cf26a79d8fe53e704416c18afe667103fe58d84180d8a3e33244cd10baabeaeb0eb7541760ab776e3db2dee5e15a9ad26b0966703889c4eb45",
output: "sha512:36fb26cde46557cf26a79d8fe53e704416c18afe667103fe58d84180d8a3e33244cd10baabeaeb0eb7541760ab776e3db2dee5e15a9ad26b0966703889c4eb45",
},
}

for _, c := range cases {
Expand Down
5 changes: 1 addition & 4 deletions sensor/common/scan/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,10 @@ func EnrichLocalImage(ctx context.Context, centralClient v1.ImageServiceClient,
imgName, matchingRegistry.Name())
}

// Retrieve the image ID with best-effort from image and metadata.
imgID := utils.GetSHAFromIDAndMetadata(image.GetId(), metadata)

// Send local enriched data to central to receive a fully enrich image. This includes image vulnerabilities and
// signature verification results.
centralResp, err := centralClient.EnrichLocalImageInternal(ctx, &v1.EnrichLocalImageInternalRequest{
ImageId: imgID,
ImageId: utils.GetSHA(image),
ImageName: image.GetName(),
Metadata: metadata,
Components: scannerResp.GetComponents(),
Expand Down