diff --git a/server/datastore/datastore_labels_test.go b/server/datastore/datastore_labels_test.go index f10ad9fcf9..0107b14fc9 100644 --- a/server/datastore/datastore_labels_test.go +++ b/server/datastore/datastore_labels_test.go @@ -412,7 +412,7 @@ func testChangeLabelDetails(t *testing.T, db kolide.Datastore) { assert.Equal(t, label.Name, saved.Name) } -func testApplyLabelSpecsRoundtrip(t *testing.T, ds kolide.Datastore) { +func setupLabelSpecsTest(t *testing.T, ds kolide.Datastore) []*kolide.LabelSpec { expectedSpecs := []*kolide.LabelSpec{ &kolide.LabelSpec{ Name: "foo", @@ -437,6 +437,22 @@ func testApplyLabelSpecsRoundtrip(t *testing.T, ds kolide.Datastore) { err := ds.ApplyLabelSpecs(expectedSpecs) require.Nil(t, err) + return expectedSpecs +} + +func testGetLabelSpec(t *testing.T, ds kolide.Datastore) { + expectedSpecs := setupLabelSpecsTest(t, ds) + + for _, s := range expectedSpecs { + spec, err := ds.GetLabelSpec(s.Name) + require.Nil(t, err) + assert.Equal(t, s, spec) + } +} + +func testApplyLabelSpecsRoundtrip(t *testing.T, ds kolide.Datastore) { + expectedSpecs := setupLabelSpecsTest(t, ds) + specs, err := ds.GetLabelSpecs() require.Nil(t, err) assert.Equal(t, expectedSpecs, specs) diff --git a/server/datastore/datastore_packs_test.go b/server/datastore/datastore_packs_test.go index c90271e57b..dca7652c27 100644 --- a/server/datastore/datastore_packs_test.go +++ b/server/datastore/datastore_packs_test.go @@ -150,7 +150,7 @@ func testAddLabelToPackTwice(t *testing.T, ds kolide.Datastore) { require.NotNil(t, err) } -func testApplyPackSpecRoundtrip(t *testing.T, ds kolide.Datastore) { +func setupPackSpecsTest(t *testing.T, ds kolide.Datastore) []*kolide.PackSpec { zwass := test.NewUser(t, ds, "Zach", "zwass", "zwass@kolide.co", true) queries := []*kolide.Query{ {Name: "foo", Description: "get the foos", Query: "select * from foo"}, @@ -180,7 +180,7 @@ func testApplyPackSpecRoundtrip(t *testing.T, ds kolide.Datastore) { boolPtr := func(b bool) *bool { return &b } uintPtr := func(x uint) *uint { return &x } stringPtr := func(s string) *string { return &s } - specs := []*kolide.PackSpec{ + expectedSpecs := []*kolide.PackSpec{ &kolide.PackSpec{ ID: 1, Name: "test_pack", @@ -215,13 +215,27 @@ func testApplyPackSpecRoundtrip(t *testing.T, ds kolide.Datastore) { }, } - err = ds.ApplyPackSpecs(specs) + err = ds.ApplyPackSpecs(expectedSpecs) require.Nil(t, err) + return expectedSpecs +} + +func testApplyPackSpecRoundtrip(t *testing.T, ds kolide.Datastore) { + expectedSpecs := setupPackSpecsTest(t, ds) gotSpec, err := ds.GetPackSpecs() - require.Nil(t, err) - assert.Equal(t, specs, gotSpec) + assert.Equal(t, expectedSpecs, gotSpec) +} + +func testGetPackSpec(t *testing.T, ds kolide.Datastore) { + expectedSpecs := setupPackSpecsTest(t, ds) + + for _, s := range expectedSpecs { + spec, err := ds.GetPackSpec(s.Name) + require.Nil(t, err) + assert.Equal(t, s, spec) + } } func testApplyPackSpecMissingQueries(t *testing.T, ds kolide.Datastore) { diff --git a/server/datastore/datastore_test.go b/server/datastore/datastore_test.go index c886564200..a820717c55 100644 --- a/server/datastore/datastore_test.go +++ b/server/datastore/datastore_test.go @@ -80,6 +80,8 @@ var testFunctions = [...]func(*testing.T, kolide.Datastore){ testApplyQueries, testApplyPackSpecRoundtrip, testApplyPackSpecMissingQueries, + testGetPackSpec, testApplyLabelSpecsRoundtrip, + testGetLabelSpec, testListLabelsForPack, } diff --git a/server/datastore/mysql/labels.go b/server/datastore/mysql/labels.go index e1173f2da7..43b9489a3d 100644 --- a/server/datastore/mysql/labels.go +++ b/server/datastore/mysql/labels.go @@ -72,6 +72,24 @@ func (d *Datastore) GetLabelSpecs() ([]*kolide.LabelSpec, error) { return specs, nil } +func (d *Datastore) GetLabelSpec(name string) (*kolide.LabelSpec, error) { + var specs []*kolide.LabelSpec + query := ` +SELECT name, description, query, platform, label_type +FROM labels +WHERE name = ? +` + if err := d.db.Select(&specs, query, name); err != nil { + return nil, errors.Wrap(err, "get label") + } + + if len(specs) != 1 { + return nil, errors.Errorf("expected 1 label row, got %d", len(specs)) + } + + return specs[0], nil +} + // DeleteLabel deletes a kolide.Label func (d *Datastore) DeleteLabel(name string) error { return d.deleteEntityByName("labels", name) diff --git a/server/datastore/mysql/packs.go b/server/datastore/mysql/packs.go index f06540e532..09e03ddd0e 100644 --- a/server/datastore/mysql/packs.go +++ b/server/datastore/mysql/packs.go @@ -172,6 +172,67 @@ WHERE pack_id = ? return specs, nil } +func (d *Datastore) GetPackSpec(name string) (spec *kolide.PackSpec, err error) { + tx, err := d.db.Beginx() + if err != nil { + return nil, errors.Wrap(err, "begin GetPackSpecs transaction") + } + + defer func() { + if err != nil { + rbErr := tx.Rollback() + // It seems possible that there might be a case in + // which the error we are dealing with here was thrown + // by the call to tx.Commit(), and the docs suggest + // this call would then result in sql.ErrTxDone. + if rbErr != nil && rbErr != sql.ErrTxDone { + panic(fmt.Sprintf("got err '%s' rolling back after err '%s'", rbErr, err)) + } + } + }() + + // Get basic spec + var specs []*kolide.PackSpec + query := "SELECT id, name, description, platform FROM packs WHERE name = ?" + if err := tx.Select(&specs, query, name); err != nil { + return nil, errors.Wrap(err, "get packs") + } + if len(specs) != 1 { + return nil, errors.Errorf("expected 1 pack row, got %d", len(specs)) + } + + spec = specs[0] + + // Load targets + query = ` +SELECT l.name +FROM labels l JOIN pack_targets pt +WHERE pack_id = ? AND pt.type = ? AND pt.target_id = l.id +` + if err := tx.Select(&spec.Targets.Labels, query, spec.ID, kolide.TargetLabel); err != nil { + return nil, errors.Wrap(err, "get pack targets") + } + + // Load queries + query = ` +SELECT +query_name, name, description, ` + "`interval`" + `, +snapshot, removed, shard, platform, version +FROM scheduled_queries +WHERE pack_id = ? +` + if err := tx.Select(&spec.Queries, query, spec.ID); err != nil { + return nil, errors.Wrap(err, "get pack queries") + } + + err = tx.Commit() + if err != nil { + return nil, errors.Wrap(err, "commit transaction") + } + + return spec, nil +} + func (d *Datastore) PackByName(name string, opts ...kolide.OptionalArg) (*kolide.Pack, bool, error) { db := d.getTransaction(opts) sqlStatement := ` diff --git a/server/kolide/labels.go b/server/kolide/labels.go index dbbeabefb6..6fd501c0a3 100644 --- a/server/kolide/labels.go +++ b/server/kolide/labels.go @@ -11,6 +11,8 @@ type LabelStore interface { ApplyLabelSpecs(specs []*LabelSpec) error // GetLabelSpecs returns all of the stored LabelSpecs. GetLabelSpecs() ([]*LabelSpec, error) + // GetLabelSpec returns the spec for the named label. + GetLabelSpec(name string) (*LabelSpec, error) // Label methods DeleteLabel(name string) error @@ -51,6 +53,8 @@ type LabelService interface { ApplyLabelSpecs(ctx context.Context, specs []*LabelSpec) error // GetLabelSpecs returns all of the stored LabelSpecs. GetLabelSpecs(ctx context.Context) ([]*LabelSpec, error) + // GetLabelSpec gets the spec for the label with the given name. + GetLabelSpec(ctx context.Context, name string) (*LabelSpec, error) ListLabels(ctx context.Context, opt ListOptions) (labels []*Label, err error) GetLabel(ctx context.Context, id uint) (label *Label, err error) diff --git a/server/kolide/packs.go b/server/kolide/packs.go index f5d1f5e609..d597f197ed 100644 --- a/server/kolide/packs.go +++ b/server/kolide/packs.go @@ -9,9 +9,10 @@ type PackStore interface { // ApplyPackSpecs applies a list of PackSpecs to the datastore, // creating and updating packs as necessary. ApplyPackSpecs(specs []*PackSpec) error - // GetPackSpecs returns all of the stored PackSpecs. GetPackSpecs() ([]*PackSpec, error) + // GetPackSpec returns the spec for the named pack. + GetPackSpec(name string) (*PackSpec, error) // DeletePack deletes a pack record from the datastore. DeletePack(name string) error @@ -46,9 +47,10 @@ type PackService interface { // ApplyPackSpecs applies a list of PackSpecs to the datastore, // creating and updating packs as necessary. ApplyPackSpecs(ctx context.Context, specs []*PackSpec) error - // GetPackSpecs returns all of the stored PackSpecs. GetPackSpecs(ctx context.Context) ([]*PackSpec, error) + // GetPackSpec gets the spec for the pack with the given name. + GetPackSpec(ctx context.Context, name string) (*PackSpec, error) // ListPacks lists all packs in the application. ListPacks(ctx context.Context, opt ListOptions) (packs []*Pack, err error) diff --git a/server/kolide/queries.go b/server/kolide/queries.go index fcc6e05adc..6ce594d44b 100644 --- a/server/kolide/queries.go +++ b/server/kolide/queries.go @@ -43,6 +43,8 @@ type QueryService interface { ApplyQuerySpecs(ctx context.Context, specs []*QuerySpec) error // GetQuerySpecs gets the YAML file representing all the stored queries. GetQuerySpecs(ctx context.Context) ([]*QuerySpec, error) + // GetQuerySpec gets the spec for the query with the given name. + GetQuerySpec(ctx context.Context, name string) (*QuerySpec, error) // ListQueries returns a list of saved queries. Note only saved queries // should be returned (those that are created for distributed queries diff --git a/server/mock/datastore_labels.go b/server/mock/datastore_labels.go index aac4868ce2..8c3cda2fbd 100644 --- a/server/mock/datastore_labels.go +++ b/server/mock/datastore_labels.go @@ -14,6 +14,8 @@ type ApplyLabelSpecsFunc func(specs []*kolide.LabelSpec) error type GetLabelSpecsFunc func() ([]*kolide.LabelSpec, error) +type GetLabelSpecFunc func(name string) (*kolide.LabelSpec, error) + type DeleteLabelFunc func(name string) error type LabelFunc func(lid uint) (*kolide.Label, error) @@ -39,6 +41,9 @@ type LabelStore struct { GetLabelSpecsFunc GetLabelSpecsFunc GetLabelSpecsFuncInvoked bool + GetLabelSpecFunc GetLabelSpecFunc + GetLabelSpecFuncInvoked bool + DeleteLabelFunc DeleteLabelFunc DeleteLabelFuncInvoked bool @@ -77,6 +82,11 @@ func (s *LabelStore) GetLabelSpecs() ([]*kolide.LabelSpec, error) { return s.GetLabelSpecsFunc() } +func (s *LabelStore) GetLabelSpec(name string) (*kolide.LabelSpec, error) { + s.GetLabelSpecFuncInvoked = true + return s.GetLabelSpecFunc(name) +} + func (s *LabelStore) DeleteLabel(name string) error { s.DeleteLabelFuncInvoked = true return s.DeleteLabelFunc(name) diff --git a/server/mock/datastore_packs.go b/server/mock/datastore_packs.go index 67a594b4b8..87f34bcd89 100644 --- a/server/mock/datastore_packs.go +++ b/server/mock/datastore_packs.go @@ -10,6 +10,8 @@ type ApplyPackSpecsFunc func(specs []*kolide.PackSpec) error type GetPackSpecsFunc func() ([]*kolide.PackSpec, error) +type GetPackSpecFunc func(name string) (*kolide.PackSpec, error) + type DeletePackFunc func(name string) error type PackFunc func(pid uint) (*kolide.Pack, error) @@ -33,6 +35,9 @@ type PackStore struct { GetPackSpecsFunc GetPackSpecsFunc GetPackSpecsFuncInvoked bool + GetPackSpecFunc GetPackSpecFunc + GetPackSpecFuncInvoked bool + DeletePackFunc DeletePackFunc DeletePackFuncInvoked bool @@ -68,6 +73,11 @@ func (s *PackStore) GetPackSpecs() ([]*kolide.PackSpec, error) { return s.GetPackSpecsFunc() } +func (s *PackStore) GetPackSpec(name string) (*kolide.PackSpec, error) { + s.GetPackSpecFuncInvoked = true + return s.GetPackSpecFunc(name) +} + func (s *PackStore) DeletePack(name string) error { s.DeletePackFuncInvoked = true return s.DeletePackFunc(name) diff --git a/server/mock/datastore_scheduled_queries.go b/server/mock/datastore_scheduled_queries.go index 971f3fb7d6..1c6ad685ba 100644 --- a/server/mock/datastore_scheduled_queries.go +++ b/server/mock/datastore_scheduled_queries.go @@ -6,53 +6,13 @@ import "github.com/kolide/fleet/server/kolide" var _ kolide.ScheduledQueryStore = (*ScheduledQueryStore)(nil) -type NewScheduledQueryFunc func(sq *kolide.ScheduledQuery, opts ...kolide.OptionalArg) (*kolide.ScheduledQuery, error) - -type SaveScheduledQueryFunc func(sq *kolide.ScheduledQuery) (*kolide.ScheduledQuery, error) - -type DeleteScheduledQueryFunc func(id uint) error - -type ScheduledQueryFunc func(id uint) (*kolide.ScheduledQuery, error) - type ListScheduledQueriesInPackFunc func(id uint, opts kolide.ListOptions) ([]*kolide.ScheduledQuery, error) type ScheduledQueryStore struct { - NewScheduledQueryFunc NewScheduledQueryFunc - NewScheduledQueryFuncInvoked bool - - SaveScheduledQueryFunc SaveScheduledQueryFunc - SaveScheduledQueryFuncInvoked bool - - DeleteScheduledQueryFunc DeleteScheduledQueryFunc - DeleteScheduledQueryFuncInvoked bool - - ScheduledQueryFunc ScheduledQueryFunc - ScheduledQueryFuncInvoked bool - ListScheduledQueriesInPackFunc ListScheduledQueriesInPackFunc ListScheduledQueriesInPackFuncInvoked bool } -func (s *ScheduledQueryStore) NewScheduledQuery(sq *kolide.ScheduledQuery, opts ...kolide.OptionalArg) (*kolide.ScheduledQuery, error) { - s.NewScheduledQueryFuncInvoked = true - return s.NewScheduledQueryFunc(sq, opts...) -} - -func (s *ScheduledQueryStore) SaveScheduledQuery(sq *kolide.ScheduledQuery) (*kolide.ScheduledQuery, error) { - s.SaveScheduledQueryFuncInvoked = true - return s.SaveScheduledQueryFunc(sq) -} - -func (s *ScheduledQueryStore) DeleteScheduledQuery(id uint) error { - s.DeleteScheduledQueryFuncInvoked = true - return s.DeleteScheduledQueryFunc(id) -} - -func (s *ScheduledQueryStore) ScheduledQuery(id uint) (*kolide.ScheduledQuery, error) { - s.ScheduledQueryFuncInvoked = true - return s.ScheduledQueryFunc(id) -} - func (s *ScheduledQueryStore) ListScheduledQueriesInPack(id uint, opts kolide.ListOptions) ([]*kolide.ScheduledQuery, error) { s.ListScheduledQueriesInPackFuncInvoked = true return s.ListScheduledQueriesInPackFunc(id, opts) diff --git a/server/service/endpoint_labels.go b/server/service/endpoint_labels.go index 1c896857ac..2e7ce6a8d4 100644 --- a/server/service/endpoint_labels.go +++ b/server/service/endpoint_labels.go @@ -172,3 +172,25 @@ func makeGetLabelSpecsEndpoint(svc kolide.Service) endpoint.Endpoint { return getLabelSpecsResponse{Specs: specs}, nil } } + +//////////////////////////////////////////////////////////////////////////////// +// Get Label Spec +//////////////////////////////////////////////////////////////////////////////// + +type getLabelSpecResponse struct { + Spec *kolide.LabelSpec `json:"specs,omitempty"` + Err error `json:"error,omitempty"` +} + +func (r getLabelSpecResponse) error() error { return r.Err } + +func makeGetLabelSpecEndpoint(svc kolide.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(getGenericSpecRequest) + spec, err := svc.GetLabelSpec(ctx, req.Name) + if err != nil { + return getLabelSpecResponse{Err: err}, nil + } + return getLabelSpecResponse{Spec: spec}, nil + } +} diff --git a/server/service/endpoint_packs.go b/server/service/endpoint_packs.go index 8d942fac17..1b28763817 100644 --- a/server/service/endpoint_packs.go +++ b/server/service/endpoint_packs.go @@ -195,3 +195,25 @@ func makeGetPackSpecsEndpoint(svc kolide.Service) endpoint.Endpoint { return getPackSpecsResponse{Specs: specs}, nil } } + +//////////////////////////////////////////////////////////////////////////////// +// Get Pack Spec +//////////////////////////////////////////////////////////////////////////////// + +type getPackSpecResponse struct { + Spec *kolide.PackSpec `json:"specs,omitempty"` + Err error `json:"error,omitempty"` +} + +func (r getPackSpecResponse) error() error { return r.Err } + +func makeGetPackSpecEndpoint(svc kolide.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(getGenericSpecRequest) + spec, err := svc.GetPackSpec(ctx, req.Name) + if err != nil { + return getPackSpecResponse{Err: err}, nil + } + return getPackSpecResponse{Spec: spec}, nil + } +} diff --git a/server/service/endpoint_queries.go b/server/service/endpoint_queries.go index 3dca44c634..6490839eb4 100644 --- a/server/service/endpoint_queries.go +++ b/server/service/endpoint_queries.go @@ -212,3 +212,25 @@ func makeGetQuerySpecsEndpoint(svc kolide.Service) endpoint.Endpoint { return getQuerySpecsResponse{Specs: specs}, nil } } + +//////////////////////////////////////////////////////////////////////////////// +// Get Query Spec +//////////////////////////////////////////////////////////////////////////////// + +type getQuerySpecResponse struct { + Spec *kolide.QuerySpec `json:"specs,omitempty"` + Err error `json:"error,omitempty"` +} + +func (r getQuerySpecResponse) error() error { return r.Err } + +func makeGetQuerySpecEndpoint(svc kolide.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + req := request.(getGenericSpecRequest) + spec, err := svc.GetQuerySpec(ctx, req.Name) + if err != nil { + return getQuerySpecResponse{Err: err}, nil + } + return getQuerySpecResponse{Spec: spec}, nil + } +} diff --git a/server/service/handler.go b/server/service/handler.go index c2b0f42e5f..dad474e2de 100644 --- a/server/service/handler.go +++ b/server/service/handler.go @@ -47,6 +47,7 @@ type KolideEndpoints struct { DeleteQueries endpoint.Endpoint ApplyQuerySpecs endpoint.Endpoint GetQuerySpecs endpoint.Endpoint + GetQuerySpec endpoint.Endpoint CreateDistributedQueryCampaign endpoint.Endpoint GetPack endpoint.Endpoint ListPacks endpoint.Endpoint @@ -54,6 +55,7 @@ type KolideEndpoints struct { GetScheduledQueriesInPack endpoint.Endpoint ApplyPackSpecs endpoint.Endpoint GetPackSpecs endpoint.Endpoint + GetPackSpec endpoint.Endpoint EnrollAgent endpoint.Endpoint GetClientConfig endpoint.Endpoint GetDistributedQueries endpoint.Endpoint @@ -64,6 +66,7 @@ type KolideEndpoints struct { DeleteLabel endpoint.Endpoint ApplyLabelSpecs endpoint.Endpoint GetLabelSpecs endpoint.Endpoint + GetLabelSpec endpoint.Endpoint GetHost endpoint.Endpoint DeleteHost endpoint.Endpoint ListHosts endpoint.Endpoint @@ -131,6 +134,7 @@ func MakeKolideServerEndpoints(svc kolide.Service, jwtKey string) KolideEndpoint DeleteQueries: authenticatedUser(jwtKey, svc, makeDeleteQueriesEndpoint(svc)), ApplyQuerySpecs: authenticatedUser(jwtKey, svc, makeApplyQuerySpecsEndpoint(svc)), GetQuerySpecs: authenticatedUser(jwtKey, svc, makeGetQuerySpecsEndpoint(svc)), + GetQuerySpec: authenticatedUser(jwtKey, svc, makeGetQuerySpecEndpoint(svc)), CreateDistributedQueryCampaign: authenticatedUser(jwtKey, svc, makeCreateDistributedQueryCampaignEndpoint(svc)), GetPack: authenticatedUser(jwtKey, svc, makeGetPackEndpoint(svc)), ListPacks: authenticatedUser(jwtKey, svc, makeListPacksEndpoint(svc)), @@ -138,6 +142,7 @@ func MakeKolideServerEndpoints(svc kolide.Service, jwtKey string) KolideEndpoint GetScheduledQueriesInPack: authenticatedUser(jwtKey, svc, makeGetScheduledQueriesInPackEndpoint(svc)), ApplyPackSpecs: authenticatedUser(jwtKey, svc, makeApplyPackSpecsEndpoint(svc)), GetPackSpecs: authenticatedUser(jwtKey, svc, makeGetPackSpecsEndpoint(svc)), + GetPackSpec: authenticatedUser(jwtKey, svc, makeGetPackSpecEndpoint(svc)), GetHost: authenticatedUser(jwtKey, svc, makeGetHostEndpoint(svc)), ListHosts: authenticatedUser(jwtKey, svc, makeListHostsEndpoint(svc)), GetHostSummary: authenticatedUser(jwtKey, svc, makeGetHostSummaryEndpoint(svc)), @@ -147,6 +152,7 @@ func MakeKolideServerEndpoints(svc kolide.Service, jwtKey string) KolideEndpoint DeleteLabel: authenticatedUser(jwtKey, svc, makeDeleteLabelEndpoint(svc)), ApplyLabelSpecs: authenticatedUser(jwtKey, svc, makeApplyLabelSpecsEndpoint(svc)), GetLabelSpecs: authenticatedUser(jwtKey, svc, makeGetLabelSpecsEndpoint(svc)), + GetLabelSpec: authenticatedUser(jwtKey, svc, makeGetLabelSpecEndpoint(svc)), SearchTargets: authenticatedUser(jwtKey, svc, makeSearchTargetsEndpoint(svc)), GetOptions: authenticatedUser(jwtKey, svc, mustBeAdmin(makeGetOptionsEndpoint(svc))), ModifyOptions: authenticatedUser(jwtKey, svc, mustBeAdmin(makeModifyOptionsEndpoint(svc))), @@ -200,6 +206,7 @@ type kolideHandlers struct { DeleteQueries http.Handler ApplyQuerySpecs http.Handler GetQuerySpecs http.Handler + GetQuerySpec http.Handler CreateDistributedQueryCampaign http.Handler GetPack http.Handler ListPacks http.Handler @@ -207,6 +214,7 @@ type kolideHandlers struct { GetScheduledQueriesInPack http.Handler ApplyPackSpecs http.Handler GetPackSpecs http.Handler + GetPackSpec http.Handler EnrollAgent http.Handler GetClientConfig http.Handler GetDistributedQueries http.Handler @@ -217,6 +225,7 @@ type kolideHandlers struct { DeleteLabel http.Handler ApplyLabelSpecs http.Handler GetLabelSpecs http.Handler + GetLabelSpec http.Handler GetHost http.Handler DeleteHost http.Handler ListHosts http.Handler @@ -225,8 +234,8 @@ type kolideHandlers struct { GetOptions http.Handler ModifyOptions http.Handler ResetOptions http.Handler - ApplyOsqueryOptionsspec http.Handler - GetOsqueryOptionsspec http.Handler + ApplyOsqueryOptionsSpec http.Handler + GetOsqueryOptionsSpec http.Handler GetCertificate http.Handler ChangeEmail http.Handler InitiateSSO http.Handler @@ -273,6 +282,7 @@ func makeKolideKitHandlers(e KolideEndpoints, opts []kithttp.ServerOption) *koli DeleteQueries: newServer(e.DeleteQueries, decodeDeleteQueriesRequest), ApplyQuerySpecs: newServer(e.ApplyQuerySpecs, decodeApplyQuerySpecsRequest), GetQuerySpecs: newServer(e.GetQuerySpecs, decodeNoParamsRequest), + GetQuerySpec: newServer(e.GetQuerySpec, decodeGetGenericSpecRequest), CreateDistributedQueryCampaign: newServer(e.CreateDistributedQueryCampaign, decodeCreateDistributedQueryCampaignRequest), GetPack: newServer(e.GetPack, decodeGetPackRequest), ListPacks: newServer(e.ListPacks, decodeListPacksRequest), @@ -280,6 +290,7 @@ func makeKolideKitHandlers(e KolideEndpoints, opts []kithttp.ServerOption) *koli GetScheduledQueriesInPack: newServer(e.GetScheduledQueriesInPack, decodeGetScheduledQueriesInPackRequest), ApplyPackSpecs: newServer(e.ApplyPackSpecs, decodeApplyPackSpecsRequest), GetPackSpecs: newServer(e.GetPackSpecs, decodeNoParamsRequest), + GetPackSpec: newServer(e.GetPackSpec, decodeGetGenericSpecRequest), EnrollAgent: newServer(e.EnrollAgent, decodeEnrollAgentRequest), GetClientConfig: newServer(e.GetClientConfig, decodeGetClientConfigRequest), GetDistributedQueries: newServer(e.GetDistributedQueries, decodeGetDistributedQueriesRequest), @@ -290,6 +301,7 @@ func makeKolideKitHandlers(e KolideEndpoints, opts []kithttp.ServerOption) *koli DeleteLabel: newServer(e.DeleteLabel, decodeDeleteLabelRequest), ApplyLabelSpecs: newServer(e.ApplyLabelSpecs, decodeApplyLabelSpecsRequest), GetLabelSpecs: newServer(e.GetLabelSpecs, decodeNoParamsRequest), + GetLabelSpec: newServer(e.GetLabelSpec, decodeGetGenericSpecRequest), GetHost: newServer(e.GetHost, decodeGetHostRequest), DeleteHost: newServer(e.DeleteHost, decodeDeleteHostRequest), ListHosts: newServer(e.ListHosts, decodeListHostsRequest), @@ -298,8 +310,8 @@ func makeKolideKitHandlers(e KolideEndpoints, opts []kithttp.ServerOption) *koli GetOptions: newServer(e.GetOptions, decodeNoParamsRequest), ModifyOptions: newServer(e.ModifyOptions, decodeModifyOptionsRequest), ResetOptions: newServer(e.ResetOptions, decodeNoParamsRequest), - ApplyOsqueryOptionsspec: newServer(e.ApplyOsqueryOptionsSpec, decodeApplyOsqueryOptionsSpecRequest), - GetOsqueryOptionsspec: newServer(e.GetOsqueryOptionsSpec, decodeNoParamsRequest), + ApplyOsqueryOptionsSpec: newServer(e.ApplyOsqueryOptionsSpec, decodeApplyOsqueryOptionsSpecRequest), + GetOsqueryOptionsSpec: newServer(e.GetOsqueryOptionsSpec, decodeNoParamsRequest), GetCertificate: newServer(e.GetCertificate, decodeNoParamsRequest), ChangeEmail: newServer(e.ChangeEmail, decodeChangeEmailRequest), InitiateSSO: newServer(e.InitiateSSO, decodeInitiateSSORequest), @@ -390,6 +402,7 @@ func attachKolideAPIRoutes(r *mux.Router, h *kolideHandlers) { r.Handle("/api/v1/kolide/queries/delete", h.DeleteQueries).Methods("POST").Name("delete_queries") r.Handle("/api/v1/kolide/spec/queries", h.ApplyQuerySpecs).Methods("POST").Name("apply_query_specs") r.Handle("/api/v1/kolide/spec/queries", h.GetQuerySpecs).Methods("GET").Name("get_query_specs") + r.Handle("/api/v1/kolide/spec/queries/{name}", h.GetQuerySpec).Methods("GET").Name("get_query_spec") r.Handle("/api/v1/kolide/queries/run", h.CreateDistributedQueryCampaign).Methods("POST").Name("create_distributed_query_campaign") r.Handle("/api/v1/kolide/packs/{id}", h.GetPack).Methods("GET").Name("get_pack") @@ -398,12 +411,14 @@ func attachKolideAPIRoutes(r *mux.Router, h *kolideHandlers) { r.Handle("/api/v1/kolide/packs/{id}/scheduled", h.GetScheduledQueriesInPack).Methods("GET").Name("get_scheduled_queries_in_pack") r.Handle("/api/v1/kolide/spec/packs", h.ApplyPackSpecs).Methods("POST").Name("apply_pack_specs") r.Handle("/api/v1/kolide/spec/packs", h.GetPackSpecs).Methods("GET").Name("get_pack_specs") + r.Handle("/api/v1/kolide/spec/packs/{name}", h.GetPackSpec).Methods("GET").Name("get_pack_spec") r.Handle("/api/v1/kolide/labels/{id}", h.GetLabel).Methods("GET").Name("get_label") r.Handle("/api/v1/kolide/labels", h.ListLabels).Methods("GET").Name("list_labels") r.Handle("/api/v1/kolide/labels/{name}", h.DeleteLabel).Methods("DELETE").Name("delete_label") r.Handle("/api/v1/kolide/spec/labels", h.ApplyLabelSpecs).Methods("POST").Name("apply_label_specs") r.Handle("/api/v1/kolide/spec/labels", h.GetLabelSpecs).Methods("GET").Name("get_label_specs") + r.Handle("/api/v1/kolide/spec/labels/{name}", h.GetLabelSpec).Methods("GET").Name("get_label_spec") r.Handle("/api/v1/kolide/hosts", h.ListHosts).Methods("GET").Name("list_hosts") r.Handle("/api/v1/kolide/host_summary", h.GetHostSummary).Methods("GET").Name("get_host_summary") @@ -416,8 +431,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/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/targets", h.SearchTargets).Methods("POST").Name("search_targets") diff --git a/server/service/service_labels.go b/server/service/service_labels.go index 7c8a6a54d9..49c2d4495b 100644 --- a/server/service/service_labels.go +++ b/server/service/service_labels.go @@ -14,6 +14,10 @@ func (svc service) GetLabelSpecs(ctx context.Context) ([]*kolide.LabelSpec, erro return svc.ds.GetLabelSpecs() } +func (svc service) GetLabelSpec(ctx context.Context, name string) (*kolide.LabelSpec, error) { + return svc.ds.GetLabelSpec(name) +} + func (svc service) ListLabels(ctx context.Context, opt kolide.ListOptions) ([]*kolide.Label, error) { return svc.ds.ListLabels(opt) } diff --git a/server/service/service_packs.go b/server/service/service_packs.go index 0a03aa4823..8eda791556 100644 --- a/server/service/service_packs.go +++ b/server/service/service_packs.go @@ -14,6 +14,10 @@ func (svc service) GetPackSpecs(ctx context.Context) ([]*kolide.PackSpec, error) return svc.ds.GetPackSpecs() } +func (svc service) GetPackSpec(ctx context.Context, name string) (*kolide.PackSpec, error) { + return svc.ds.GetPackSpec(name) +} + func (svc service) ListPacks(ctx context.Context, opt kolide.ListOptions) ([]*kolide.Pack, error) { return svc.ds.ListPacks(opt) } diff --git a/server/service/service_queries.go b/server/service/service_queries.go index cd8f61fd7c..2f330ed853 100644 --- a/server/service/service_queries.go +++ b/server/service/service_queries.go @@ -52,6 +52,17 @@ func (svc service) GetQuerySpecs(ctx context.Context) ([]*kolide.QuerySpec, erro return specs, nil } +func (svc service) GetQuerySpec(ctx context.Context, name string) (*kolide.QuerySpec, error) { + query, ok, err := svc.ds.QueryByName(name) + if !ok { + return nil, errors.Errorf("no query with name %s", name) + } + if err != nil { + return nil, errors.Wrap(err, "get query by name") + } + return specFromQuery(query), nil +} + func (svc service) ListQueries(ctx context.Context, opt kolide.ListOptions) ([]*kolide.Query, error) { return svc.ds.ListQueries(opt) } diff --git a/server/service/transport.go b/server/service/transport.go index 581ee00b69..edec258230 100644 --- a/server/service/transport.go +++ b/server/service/transport.go @@ -150,3 +150,17 @@ func listOptionsFromRequest(r *http.Request) (kolide.ListOptions, error) { func decodeNoParamsRequest(ctx context.Context, r *http.Request) (interface{}, error) { return nil, nil } + +type getGenericSpecRequest struct { + Name string +} + +func decodeGetGenericSpecRequest(ctx context.Context, r *http.Request) (interface{}, error) { + name, err := nameFromRequest(r, "name") + if err != nil { + return nil, err + } + var req getGenericSpecRequest + req.Name = name + return req, nil +}