From 52b66abafd89fa27eb983e508777d020ada9b9f1 Mon Sep 17 00:00:00 2001 From: dantecatalfamo Date: Tue, 7 Jan 2025 13:06:14 -0500 Subject: [PATCH] Move error checking back up to service method so error can be logged --- ee/server/service/teams.go | 17 +++++++++++++++++ server/fleet/agent_options.go | 23 +---------------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/ee/server/service/teams.go b/ee/server/service/teams.go index eded9b4788ac..121351b2559a 100644 --- a/ee/server/service/teams.go +++ b/ee/server/service/teams.go @@ -414,6 +414,23 @@ func (svc *Service) ModifyTeamAgentOptions(ctx context.Context, teamID uint, tea if teamOptions != nil { if err := fleet.ValidateJSONAgentOptions(ctx, svc.ds, teamOptions, true); err != nil { + if field := fleet.GetJSONUnknownField(err); field != nil { + correctKeyPath, keyErr := fleet.FindAgentOptionsKeyPath(*field) + if keyErr != nil { + level.Error(svc.logger).Log("err", err, "msg", "error parsing generated agent options structs") + } + var keyPathJoined string + switch pathLen := len(correctKeyPath); { + case pathLen > 1: + keyPathJoined = fmt.Sprintf("%q", strings.Join(correctKeyPath[:len(correctKeyPath)-1], ".")) + case pathLen == 1: + keyPathJoined = "top level" + } + if keyPathJoined != "" { + err = fmt.Errorf("%q should be part of the %s object", *field, keyPathJoined) + } + } + err = fleet.NewUserMessageError(err, http.StatusBadRequest) if applyOptions.Force && !applyOptions.DryRun { level.Info(svc.logger).Log("err", err, "msg", "force-apply team agent options with validation errors") diff --git a/server/fleet/agent_options.go b/server/fleet/agent_options.go index 5983f25b0fe9..51f9d94dcfdc 100644 --- a/server/fleet/agent_options.go +++ b/server/fleet/agent_options.go @@ -48,27 +48,6 @@ func (o *AgentOptions) ForPlatform(platform string) json.RawMessage { // The validation always uses the most recent Osquery version that is available // at the time of the Fleet release. func ValidateJSONAgentOptions(ctx context.Context, ds Datastore, rawJSON json.RawMessage, isPremium bool) error { - err := validateJSONAgentOptionsInternal(ctx, ds, rawJSON, isPremium) - if field := GetJSONUnknownField(err); field != nil { - correctKeyPath, keyErr := findAgentOptionsKeyPath(*field) - if keyErr != nil { - return fmt.Errorf("agent options struct parsing: %w", err) - } - var keyPathJoined string - switch pathLen := len(correctKeyPath); { - case pathLen > 1: - keyPathJoined = fmt.Sprintf("%q", strings.Join(correctKeyPath[:len(correctKeyPath)-1], ".")) - case pathLen == 1: - keyPathJoined = "top level" - } - if keyPathJoined != "" { - err = fmt.Errorf("%q should be part of the %s object", *field, keyPathJoined) - } - } - return err -} - -func validateJSONAgentOptionsInternal(ctx context.Context, ds Datastore, rawJSON json.RawMessage, isPremium bool) error { var opts AgentOptions if err := JSONStrictDecode(bytes.NewReader(rawJSON), &opts); err != nil { return err @@ -347,7 +326,7 @@ func validateJSONAgentOptionsSet(rawJSON json.RawMessage) error { return nil } -func findAgentOptionsKeyPath(key string) ([]string, error) { +func FindAgentOptionsKeyPath(key string) ([]string, error) { if key == "script_execution_timeout" { return []string{"script_execution_timeout"}, nil }