github.com/quay/claircore@v1.5.28/aws/distributionscanner.go (about) 1 package aws 2 3 import ( 4 "bytes" 5 "context" 6 "regexp" 7 "runtime/trace" 8 9 "github.com/quay/zlog" 10 11 "github.com/quay/claircore" 12 "github.com/quay/claircore/indexer" 13 ) 14 15 // Amazon Linux keeps a consistent os-release file between 16 // major releases. 17 // All tested images on docker hub contained os-release file 18 // 19 // ScannerVersion increased to 2 when adding AL2023 20 21 const ( 22 scannerName = "aws" 23 scannerVersion = "2" 24 scannerKind = "distribution" 25 ) 26 27 type awsRegex struct { 28 release Release 29 regexp *regexp.Regexp 30 } 31 32 var awsRegexes = []awsRegex{ 33 { 34 release: AmazonLinux1, 35 regexp: regexp.MustCompile(`CPE_NAME="cpe:/o:amazon:linux:201.\.0[39]:ga"`), 36 }, 37 { 38 release: AmazonLinux2, 39 regexp: regexp.MustCompile(`CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"`), 40 }, 41 { 42 release: AmazonLinux2023, 43 regexp: regexp.MustCompile(`CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2023"`), 44 }, 45 } 46 47 const osReleasePath = `etc/os-release` 48 49 var ( 50 _ indexer.DistributionScanner = (*DistributionScanner)(nil) 51 _ indexer.VersionedScanner = (*DistributionScanner)(nil) 52 ) 53 54 // DistributionScanner attempts to discover if a layer 55 // displays characteristics of a AWS distribution 56 type DistributionScanner struct{} 57 58 // Name implements scanner.VersionedScanner. 59 func (*DistributionScanner) Name() string { return scannerName } 60 61 // Version implements scanner.VersionedScanner. 62 func (*DistributionScanner) Version() string { return scannerVersion } 63 64 // Kind implements scanner.VersionedScanner. 65 func (*DistributionScanner) Kind() string { return scannerKind } 66 67 // Scan will inspect the layer for an os-release or lsb-release file 68 // and perform a regex match for keywords indicating the associated AWS release 69 // 70 // If neither file is found a (nil,nil) is returned. 71 // If the files are found but all regexp fail to match an empty slice is returned. 72 func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { 73 defer trace.StartRegion(ctx, "Scanner.Scan").End() 74 ctx = zlog.ContextWithValues(ctx, 75 "component", "aws_dist_scanner", 76 "name", ds.Name(), 77 "version", ds.Version(), 78 "kind", ds.Kind(), 79 "layer", l.Hash.String()) 80 zlog.Debug(ctx).Msg("start") 81 defer zlog.Debug(ctx).Msg("done") 82 files, err := l.Files(osReleasePath) 83 if err != nil { 84 zlog.Debug(ctx).Msg("didn't find an os-release") 85 return nil, nil 86 } 87 for _, buff := range files { 88 dist := ds.parse(buff) 89 if dist != nil { 90 return []*claircore.Distribution{dist}, nil 91 } 92 } 93 return []*claircore.Distribution{}, nil 94 } 95 96 // parse attempts to match all AWS release regexp and returns the associated 97 // distribution if it exists. 98 // 99 // separated into its own method to aid testing. 100 func (ds *DistributionScanner) parse(buff *bytes.Buffer) *claircore.Distribution { 101 for _, ur := range awsRegexes { 102 if ur.regexp.Match(buff.Bytes()) { 103 dist := releaseToDist(ur.release) 104 return dist 105 } 106 } 107 return nil 108 }