Move carve requests to server/fleet/ (#45785)

Resolves #36087 (one of several PRs)

## Testing

- [x] QA'd all new/changed functionality manually.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Reorganized internal API request/response types for carve operations
to centralize type definitions and improve code maintainability.

* **Tests**
* Updated carve operation tests to align with refactored code structure.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45785?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Lucas Manuel Rodriguez
2026-05-20 09:12:38 -03:00
committed by GitHub
parent cd9d0395c8
commit 9100a1265d
9 changed files with 173 additions and 144 deletions
+90
View File
@@ -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 }
+23 -86
View File
@@ -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
+10 -11
View File
@@ -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 {
+4 -4
View File
@@ -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)
+3
View File
@@ -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
}
+5 -5
View File
@@ -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{})
+26 -26
View File
@@ -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",
@@ -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{
+6 -6
View File
@@ -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{