@@ -13,6 +13,9 @@ import (
1313 "github.com/quay/zlog"
1414
1515 "github.com/quay/claircore"
16+ "github.com/quay/claircore/libvuln/driver"
17+ _ "github.com/quay/claircore/matchers/defaults"
18+ "github.com/quay/claircore/matchers/registry"
1619)
1720
1821var (
@@ -39,71 +42,71 @@ var (
3942 )
4043)
4144
42- func queryBuilder (v * claircore.Vulnerability , vp claircore. CheckVulnerablePipeline ) (string , error ) {
45+ func queryBuilder (v * claircore.Vulnerability , m driver. Matcher ) (string , error ) {
4346 psql := goqu .Dialect ("postgres" )
4447 exps := []goqu.Expression {}
4548 packageQuery := goqu.Ex {"package.name" : v .Package .Name }
4649 exps = append (exps , packageQuery )
47- seen := make (map [claircore .MatchConstraint ]struct {})
48- for _ , m := range vp .Query () {
50+ seen := make (map [driver .MatchConstraint ]struct {})
51+ for _ , m := range m .Query () {
4952 if _ , ok := seen [m ]; ok {
5053 continue
5154 }
5255 var ex goqu.Ex
5356 switch m {
54- case claircore .PackageModule :
57+ case driver .PackageModule :
5558 ex = goqu.Ex {"package.module" : v .Package .Module }
56- case claircore .DistributionDID :
59+ case driver .DistributionDID :
5760 if v .Dist .DID == "" {
5861 return "" , ErrVulnNotApplicable
5962 }
6063 ex = goqu.Ex {"dist.did" : v .Dist .DID }
61- case claircore .DistributionName :
64+ case driver .DistributionName :
6265 if v .Dist .Name == "" {
6366 return "" , ErrVulnNotApplicable
6467 }
6568 ex = goqu.Ex {"dist.name" : v .Dist .Name }
66- case claircore .DistributionVersionID :
69+ case driver .DistributionVersionID :
6770 if v .Dist .VersionID == "" {
6871 return "" , ErrVulnNotApplicable
6972 }
7073 ex = goqu.Ex {"dist.version_id" : v .Dist .VersionID }
71- case claircore .DistributionVersion :
74+ case driver .DistributionVersion :
7275 if v .Dist .Version == "" {
7376 return "" , ErrVulnNotApplicable
7477 }
7578 ex = goqu.Ex {"dist.version" : v .Dist .Version }
76- case claircore .DistributionVersionCodeName :
79+ case driver .DistributionVersionCodeName :
7780 if v .Dist .VersionCodeName == "" {
7881 return "" , ErrVulnNotApplicable
7982 }
8083 ex = goqu.Ex {"dist.version_code_name" : v .Dist .VersionCodeName }
81- case claircore .DistributionPrettyName :
84+ case driver .DistributionPrettyName :
8285 if v .Dist .PrettyName == "" {
8386 return "" , ErrVulnNotApplicable
8487 }
8588 ex = goqu.Ex {"dist.pretty_name" : v .Dist .PrettyName }
86- case claircore .DistributionCPE :
89+ case driver .DistributionCPE :
8790 if v .Dist .CPE .String () == "" {
8891 return "" , ErrVulnNotApplicable
8992 }
9093 ex = goqu.Ex {"dist.cpe" : v .Dist .CPE }
91- case claircore .DistributionArch :
94+ case driver .DistributionArch :
9295 if v .Dist .Arch == "" {
9396 return "" , ErrVulnNotApplicable
9497 }
9598 ex = goqu.Ex {"dist.arch" : v .Dist .Arch }
96- case claircore .RepositoryName :
99+ case driver .RepositoryName :
97100 if v .Repo .Name == "" {
98101 return "" , ErrVulnNotApplicable
99102 }
100103 ex = goqu.Ex {"repo.name" : v .Repo .Name }
101- case claircore .RepositoryKey :
104+ case driver .RepositoryKey :
102105 if v .Repo .Key == "" {
103106 return "" , ErrVulnNotApplicable
104107 }
105108 ex = goqu.Ex {"repo.key" : v .Repo .Key }
106- case claircore .HasFixedInVersion :
109+ case driver .HasFixedInVersion :
107110 if v .FixedInVersion == "" {
108111 // No unpatched vulnerabilities wanted
109112 return "" , ErrVulnNotApplicable
@@ -114,7 +117,8 @@ func queryBuilder(v *claircore.Vulnerability, vp claircore.CheckVulnerablePipeli
114117 exps = append (exps , ex )
115118 seen [m ] = struct {}{}
116119 }
117- if vp .VersionAuthoritative != nil {
120+ f , ok := m .(driver.VersionFilter )
121+ if ok && f .VersionAuthoritative () {
118122 kind , lower , upper := rangefmt (v .Range )
119123 if kind != nil {
120124 exps = append (exps , goqu .And (
@@ -156,100 +160,108 @@ func queryBuilder(v *claircore.Vulnerability, vp claircore.CheckVulnerablePipeli
156160 return sql , nil
157161}
158162
159- func (s * IndexerStore ) AffectedManifests (ctx context.Context , v claircore.Vulnerability , vps []claircore.CheckVulnerablePipeline ) ([]claircore.Digest , error ) {
163+ func (s * IndexerStore ) AffectedManifests (ctx context.Context , v claircore.Vulnerability ) ([]claircore.Digest , error ) {
164+ matcherFactories := registry .Registered ()
160165 ctx = zlog .ContextWithValues (ctx , "component" , "datastore/postgres/AffectedManifests" )
161166 mrs := map [string ]struct {}{}
162167 out := []claircore.Digest {}
163- for _ , vp := range vps {
164- miQuery , err := queryBuilder (& v , vp )
165- switch {
166- case errors .Is (err , nil ):
167- case errors .Is (err , ErrVulnNotApplicable ):
168- continue
169- default :
170- return nil , fmt .Errorf ("error building query %w" , err )
168+ for n , mf := range matcherFactories {
169+ ms , err := mf .Matcher (ctx )
170+ if err != nil {
171+ return nil , fmt .Errorf ("failed to create matchers from factory %s: %w" , n , err )
171172 }
172- err = func () error {
173- start := time .Now ()
174- rows , err := s .pool .Query (ctx , miQuery )
173+ for _ , m := range ms {
174+ miQuery , err := queryBuilder (& v , m )
175175 switch {
176176 case errors .Is (err , nil ):
177+ case errors .Is (err , ErrVulnNotApplicable ):
178+ continue
177179 default :
178- return fmt .Errorf ("failed to query packages associated with vulnerability %q: %w" , v . ID , err )
180+ return nil , fmt .Errorf ("error building query %w" , err )
179181 }
180-
181- defer rows . Close ()
182- for rows . Next () {
183- ir := & claircore. IndexRecord {
184- Package : & claircore. Package {},
185- Repository : & claircore. Repository {},
186- Distribution : & claircore. Distribution {},
182+ err = func () error {
183+ start := time . Now ()
184+ rows , err := s . pool . Query ( ctx , miQuery )
185+ switch {
186+ case errors . Is ( err , nil ):
187+ default :
188+ return fmt . Errorf ( "failed to query packages associated with vulnerability %q: %w" , v . ID , err )
187189 }
188- var (
189- manifestDigest * claircore.Digest
190- nVer pgtype.Int4Array
191- nKind * string
192- )
193- err := rows .Scan (
194- & manifestDigest ,
195- & ir .Package .Name ,
196- & ir .Package .Version ,
197- & ir .Package .Kind ,
198- & nKind ,
199- & nVer ,
200- & ir .Package .Arch ,
201- & ir .Distribution .Name ,
202- & ir .Distribution .DID ,
203- & ir .Distribution .Version ,
204- & ir .Distribution .VersionCodeName ,
205- & ir .Distribution .VersionID ,
206- & ir .Distribution .Arch ,
207- & ir .Distribution .CPE ,
208- & ir .Distribution .PrettyName ,
209- & ir .Repository .Name ,
210- & ir .Repository .Key ,
211- & ir .Repository .URI ,
212- & ir .Repository .CPE ,
213- )
214- if err != nil {
215- return fmt .Errorf ("failed to scan index record: %w" , err )
216- }
217- if nKind != nil {
218- ir .Package .NormalizedVersion .Kind = * nKind
219- for i , n := range nVer .Elements {
220- ir .Package .NormalizedVersion .V [i ] = n .Int
190+
191+ defer rows .Close ()
192+ for rows .Next () {
193+ ir := & claircore.IndexRecord {
194+ Package : & claircore.Package {},
195+ Repository : & claircore.Repository {},
196+ Distribution : & claircore.Distribution {},
221197 }
222- }
223- if _ , ok := mrs [manifestDigest .String ()]; ok {
224- // We've already seen the manifest we don't need to
225- // redo the work.
226- continue
227- }
228- if ! vp .Filter (ir ) {
229- continue
230- }
231- var match bool
232- if vp .VersionAuthoritative != nil && vp .VersionAuthoritative () {
233- // We've already done the vulnerable checking so don't need
234- // to call the Vulnerable() function.
235- match = true
236- } else {
237- match , err = vp .Vulnernable (ctx , ir , & v )
198+ var (
199+ manifestDigest * claircore.Digest
200+ nVer pgtype.Int4Array
201+ nKind * string
202+ )
203+ err := rows .Scan (
204+ & manifestDigest ,
205+ & ir .Package .Name ,
206+ & ir .Package .Version ,
207+ & ir .Package .Kind ,
208+ & nKind ,
209+ & nVer ,
210+ & ir .Package .Arch ,
211+ & ir .Distribution .Name ,
212+ & ir .Distribution .DID ,
213+ & ir .Distribution .Version ,
214+ & ir .Distribution .VersionCodeName ,
215+ & ir .Distribution .VersionID ,
216+ & ir .Distribution .Arch ,
217+ & ir .Distribution .CPE ,
218+ & ir .Distribution .PrettyName ,
219+ & ir .Repository .Name ,
220+ & ir .Repository .Key ,
221+ & ir .Repository .URI ,
222+ & ir .Repository .CPE ,
223+ )
238224 if err != nil {
239- return fmt .Errorf ("error checking for if IndexRecord is vulnerable %w" , err )
225+ return fmt .Errorf ("failed to scan index record: %w" , err )
226+ }
227+ if nKind != nil {
228+ ir .Package .NormalizedVersion .Kind = * nKind
229+ for i , n := range nVer .Elements {
230+ ir .Package .NormalizedVersion .V [i ] = n .Int
231+ }
232+ }
233+ if _ , ok := mrs [manifestDigest .String ()]; ok {
234+ // We've already seen the manifest we don't need to
235+ // redo the work.
236+ continue
237+ }
238+ if ! m .Filter (ir ) {
239+ continue
240+ }
241+ var match bool
242+ f , ok := m .(driver.VersionFilter )
243+ if ok && f .VersionAuthoritative () {
244+ // We've already done the vulnerable checking so don't need
245+ // to call the Vulnerable() function.
246+ match = true
247+ } else {
248+ match , err = m .Vulnerable (ctx , ir , & v )
249+ if err != nil {
250+ return fmt .Errorf ("error checking for if IndexRecord is vulnerable %w" , err )
251+ }
252+ }
253+ if match {
254+ mrs [manifestDigest .String ()] = struct {}{}
255+ out = append (out , * manifestDigest )
240256 }
241257 }
242- if match {
243- mrs [manifestDigest .String ()] = struct {}{}
244- out = append (out , * manifestDigest )
245- }
258+ getAffectedManifestsCounter .WithLabelValues ("query_batch" ).Add (1 )
259+ getAffectedManifestsDuration .WithLabelValues ("query_batch" ).Observe (time .Since (start ).Seconds ())
260+ return nil
261+ }()
262+ if err != nil {
263+ return nil , err
246264 }
247- getAffectedManifestsCounter .WithLabelValues ("query_batch" ).Add (1 )
248- getAffectedManifestsDuration .WithLabelValues ("query_batch" ).Observe (time .Since (start ).Seconds ())
249- return nil
250- }()
251- if err != nil {
252- return nil , err
253265 }
254266 }
255267 return out , nil
0 commit comments