diff --git a/cmd/fleetctl/apply.go b/cmd/fleetctl/apply.go index b0f1dd7b9b..d08b6bb520 100644 --- a/cmd/fleetctl/apply.go +++ b/cmd/fleetctl/apply.go @@ -154,6 +154,14 @@ func applyCommand() cli.Command { fmt.Printf("[+] applied %d packs\n", len(specs.Packs)) } + if specs.Options != nil { + if err := fleet.ApplyOptions(specs.Options); err != nil { + return errors.Wrap(err, "applying options") + } + fmt.Printf("[+] applied options\n") + + } + return nil }, } diff --git a/cmd/fleetctl/fleetctl.go b/cmd/fleetctl/fleetctl.go index 4e57678b22..039f8dbae0 100644 --- a/cmd/fleetctl/fleetctl.go +++ b/cmd/fleetctl/fleetctl.go @@ -35,6 +35,7 @@ func main() { getQueriesCommand(), getPacksCommand(), getLabelsCommand(), + getOptionsCommand(), }, }, cli.Command{ diff --git a/cmd/fleetctl/get.go b/cmd/fleetctl/get.go index 85a2cd146f..c7a971484e 100644 --- a/cmd/fleetctl/get.go +++ b/cmd/fleetctl/get.go @@ -231,3 +231,40 @@ func getLabelsCommand() cli.Command { }, } } + +func getOptionsCommand() cli.Command { + return cli.Command{ + Name: "options", + Usage: "Retrieve the osquery configuration", + Flags: []cli.Flag{ + configFlag(), + contextFlag(), + }, + Action: func(c *cli.Context) error { + fleet, err := clientFromCLI(c) + if err != nil { + return err + } + + options, err := fleet.GetOptions() + if err != nil { + return err + } + + spec := specGeneric{ + Kind: "options", + Version: kolide.ApiVersion, + Spec: options, + } + + b, err := yaml.Marshal(spec) + if err != nil { + return err + } + + fmt.Print(string(b)) + return nil + + }, + } +} diff --git a/server/service/client_options.go b/server/service/client_options.go new file mode 100644 index 0000000000..ab561a471b --- /dev/null +++ b/server/service/client_options.go @@ -0,0 +1,73 @@ +package service + +import ( + "encoding/json" + "net/http" + + "github.com/kolide/fleet/server/kolide" + "github.com/pkg/errors" +) + +// ApplyOptions sends the osquery options to be applied to the Fleet instance. +func (c *Client) ApplyOptions(spec *kolide.OptionsSpec) error { + req := applyOsqueryOptionsSpecRequest{Spec: spec} + response, err := c.AuthenticatedDo("POST", "/api/v1/kolide/spec/osquery_options", req) + if err != nil { + return errors.Wrap(err, "POST /api/v1/kolide/spec/osquery_options") + } + defer response.Body.Close() + + if response.StatusCode != http.StatusOK { + return errors.Errorf( + "apply options received status %d %s", + response.StatusCode, + extractServerErrorText(response.Body), + ) + } + + var responseBody applyOsqueryOptionsSpecResponse + err = json.NewDecoder(response.Body).Decode(&responseBody) + if err != nil { + return errors.Wrap(err, "decode apply options spec response") + } + + if responseBody.Err != nil { + return errors.Errorf("apply options spec: %s", responseBody.Err) + } + + return nil +} + +// GetOptions retrieves the configured osquery options. +func (c *Client) GetOptions() (*kolide.OptionsSpec, error) { + verb, path := "GET", "/api/v1/kolide/spec/osquery_options" + response, err := c.AuthenticatedDo(verb, path, nil) + if err != nil { + return nil, errors.Wrap(err, verb+" "+path) + } + defer response.Body.Close() + + switch response.StatusCode { + case http.StatusNotFound: + return nil, notFoundErr{} + } + if response.StatusCode != http.StatusOK { + return nil, errors.Errorf( + "get options received status %d %s", + response.StatusCode, + extractServerErrorText(response.Body), + ) + } + + var responseBody getOsqueryOptionsSpecResponse + err = json.NewDecoder(response.Body).Decode(&responseBody) + if err != nil { + return nil, errors.Wrap(err, "decode get options spec response") + } + + if responseBody.Err != nil { + return nil, errors.Errorf("get options spec: %s", responseBody.Err) + } + + return responseBody.Spec, nil +} diff --git a/server/service/handler.go b/server/service/handler.go index 00cc82c752..202b417168 100644 --- a/server/service/handler.go +++ b/server/service/handler.go @@ -436,8 +436,8 @@ func attachKolideAPIRoutes(r *mux.Router, h *kolideHandlers) { r.Handle("/api/v1/kolide/options", h.GetOptions).Methods("GET").Name("get_options") r.Handle("/api/v1/kolide/options", h.ModifyOptions).Methods("PATCH").Name("modify_options") r.Handle("/api/v1/kolide/options/reset", h.ResetOptions).Methods("GET").Name("reset_options") - r.Handle("/api/v1/kolide/osquery_options/spec", h.ApplyOsqueryOptionsSpec).Methods("POST").Name("apply_osquery_options_spec") - r.Handle("/api/v1/kolide/osquery_options/spec", h.GetOsqueryOptionsSpec).Methods("GET").Name("get_osquery_options_spec") + r.Handle("/api/v1/kolide/spec/osquery_options", h.ApplyOsqueryOptionsSpec).Methods("POST").Name("apply_osquery_options_spec") + r.Handle("/api/v1/kolide/spec/osquery_options", h.GetOsqueryOptionsSpec).Methods("GET").Name("get_osquery_options_spec") r.Handle("/api/v1/kolide/targets", h.SearchTargets).Methods("POST").Name("search_targets") diff --git a/server/service/logging_oquery_options.go b/server/service/logging_osquery_options.go similarity index 100% rename from server/service/logging_oquery_options.go rename to server/service/logging_osquery_options.go