Skip to content

Commit

Permalink
Added support for targets in image exceptions
Browse files Browse the repository at this point in the history
This commit introduces the ability to specify targets in image
exceptions. Each target will have the following 4 attributes:

1. Registry
2. Organization
3. ImageName
4. ImageTag

These attributes will be used to match against the canonical image name
of the image to be scanned. The vulnerabilites and the severities
specified in the VulnerabilitiesIgnorePolicy object will be considered
only if the image to be scanned matches the targets specified for that
policy. Regular expressions can also be used to specify the image
attributes.

Signed-off-by: VaibhavMalik4187 <vaibhavmalik2018@gmail.com>
  • Loading branch information
VaibhavMalik4187 committed Jan 18, 2024
1 parent abc5e9b commit e26ea2a
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 16 deletions.
84 changes: 72 additions & 12 deletions core/core/image_scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"os"
"regexp"
"strings"

"github.com/anchore/grype/grype/presenter/models"
Expand Down Expand Up @@ -60,23 +61,82 @@ func GetImageExceptionsFromFile(filePath string) ([]VulnerabilitiesIgnorePolicy,
return policies, nil
}

func getUniqueVulnerabilitiesAndSeverities(policies []VulnerabilitiesIgnorePolicy) ([]string, []string) {
func getAttributesFromImage(imgName string) (Attributes, error) {
canonicalImageName, err := cautils.NormalizeImageName(imgName)
if err != nil {
return Attributes{}, err
}

tokens := strings.Split(canonicalImageName, "/")
registry := tokens[0]
organization := tokens[1]

imageNameAndTag := strings.Split(tokens[2], ":")
imageName := imageNameAndTag[0]

// Intialize the image tag with default value
imageTag := "latest"
if len(imageNameAndTag) > 1 {
imageTag = imageNameAndTag[1]
}

attributes := Attributes{
Registry: registry,
Organization: organization,
ImageName: imageName,
ImageTag: imageTag,
}

return attributes, nil
}

func regexStringMatch(pattern, target string) bool {
re, err := regexp.Compile(pattern)
if err != nil {
logger.L().StopError(fmt.Sprintf("Failed to generate regular expression: %s", err))
return false
}

if re.MatchString(target) {
return true
}

return false
}

func isTargetImage(targets []Target, attributes Attributes) bool {
for _, target := range targets {
return regexStringMatch(target.Attributes.Registry, attributes.Registry) && regexStringMatch(target.Attributes.Organization, attributes.Organization) && regexStringMatch(target.Attributes.ImageName, attributes.ImageName) && regexStringMatch(target.Attributes.ImageTag, attributes.ImageTag)
}

return false
}

func getUniqueVulnerabilitiesAndSeverities(policies []VulnerabilitiesIgnorePolicy, image string) ([]string, []string) {
// Create maps with slices as values to store unique vulnerabilities and severities (case-insensitive)
uniqueVulns := make(map[string][]string)
uniqueSevers := make(map[string][]string)

imageAttributes, err := getAttributesFromImage(image)
if err != nil {
logger.L().StopError(fmt.Sprintf("Failed to generate image attributes: %s", err))
}

// Iterate over each policy and its vulnerabilities/severities
for _, policy := range policies {
for _, vulnerability := range policy.Vulnerabilities {
// Add to slice directly
vulnerabilityUppercase := strings.ToUpper(vulnerability)
uniqueVulns[vulnerabilityUppercase] = append(uniqueVulns[vulnerabilityUppercase], vulnerability)
}

for _, severity := range policy.Severities {
// Add to slice directly
severityUppercase := strings.ToUpper(severity)
uniqueSevers[severityUppercase] = append(uniqueSevers[severityUppercase], severity)
// Include the exceptions only if the image is one of the targets
if isTargetImage(policy.Targets, imageAttributes) {
for _, vulnerability := range policy.Vulnerabilities {
// Add to slice directly
vulnerabilityUppercase := strings.ToUpper(vulnerability)
uniqueVulns[vulnerabilityUppercase] = append(uniqueVulns[vulnerabilityUppercase], vulnerability)
}

for _, severity := range policy.Severities {
// Add to slice directly
severityUppercase := strings.ToUpper(severity)
uniqueSevers[severityUppercase] = append(uniqueSevers[severityUppercase], severity)
}
}
}

Expand Down Expand Up @@ -114,7 +174,7 @@ func (ks *Kubescape) ScanImage(ctx context.Context, imgScanInfo *ksmetav1.ImageS
return nil, err
}

vulnerabilityExceptions, severityExceptions = getUniqueVulnerabilitiesAndSeverities(exceptionPolicies)
vulnerabilityExceptions, severityExceptions = getUniqueVulnerabilitiesAndSeverities(exceptionPolicies, imgScanInfo.Image)
}

scanResults, err := svc.Scan(ctx, imgScanInfo.Image, creds, vulnerabilityExceptions, severityExceptions)
Expand Down
9 changes: 5 additions & 4 deletions core/meta/datastructures/v1/image_scan.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package v1

type ImageScanInfo struct {
Username string
Password string
Image string
Exceptions string
Username string
Password string
Image string
Exceptions string
CanonicalImageName string
}

0 comments on commit e26ea2a

Please sign in to comment.