github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/file/cataloger/secrets/generate_search_patterns.go (about)

     1  package secrets
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  
     7  	"github.com/bmatcuk/doublestar/v4"
     8  	"github.com/hashicorp/go-multierror"
     9  )
    10  
    11  // GenerateSearchPatterns takes a set of named base patterns, a set of additional named patterns and an name exclusion list and generates a final
    12  // set of regular expressions (indexed by name). The sets are aggregated roughly as such: (base - excluded) + additional.
    13  func GenerateSearchPatterns(basePatterns map[string]string, additionalPatterns map[string]string, excludePatternNames []string) (map[string]*regexp.Regexp, error) {
    14  	var regexObjs = make(map[string]*regexp.Regexp)
    15  	var errs error
    16  
    17  	addFn := func(name, pattern string) {
    18  		// always enable multiline search option for extracting secrets with multiline values
    19  		obj, err := regexp.Compile(`(?m)` + pattern)
    20  		if err != nil {
    21  			errs = multierror.Append(errs, fmt.Errorf("unable to parse %q regular expression: %w", name, err))
    22  		}
    23  		regexObjs[name] = obj
    24  	}
    25  
    26  	// add all base cases... unless that base case was asked to be excluded
    27  	for name, pattern := range basePatterns {
    28  		if !matchesExclusion(excludePatternNames, name) {
    29  			addFn(name, pattern)
    30  		}
    31  	}
    32  
    33  	// add all additional cases
    34  	for name, pattern := range additionalPatterns {
    35  		addFn(name, pattern)
    36  	}
    37  
    38  	if errs != nil {
    39  		return nil, errs
    40  	}
    41  
    42  	return regexObjs, nil
    43  }
    44  
    45  func matchesExclusion(excludePatternNames []string, name string) bool {
    46  	for _, exclude := range excludePatternNames {
    47  		matches, err := doublestar.Match(exclude, name)
    48  		if err != nil {
    49  			return false
    50  		}
    51  		if matches {
    52  			return true
    53  		}
    54  	}
    55  	return false
    56  }