diff --git a/server/fleet/api_carves.go b/server/fleet/api_carves.go new file mode 100644 index 0000000000..de696b3321 --- /dev/null +++ b/server/fleet/api_carves.go @@ -0,0 +1,90 @@ +package fleet + +//////////////////////////////////////////////////////////////////////////////// +// List Carves +//////////////////////////////////////////////////////////////////////////////// + +type ListCarvesRequest struct { + ListOptions CarveListOptions `url:"carve_options"` +} + +type ListCarvesResponse struct { + Carves []CarveMetadata `json:"carves"` + Err error `json:"error,omitempty"` +} + +func (r ListCarvesResponse) Error() error { return r.Err } + +//////////////////////////////////////////////////////////////////////////////// +// Get Carve +//////////////////////////////////////////////////////////////////////////////// + +type GetCarveRequest struct { + ID int64 `url:"id"` +} + +type GetCarveResponse struct { + Carve CarveMetadata `json:"carve"` + Err error `json:"error,omitempty"` +} + +func (r GetCarveResponse) Error() error { return r.Err } + +//////////////////////////////////////////////////////////////////////////////// +// Get Carve Block +//////////////////////////////////////////////////////////////////////////////// + +type GetCarveBlockRequest struct { + ID int64 `url:"id"` + BlockId int64 `url:"block_id"` +} + +type GetCarveBlockResponse struct { + Data []byte `json:"data"` + Err error `json:"error,omitempty"` +} + +func (r GetCarveBlockResponse) Error() error { return r.Err } + +//////////////////////////////////////////////////////////////////////////////// +// Begin File Carve +//////////////////////////////////////////////////////////////////////////////// + +type CarveBeginRequest struct { + NodeKey string `json:"node_key"` + BlockCount int64 `json:"block_count"` + BlockSize int64 `json:"block_size"` + CarveSize int64 `json:"carve_size"` + CarveId string `json:"carve_id"` + RequestId string `json:"request_id"` +} + +func (r *CarveBeginRequest) HostNodeKey() string { + return r.NodeKey +} + +type CarveBeginResponse struct { + SessionId string `json:"session_id"` + Success bool `json:"success,omitempty"` + Err error `json:"error,omitempty"` +} + +func (r CarveBeginResponse) Error() error { return r.Err } + +//////////////////////////////////////////////////////////////////////////////// +// Receive Block for File Carve +//////////////////////////////////////////////////////////////////////////////// + +type CarveBlockRequest struct { + BlockId int64 `json:"block_id"` + SessionId string `json:"session_id"` + RequestId string `json:"request_id"` + Data []byte `json:"data"` +} + +type CarveBlockResponse struct { + Success bool `json:"success,omitempty"` + Err error `json:"error,omitempty"` +} + +func (r CarveBlockResponse) Error() error { return r.Err } diff --git a/server/service/carves.go b/server/service/carves.go index 8ca97b8894..fa41faae0a 100644 --- a/server/service/carves.go +++ b/server/service/carves.go @@ -24,25 +24,14 @@ import ( // List Carves //////////////////////////////////////////////////////////////////////////////// -type listCarvesRequest struct { - ListOptions fleet.CarveListOptions `url:"carve_options"` -} - -type listCarvesResponse struct { - Carves []fleet.CarveMetadata `json:"carves"` - Err error `json:"error,omitempty"` -} - -func (r listCarvesResponse) Error() error { return r.Err } - func listCarvesEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (fleet.Errorer, error) { - req := request.(*listCarvesRequest) + req := request.(*fleet.ListCarvesRequest) carves, err := svc.ListCarves(ctx, req.ListOptions) if err != nil { - return listCarvesResponse{Err: err}, nil + return fleet.ListCarvesResponse{Err: err}, nil } - resp := listCarvesResponse{} + resp := fleet.ListCarvesResponse{} for _, carve := range carves { resp.Carves = append(resp.Carves, *carve) } @@ -61,25 +50,14 @@ func (svc *Service) ListCarves(ctx context.Context, opt fleet.CarveListOptions) // Get Carve //////////////////////////////////////////////////////////////////////////////// -type getCarveRequest struct { - ID int64 `url:"id"` -} - -type getCarveResponse struct { - Carve fleet.CarveMetadata `json:"carve"` - Err error `json:"error,omitempty"` -} - -func (r getCarveResponse) Error() error { return r.Err } - func getCarveEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (fleet.Errorer, error) { - req := request.(*getCarveRequest) + req := request.(*fleet.GetCarveRequest) carve, err := svc.GetCarve(ctx, req.ID) if err != nil { - return getCarveResponse{Err: err}, nil + return fleet.GetCarveResponse{Err: err}, nil } - return getCarveResponse{Carve: *carve}, nil + return fleet.GetCarveResponse{Carve: *carve}, nil } func (svc *Service) GetCarve(ctx context.Context, id int64) (*fleet.CarveMetadata, error) { @@ -94,26 +72,14 @@ func (svc *Service) GetCarve(ctx context.Context, id int64) (*fleet.CarveMetadat // Get Carve Block //////////////////////////////////////////////////////////////////////////////// -type getCarveBlockRequest struct { - ID int64 `url:"id"` - BlockId int64 `url:"block_id"` -} - -type getCarveBlockResponse struct { - Data []byte `json:"data"` - Err error `json:"error,omitempty"` -} - -func (r getCarveBlockResponse) Error() error { return r.Err } - func getCarveBlockEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (fleet.Errorer, error) { - req := request.(*getCarveBlockRequest) + req := request.(*fleet.GetCarveBlockRequest) data, err := svc.GetBlock(ctx, req.ID, req.BlockId) if err != nil { - return getCarveBlockResponse{Err: err}, nil + return fleet.GetCarveBlockResponse{Err: err}, nil } - return getCarveBlockResponse{Data: data}, nil + return fleet.GetCarveBlockResponse{Data: data}, nil } func (svc *Service) GetBlock(ctx context.Context, carveId, blockId int64) ([]byte, error) { @@ -146,29 +112,8 @@ func (svc *Service) GetBlock(ctx context.Context, carveId, blockId int64) ([]byt // Begin File Carve //////////////////////////////////////////////////////////////////////////////// -type carveBeginRequest struct { - NodeKey string `json:"node_key"` - BlockCount int64 `json:"block_count"` - BlockSize int64 `json:"block_size"` - CarveSize int64 `json:"carve_size"` - CarveId string `json:"carve_id"` - RequestId string `json:"request_id"` -} - -func (r *carveBeginRequest) hostNodeKey() string { - return r.NodeKey -} - -type carveBeginResponse struct { - SessionId string `json:"session_id"` - Success bool `json:"success,omitempty"` - Err error `json:"error,omitempty"` -} - -func (r carveBeginResponse) Error() error { return r.Err } - func carveBeginEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (fleet.Errorer, error) { - req := request.(*carveBeginRequest) + req := request.(*fleet.CarveBeginRequest) payload := fleet.CarveBeginPayload{ BlockCount: req.BlockCount, @@ -180,10 +125,10 @@ func carveBeginEndpoint(ctx context.Context, request interface{}, svc fleet.Serv carve, err := svc.CarveBegin(ctx, payload) if err != nil { - return carveBeginResponse{Err: err}, nil + return fleet.CarveBeginResponse{Err: err}, nil } - return carveBeginResponse{SessionId: carve.SessionId, Success: true}, nil + return fleet.CarveBeginResponse{SessionId: carve.SessionId, Success: true}, nil } const ( @@ -249,19 +194,11 @@ func (svc *Service) CarveBegin(ctx context.Context, payload fleet.CarveBeginPayl // Receive Block for File Carve //////////////////////////////////////////////////////////////////////////////// -type carveBlockRequest struct { - BlockId int64 `json:"block_id"` - SessionId string `json:"session_id"` - RequestId string `json:"request_id"` - Data []byte `json:"data"` -} - -type carveBlockResponse struct { - Success bool `json:"success,omitempty"` - Err error `json:"error,omitempty"` -} - -func (r carveBlockResponse) Error() error { return r.Err } +// decodeCarveBlockRequest is a service-local wrapper that owns the streaming +// DecodeRequest used by the unauthenticated /osquery/carve/block endpoint. +// The wrapper lives here (not in server/fleet) because it uses carvestorectx, +// which imports server/fleet and would create a cycle. +type decodeCarveBlockRequest struct{} // DecodeRequest for the /api/v1/osquery/carve/block endpoint performs raw JSON parsing // to prevent DoS attacks on this unauthenticated endpoint. @@ -281,7 +218,7 @@ func (r carveBlockResponse) Error() error { return r.Err } // check remains the primary authentication mechanism. When the header is // valid, CarveBlock additionally verifies that the carve's host_id matches // the authenticated host. -func (r carveBlockRequest) DecodeRequest(ctx context.Context, req *http.Request) (any, error) { +func (decodeCarveBlockRequest) DecodeRequest(ctx context.Context, req *http.Request) (any, error) { carveStore := carvestorectx.FromContext(ctx) if carveStore == nil { return nil, ctxerr.New(ctx, "missing carve store from context") @@ -419,7 +356,7 @@ func (r carveBlockRequest) DecodeRequest(ctx context.Context, req *http.Request) } data = data[:n] - return &carveBlockRequest{ + return &fleet.CarveBlockRequest{ BlockId: blockID, SessionId: sessionID, RequestId: requestID, @@ -428,7 +365,7 @@ func (r carveBlockRequest) DecodeRequest(ctx context.Context, req *http.Request) } func carveBlockEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (fleet.Errorer, error) { - req := request.(*carveBlockRequest) + req := request.(*fleet.CarveBlockRequest) payload := fleet.CarveBlockPayload{ SessionId: req.SessionId, @@ -439,10 +376,10 @@ func carveBlockEndpoint(ctx context.Context, request interface{}, svc fleet.Serv err := svc.CarveBlock(ctx, payload) if err != nil { - return carveBlockResponse{Err: err}, nil + return fleet.CarveBlockResponse{Err: err}, nil } - return carveBlockResponse{Success: true}, nil + return fleet.CarveBlockResponse{Success: true}, nil } func (svc *Service) CarveBlock(ctx context.Context, payload fleet.CarveBlockPayload) error { @@ -450,7 +387,7 @@ func (svc *Service) CarveBlock(ctx context.Context, payload fleet.CarveBlockPayl svc.authz.SkipAuthorization(ctx) // Authentication on this endpoint is layered: - // 1. The streaming body parser (carveBlockRequest.DecodeRequest) + // 1. The streaming body parser (decodeCarveBlockRequest.DecodeRequest) // verifies session_id+request_id against the carve store. // 2. When osquery.allow_body_auth_fallback=false, the HTTP pre-auth // middleware (osqueryCarveBlockHeaderPreAuth) is installed and diff --git a/server/service/carves_test.go b/server/service/carves_test.go index 367cf387ac..b1c204fb6e 100644 --- a/server/service/carves_test.go +++ b/server/service/carves_test.go @@ -789,7 +789,7 @@ func TestCarveBlockDecodeRequest(t *testing.T) { wantErr bool wantErrType string // e.g., "AuthFailedError", "ctxerr", "" wantErrMessage string - wantResult *carveBlockRequest + wantResult *fleet.CarveBlockRequest }{ { name: "valid request MySQL session IDs", @@ -803,7 +803,7 @@ func TestCarveBlockDecodeRequest(t *testing.T) { return carvestorectx.NewContext(ctx, store) }, wantErr: false, - wantResult: &carveBlockRequest{ + wantResult: &fleet.CarveBlockRequest{ BlockId: 123, SessionId: "23bbbcf6-6b8a-4f3a-9924-bdd084f31097", RequestId: "req123", @@ -822,7 +822,7 @@ func TestCarveBlockDecodeRequest(t *testing.T) { return carvestorectx.NewContext(ctx, store) }, wantErr: false, - wantResult: &carveBlockRequest{ + wantResult: &fleet.CarveBlockRequest{ BlockId: 123, SessionId: "JUMHLnWZ.A7y5ns2jUODzG8eTr5m9lvFKDD3nBN.hJ8mwr2szW0iUSNrusaE41__.wrtsNokzejFLQyNJTTqY_QN1grwAT0yXGi8A77Kf9ZJlvSiWggmncDAhVev4QXxx2PyN_GtTRPC71WGKPN2YxBFfWBjZlCZBXmPCtc4zrQ", RequestId: "req123", @@ -841,7 +841,7 @@ func TestCarveBlockDecodeRequest(t *testing.T) { return carvestorectx.NewContext(ctx, store) }, wantErr: false, - wantResult: &carveBlockRequest{ + wantResult: &fleet.CarveBlockRequest{ BlockId: 123, SessionId: "ZGVhZDYwYTctZTVlOC00MzE1LWFhOWMtZDIzMzc5MTI4NGUyLjUzM2MxZjhhLTFiODktNDQ1YS04NTE0LTBjMWE0NDVlNjkwMXgxNzcwMTQ1Njc5NDgyNDg3NzE3", RequestId: "req123", @@ -860,7 +860,7 @@ func TestCarveBlockDecodeRequest(t *testing.T) { return carvestorectx.NewContext(ctx, store) }, wantErr: false, - wantResult: &carveBlockRequest{ + wantResult: &fleet.CarveBlockRequest{ BlockId: 123, SessionId: strings.Repeat("F", 255), RequestId: "req123", @@ -1066,7 +1066,7 @@ func TestCarveBlockDecodeRequest(t *testing.T) { return carvestorectx.NewContext(ctx, store) }, wantErr: false, - wantResult: &carveBlockRequest{ + wantResult: &fleet.CarveBlockRequest{ BlockId: 123, SessionId: "sess123", RequestId: strings.Repeat("F", 64), @@ -1291,7 +1291,7 @@ func TestCarveBlockDecodeRequest(t *testing.T) { return carvestorectx.NewContext(ctx, store) }, wantErr: false, - wantResult: &carveBlockRequest{ + wantResult: &fleet.CarveBlockRequest{ BlockId: 1<<63 - 1, SessionId: "sess123", RequestId: "req123", @@ -1320,8 +1320,7 @@ func TestCarveBlockDecodeRequest(t *testing.T) { req := &http.Request{ Body: io.NopCloser(bytes.NewReader([]byte(tt.body))), } - var r carveBlockRequest - result, err := r.DecodeRequest(ctx, req) + result, err := decodeCarveBlockRequest{}.DecodeRequest(ctx, req) if (err != nil) != tt.wantErr { t.Errorf("DecodeRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -1336,9 +1335,9 @@ func TestCarveBlockDecodeRequest(t *testing.T) { } return } - got, ok := result.(*carveBlockRequest) + got, ok := result.(*fleet.CarveBlockRequest) if !ok { - t.Errorf("result not *carveBlockRequest") + t.Errorf("result not *fleet.CarveBlockRequest") return } if tt.wantResult != nil { diff --git a/server/service/client_carves.go b/server/service/client_carves.go index d9301d5abf..70637dd254 100644 --- a/server/service/client_carves.go +++ b/server/service/client_carves.go @@ -30,7 +30,7 @@ func (c *Client) ListCarves(opt fleet.CarveListOptions) ([]*fleet.CarveMetadata, ) } - var responseBody listCarvesResponse + var responseBody fleet.ListCarvesResponse err = json.NewDecoder(response.Body).Decode(&responseBody) if err != nil { return nil, fmt.Errorf("decode get carves response: %w", err) @@ -63,7 +63,7 @@ func (c *Client) GetCarve(carveId int64) (*fleet.CarveMetadata, error) { extractServerErrorText(response.Body), ) } - var responseBody getCarveResponse + var responseBody fleet.GetCarveResponse err = json.NewDecoder(response.Body).Decode(&responseBody) if err != nil { return nil, fmt.Errorf("decode carve response: %w", err) @@ -95,7 +95,7 @@ func (c *Client) getCarveBlock(carveId, blockId int64) ([]byte, error) { ) } - var responseBody getCarveBlockResponse + var responseBody fleet.GetCarveBlockResponse err = json.NewDecoder(response.Body).Decode(&responseBody) if err != nil { return nil, fmt.Errorf("decode get carve block response: %w", err) @@ -175,7 +175,7 @@ func (c *Client) DownloadCarve(id int64) (io.Reader, error) { ) } - var responseBody getCarveResponse + var responseBody fleet.GetCarveResponse err = json.NewDecoder(response.Body).Decode(&responseBody) if err != nil { return nil, fmt.Errorf("decode get carve by name response: %w", err) diff --git a/server/service/endpoint_middleware.go b/server/service/endpoint_middleware.go index 05a234b5d6..46d7261ccc 100644 --- a/server/service/endpoint_middleware.go +++ b/server/service/endpoint_middleware.go @@ -272,6 +272,9 @@ func authHeaderValue(prefix string) func(ctx context.Context, r interface{}) (st } func getNodeKey(r interface{}) (string, error) { + if hnk, ok := r.(interface{ HostNodeKey() string }); ok { + return hnk.HostNodeKey(), nil + } if hnk, ok := r.(interface{ hostNodeKey() string }); ok { return hnk.hostNodeKey(), nil } diff --git a/server/service/handler.go b/server/service/handler.go index 1acb05527e..6fcf5e46f0 100644 --- a/server/service/handler.go +++ b/server/service/handler.go @@ -540,9 +540,9 @@ func attachFleetAPIRoutes(r *mux.Router, svc fleet.Service, config config.FleetC ue.PATCH("/api/_version_/fleet/fleets/{fleet_id}/schedule/{report_id}", modifyTeamScheduleEndpoint, modifyTeamScheduleRequest{}) ue.DELETE("/api/_version_/fleet/fleets/{fleet_id}/schedule/{report_id}", deleteTeamScheduleEndpoint, deleteTeamScheduleRequest{}) - ue.GET("/api/_version_/fleet/carves", listCarvesEndpoint, listCarvesRequest{}) - ue.GET("/api/_version_/fleet/carves/{id:[0-9]+}", getCarveEndpoint, getCarveRequest{}) - ue.GET("/api/_version_/fleet/carves/{id:[0-9]+}/block/{block_id}", getCarveBlockEndpoint, getCarveBlockRequest{}) + ue.GET("/api/_version_/fleet/carves", listCarvesEndpoint, fleet.ListCarvesRequest{}) + ue.GET("/api/_version_/fleet/carves/{id:[0-9]+}", getCarveEndpoint, fleet.GetCarveRequest{}) + ue.GET("/api/_version_/fleet/carves/{id:[0-9]+}/block/{block_id}", getCarveBlockEndpoint, fleet.GetCarveBlockRequest{}) ue.GET("/api/_version_/fleet/hosts/{id:[0-9]+}/macadmins", getMacadminsDataEndpoint, getMacadminsDataRequest{}) ue.GET("/api/_version_/fleet/macadmins", getAggregatedMacadminsDataEndpoint, getAggregatedMacadminsDataRequest{}) @@ -988,7 +988,7 @@ func attachFleetAPIRoutes(r *mux.Router, svc fleet.Service, config config.FleetC distWriteReg.WithAltPaths("/api/v1/osquery/distributed/write"). POST("/api/osquery/distributed/write", submitDistributedQueryResultsEndpoint, submitDistributedQueryResultsRequestShim{}) heHeader.WithAltPaths("/api/v1/osquery/carve/begin"). - POST("/api/osquery/carve/begin", carveBeginEndpoint, carveBeginRequest{}) + POST("/api/osquery/carve/begin", carveBeginEndpoint, fleet.CarveBeginRequest{}) logWriteReg.WithAltPaths("/api/v1/osquery/log"). POST("/api/osquery/log", submitLogsEndpoint, submitLogsRequest{}) he.WithAltPaths("/api/v1/osquery/yara/{name}"). @@ -1119,7 +1119,7 @@ func attachFleetAPIRoutes(r *mux.Router, svc fleet.Service, config config.FleetC carveBlockReg = carveBlockReg.WithHTTPPreAuth(osqueryCarveBlockHeaderPreAuth(svc, logger)) } carveBlockReg.WithAltPaths("/api/v1/osquery/carve/block"). - POST("/api/osquery/carve/block", carveBlockEndpoint, carveBlockRequest{}) + POST("/api/osquery/carve/block", carveBlockEndpoint, decodeCarveBlockRequest{}) ne.GET("/api/_version_/fleet/software/titles/{title_id:[0-9]+}/package/token/{token}", downloadSoftwareInstallerEndpoint, downloadSoftwareInstallerRequest{}) diff --git a/server/service/integration_core_test.go b/server/service/integration_core_test.go index 24d47f1a44..caf1a5fe9a 100644 --- a/server/service/integration_core_test.go +++ b/server/service/integration_core_test.go @@ -3829,7 +3829,7 @@ func (s *integrationTestSuite) TestListGetCarves() { c2.MaxBlock = 3 require.NoError(t, s.ds.UpdateCarve(ctx, c2)) - var listResp listCarvesResponse + var listResp fleet.ListCarvesResponse s.DoJSON("GET", "/api/latest/fleet/carves", nil, http.StatusOK, &listResp, "per_page", "2", "order_key", "id") require.Len(t, listResp.Carves, 2) assert.Equal(t, c1.ID, listResp.Carves[0].ID) @@ -3854,7 +3854,7 @@ func (s *integrationTestSuite) TestListGetCarves() { require.Len(t, listResp.Carves, 0) // get specific carve - var getResp getCarveResponse + var getResp fleet.GetCarveResponse s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/carves/%d", c2.ID), nil, http.StatusOK, &getResp) require.Equal(t, c2.ID, getResp.Carve.ID) require.True(t, getResp.Carve.Expired) @@ -3863,7 +3863,7 @@ func (s *integrationTestSuite) TestListGetCarves() { s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/carves/%d", c3.ID+1), nil, http.StatusNotFound, &getResp) // get expired carve block - var blkResp getCarveBlockResponse + var blkResp fleet.GetCarveBlockResponse s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/carves/%d/block/%d", c2.ID, 1), nil, http.StatusInternalServerError, &blkResp) // get valid carve block, but block not inserted yet @@ -9835,7 +9835,7 @@ func (s *integrationTestSuite) TestCarve() { // begin a carve with an invalid node key var errRes map[string]interface{} - s.DoJSON("POST", "/api/osquery/carve/begin", carveBeginRequest{ + s.DoJSON("POST", "/api/osquery/carve/begin", fleet.CarveBeginRequest{ NodeKey: *hosts[0].NodeKey + "zzz", BlockCount: 1, BlockSize: 1, @@ -9845,7 +9845,7 @@ func (s *integrationTestSuite) TestCarve() { assert.Contains(t, errRes["error"], "invalid node key") // invalid carve size - s.DoJSON("POST", "/api/osquery/carve/begin", carveBeginRequest{ + s.DoJSON("POST", "/api/osquery/carve/begin", fleet.CarveBeginRequest{ NodeKey: *hosts[0].NodeKey, BlockCount: 3, BlockSize: 3, @@ -9855,7 +9855,7 @@ func (s *integrationTestSuite) TestCarve() { assert.Contains(t, errRes["error"], "carve_size must be greater") // invalid block size too big - s.DoJSON("POST", "/api/osquery/carve/begin", carveBeginRequest{ + s.DoJSON("POST", "/api/osquery/carve/begin", fleet.CarveBeginRequest{ NodeKey: *hosts[0].NodeKey, BlockCount: 3, BlockSize: maxBlockSize + 1, @@ -9865,7 +9865,7 @@ func (s *integrationTestSuite) TestCarve() { assert.Contains(t, errRes["error"], "block_size exceeds max") // invalid carve size too big - s.DoJSON("POST", "/api/osquery/carve/begin", carveBeginRequest{ + s.DoJSON("POST", "/api/osquery/carve/begin", fleet.CarveBeginRequest{ NodeKey: *hosts[0].NodeKey, BlockCount: 3, BlockSize: maxBlockSize, @@ -9875,7 +9875,7 @@ func (s *integrationTestSuite) TestCarve() { assert.Contains(t, errRes["error"], "carve_size exceeds max") // invalid carve size, does not match blocks - s.DoJSON("POST", "/api/osquery/carve/begin", carveBeginRequest{ + s.DoJSON("POST", "/api/osquery/carve/begin", fleet.CarveBeginRequest{ NodeKey: *hosts[0].NodeKey, BlockCount: 3, BlockSize: 3, @@ -9885,8 +9885,8 @@ func (s *integrationTestSuite) TestCarve() { assert.Contains(t, errRes["error"], "carve_size does not match") // valid carve begin - var beginResp carveBeginResponse - s.DoJSON("POST", "/api/osquery/carve/begin", carveBeginRequest{ + var beginResp fleet.CarveBeginResponse + s.DoJSON("POST", "/api/osquery/carve/begin", fleet.CarveBeginRequest{ NodeKey: *hosts[0].NodeKey, BlockCount: 3, BlockSize: 3, @@ -9898,8 +9898,8 @@ func (s *integrationTestSuite) TestCarve() { sid := beginResp.SessionId // sending a block with invalid session id - var blockResp carveBlockResponse - s.DoJSON("POST", "/api/osquery/carve/block", carveBlockRequest{ + var blockResp fleet.CarveBlockResponse + s.DoJSON("POST", "/api/osquery/carve/block", fleet.CarveBlockRequest{ BlockId: 1, SessionId: sid + "zz", RequestId: "??", @@ -9907,7 +9907,7 @@ func (s *integrationTestSuite) TestCarve() { }, http.StatusUnauthorized, &blockResp) // sending a block with valid session id but invalid request id - s.DoJSON("POST", "/api/osquery/carve/block", carveBlockRequest{ + s.DoJSON("POST", "/api/osquery/carve/block", fleet.CarveBlockRequest{ BlockId: 1, SessionId: sid, RequestId: "??", @@ -9915,13 +9915,13 @@ func (s *integrationTestSuite) TestCarve() { }, http.StatusUnauthorized, &blockResp) checkCarveError := func(id uint, err string) { - var getResp getCarveResponse + var getResp fleet.GetCarveResponse s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/carves/%d", id), nil, http.StatusOK, &getResp) require.Equal(t, err, *getResp.Carve.Error) } // sending a block with unexpected block id (expects 0, got 1) - s.DoJSON("POST", "/api/osquery/carve/block", carveBlockRequest{ + s.DoJSON("POST", "/api/osquery/carve/block", fleet.CarveBlockRequest{ BlockId: 1, SessionId: sid, RequestId: "r1", @@ -9930,7 +9930,7 @@ func (s *integrationTestSuite) TestCarve() { checkCarveError(1, "block_id does not match expected block (0): 1") // sending a block with valid payload, block 0 - s.DoJSON("POST", "/api/osquery/carve/block", carveBlockRequest{ + s.DoJSON("POST", "/api/osquery/carve/block", fleet.CarveBlockRequest{ BlockId: 0, SessionId: sid, RequestId: "r1", @@ -9939,8 +9939,8 @@ func (s *integrationTestSuite) TestCarve() { require.True(t, blockResp.Success) // sending next block - blockResp = carveBlockResponse{} - s.DoJSON("POST", "/api/osquery/carve/block", carveBlockRequest{ + blockResp = fleet.CarveBlockResponse{} + s.DoJSON("POST", "/api/osquery/carve/block", fleet.CarveBlockRequest{ BlockId: 1, SessionId: sid, RequestId: "r1", @@ -9949,8 +9949,8 @@ func (s *integrationTestSuite) TestCarve() { require.True(t, blockResp.Success) // sending already-sent block again - blockResp = carveBlockResponse{} - s.DoJSON("POST", "/api/osquery/carve/block", carveBlockRequest{ + blockResp = fleet.CarveBlockResponse{} + s.DoJSON("POST", "/api/osquery/carve/block", fleet.CarveBlockRequest{ BlockId: 1, SessionId: sid, RequestId: "r1", @@ -9959,8 +9959,8 @@ func (s *integrationTestSuite) TestCarve() { checkCarveError(1, "block_id does not match expected block (2): 1") // sending final block with too many bytes - blockResp = carveBlockResponse{} - s.DoJSON("POST", "/api/osquery/carve/block", carveBlockRequest{ + blockResp = fleet.CarveBlockResponse{} + s.DoJSON("POST", "/api/osquery/carve/block", fleet.CarveBlockRequest{ BlockId: 2, SessionId: sid, RequestId: "r1", @@ -9969,8 +9969,8 @@ func (s *integrationTestSuite) TestCarve() { checkCarveError(1, "exceeded declared block size 3: 7") // sending actual final block - blockResp = carveBlockResponse{} - s.DoJSON("POST", "/api/osquery/carve/block", carveBlockRequest{ + blockResp = fleet.CarveBlockResponse{} + s.DoJSON("POST", "/api/osquery/carve/block", fleet.CarveBlockRequest{ BlockId: 2, SessionId: sid, RequestId: "r1", @@ -9979,8 +9979,8 @@ func (s *integrationTestSuite) TestCarve() { require.True(t, blockResp.Success) // sending unexpected block - blockResp = carveBlockResponse{} - s.DoJSON("POST", "/api/osquery/carve/block", carveBlockRequest{ + blockResp = fleet.CarveBlockResponse{} + s.DoJSON("POST", "/api/osquery/carve/block", fleet.CarveBlockRequest{ BlockId: 3, SessionId: sid, RequestId: "r1", diff --git a/server/service/integration_enterprise_test.go b/server/service/integration_enterprise_test.go index 03cf9bf713..df41f81078 100644 --- a/server/service/integration_enterprise_test.go +++ b/server/service/integration_enterprise_test.go @@ -6919,8 +6919,8 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { }, }, http.StatusOK, &cur) maintainer := cur.User - var carveBeginResp carveBeginResponse - s.DoJSON("POST", "/api/osquery/carve/begin", carveBeginRequest{ + var carveBeginResp fleet.CarveBeginResponse + s.DoJSON("POST", "/api/osquery/carve/begin", fleet.CarveBeginRequest{ NodeKey: *h1.NodeKey, BlockCount: 3, BlockSize: 3, @@ -6929,8 +6929,8 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { RequestId: "r1", }, http.StatusOK, &carveBeginResp) require.NotEmpty(t, carveBeginResp.SessionId) - lcr := listCarvesResponse{} - s.DoJSON("GET", "/api/latest/fleet/carves", listCarvesRequest{}, http.StatusOK, &lcr) + lcr := fleet.ListCarvesResponse{} + s.DoJSON("GET", "/api/latest/fleet/carves", fleet.ListCarvesRequest{}, http.StatusOK, &lcr) require.NotEmpty(t, lcr.Carves) carveID := lcr.Carves[0].ID // Create the global GitOps user we'll use in tests. @@ -7343,10 +7343,10 @@ func (s *integrationEnterpriseTestSuite) TestGitOpsUserActions() { s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/teams/%d/secrets", t1.ID), teamEnrollSecretsRequest{}, http.StatusForbidden, &teamEnrollSecretsResponse{}) // Attempt to list carved files, should fail. - s.DoJSON("GET", "/api/latest/fleet/carves", listCarvesRequest{}, http.StatusForbidden, &listCarvesResponse{}) + s.DoJSON("GET", "/api/latest/fleet/carves", fleet.ListCarvesRequest{}, http.StatusForbidden, &fleet.ListCarvesResponse{}) // Attempt to get a carved file, should fail. - s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/carves/%d", carveID), listCarvesRequest{}, http.StatusForbidden, &listCarvesResponse{}) + s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/carves/%d", carveID), fleet.GetCarveRequest{}, http.StatusForbidden, &fleet.GetCarveResponse{}) // Attempt to search hosts, should fail. s.DoJSON("POST", "/api/latest/fleet/targets", searchTargetsRequest{ diff --git a/server/service/integration_mdm_test.go b/server/service/integration_mdm_test.go index 2a000fae36..33b556a5f6 100644 --- a/server/service/integration_mdm_test.go +++ b/server/service/integration_mdm_test.go @@ -21741,8 +21741,8 @@ func (s *integrationMDMTestSuite) TestTechnicianPermissions() { }, }, http.StatusOK, &cur) maintainer := cur.User - var carveBeginResp carveBeginResponse - s.DoJSON("POST", "/api/osquery/carve/begin", carveBeginRequest{ + var carveBeginResp fleet.CarveBeginResponse + s.DoJSON("POST", "/api/osquery/carve/begin", fleet.CarveBeginRequest{ NodeKey: *h1.NodeKey, BlockCount: 3, BlockSize: 3, @@ -21751,8 +21751,8 @@ func (s *integrationMDMTestSuite) TestTechnicianPermissions() { RequestId: "r1", }, http.StatusOK, &carveBeginResp) require.NotEmpty(t, carveBeginResp.SessionId) - lcr := listCarvesResponse{} - s.DoJSON("GET", "/api/latest/fleet/carves", listCarvesRequest{}, http.StatusOK, &lcr) + lcr := fleet.ListCarvesResponse{} + s.DoJSON("GET", "/api/latest/fleet/carves", fleet.ListCarvesRequest{}, http.StatusOK, &lcr) require.NotEmpty(t, lcr.Carves) carveID := lcr.Carves[0].ID // Create the global Technician user we'll use in tests. @@ -22281,10 +22281,10 @@ func (s *integrationMDMTestSuite) TestTechnicianPermissions() { require.Equal(t, fleet.MaskedPassword, tesr.Secrets[0].Secret) // Attempt to list carved files, should fail. - s.DoJSON("GET", "/api/latest/fleet/carves", listCarvesRequest{}, http.StatusForbidden, &listCarvesResponse{}) + s.DoJSON("GET", "/api/latest/fleet/carves", fleet.ListCarvesRequest{}, http.StatusForbidden, &fleet.ListCarvesResponse{}) // Attempt to get a carved file, should fail. - s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/carves/%d", carveID), listCarvesRequest{}, http.StatusForbidden, &listCarvesResponse{}) + s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/carves/%d", carveID), fleet.GetCarveRequest{}, http.StatusForbidden, &fleet.GetCarveResponse{}) // Attempt to search hosts, should allow. s.DoJSON("POST", "/api/latest/fleet/targets", searchTargetsRequest{