fleet/server/webhooks/vulnerabilities.go
Juan Fernandez b6d084deec
Feature 7559: Include 3rd party severity scores in the vulnerability web-hook payload (#7581)
Premium users should receive vulnerability scores as part of the web-hook payload.
2022-09-06 15:12:17 -04:00

78 lines
2 KiB
Go

package webhooks
import (
"context"
"net/url"
"time"
"github.com/fleetdm/fleet/v4/server"
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
"github.com/fleetdm/fleet/v4/server/fleet"
kitlog "github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
)
// TriggerVulnerabilitiesWebhook performs the webhook requests for vulnerabilities.
func TriggerVulnerabilitiesWebhook(
ctx context.Context,
ds fleet.Datastore,
logger kitlog.Logger,
args VulnArgs,
mapper VulnMapper,
) error {
vulnConfig := args.AppConfig.WebhookSettings.VulnerabilitiesWebhook
if !vulnConfig.Enable {
return nil
}
level.Debug(logger).Log("enabled", "true", "recentVulns", len(args.Vulnerablities))
serverURL, err := url.Parse(args.AppConfig.ServerSettings.ServerURL)
if err != nil {
return ctxerr.Wrap(ctx, err, "invalid server url")
}
targetURL := vulnConfig.DestinationURL
batchSize := vulnConfig.HostBatchSize
softwareIDsGroupedByCVE := make(map[string][]uint)
for _, v := range args.Vulnerablities {
softwareIDsGroupedByCVE[v.CVE] = append(softwareIDsGroupedByCVE[v.CVE], v.SoftwareID)
}
for _, v := range args.Vulnerablities {
softwareIDs := softwareIDsGroupedByCVE[v.CVE]
hosts, err := ds.HostsBySoftwareIDs(ctx, softwareIDs)
if err != nil {
return ctxerr.Wrap(ctx, err, "get hosts by CPE")
}
for len(hosts) > 0 {
limit := len(hosts)
if batchSize > 0 && len(hosts) > batchSize {
limit = batchSize
}
payload := mapper.GetPayload(serverURL, hosts[:limit], v, args.Meta[v.CVE])
if err := sendVulnerabilityHostBatch(ctx, targetURL, payload, args.Time); err != nil {
return ctxerr.Wrap(ctx, err, "send vulnerability host batch")
}
hosts = hosts[limit:]
}
}
return nil
}
func sendVulnerabilityHostBatch(ctx context.Context, targetURL string, vuln WebhookPayload, now time.Time) error {
payload := map[string]interface{}{
"timestamp": now,
"vulnerability": vuln,
}
if err := server.PostJSONWithTimeout(ctx, targetURL, &payload); err != nil {
return ctxerr.Wrapf(ctx, err, "posting to %s", targetURL)
}
return nil
}