Skip to content

Commit e6cd4c8

Browse files
committed
datastore/postgres: populate Aliases and Self when retrieving vulnerabilities
Signed-off-by: J. Victor Martins <jvdm@sdf.org>
1 parent 384aae8 commit e6cd4c8

1 file changed

Lines changed: 94 additions & 0 deletions

File tree

datastore/postgres/get.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"log/slog"
77
"strconv"
88
"time"
9+
"unique"
910

1011
"github.com/jackc/pgx/v5"
1112
"github.com/prometheus/client_golang/prometheus"
@@ -172,8 +173,101 @@ func (s *MatcherStore) Get(ctx context.Context, records []*claircore.IndexRecord
172173
getVulnerabilitiesCounter.WithLabelValues("query_batch").Add(1)
173174
getVulnerabilitiesDuration.WithLabelValues("query_batch").Observe(time.Since(start).Seconds())
174175

176+
if err := populateAliases(ctx, tx, results); err != nil {
177+
return nil, fmt.Errorf("populating aliases: %w", err)
178+
}
179+
175180
if err := tx.Commit(ctx); err != nil {
176181
return nil, fmt.Errorf("failed to commit tx: %v", err)
177182
}
178183
return results, nil
179184
}
185+
186+
// populateAliases fetches aliases and self references for all vulnerabilities
187+
// in the results map and populates the Aliases and Self fields.
188+
func populateAliases(ctx context.Context, tx pgx.Tx, results map[string][]*claircore.Vulnerability) error {
189+
vulnByID := make(map[string]*claircore.Vulnerability)
190+
for _, vulns := range results {
191+
for _, v := range vulns {
192+
vulnByID[v.ID] = v
193+
}
194+
}
195+
if len(vulnByID) == 0 {
196+
return nil
197+
}
198+
199+
ids := make([]int64, 0, len(vulnByID))
200+
for id := range vulnByID {
201+
n, err := strconv.ParseInt(id, 10, 64)
202+
if err != nil {
203+
continue
204+
}
205+
ids = append(ids, n)
206+
}
207+
208+
const aliasQuery = `
209+
SELECT va.vulnerability, ns.namespace, a.name
210+
FROM vulnerability_alias va
211+
JOIN alias a ON va.alias = a.id
212+
JOIN alias_namespace ns ON a.namespace = ns.id
213+
WHERE va.vulnerability = ANY($1)
214+
`
215+
aliasRows, err := tx.Query(ctx, aliasQuery, ids)
216+
if err != nil {
217+
return fmt.Errorf("querying aliases: %w", err)
218+
}
219+
defer aliasRows.Close()
220+
221+
for aliasRows.Next() {
222+
var vulnID int64
223+
var namespace, name string
224+
if err := aliasRows.Scan(&vulnID, &namespace, &name); err != nil {
225+
return fmt.Errorf("scanning alias row: %w", err)
226+
}
227+
v := vulnByID[strconv.FormatInt(vulnID, 10)]
228+
if v == nil {
229+
continue
230+
}
231+
v.Aliases = append(v.Aliases, claircore.Alias{
232+
Space: unique.Make(namespace),
233+
Name: name,
234+
})
235+
}
236+
if err := aliasRows.Err(); err != nil {
237+
return fmt.Errorf("iterating alias rows: %w", err)
238+
}
239+
240+
const selfQuery = `
241+
SELECT vs.vulnerability, ns.namespace, a.name
242+
FROM vulnerability_self vs
243+
JOIN alias a ON vs.self = a.id
244+
JOIN alias_namespace ns ON a.namespace = ns.id
245+
WHERE vs.vulnerability = ANY($1)
246+
`
247+
selfRows, err := tx.Query(ctx, selfQuery, ids)
248+
if err != nil {
249+
return fmt.Errorf("querying self aliases: %w", err)
250+
}
251+
defer selfRows.Close()
252+
253+
for selfRows.Next() {
254+
var vulnID int64
255+
var namespace, name string
256+
if err := selfRows.Scan(&vulnID, &namespace, &name); err != nil {
257+
return fmt.Errorf("scanning self row: %w", err)
258+
}
259+
v := vulnByID[strconv.FormatInt(vulnID, 10)]
260+
if v == nil {
261+
continue
262+
}
263+
v.Self = claircore.Alias{
264+
Space: unique.Make(namespace),
265+
Name: name,
266+
}
267+
}
268+
if err := selfRows.Err(); err != nil {
269+
return fmt.Errorf("iterating self rows: %w", err)
270+
}
271+
272+
return nil
273+
}

0 commit comments

Comments
 (0)