github.com/quay/claircore@v1.5.28/photon/distributionscanner.go (about) 1 package photon 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 // Photon provides one security database file per major version. So far, there are 3 versions 16 // Photon 1.0, Photon 2.0 and Photon 3.0 17 18 const ( 19 scannerName = "photon" 20 scannerVersion = "v0.0.1" 21 scannerKind = "distribution" 22 ) 23 24 const ( 25 osReleasePath = `etc/os-release` 26 photonReleasePath = `etc/photon-release` 27 ) 28 29 type photonRegex struct { 30 release Release 31 regexp *regexp.Regexp 32 } 33 34 var photonRegexes = []photonRegex{ 35 { 36 release: Photon1, 37 // regex for /etc/os-release 38 regexp: regexp.MustCompile(`^.*"VMware Photon"\sVERSION="1.0"`), 39 }, 40 { 41 release: Photon2, 42 // regex for /etc/os-release 43 regexp: regexp.MustCompile(`^.*"VMware Photon OS"\sVERSION="2.0"`), 44 }, 45 { 46 release: Photon3, 47 // regex for /etc/os-release 48 regexp: regexp.MustCompile(`^.*"VMware Photon OS"\sVERSION="3.0"`), 49 }, 50 } 51 52 var ( 53 _ indexer.DistributionScanner = (*DistributionScanner)(nil) 54 _ indexer.VersionedScanner = (*DistributionScanner)(nil) 55 ) 56 57 // DistributionScanner attempts to discover if a layer 58 // displays characteristics of a photon distribution 59 type DistributionScanner struct{} 60 61 // Name implements scanner.VersionedScanner. 62 func (*DistributionScanner) Name() string { return scannerName } 63 64 // Version implements scanner.VersionedScanner. 65 func (*DistributionScanner) Version() string { return scannerVersion } 66 67 // Kind implements scanner.VersionedScanner. 68 func (*DistributionScanner) Kind() string { return scannerKind } 69 70 // Scan will inspect the layer for an os-release or lsb-release file 71 // and perform a regex match for keywords indicating the associated photon release 72 // 73 // If neither file is found a (nil,nil) is returned. 74 // If the files are found but all regexp fail to match an empty slice is returned. 75 func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { 76 defer trace.StartRegion(ctx, "Scanner.Scan").End() 77 ctx = zlog.ContextWithValues(ctx, 78 "component", "photon/DistributionScanner.Scan", 79 "version", ds.Version(), 80 "layer", l.Hash.String()) 81 zlog.Debug(ctx).Msg("start") 82 defer zlog.Debug(ctx).Msg("done") 83 files, err := l.Files(osReleasePath, photonReleasePath) 84 if err != nil { 85 zlog.Debug(ctx).Msg("didn't find an os-release or photon-release") 86 return nil, nil 87 } 88 for _, buff := range files { 89 dist := ds.parse(buff) 90 if dist != nil { 91 return []*claircore.Distribution{dist}, nil 92 } 93 } 94 return []*claircore.Distribution{}, nil 95 } 96 97 // parse attempts to match all Photon release regexp and returns the associated 98 // distribution if it exists. 99 // 100 // separated into its own method to aid testing. 101 func (ds *DistributionScanner) parse(buff *bytes.Buffer) *claircore.Distribution { 102 for _, ur := range photonRegexes { 103 if ur.regexp.Match(buff.Bytes()) { 104 return releaseToDist(ur.release) 105 } 106 } 107 return nil 108 }