Skip to content

Commit

Permalink
admin: add pre v4.8.0 admin command to delete OVAL vulns
Browse files Browse the repository at this point in the history
The migration to delete OVAL vulnerabilities can take a while (10 mins
plus depending on resources). This patch adds a command to pre-delete
the vulnerabilities after adding the migration version entry.

Signed-off-by: crozzy <[email protected]>
  • Loading branch information
crozzy committed Sep 11, 2024
1 parent 5fb41ed commit d3467ba
Showing 1 changed file with 143 additions and 0 deletions.
143 changes: 143 additions & 0 deletions cmd/clairctl/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ var AdminCmd = &cli.Command{
Usage: "create `idx_manifest_layer_layer_id` index in the `indexer` database",
Action: adminPre473,
},
{
Name: "v4.8.0",
Aliases: []string{"4.8.0"},
Description: "This task sets the matcher migration version to 13 to avert the migration deleting RHEL OVAL vulnerabilities.",
Usage: "set matcher migration version to 13",
Action: adminPre480,
},
},
Before: otherVersion,
},
Expand All @@ -64,6 +71,14 @@ var AdminCmd = &cli.Command{
Usage: "delete pyupio vulns in from the matcher DB",
Action: adminPost470,
},
{
Name: "v4.8.0",
Aliases: []string{"4.8.0"},
Description: "This task deletes RHEL OVALv2 vulnerabilities from the database.\n" +
"This could take a while so this command allows an operator to delete the vulnerabilities outside of migrations.\n",
Usage: "delete RHEL OVALv2 vulnerabilities",
Action: adminPost480,
},
},
Before: otherVersion,
},
Expand Down Expand Up @@ -476,3 +491,131 @@ func fromSemver(v *semver.Version) (out claircore.Version) {
out.V[3] = int32(v.Patch())
return out
}

// Set matcher migration version to 13.
func adminPre480(c *cli.Context) error {
ctx := c.Context
fi, err := os.Stat(c.Path("config"))
switch {
case !errors.Is(err, nil):
return fmt.Errorf("bad config: %w", err)
case fi.IsDir():
return fmt.Errorf("bad config: is a directory")
}
cfg, err := loadConfig(c.Path("config"))
if err != nil {
return fmt.Errorf("error loading config: %w", err)
}
dsn := cfg.Matcher.ConnString

pgcfg, err := pgxpool.ParseConfig(dsn)
if err != nil {
return fmt.Errorf("error parsing dsn: %w", err)
}
zlog.Info(ctx).
Str("host", pgcfg.ConnConfig.Host).
Str("database", pgcfg.ConnConfig.Database).
Str("user", pgcfg.ConnConfig.User).
Uint16("port", pgcfg.ConnConfig.Port).
Msg("using discovered connection params")

zlog.Debug(ctx).
Msg("resizing pool to 1 connections")
pgcfg.MaxConns = 1
pool, err := pgxpool.ConnectConfig(ctx, pgcfg)
if err != nil {
return fmt.Errorf("error creating pool: %w", err)
}
defer pool.Close()
if err := pool.Ping(ctx); err != nil {
return fmt.Errorf("error connecting to database: %w", err)
}

return pool.AcquireFunc(ctx, func(conn *pgxpool.Conn) error {
const (
setMatcherMigration = `INSERT INTO libvuln_migrations ("version") VALUES (13) ON CONFLICT DO NOTHING;`
)
if _, err := conn.Exec(ctx, setMatcherMigration); err != nil {
return fmt.Errorf("error setting matcher migration: %w", err)
}
zlog.Debug(ctx).Msg("Set migration version done")
zlog.Info(ctx).Msg("pre v4.8.0 admin done")
return nil
})
}

// Attempt to remove RHEL OVALv2 vulnerabilities before v4.8.0 (where vulnerabilities come from VEX).
func adminPost480(c *cli.Context) error {
ctx := c.Context
fi, err := os.Stat(c.Path("config"))
switch {
case !errors.Is(err, nil):
return fmt.Errorf("bad config: %w", err)
case fi.IsDir():
return fmt.Errorf("bad config: is a directory")
}
cfg, err := loadConfig(c.Path("config"))
if err != nil {
return fmt.Errorf("error loading config: %w", err)
}
dsn := cfg.Matcher.ConnString

pgcfg, err := pgxpool.ParseConfig(dsn)
if err != nil {
return fmt.Errorf("error parsing dsn: %w", err)
}
zlog.Info(ctx).
Str("host", pgcfg.ConnConfig.Host).
Str("database", pgcfg.ConnConfig.Database).
Str("user", pgcfg.ConnConfig.User).
Uint16("port", pgcfg.ConnConfig.Port).
Msg("using discovered connection params")

zlog.Debug(ctx).
Msg("resizing pool to 2 connections")
pgcfg.MaxConns = 2
pool, err := pgxpool.ConnectConfig(ctx, pgcfg)
if err != nil {
return fmt.Errorf("error creating pool: %w", err)
}
defer pool.Close()
if err := pool.Ping(ctx); err != nil {
return fmt.Errorf("error connecting to database: %w", err)
}

return pool.AcquireFunc(ctx, func(conn *pgxpool.Conn) error {
const (
selectUpdateOperations = `SELECT DISTINCT(updater) FROM update_operation WHERE updater ~ 'RHEL[5-9]-*'; `
deleteOVALUO = `DELETE FROM update_operation WHERE updater = ANY($1::TEXT[]);`
deleteOVALVulns = `DELETE FROM vuln where updater = ANY($1::TEXT[]);`
)
updaters := []string{}
rows, err := conn.Query(ctx, selectUpdateOperations)
if err != nil {
return err
}
defer rows.Close()

var updater string
for rows.Next() {
if err := rows.Scan(&updater); err != nil {
return err
}
updaters = append(updaters, updater)
}
if err := rows.Err(); err != nil {
return err
}
zlog.Debug(ctx).Strs("updaters", updaters).Msg("Got updaters")
if _, err := conn.Exec(ctx, deleteOVALUO, updaters); err != nil {
return fmt.Errorf("error deleting OVAL update_operations: %w", err)
}
zlog.Debug(ctx).Msg("Delete update_operations done")
if _, err := conn.Exec(ctx, deleteOVALVulns, updaters); err != nil {
return fmt.Errorf("error deleting OVAL vulns: %w", err)
}
zlog.Debug(ctx).Msg("Delete vulns done")
zlog.Info(ctx).Msg("post v4.8.0 admin done")
return nil
})
}

0 comments on commit d3467ba

Please sign in to comment.