github.com/quay/claircore@v1.5.28/oracle/distributionscanner.go (about) 1 package oracle 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 // Oracle Linux has minor releases such as 7.7 and 6.10 16 // however their elsa OVAL xml sec db always references the major release 17 // for example: <platform>Oracle Linux 5</platform> 18 // for this reason the oracle distribution scanner will detect and normalize 19 // minor releases to major releases to match vulnerabilities correctly 20 21 const ( 22 scannerName = "oracle" 23 scannerVersion = "1" 24 scannerKind = "distribution" 25 ) 26 27 const osReleasePath = `etc/os-release` 28 29 // Oracle Linux 5 will not have os-release and only has etc/issue 30 const issuePath = `etc/issue` 31 32 type oracleRegex struct { 33 release Release 34 regexp *regexp.Regexp 35 } 36 37 var oracleRegexes = []oracleRegex{ 38 { 39 release: Five, 40 // regex for /etc/issue 41 regexp: regexp.MustCompile(`(?is)Oracle Linux Server release ?5(\.\d*)?`), 42 }, 43 { 44 release: Six, 45 regexp: regexp.MustCompile(`(?is)Oracle Linux Server 6(\.\d*)?`), 46 }, 47 { 48 release: Seven, 49 regexp: regexp.MustCompile(`(?is)Oracle Linux Server 7(\.\d*)?`), 50 }, 51 { 52 release: Eight, 53 regexp: regexp.MustCompile(`(?is)Oracle Linux Server 8(\.\d*)?`), 54 }, 55 { 56 release: Nine, 57 regexp: regexp.MustCompile(`(?is)Oracle Linux Server 9(\.\d*)?`), 58 }, 59 } 60 61 var ( 62 _ indexer.DistributionScanner = (*DistributionScanner)(nil) 63 _ indexer.VersionedScanner = (*DistributionScanner)(nil) 64 ) 65 66 // DistributionScanner attempts to discover if a layer 67 // displays characteristics of a Oracle distribution 68 type DistributionScanner struct{} 69 70 // Name implements scanner.VersionedScanner. 71 func (*DistributionScanner) Name() string { return scannerName } 72 73 // Version implements scanner.VersionedScanner. 74 func (*DistributionScanner) Version() string { return scannerVersion } 75 76 // Kind implements scanner.VersionedScanner. 77 func (*DistributionScanner) Kind() string { return scannerKind } 78 79 // Scan will inspect the layer for an os-release or lsb-release file 80 // and perform a regex match for keywords indicating the associated Oracle release 81 // 82 // If neither file is found a (nil,nil) is returned. 83 // If the files are found but all regexp fail to match an empty slice is returned. 84 func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { 85 defer trace.StartRegion(ctx, "Scanner.Scan").End() 86 ctx = zlog.ContextWithValues(ctx, 87 "component", "oracle/DistributionScanner.Scan", 88 "version", ds.Version(), 89 "layer", l.Hash.String()) 90 zlog.Debug(ctx).Msg("start") 91 defer zlog.Debug(ctx).Msg("done") 92 files, err := l.Files(osReleasePath, issuePath) 93 if err != nil { 94 zlog.Debug(ctx).Msg("didn't find an os-release or issues file") 95 return nil, nil 96 } 97 for _, buff := range files { 98 dist := ds.parse(buff) 99 if dist != nil { 100 return []*claircore.Distribution{dist}, nil 101 } 102 } 103 return []*claircore.Distribution{}, nil 104 } 105 106 // parse attempts to match all Oracle release regexp and returns the associated 107 // distribution if it exists. 108 // 109 // separated into its own method to aid testing. 110 func (ds *DistributionScanner) parse(buff *bytes.Buffer) *claircore.Distribution { 111 for _, ur := range oracleRegexes { 112 if ur.regexp.Match(buff.Bytes()) { 113 return releaseToDist(ur.release) 114 } 115 } 116 return nil 117 }