Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions cmd/fleet/cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ func scanVulnerabilities(
if err := webhooks.TriggerVulnerabilitiesWebhook(
automationCtx,
ds,
logger.With("webhook", "vulnerabilities"),
logger.SlogLogger().With("webhook", "vulnerabilities"),
args,
mapper,
); err != nil {
Expand Down Expand Up @@ -620,7 +620,7 @@ func newAutomationsSchedule(
"host_status_webhook",
func(ctx context.Context) error {
return webhooks.TriggerHostStatusWebhook(
ctx, ds, logger.With("automation", "host_status"),
ctx, ds, logger.SlogLogger().With("automation", "host_status"),
)
},
),
Expand Down Expand Up @@ -680,11 +680,12 @@ func triggerFailingPoliciesAutomation(
return fmt.Errorf("parsing appConfig.ServerSettings.ServerURL: %w", err)
}

err = policies.TriggerFailingPoliciesAutomation(ctx, ds, logger, failingPoliciesSet, func(policy *fleet.Policy, cfg policies.FailingPolicyAutomationConfig) error {
slogLogger := logger.SlogLogger()
err = policies.TriggerFailingPoliciesAutomation(ctx, ds, slogLogger, failingPoliciesSet, func(policy *fleet.Policy, cfg policies.FailingPolicyAutomationConfig) error {
switch cfg.AutomationType {
case policies.FailingPolicyWebhook:
return webhooks.SendFailingPoliciesBatchedPOSTs(
ctx, policy, failingPoliciesSet, cfg.HostBatchSize, serverURL, cfg.WebhookURL, time.Now(), logger)
ctx, policy, failingPoliciesSet, cfg.HostBatchSize, serverURL, cfg.WebhookURL, time.Now(), slogLogger)

case policies.FailingPolicyJira:
hosts, err := failingPoliciesSet.ListHosts(policy.ID)
Expand Down
17 changes: 7 additions & 10 deletions cmd/maintained-apps/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"flag"
"fmt"
"log/slog"
"os"
"path"
"slices"
Expand All @@ -16,24 +17,20 @@ import (
"github.com/fleetdm/fleet/v4/ee/maintained-apps/ingesters/winget"
"github.com/fleetdm/fleet/v4/pkg/file"
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
kitlog "github.com/go-kit/log"
"github.com/go-kit/log/level"
)

func main() {
slugPtr := flag.String("slug", "", "app slug")
debugPtr := flag.Bool("debug", false, "enable debug logging")
flag.Parse()
ctx := context.Background()
logger := kitlog.NewJSONLogger(os.Stderr)
lvl := level.AllowInfo()
logLevel := slog.LevelInfo
if *debugPtr {
lvl = level.AllowDebug()
logLevel = slog.LevelDebug
}
logger = level.NewFilter(logger, lvl)
logger = kitlog.With(logger, "ts", kitlog.DefaultTimestampUTC)
logger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: logLevel}))

level.Info(logger).Log("msg", "starting maintained app ingestion")
logger.InfoContext(ctx, "starting maintained app ingestion")

ingesters := map[string]maintained_apps.Ingester{
"ee/maintained-apps/inputs/homebrew": homebrew.IngestApps,
Expand All @@ -49,12 +46,12 @@ func main() {
for _, app := range apps {

if app.IsEmpty() {
level.Info(logger).Log("msg", "skipping manifest update due to empty output", "slug", app.Slug)
logger.InfoContext(ctx, "skipping manifest update due to empty output", "slug", app.Slug)
continue
}

if err := processOutput(ctx, app); err != nil {
level.Error(logger).Log("msg", "failed to process maintained app output", "err", err)
logger.ErrorContext(ctx, "failed to process maintained app output", "err", err)
}
}
}
Expand Down
11 changes: 5 additions & 6 deletions ee/maintained-apps/ingesters/homebrew/ingester.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"net/url"
"os"
Expand All @@ -17,12 +18,10 @@ import (
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
"github.com/fleetdm/fleet/v4/pkg/optjson"
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
kitlog "github.com/go-kit/log"
"github.com/go-kit/log/level"
)

func IngestApps(ctx context.Context, logger kitlog.Logger, inputsPath, slugFilter string) ([]*maintained_apps.FMAManifestApp, error) {
level.Info(logger).Log("msg", "starting homebrew app data ingestion")
func IngestApps(ctx context.Context, logger *slog.Logger, inputsPath, slugFilter string) ([]*maintained_apps.FMAManifestApp, error) {
logger.InfoContext(ctx, "starting homebrew app data ingestion")
// Read from our list of apps we should be ingesting
files, err := os.ReadDir(inputsPath)
if err != nil {
Expand Down Expand Up @@ -73,7 +72,7 @@ func IngestApps(ctx context.Context, logger kitlog.Logger, inputsPath, slugFilte
continue
}

level.Info(i.logger).Log("msg", "ingesting homebrew app", "name", input.Name)
i.logger.InfoContext(ctx, "ingesting homebrew app", "name", input.Name)

outApp, err := i.ingestOne(ctx, input)
if err != nil {
Expand All @@ -91,7 +90,7 @@ const baseBrewAPIURL = "https://formulae.brew.sh/api/"

type brewIngester struct {
baseURL string
logger kitlog.Logger
logger *slog.Logger
client *http.Client
}

Expand Down
4 changes: 2 additions & 2 deletions ee/maintained-apps/ingesters/homebrew/ingester_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package homebrew
import (
"context"
"encoding/json"
"log/slog"
"net/http"
"net/http/httptest"
"os"
Expand All @@ -12,7 +13,6 @@ import (
"time"

"github.com/fleetdm/fleet/v4/pkg/fleethttp"
"github.com/go-kit/log"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -127,7 +127,7 @@ func TestIngestValidations(t *testing.T) {
for _, c := range cases {
t.Run(c.inputApp.Token, func(t *testing.T) {
i := &brewIngester{
logger: log.NewNopLogger(),
logger: slog.New(slog.DiscardHandler),
client: fleethttp.NewClient(fleethttp.WithTimeout(10 * time.Second)),
baseURL: srv.URL + "/",
}
Expand Down
13 changes: 6 additions & 7 deletions ee/maintained-apps/ingesters/winget/ingester.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
_ "embed"
"encoding/json"
"fmt"
"log/slog"
"os"
"path"
"path/filepath"
Expand All @@ -17,14 +18,12 @@ import (
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
feednvd "github.com/fleetdm/fleet/v4/server/vulnerabilities/nvd/tools/cvefeed/nvd"
kitlog "github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/google/go-github/v37/github"
"gopkg.in/yaml.v2"
)

func IngestApps(ctx context.Context, logger kitlog.Logger, inputsPath string, slugFilter string) ([]*maintained_apps.FMAManifestApp, error) {
level.Info(logger).Log("msg", "starting winget app data ingestion")
func IngestApps(ctx context.Context, logger *slog.Logger, inputsPath string, slugFilter string) ([]*maintained_apps.FMAManifestApp, error) {
logger.InfoContext(ctx, "starting winget app data ingestion")
// Read from our list of apps we should be ingesting
files, err := os.ReadDir(inputsPath)
if err != nil {
Expand Down Expand Up @@ -85,7 +84,7 @@ func IngestApps(ctx context.Context, logger kitlog.Logger, inputsPath string, sl
continue
}

level.Info(logger).Log("msg", "ingesting winget app", "name", input.Name)
logger.InfoContext(ctx, "ingesting winget app", "name", input.Name)

outApp, err := i.ingestOne(ctx, input)
if err != nil {
Expand All @@ -101,7 +100,7 @@ func IngestApps(ctx context.Context, logger kitlog.Logger, inputsPath string, sl
type wingetIngester struct {
githubClient *github.Client
ghClientOpts *github.RepositoryContentGetOptions
logger kitlog.Logger
logger *slog.Logger
}

func (i *wingetIngester) ingestOne(ctx context.Context, input inputApp) (*maintained_apps.FMAManifestApp, error) {
Expand Down Expand Up @@ -204,7 +203,7 @@ func (i *wingetIngester) ingestOne(ctx context.Context, input inputApp) (*mainta
}

for _, installer := range m.Installers {
level.Debug(i.logger).Log("msg", "checking installer", "arch", installer.Architecture, "type", installer.InstallerType, "locale", installer.InstallerLocale, "scope", installer.Scope)
i.logger.DebugContext(ctx, "checking installer", "arch", installer.Architecture, "type", installer.InstallerType, "locale", installer.InstallerLocale, "scope", installer.Scope)
installerType := m.InstallerType
if installerType == "" || isVendorType(installerType) {
installerType = installer.InstallerType
Expand Down
5 changes: 2 additions & 3 deletions ee/maintained-apps/maintained_apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import (
"crypto/sha256"
"encoding/hex"
"io"
"log/slog"
"strings"

kitlog "github.com/go-kit/log"
)

// Ingester is responsible for ingesting the metadata for maintained apps for a given platform.
// Each platform may have multiple sources for metadata (e.g. homebrew and autopkg for macOS). Each
// source must have its own Ingester implementation.
type Ingester func(ctx context.Context, logger kitlog.Logger, inputsPath string, slugFilter string) ([]*FMAManifestApp, error)
type Ingester func(ctx context.Context, logger *slog.Logger, inputsPath string, slugFilter string) ([]*FMAManifestApp, error)

const OutputPath = "ee/maintained-apps/outputs"

Expand Down
53 changes: 26 additions & 27 deletions server/policies/failing_policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import (
"database/sql"
"errors"
"fmt"
"log/slog"
"net/url"

"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
"github.com/fleetdm/fleet/v4/server/fleet"
kitlog "github.com/go-kit/log"
"github.com/go-kit/log/level"
)

// FailingPolicyAutomationType is the type of automations supported for
Expand Down Expand Up @@ -41,7 +40,7 @@ type FailingPolicyAutomationConfig struct {
func TriggerFailingPoliciesAutomation(
ctx context.Context,
ds fleet.Datastore,
logger kitlog.Logger,
logger *slog.Logger,
failingPoliciesSet fleet.FailingPolicySet,
sendFunc func(*fleet.Policy, FailingPolicyAutomationConfig) error,
) error {
Expand All @@ -57,9 +56,9 @@ func TriggerFailingPoliciesAutomation(
}

if globalAutomationCfg.AutomationType != "" {
level.Debug(logger).Log("global_failing_policy", "enabled", "automation", globalAutomationCfg.AutomationType)
logger.DebugContext(ctx, "global failing policy enabled", "automation", string(globalAutomationCfg.AutomationType))
} else {
level.Debug(logger).Log("global_failing_policy", "disabled")
logger.DebugContext(ctx, "global failing policy disabled")
}

// prepare the per-team configuration caches
Expand All @@ -75,9 +74,9 @@ func TriggerFailingPoliciesAutomation(
policy, err := ds.Policy(ctx, policyID)
switch {
case errors.Is(err, sql.ErrNoRows):
level.Debug(logger).Log("msg", "skipping failing policy, deleted", "policyID", policyID)
logger.DebugContext(ctx, "skipping failing policy, deleted", "policyID", policyID)
if err := failingPoliciesSet.RemoveSet(policyID); err != nil {
level.Error(logger).Log("msg", "failed to remove policy from set", "policyID", policyID, "err", err)
logger.ErrorContext(ctx, "failed to remove policy from set", "policyID", policyID, "err", err)
}
continue
case err != nil:
Expand All @@ -89,15 +88,15 @@ func TriggerFailingPoliciesAutomation(
case policy.TeamID == nil:
// Global policy - use global config
if !globalAutomationCfg.PolicyIDs[policy.ID] {
level.Debug(logger).Log("msg", "skipping failing policy, not found in global policy IDs", "policyID", policyID)
logger.DebugContext(ctx, "skipping failing policy, not found in global policy IDs", "policyID", policyID)
if err := failingPoliciesSet.RemoveSet(policy.ID); err != nil {
level.Error(logger).Log("msg", "failed to remove policy from set", "policyID", policyID, "err", err)
logger.ErrorContext(ctx, "failed to remove policy from set", "policyID", policyID, "err", err)
}
continue
}

if err := sendFunc(policy, globalAutomationCfg); err != nil {
level.Error(logger).Log("msg", "failed to send failing policies", "policyID", policy.ID, "err", err)
logger.ErrorContext(ctx, "failed to send failing policies", "policyID", policy.ID, "err", err)
}
case *policy.TeamID == 0:
// "No Team" policy - use default team config
Expand All @@ -108,23 +107,23 @@ func TriggerFailingPoliciesAutomation(
}

if cfg.AutomationType == "" {
level.Debug(logger).Log("msg", "default team automation disabled", "policyID", policyID)
logger.DebugContext(ctx, "default team automation disabled", "policyID", policyID)
if err := failingPoliciesSet.RemoveSet(policy.ID); err != nil {
level.Error(logger).Log("msg", "failed to remove policy from set", "policyID", policyID, "err", err)
logger.ErrorContext(ctx, "failed to remove policy from set", "policyID", policyID, "err", err)
}
continue
}

if !cfg.PolicyIDs[policy.ID] {
level.Debug(logger).Log("msg", "skipping failing policy, not found in default team policy IDs", "policyID", policyID)
logger.DebugContext(ctx, "skipping failing policy, not found in default team policy IDs", "policyID", policyID)
if err := failingPoliciesSet.RemoveSet(policy.ID); err != nil {
level.Error(logger).Log("msg", "failed to remove policy from set", "policyID", policyID, "err", err)
logger.ErrorContext(ctx, "failed to remove policy from set", "policyID", policyID, "err", err)
}
continue
}

if err := sendFunc(policy, cfg); err != nil {
level.Error(logger).Log("msg", "failed to send failing policies", "policyID", policy.ID, "err", err)
logger.ErrorContext(ctx, "failed to send failing policies", "policyID", policy.ID, "err", err)
}

default:
Expand All @@ -133,34 +132,34 @@ func TriggerFailingPoliciesAutomation(
switch {
case errors.Is(err, sql.ErrNoRows):
// shouldn't happen, unless the team was deleted after the policy was retrieved above
level.Debug(logger).Log("msg", "team does not exist", "teamID", *policy.TeamID)
logger.DebugContext(ctx, "team does not exist", "teamID", *policy.TeamID)
if err := failingPoliciesSet.RemoveSet(policy.ID); err != nil {
level.Error(logger).Log("msg", "failed to remove policy from set", "policyID", policy.ID, "err", err)
logger.ErrorContext(ctx, "failed to remove policy from set", "policyID", policy.ID, "err", err)
}
continue
case err != nil:
level.Error(logger).Log("msg", "failed to get team", "teamID", *policy.TeamID, "err", err)
logger.ErrorContext(ctx, "failed to get team", "teamID", *policy.TeamID, "err", err)
continue
}

if teamCfg.AutomationType == "" {
level.Debug(logger).Log("msg", "team automation disabled", "teamID", *policy.TeamID, "policyID", policyID)
logger.DebugContext(ctx, "team automation disabled", "teamID", *policy.TeamID, "policyID", policyID)
if err := failingPoliciesSet.RemoveSet(policy.ID); err != nil {
level.Error(logger).Log("msg", "failed to remove policy from set", "policyID", policyID, "err", err)
logger.ErrorContext(ctx, "failed to remove policy from set", "policyID", policyID, "err", err)
}
continue
}

if !teamCfg.PolicyIDs[policy.ID] {
level.Debug(logger).Log("msg", "skipping failing policy, not found in team policy IDs", "policyID", policyID)
logger.DebugContext(ctx, "skipping failing policy, not found in team policy IDs", "policyID", policyID)
if err := failingPoliciesSet.RemoveSet(policy.ID); err != nil {
level.Error(logger).Log("msg", "failed to remove policy from set", "policyID", policyID, "err", err)
logger.ErrorContext(ctx, "failed to remove policy from set", "policyID", policyID, "err", err)
}
continue
}

if err := sendFunc(policy, teamCfg); err != nil {
level.Error(logger).Log("msg", "failed to send failing policies", "policyID", policy.ID, "err", err)
logger.ErrorContext(ctx, "failed to send failing policies", "policyID", policy.ID, "err", err)
}
}
}
Expand Down Expand Up @@ -227,7 +226,7 @@ func makeTeamConfigCache(ds fleet.Datastore, globalIntgs fleet.Integrations) fun
}
}

func makeDefaultTeamConfigCache(ds fleet.Datastore, globalIntgs fleet.Integrations, logger kitlog.Logger) func(ctx context.Context) (FailingPolicyAutomationConfig, error) {
func makeDefaultTeamConfigCache(ds fleet.Datastore, globalIntgs fleet.Integrations, logger *slog.Logger) func(ctx context.Context) (FailingPolicyAutomationConfig, error) {
var cached *FailingPolicyAutomationConfig
var cachedErr error

Expand All @@ -245,21 +244,21 @@ func makeDefaultTeamConfigCache(ds fleet.Datastore, globalIntgs fleet.Integratio
defaultTeamConfig, err := ds.DefaultTeamConfig(ctx)
if err != nil {
cachedErr = err
level.Error(logger).Log("msg", "failed to get default team config", "err", err)
logger.ErrorContext(ctx, "failed to get default team config", "err", err)
return cfg, err
}

intgs, err := defaultTeamConfig.Integrations.MatchWithIntegrations(globalIntgs)
if err != nil {
cachedErr = err
level.Error(logger).Log("msg", "failed to match default team integrations", "err", err)
logger.ErrorContext(ctx, "failed to match default team integrations", "err", err)
return cfg, err
}

cfg, err = buildFailingPolicyAutomationConfig(defaultTeamConfig.WebhookSettings.FailingPoliciesWebhook, intgs)
if err != nil {
// Log error but don't fail - just disable automation
level.Error(logger).Log("msg", "failed to build default team automation config", "err", err)
logger.ErrorContext(ctx, "failed to build default team automation config", "err", err)
cfg = FailingPolicyAutomationConfig{} // Return empty config
}

Expand Down
Loading
Loading