Add validation to reject requests to enqueue scripts for plain osquery hosts (#16893)
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
- Added validation to reject requests to enqueue scripts for hosts that do not have fleetd installed
|
||||
(i.e. plain osquery hosts).
|
||||
@@ -215,13 +215,13 @@ Fleet records the last 10,000 characters to prevent downtime.
|
||||
if ident != "host1" || c.expectNotFound {
|
||||
return nil, ¬FoundError{}
|
||||
}
|
||||
return &fleet.Host{ID: 42, SeenTime: time.Now()}, nil
|
||||
return &fleet.Host{ID: 42, SeenTime: time.Now(), OrbitNodeKey: ptr.String("abc")}, nil
|
||||
}
|
||||
ds.HostFunc = func(ctx context.Context, hid uint) (*fleet.Host, error) {
|
||||
if hid != 42 || c.expectNotFound {
|
||||
return nil, ¬FoundError{}
|
||||
}
|
||||
h := fleet.Host{ID: hid, SeenTime: time.Now()}
|
||||
h := fleet.Host{ID: hid, SeenTime: time.Now(), OrbitNodeKey: ptr.String("abc")}
|
||||
if c.expectOffline {
|
||||
h.SeenTime = time.Now().Add(-time.Hour)
|
||||
}
|
||||
|
||||
@@ -577,6 +577,7 @@ SELECT
|
||||
h.updated_at,
|
||||
h.detail_updated_at,
|
||||
h.node_key,
|
||||
h.orbit_node_key,
|
||||
h.hostname,
|
||||
h.uuid,
|
||||
h.platform,
|
||||
|
||||
@@ -4696,6 +4696,25 @@ func (s *integrationEnterpriseTestSuite) TestRunHostScript() {
|
||||
|
||||
// attempt to create an async script execution request, succeeds because script is added to queue.
|
||||
s.Do("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptContents: "echo"}, http.StatusAccepted)
|
||||
|
||||
// attempt to run a script on a plain osquery host
|
||||
plainOsqueryHost, err := s.ds.NewHost(context.Background(), &fleet.Host{
|
||||
DetailUpdatedAt: time.Now(),
|
||||
LabelUpdatedAt: time.Now(),
|
||||
PolicyUpdatedAt: time.Now(),
|
||||
SeenTime: time.Now().Add(-time.Minute),
|
||||
OsqueryHostID: ptr.String("plain-osquery-host"),
|
||||
NodeKey: ptr.String("plain-osquery-host"),
|
||||
UUID: uuid.New().String(),
|
||||
Hostname: fmt.Sprintf("%s.local", "plain-osquery-host"),
|
||||
HardwareSerial: uuid.New().String(),
|
||||
Platform: "linux",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
res = s.Do("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: plainOsqueryHost.ID, ScriptContents: "echo"}, http.StatusUnprocessableEntity)
|
||||
require.Contains(t, extractServerErrorText(res.Body), fleet.RunScriptDisabledErrMsg)
|
||||
res = s.Do("POST", "/api/latest/fleet/scripts/run/sync", fleet.HostScriptRequestPayload{HostID: plainOsqueryHost.ID, ScriptContents: "echo"}, http.StatusUnprocessableEntity)
|
||||
require.Contains(t, extractServerErrorText(res.Body), fleet.RunScriptDisabledErrMsg)
|
||||
}
|
||||
|
||||
func (s *integrationEnterpriseTestSuite) TestRunHostSavedScript() {
|
||||
@@ -4857,6 +4876,25 @@ func (s *integrationEnterpriseTestSuite) TestRunHostSavedScript() {
|
||||
require.NoError(t, err)
|
||||
|
||||
s.DoJSON("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: host.ID, ScriptID: &script.ID}, http.StatusConflict, &runResp)
|
||||
|
||||
// attempt to run a script on a plain osquery host
|
||||
plainOsqueryHost, err := s.ds.NewHost(context.Background(), &fleet.Host{
|
||||
DetailUpdatedAt: time.Now(),
|
||||
LabelUpdatedAt: time.Now(),
|
||||
PolicyUpdatedAt: time.Now(),
|
||||
SeenTime: time.Now().Add(-time.Minute),
|
||||
OsqueryHostID: ptr.String("plain-osquery-host-2"),
|
||||
NodeKey: ptr.String("plain-osquery-host-2"),
|
||||
UUID: uuid.New().String(),
|
||||
Hostname: fmt.Sprintf("%s.local", "plain-osquery-host-2"),
|
||||
HardwareSerial: uuid.New().String(),
|
||||
Platform: "linux",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
res = s.Do("POST", "/api/latest/fleet/scripts/run", fleet.HostScriptRequestPayload{HostID: plainOsqueryHost.ID, ScriptID: &script.ID}, http.StatusUnprocessableEntity)
|
||||
require.Contains(t, extractServerErrorText(res.Body), fleet.RunScriptDisabledErrMsg)
|
||||
res = s.Do("POST", "/api/latest/fleet/scripts/run/sync", fleet.HostScriptRequestPayload{HostID: plainOsqueryHost.ID, ScriptID: &script.ID}, http.StatusUnprocessableEntity)
|
||||
require.Contains(t, extractServerErrorText(res.Body), fleet.RunScriptDisabledErrMsg)
|
||||
}
|
||||
|
||||
func (s *integrationEnterpriseTestSuite) TestEnqueueSameScriptTwice() {
|
||||
|
||||
@@ -142,6 +142,13 @@ func (svc *Service) RunHostScript(ctx context.Context, request *fleet.HostScript
|
||||
return nil, ctxerr.Wrap(ctx, err, "get host lite")
|
||||
}
|
||||
|
||||
if host.OrbitNodeKey == nil || *host.OrbitNodeKey == "" {
|
||||
// fleetd is required to run scripts so if the host is enrolled via plain osquery we return
|
||||
// an error
|
||||
svc.authz.SkipAuthorization(ctx)
|
||||
return nil, fleet.NewUserMessageError(errors.New(fleet.RunScriptDisabledErrMsg), http.StatusUnprocessableEntity)
|
||||
}
|
||||
|
||||
maxPending := maxPendingScripts
|
||||
|
||||
// must check that only one of script id or contents is provided before
|
||||
|
||||
@@ -32,8 +32,8 @@ func TestHostRunScript(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
teamHost := &fleet.Host{ID: 1, Hostname: "host-team", TeamID: ptr.Uint(1), SeenTime: time.Now()}
|
||||
noTeamHost := &fleet.Host{ID: 2, Hostname: "host-no-team", TeamID: nil, SeenTime: time.Now()}
|
||||
teamHost := &fleet.Host{ID: 1, Hostname: "host-team", TeamID: ptr.Uint(1), SeenTime: time.Now(), OrbitNodeKey: ptr.String("abc")}
|
||||
noTeamHost := &fleet.Host{ID: 2, Hostname: "host-no-team", TeamID: nil, SeenTime: time.Now(), OrbitNodeKey: ptr.String("def")}
|
||||
nonExistingHost := &fleet.Host{ID: 3, Hostname: "no-such-host", TeamID: nil}
|
||||
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
|
||||
return &fleet.AppConfig{}, nil
|
||||
|
||||
Reference in New Issue
Block a user