mirror of
https://github.com/fleetdm/fleet
synced 2026-05-18 06:28:40 +00:00
156 lines
4.4 KiB
Go
156 lines
4.4 KiB
Go
package mysql
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
|
"github.com/jmoiron/sqlx"
|
|
)
|
|
|
|
func (ds *Datastore) ListOSVulnerabilitiesByOS(ctx context.Context, osID uint) ([]fleet.OSVulnerability, error) {
|
|
r := []fleet.OSVulnerability{}
|
|
|
|
stmt := `
|
|
SELECT
|
|
operating_system_id,
|
|
cve,
|
|
resolved_in_version,
|
|
source
|
|
FROM operating_system_vulnerabilities
|
|
WHERE operating_system_id = ?
|
|
`
|
|
|
|
if err := sqlx.SelectContext(ctx, ds.reader(ctx), &r, stmt, osID); err != nil {
|
|
return nil, ctxerr.Wrap(ctx, err, "error executing SQL statement")
|
|
}
|
|
|
|
return r, nil
|
|
}
|
|
|
|
func (ds *Datastore) ListVulnsByOsNameAndVersion(ctx context.Context, name, version string, includeCVSS bool) (fleet.Vulnerabilities, error) {
|
|
r := fleet.Vulnerabilities{}
|
|
|
|
var sqlstmt string
|
|
|
|
if includeCVSS == true {
|
|
sqlstmt = `
|
|
SELECT DISTINCT
|
|
osv.cve,
|
|
cm.cvss_score,
|
|
cm.epss_probability,
|
|
cm.cisa_known_exploit,
|
|
cm.published as cve_published,
|
|
cm.description,
|
|
osv.resolved_in_version
|
|
FROM operating_system_vulnerabilities osv
|
|
LEFT JOIN cve_meta cm ON cm.cve = osv.cve
|
|
WHERE osv.operating_system_id IN (
|
|
SELECT id FROM operating_systems WHERE name = ? AND version = ?
|
|
)
|
|
`
|
|
} else {
|
|
sqlstmt = `
|
|
SELECT DISTINCT
|
|
osv.cve
|
|
FROM operating_system_vulnerabilities osv
|
|
WHERE osv.operating_system_id IN (
|
|
SELECT id FROM operating_systems WHERE name = ? AND version = ?
|
|
)
|
|
`
|
|
}
|
|
|
|
if err := sqlx.SelectContext(ctx, ds.reader(ctx), &r, sqlstmt, name, version); err != nil {
|
|
return nil, ctxerr.Wrap(ctx, err, "error executing SQL statement")
|
|
}
|
|
|
|
return r, nil
|
|
}
|
|
|
|
func (ds *Datastore) InsertOSVulnerabilities(ctx context.Context, vulnerabilities []fleet.OSVulnerability, source fleet.VulnerabilitySource) (int64, error) {
|
|
var args []interface{}
|
|
|
|
if len(vulnerabilities) == 0 {
|
|
return 0, nil
|
|
}
|
|
|
|
values := strings.TrimSuffix(strings.Repeat("(?,?,?,?),", len(vulnerabilities)), ",")
|
|
sql := fmt.Sprintf(`INSERT IGNORE INTO operating_system_vulnerabilities (operating_system_id, cve, source, resolved_in_version) VALUES %s`, values)
|
|
|
|
for _, v := range vulnerabilities {
|
|
args = append(args, v.OSID, v.CVE, source, v.ResolvedInVersion)
|
|
}
|
|
res, err := ds.writer(ctx).ExecContext(ctx, sql, args...)
|
|
if err != nil {
|
|
return 0, ctxerr.Wrap(ctx, err, "insert operating system vulnerabilities")
|
|
}
|
|
count, _ := res.RowsAffected()
|
|
|
|
return count, nil
|
|
}
|
|
|
|
func (ds *Datastore) InsertOSVulnerability(ctx context.Context, v fleet.OSVulnerability, s fleet.VulnerabilitySource) (bool, error) {
|
|
if v.CVE == "" {
|
|
return false, fmt.Errorf("inserting operating system vulnerability: CVE cannot be empty %#v", v)
|
|
}
|
|
|
|
var args []interface{}
|
|
|
|
// statement assumes a unique index on (host_id, cve)
|
|
sqlStmt := `
|
|
INSERT INTO operating_system_vulnerabilities (
|
|
operating_system_id,
|
|
cve,
|
|
source,
|
|
resolved_in_version
|
|
) VALUES (?,?,?,?)
|
|
ON DUPLICATE KEY UPDATE
|
|
operating_system_id = VALUES(operating_system_id),
|
|
source = VALUES(source),
|
|
resolved_in_version = VALUES(resolved_in_version),
|
|
updated_at = ?
|
|
`
|
|
|
|
args = append(args, v.OSID, v.CVE, s, v.ResolvedInVersion, time.Now().UTC())
|
|
|
|
res, err := ds.writer(ctx).ExecContext(ctx, sqlStmt, args...)
|
|
if err != nil {
|
|
return false, ctxerr.Wrap(ctx, err, "insert operating system vulnerability")
|
|
}
|
|
|
|
return insertOnDuplicateDidInsert(res), nil
|
|
}
|
|
|
|
func (ds *Datastore) DeleteOSVulnerabilities(ctx context.Context, vulnerabilities []fleet.OSVulnerability) error {
|
|
if len(vulnerabilities) == 0 {
|
|
return nil
|
|
}
|
|
|
|
sql := fmt.Sprintf(
|
|
`DELETE FROM operating_system_vulnerabilities WHERE (operating_system_id, cve) IN (%s)`,
|
|
strings.TrimSuffix(strings.Repeat("(?,?),", len(vulnerabilities)), ","),
|
|
)
|
|
|
|
var args []interface{}
|
|
for _, v := range vulnerabilities {
|
|
args = append(args, v.OSID, v.CVE)
|
|
}
|
|
if _, err := ds.writer(ctx).ExecContext(ctx, sql, args...); err != nil {
|
|
return ctxerr.Wrapf(ctx, err, "deleting operating system vulnerabilities")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ds *Datastore) DeleteOutOfDateOSVulnerabilities(ctx context.Context, src fleet.VulnerabilitySource, d time.Duration) error {
|
|
deleteStmt := `
|
|
DELETE FROM operating_system_vulnerabilities
|
|
WHERE source = ? AND updated_at < ?
|
|
`
|
|
if _, err := ds.writer(ctx).ExecContext(ctx, deleteStmt, src, time.Now().UTC().Add(-d)); err != nil {
|
|
return ctxerr.Wrap(ctx, err, "deleting out of date operating system vulnerabilities")
|
|
}
|
|
return nil
|
|
}
|