mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
97 lines
2.6 KiB
Go
97 lines
2.6 KiB
Go
package webhooks
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
"path"
|
|
"sort"
|
|
"strconv"
|
|
"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"
|
|
)
|
|
|
|
// SendFailingPoliciesBatchedPOSTs sends a failing policy to the provided
|
|
// webhook URL. It sends in batches if hostBatchSize > 0. After a successful
|
|
// send, the corresponding hosts are removed from the failing policies set.
|
|
func SendFailingPoliciesBatchedPOSTs(
|
|
ctx context.Context,
|
|
policy *fleet.Policy,
|
|
failingPoliciesSet fleet.FailingPolicySet,
|
|
hostBatchSize int,
|
|
serverURL *url.URL,
|
|
webhookURL *url.URL,
|
|
now time.Time,
|
|
logger kitlog.Logger,
|
|
) error {
|
|
hosts, err := failingPoliciesSet.ListHosts(policy.ID)
|
|
if err != nil {
|
|
return ctxerr.Wrapf(ctx, err, "listing hosts for failing policies set %d", policy.ID)
|
|
}
|
|
if len(hosts) == 0 {
|
|
level.Debug(logger).Log("msg", "no hosts", "policyID", policy.ID)
|
|
return nil
|
|
}
|
|
sort.Slice(hosts, func(i, j int) bool {
|
|
return hosts[i].ID < hosts[j].ID
|
|
})
|
|
|
|
if hostBatchSize == 0 {
|
|
hostBatchSize = len(hosts)
|
|
}
|
|
for i := 0; i < len(hosts); i += hostBatchSize {
|
|
end := i + hostBatchSize
|
|
if end > len(hosts) {
|
|
end = len(hosts)
|
|
}
|
|
batch := hosts[i:end]
|
|
|
|
failingHosts := make([]failingHost, len(batch))
|
|
for i, host := range batch {
|
|
failingHosts[i] = makeFailingHost(host, serverURL)
|
|
}
|
|
|
|
payload := failingPoliciesPayload{
|
|
Timestamp: now,
|
|
Policy: policy,
|
|
FailingHosts: failingHosts,
|
|
}
|
|
level.Debug(logger).Log("payload", payload, "url", webhookURL.String(), "batch", len(batch))
|
|
if err := server.PostJSONWithTimeout(ctx, webhookURL.String(), &payload); err != nil {
|
|
return ctxerr.Wrapf(ctx, err, "posting to %q", webhookURL)
|
|
}
|
|
if err := failingPoliciesSet.RemoveHosts(policy.ID, batch); err != nil {
|
|
return ctxerr.Wrapf(ctx, err, "removing hosts %+v from failing policies set %d", batch, policy.ID)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type failingPoliciesPayload struct {
|
|
Timestamp time.Time `json:"timestamp"`
|
|
Policy *fleet.Policy `json:"policy"`
|
|
FailingHosts []failingHost `json:"hosts"`
|
|
}
|
|
|
|
type failingHost struct {
|
|
ID uint `json:"id"`
|
|
Hostname string `json:"hostname"`
|
|
DisplayName string `json:"display_name"`
|
|
URL string `json:"url"`
|
|
}
|
|
|
|
func makeFailingHost(host fleet.PolicySetHost, serverURL *url.URL) failingHost {
|
|
u := *serverURL
|
|
u.Path = path.Join(serverURL.Path, "hosts", strconv.FormatUint(uint64(host.ID), 10))
|
|
return failingHost{
|
|
ID: host.ID,
|
|
Hostname: host.Hostname,
|
|
DisplayName: host.DisplayName,
|
|
URL: u.String(),
|
|
}
|
|
}
|