mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 08:58:41 +00:00
Implement API endpoints for Teams agent options (#757)
- Add agent options endpoint. - Remove setting agent options from standard modify team endpoint.
This commit is contained in:
parent
9b4976ef8f
commit
9de5b720b4
5 changed files with 84 additions and 37 deletions
|
|
@ -25,8 +25,10 @@ type TeamStore interface {
|
|||
type TeamService interface {
|
||||
// NewTeam creates a new team.
|
||||
NewTeam(ctx context.Context, p TeamPayload) (*Team, error)
|
||||
// ModifyTeam modifies an existing team.
|
||||
// ModifyTeam modifies an existing team (besides agent options).
|
||||
ModifyTeam(ctx context.Context, id uint, payload TeamPayload) (*Team, error)
|
||||
// ModifyTeam modifies agent options for a team.
|
||||
ModifyTeamAgentOptions(ctx context.Context, id uint, options json.RawMessage) (*Team, error)
|
||||
// AddTeamUsers adds users to an existing team.
|
||||
AddTeamUsers(ctx context.Context, teamID uint, users []TeamUser) (*Team, error)
|
||||
// DeleteTeamUsers deletes users from an existing team.
|
||||
|
|
@ -41,9 +43,9 @@ type TeamService interface {
|
|||
}
|
||||
|
||||
type TeamPayload struct {
|
||||
Name *string `json:"name"`
|
||||
Description *string `json:"description"`
|
||||
AgentOptions *json.RawMessage `json:"agent_options"`
|
||||
Name *string `json:"name"`
|
||||
Description *string `json:"description"`
|
||||
// Note AgentOptions must be set by a separate endpoint.
|
||||
}
|
||||
|
||||
// Team is the data representation for the "Team" concept (group of hosts and
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package service
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
|
|
@ -15,12 +16,12 @@ type createTeamRequest struct {
|
|||
payload kolide.TeamPayload
|
||||
}
|
||||
|
||||
type createTeamResponse struct {
|
||||
type teamResponse struct {
|
||||
Team *kolide.Team `json:"team,omitempty"`
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r createTeamResponse) error() error { return r.Err }
|
||||
func (r teamResponse) error() error { return r.Err }
|
||||
|
||||
func makeCreateTeamEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
|
|
@ -28,10 +29,10 @@ func makeCreateTeamEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|||
|
||||
team, err := svc.NewTeam(ctx, req.payload)
|
||||
if err != nil {
|
||||
return createTeamResponse{Err: err}, nil
|
||||
return teamResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
return createTeamResponse{Team: team}, nil
|
||||
return teamResponse{Team: team}, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -44,22 +45,36 @@ type modifyTeamRequest struct {
|
|||
payload kolide.TeamPayload
|
||||
}
|
||||
|
||||
type modifyTeamResponse struct {
|
||||
Team *kolide.Team `json:"team,omitempty"`
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r modifyTeamResponse) error() error { return r.Err }
|
||||
|
||||
func makeModifyTeamEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(modifyTeamRequest)
|
||||
team, err := svc.ModifyTeam(ctx, req.ID, req.payload)
|
||||
if err != nil {
|
||||
return modifyTeamResponse{Err: err}, nil
|
||||
return teamResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
return modifyTeamResponse{Team: team}, err
|
||||
return teamResponse{Team: team}, err
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Modify Team Agent Options
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type modifyTeamAgentOptionsRequest struct {
|
||||
ID uint
|
||||
options json.RawMessage
|
||||
}
|
||||
|
||||
func makeModifyTeamAgentOptionsEndpoint(svc kolide.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(modifyTeamAgentOptionsRequest)
|
||||
team, err := svc.ModifyTeamAgentOptions(ctx, req.ID, req.options)
|
||||
if err != nil {
|
||||
return teamResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
return teamResponse{Team: team}, err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,10 +175,10 @@ func makeAddTeamUsersEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|||
req := request.(modifyTeamUsersRequest)
|
||||
team, err := svc.AddTeamUsers(ctx, req.TeamID, req.Users)
|
||||
if err != nil {
|
||||
return modifyTeamResponse{Err: err}, nil
|
||||
return teamResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
return modifyTeamResponse{Team: team}, err
|
||||
return teamResponse{Team: team}, err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -172,9 +187,9 @@ func makeDeleteTeamUsersEndpoint(svc kolide.Service) endpoint.Endpoint {
|
|||
req := request.(modifyTeamUsersRequest)
|
||||
team, err := svc.DeleteTeamUsers(ctx, req.TeamID, req.Users)
|
||||
if err != nil {
|
||||
return modifyTeamResponse{Err: err}, nil
|
||||
return teamResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
return modifyTeamResponse{Team: team}, err
|
||||
return teamResponse{Team: team}, err
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ type KolideEndpoints struct {
|
|||
Version endpoint.Endpoint
|
||||
CreateTeam endpoint.Endpoint
|
||||
ModifyTeam endpoint.Endpoint
|
||||
ModifyTeamAgentOptions endpoint.Endpoint
|
||||
DeleteTeam endpoint.Endpoint
|
||||
ListTeams endpoint.Endpoint
|
||||
ListTeamUsers endpoint.Endpoint
|
||||
|
|
@ -216,13 +217,14 @@ func MakeKolideServerEndpoints(svc kolide.Service, jwtKey, urlPrefix string, lim
|
|||
GetCarveBlock: authenticatedUser(jwtKey, svc, makeGetCarveBlockEndpoint(svc)),
|
||||
Version: authenticatedUser(jwtKey, svc, makeVersionEndpoint(svc)),
|
||||
// TODO permissions for teams endpoints
|
||||
CreateTeam: authenticatedUser(jwtKey, svc, makeCreateTeamEndpoint(svc)),
|
||||
ModifyTeam: authenticatedUser(jwtKey, svc, makeModifyTeamEndpoint(svc)),
|
||||
DeleteTeam: authenticatedUser(jwtKey, svc, makeDeleteTeamEndpoint(svc)),
|
||||
ListTeams: authenticatedUser(jwtKey, svc, makeListTeamsEndpoint(svc)),
|
||||
ListTeamUsers: authenticatedUser(jwtKey, svc, makeListTeamUsersEndpoint(svc)),
|
||||
AddTeamUsers: authenticatedUser(jwtKey, svc, makeAddTeamUsersEndpoint(svc)),
|
||||
DeleteTeamUsers: authenticatedUser(jwtKey, svc, makeDeleteTeamUsersEndpoint(svc)),
|
||||
CreateTeam: authenticatedUser(jwtKey, svc, makeCreateTeamEndpoint(svc)),
|
||||
ModifyTeam: authenticatedUser(jwtKey, svc, makeModifyTeamEndpoint(svc)),
|
||||
ModifyTeamAgentOptions: authenticatedUser(jwtKey, svc, makeModifyTeamAgentOptionsEndpoint(svc)),
|
||||
DeleteTeam: authenticatedUser(jwtKey, svc, makeDeleteTeamEndpoint(svc)),
|
||||
ListTeams: authenticatedUser(jwtKey, svc, makeListTeamsEndpoint(svc)),
|
||||
ListTeamUsers: authenticatedUser(jwtKey, svc, makeListTeamUsersEndpoint(svc)),
|
||||
AddTeamUsers: authenticatedUser(jwtKey, svc, makeAddTeamUsersEndpoint(svc)),
|
||||
DeleteTeamUsers: authenticatedUser(jwtKey, svc, makeDeleteTeamUsersEndpoint(svc)),
|
||||
|
||||
// Authenticated status endpoints
|
||||
StatusResultStore: authenticatedUser(jwtKey, svc, makeStatusResultStoreEndpoint(svc)),
|
||||
|
|
@ -332,6 +334,7 @@ type kolideHandlers struct {
|
|||
Version http.Handler
|
||||
CreateTeam http.Handler
|
||||
ModifyTeam http.Handler
|
||||
ModifyTeamAgentOptions http.Handler
|
||||
DeleteTeam http.Handler
|
||||
ListTeams http.Handler
|
||||
ListTeamUsers http.Handler
|
||||
|
|
@ -433,6 +436,7 @@ func makeKolideKitHandlers(e KolideEndpoints, opts []kithttp.ServerOption) *koli
|
|||
Version: newServer(e.Version, decodeNoParamsRequest),
|
||||
CreateTeam: newServer(e.CreateTeam, decodeCreateTeamRequest),
|
||||
ModifyTeam: newServer(e.ModifyTeam, decodeModifyTeamRequest),
|
||||
ModifyTeamAgentOptions: newServer(e.ModifyTeamAgentOptions, decodeModifyTeamAgentOptionsRequest),
|
||||
DeleteTeam: newServer(e.DeleteTeam, decodeDeleteTeamRequest),
|
||||
ListTeams: newServer(e.ListTeams, decodeListTeamsRequest),
|
||||
ListTeamUsers: newServer(e.ListTeamUsers, decodeListTeamUsersRequest),
|
||||
|
|
@ -651,6 +655,7 @@ func attachKolideAPIRoutes(r *mux.Router, h *kolideHandlers) {
|
|||
r.Handle("/api/v1/fleet/teams", h.ListTeams).Methods("GET").Name("list_teams")
|
||||
r.Handle("/api/v1/fleet/teams/{id}", h.ModifyTeam).Methods("PATCH").Name("modify_team")
|
||||
r.Handle("/api/v1/fleet/teams/{id}", h.DeleteTeam).Methods("DELETE").Name("delete_team")
|
||||
r.Handle("/api/v1/fleet/teams/{id}/agent_options", h.ModifyTeamAgentOptions).Methods("POST").Name("modify_team_agent_options")
|
||||
r.Handle("/api/v1/fleet/teams/{id}/users", h.ListTeamUsers).Methods("GET").Name("team_users")
|
||||
r.Handle("/api/v1/fleet/teams/{id}/users", h.AddTeamUsers).Methods("PATCH").Name("add_team_users")
|
||||
r.Handle("/api/v1/fleet/teams/{id}/users", h.DeleteTeamUsers).Methods("DELETE").Name("delete_team_users")
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@ package service
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
)
|
||||
|
||||
func (svc service) NewTeam(ctx context.Context, p kolide.TeamPayload) (*kolide.Team, error) {
|
||||
team := &kolide.Team{AgentOptions: p.AgentOptions}
|
||||
team := &kolide.Team{}
|
||||
|
||||
if p.Name == nil {
|
||||
return nil, newInvalidArgumentError("name", "missing required argument")
|
||||
|
|
@ -43,8 +44,20 @@ func (svc service) ModifyTeam(ctx context.Context, id uint, payload kolide.TeamP
|
|||
if payload.Description != nil {
|
||||
team.Description = *payload.Description
|
||||
}
|
||||
if payload.AgentOptions != nil {
|
||||
team.AgentOptions = payload.AgentOptions
|
||||
|
||||
return svc.ds.SaveTeam(team)
|
||||
}
|
||||
|
||||
func (svc service) ModifyTeamAgentOptions(ctx context.Context, id uint, options json.RawMessage) (*kolide.Team, error) {
|
||||
team, err := svc.ds.Team(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if options != nil {
|
||||
team.AgentOptions = &options
|
||||
} else {
|
||||
team.AgentOptions = nil
|
||||
}
|
||||
|
||||
return svc.ds.SaveTeam(team)
|
||||
|
|
|
|||
|
|
@ -19,13 +19,26 @@ func decodeModifyTeamRequest(ctx context.Context, r *http.Request) (interface{},
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp modifyTeamRequest
|
||||
err = json.NewDecoder(r.Body).Decode(&resp.payload)
|
||||
req := modifyTeamRequest{ID: id}
|
||||
err = json.NewDecoder(r.Body).Decode(&req.payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.ID = id
|
||||
return resp, nil
|
||||
req.ID = id
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeModifyTeamAgentOptionsRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
id, err := idFromRequest(r, "id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := modifyTeamAgentOptionsRequest{ID: id}
|
||||
err = json.NewDecoder(r.Body).Decode(&req.options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeListTeamsRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
|
|
@ -61,11 +74,10 @@ func decodeModifyTeamUsersRequest(ctx context.Context, r *http.Request) (interfa
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var req modifyTeamUsersRequest
|
||||
req := modifyTeamUsersRequest{TeamID: id}
|
||||
err = json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.TeamID = id
|
||||
return req, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue