2022-03-07 18:10:55 +00:00
package service
import (
"context"
"encoding/json"
"errors"
"fmt"
2024-01-30 00:38:10 +00:00
"net/http"
2022-03-07 18:10:55 +00:00
"regexp"
2024-09-16 16:01:21 +00:00
"sort"
2022-03-07 18:10:55 +00:00
"strconv"
"strings"
2022-03-08 16:27:38 +00:00
"sync/atomic"
2022-03-07 18:10:55 +00:00
"time"
2024-04-05 17:44:56 +00:00
"github.com/cenkalti/backoff/v4"
2022-03-08 16:27:38 +00:00
"github.com/fleetdm/fleet/v4/server"
2022-03-07 18:10:55 +00:00
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
hostctx "github.com/fleetdm/fleet/v4/server/contexts/host"
2022-11-15 14:08:05 +00:00
"github.com/fleetdm/fleet/v4/server/contexts/license"
2022-03-07 18:10:55 +00:00
"github.com/fleetdm/fleet/v4/server/contexts/logging"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/fleetdm/fleet/v4/server/ptr"
"github.com/fleetdm/fleet/v4/server/pubsub"
"github.com/fleetdm/fleet/v4/server/service/osquery_utils"
2024-04-05 17:44:56 +00:00
kithttp "github.com/go-kit/kit/transport/http"
2023-10-10 12:44:03 +00:00
"github.com/go-kit/log"
"github.com/go-kit/log/level"
2022-03-07 18:10:55 +00:00
"github.com/spf13/cast"
2024-05-30 16:10:16 +00:00
"golang.org/x/exp/slices"
2022-03-07 18:10:55 +00:00
)
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
// osqueryError is the error returned to osquery agents.
2022-03-08 16:27:38 +00:00
type osqueryError struct {
message string
nodeInvalid bool
2024-01-30 00:38:10 +00:00
statusCode int
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
fleet . ErrorWithUUID
2022-03-08 16:27:38 +00:00
}
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
var _ fleet . ErrorUUIDer = ( * osqueryError ) ( nil )
// Error implements the error interface.
func ( e * osqueryError ) Error ( ) string {
2022-03-08 16:27:38 +00:00
return e . message
}
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
// NodeInvalid returns whether the error returned to osquery
// should contain the node_invalid property.
func ( e * osqueryError ) NodeInvalid ( ) bool {
2022-03-08 16:27:38 +00:00
return e . nodeInvalid
}
2024-01-30 00:38:10 +00:00
func ( e * osqueryError ) Status ( ) int {
return e . statusCode
}
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
func newOsqueryErrorWithInvalidNode ( msg string ) * osqueryError {
return & osqueryError {
message : msg ,
nodeInvalid : true ,
}
}
func newOsqueryError ( msg string ) * osqueryError {
return & osqueryError {
message : msg ,
nodeInvalid : false ,
}
}
2022-03-08 16:27:38 +00:00
func ( svc * Service ) AuthenticateHost ( ctx context . Context , nodeKey string ) ( * fleet . Host , bool , error ) {
// skipauth: Authorization is currently for user endpoints only.
svc . authz . SkipAuthorization ( ctx )
if nodeKey == "" {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , false , newOsqueryErrorWithInvalidNode ( "authentication error: missing node key" )
2022-03-08 16:27:38 +00:00
}
host , err := svc . ds . LoadHostByNodeKey ( ctx , nodeKey )
switch {
case err == nil :
// OK
case fleet . IsNotFound ( err ) :
2024-08-30 21:58:33 +00:00
return nil , false , newOsqueryErrorWithInvalidNode ( "authentication error: invalid node key" )
2022-03-08 16:27:38 +00:00
default :
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , false , newOsqueryError ( "authentication error: " + err . Error ( ) )
2022-03-08 16:27:38 +00:00
}
// Update the "seen" time used to calculate online status. These updates are
// batched for MySQL performance reasons. Because this is done
// asynchronously, it is possible for the server to shut down before
// updating the seen time for these hosts. This seems to be an acceptable
// tradeoff as an online host will continue to check in and quickly be
// marked online again.
2022-05-10 15:29:17 +00:00
if err := svc . task . RecordHostLastSeen ( ctx , host . ID ) ; err != nil {
logging . WithErr ( ctx , ctxerr . Wrap ( ctx , err , "record host last seen" ) )
}
2022-03-08 16:27:38 +00:00
host . SeenTime = svc . clock . Now ( )
return host , svc . debugEnabledForHost ( ctx , host . ID ) , nil
}
////////////////////////////////////////////////////////////////////////////////
// Enroll Agent
////////////////////////////////////////////////////////////////////////////////
type enrollAgentRequest struct {
EnrollSecret string ` json:"enroll_secret" `
HostIdentifier string ` json:"host_identifier" `
HostDetails map [ string ] ( map [ string ] string ) ` json:"host_details" `
}
type enrollAgentResponse struct {
NodeKey string ` json:"node_key,omitempty" `
Err error ` json:"error,omitempty" `
}
func ( r enrollAgentResponse ) error ( ) error { return r . Err }
2022-12-27 14:26:59 +00:00
func enrollAgentEndpoint ( ctx context . Context , request interface { } , svc fleet . Service ) ( errorer , error ) {
2022-03-08 16:27:38 +00:00
req := request . ( * enrollAgentRequest )
nodeKey , err := svc . EnrollAgent ( ctx , req . EnrollSecret , req . HostIdentifier , req . HostDetails )
if err != nil {
return enrollAgentResponse { Err : err } , nil
}
return enrollAgentResponse { NodeKey : nodeKey } , nil
}
func ( svc * Service ) EnrollAgent ( ctx context . Context , enrollSecret , hostIdentifier string , hostDetails map [ string ] ( map [ string ] string ) ) ( string , error ) {
// skipauth: Authorization is currently for user endpoints only.
svc . authz . SkipAuthorization ( ctx )
logging . WithExtras ( ctx , "hostIdentifier" , hostIdentifier )
secret , err := svc . ds . VerifyEnrollSecret ( ctx , enrollSecret )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return "" , newOsqueryErrorWithInvalidNode ( "enroll failed: " + err . Error ( ) )
2022-03-08 16:27:38 +00:00
}
nodeKey , err := server . GenerateRandomText ( svc . config . Osquery . NodeKeySize )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return "" , newOsqueryErrorWithInvalidNode ( "generate node key failed: " + err . Error ( ) )
2022-03-08 16:27:38 +00:00
}
hostIdentifier = getHostIdentifier ( svc . logger , svc . config . Osquery . HostIdentifier , hostIdentifier , hostDetails )
2022-06-13 20:29:32 +00:00
canEnroll , err := svc . enrollHostLimiter . CanEnrollNewHost ( ctx )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return "" , newOsqueryErrorWithInvalidNode ( "can enroll host check failed: " + err . Error ( ) )
2022-06-13 20:29:32 +00:00
}
if ! canEnroll {
2022-11-15 14:08:05 +00:00
deviceCount := "unknown"
if lic , _ := license . FromContext ( ctx ) ; lic != nil {
deviceCount = strconv . Itoa ( lic . DeviceCount )
}
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return "" , newOsqueryErrorWithInvalidNode ( fmt . Sprintf ( "enroll host failed: maximum number of hosts reached: %s" , deviceCount ) )
2022-06-13 20:29:32 +00:00
}
2022-03-08 16:27:38 +00:00
2023-02-28 17:55:04 +00:00
// the the device's uuid and serial from the system_info table provided with
// the osquery enrollment
var hardwareUUID , hardwareSerial string
if r , ok := hostDetails [ "system_info" ] ; ok {
hardwareUUID = r [ "uuid" ]
hardwareSerial = r [ "hardware_serial" ]
2022-03-08 16:27:38 +00:00
}
appConfig , err := svc . ds . AppConfig ( ctx )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return "" , newOsqueryErrorWithInvalidNode ( "app config load failed: " + err . Error ( ) )
2022-03-08 16:27:38 +00:00
}
2023-02-28 17:55:04 +00:00
host , err := svc . ds . EnrollHost ( ctx , appConfig . MDM . EnabledAndConfigured , hostIdentifier , hardwareUUID , hardwareSerial , nodeKey , secret . TeamID , svc . config . Osquery . EnrollCooldown )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return "" , newOsqueryErrorWithInvalidNode ( "save enroll failed: " + err . Error ( ) )
2023-02-28 17:55:04 +00:00
}
2022-08-30 11:13:09 +00:00
features , err := svc . HostFeatures ( ctx , host )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return "" , newOsqueryErrorWithInvalidNode ( "host features load failed: " + err . Error ( ) )
2022-08-30 11:13:09 +00:00
}
2022-03-08 16:27:38 +00:00
// Save enrollment details if provided
2023-02-08 14:49:42 +00:00
detailQueries := osquery_utils . GetDetailQueries ( ctx , svc . config , appConfig , features )
2022-03-08 16:27:38 +00:00
save := false
if r , ok := hostDetails [ "os_version" ] ; ok {
2022-03-21 16:29:52 +00:00
err := detailQueries [ "os_version" ] . IngestFunc ( ctx , svc . logger , host , [ ] map [ string ] string { r } )
2022-03-08 16:27:38 +00:00
if err != nil {
return "" , ctxerr . Wrap ( ctx , err , "Ingesting os_version" )
}
save = true
}
if r , ok := hostDetails [ "osquery_info" ] ; ok {
2022-03-21 16:29:52 +00:00
err := detailQueries [ "osquery_info" ] . IngestFunc ( ctx , svc . logger , host , [ ] map [ string ] string { r } )
2022-03-08 16:27:38 +00:00
if err != nil {
return "" , ctxerr . Wrap ( ctx , err , "Ingesting osquery_info" )
}
save = true
}
if r , ok := hostDetails [ "system_info" ] ; ok {
2022-03-21 16:29:52 +00:00
err := detailQueries [ "system_info" ] . IngestFunc ( ctx , svc . logger , host , [ ] map [ string ] string { r } )
2022-03-08 16:27:38 +00:00
if err != nil {
return "" , ctxerr . Wrap ( ctx , err , "Ingesting system_info" )
}
save = true
}
if save {
if appConfig . ServerSettings . DeferredSaveHost {
go svc . serialUpdateHost ( host )
} else {
if err := svc . ds . UpdateHost ( ctx , host ) ; err != nil {
return "" , ctxerr . Wrap ( ctx , err , "save host in enroll agent" )
}
}
}
return nodeKey , nil
}
var counter = int64 ( 0 )
func ( svc * Service ) serialUpdateHost ( host * fleet . Host ) {
newVal := atomic . AddInt64 ( & counter , 1 )
defer func ( ) {
atomic . AddInt64 ( & counter , - 1 )
} ( )
level . Debug ( svc . logger ) . Log ( "background" , newVal )
ctx , cancelFunc := context . WithTimeout ( context . Background ( ) , 30 * time . Second )
defer cancelFunc ( )
err := svc . ds . SerialUpdateHost ( ctx , host )
if err != nil {
level . Error ( svc . logger ) . Log ( "background-err" , err )
}
}
func getHostIdentifier ( logger log . Logger , identifierOption , providedIdentifier string , details map [ string ] ( map [ string ] string ) ) string {
switch identifierOption {
case "provided" :
// Use the host identifier already provided in the request.
return providedIdentifier
case "instance" :
r , ok := details [ "osquery_info" ]
2024-10-18 17:38:26 +00:00
if ! ok { //nolint:gocritic // ignore ifElseChain
2022-03-08 16:27:38 +00:00
level . Info ( logger ) . Log (
"msg" , "could not get host identifier" ,
"reason" , "missing osquery_info" ,
"identifier" , "instance" ,
)
} else if r [ "instance_id" ] == "" {
level . Info ( logger ) . Log (
"msg" , "could not get host identifier" ,
"reason" , "missing instance_id in osquery_info" ,
"identifier" , "instance" ,
)
} else {
return r [ "instance_id" ]
}
case "uuid" :
r , ok := details [ "osquery_info" ]
2024-10-18 17:38:26 +00:00
if ! ok { //nolint:gocritic // ignore ifElseChain
2022-03-08 16:27:38 +00:00
level . Info ( logger ) . Log (
"msg" , "could not get host identifier" ,
"reason" , "missing osquery_info" ,
"identifier" , "uuid" ,
)
} else if r [ "uuid" ] == "" {
level . Info ( logger ) . Log (
"msg" , "could not get host identifier" ,
"reason" , "missing instance_id in osquery_info" ,
"identifier" , "uuid" ,
)
} else {
return r [ "uuid" ]
}
case "hostname" :
r , ok := details [ "system_info" ]
2024-10-18 17:38:26 +00:00
if ! ok { //nolint:gocritic // ignore ifElseChain
2022-03-08 16:27:38 +00:00
level . Info ( logger ) . Log (
"msg" , "could not get host identifier" ,
"reason" , "missing system_info" ,
"identifier" , "hostname" ,
)
} else if r [ "hostname" ] == "" {
level . Info ( logger ) . Log (
"msg" , "could not get host identifier" ,
"reason" , "missing instance_id in system_info" ,
"identifier" , "hostname" ,
)
} else {
return r [ "hostname" ]
}
default :
panic ( "Unknown option for host_identifier: " + identifierOption )
}
return providedIdentifier
}
func ( svc * Service ) debugEnabledForHost ( ctx context . Context , id uint ) bool {
hlogger := log . With ( svc . logger , "host-id" , id )
ac , err := svc . ds . AppConfig ( ctx )
if err != nil {
level . Debug ( hlogger ) . Log ( "err" , ctxerr . Wrap ( ctx , err , "getting app config for host debug" ) )
return false
}
for _ , hostID := range ac . ServerSettings . DebugHostIDs {
if hostID == id {
return true
}
}
return false
}
2022-03-07 18:10:55 +00:00
////////////////////////////////////////////////////////////////////////////////
// Get Client Config
////////////////////////////////////////////////////////////////////////////////
type getClientConfigRequest struct {
NodeKey string ` json:"node_key" `
}
2022-03-09 21:13:56 +00:00
func ( r * getClientConfigRequest ) hostNodeKey ( ) string {
return r . NodeKey
}
2022-03-07 18:10:55 +00:00
type getClientConfigResponse struct {
Config map [ string ] interface { }
Err error ` json:"error,omitempty" `
}
func ( r getClientConfigResponse ) error ( ) error { return r . Err }
2022-12-27 14:26:59 +00:00
// MarshalJSON implements json.Marshaler.
//
// Osquery expects the response for configs to be at the
// top-level of the JSON response.
func ( r getClientConfigResponse ) MarshalJSON ( ) ( [ ] byte , error ) {
return json . Marshal ( r . Config )
}
2023-09-01 18:14:49 +00:00
// UnmarshalJSON implements json.Unmarshaler.
//
// Osquery expects the response for configs to be at the
// top-level of the JSON response.
func ( r * getClientConfigResponse ) UnmarshalJSON ( data [ ] byte ) error {
return json . Unmarshal ( data , & r . Config )
}
2022-12-27 14:26:59 +00:00
func getClientConfigEndpoint ( ctx context . Context , request interface { } , svc fleet . Service ) ( errorer , error ) {
2022-03-07 18:10:55 +00:00
config , err := svc . GetClientConfig ( ctx )
if err != nil {
return getClientConfigResponse { Err : err } , nil
}
2022-12-27 14:26:59 +00:00
return getClientConfigResponse {
Config : config ,
} , nil
2022-03-07 18:10:55 +00:00
}
2023-07-14 17:37:09 +00:00
func ( svc * Service ) getScheduledQueries ( ctx context . Context , teamID * uint ) ( fleet . Queries , error ) {
2023-10-11 18:20:06 +00:00
appConfig , err := svc . ds . AppConfig ( ctx )
if err != nil {
return nil , ctxerr . Wrap ( ctx , err , "load app config" )
}
queries , err := svc . ds . ListScheduledQueriesForAgents ( ctx , teamID , appConfig . ServerSettings . QueryReportsDisabled )
2023-07-14 17:37:09 +00:00
if err != nil {
return nil , err
}
if len ( queries ) == 0 {
return nil , nil
}
config := make ( fleet . Queries , len ( queries ) )
for _ , query := range queries {
config [ query . Name ] = query . ToQueryContent ( )
}
return config , nil
}
2022-03-07 18:10:55 +00:00
func ( svc * Service ) GetClientConfig ( ctx context . Context ) ( map [ string ] interface { } , error ) {
// skipauth: Authorization is currently for user endpoints only.
svc . authz . SkipAuthorization ( ctx )
host , ok := hostctx . FromContext ( ctx )
if ! ok {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , newOsqueryError ( "internal error: missing host from request context" )
2022-03-07 18:10:55 +00:00
}
baseConfig , err := svc . AgentOptionsForHost ( ctx , host . TeamID , host . Platform )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , newOsqueryError ( "internal error: fetch base config: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
config := make ( map [ string ] interface { } )
if baseConfig != nil {
err = json . Unmarshal ( baseConfig , & config )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , newOsqueryError ( "internal error: parse base configuration: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
}
2023-07-14 17:37:09 +00:00
packConfig := fleet . Packs { }
2022-03-07 18:10:55 +00:00
packs , err := svc . ds . ListPacksForHost ( ctx , host . ID )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , newOsqueryError ( "database error: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
for _ , pack := range packs {
// first, we must figure out what queries are in this pack
queries , err := svc . ds . ListScheduledQueriesInPack ( ctx , pack . ID )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , newOsqueryError ( "database error: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
// the serializable osquery config struct expects content in a
// particular format, so we do the conversion here
configQueries := fleet . Queries { }
for _ , query := range queries {
queryContent := fleet . QueryContent {
Query : query . Query ,
Interval : query . Interval ,
Platform : query . Platform ,
Version : query . Version ,
Removed : query . Removed ,
Shard : query . Shard ,
Denylist : query . Denylist ,
}
if query . Removed != nil {
queryContent . Removed = query . Removed
}
if query . Snapshot != nil && * query . Snapshot {
queryContent . Snapshot = query . Snapshot
}
configQueries [ query . Name ] = queryContent
}
// finally, we add the pack to the client config struct with all of
// the pack's queries
packConfig [ pack . Name ] = fleet . PackContent {
Platform : pack . Platform ,
Queries : configQueries ,
}
}
2023-07-14 17:37:09 +00:00
globalQueries , err := svc . getScheduledQueries ( ctx , nil )
if err != nil {
return nil , newOsqueryError ( "database error: " + err . Error ( ) )
}
if len ( globalQueries ) > 0 {
packConfig [ "Global" ] = fleet . PackContent {
Queries : globalQueries ,
}
}
if host . TeamID != nil {
2023-07-25 00:17:20 +00:00
teamQueries , err := svc . getScheduledQueries ( ctx , host . TeamID )
2023-07-14 17:37:09 +00:00
if err != nil {
return nil , newOsqueryError ( "database error: " + err . Error ( ) )
}
2023-07-25 00:17:20 +00:00
if len ( teamQueries ) > 0 {
packName := fmt . Sprintf ( "team-%d" , * host . TeamID )
packConfig [ packName ] = fleet . PackContent {
Queries : teamQueries ,
2023-07-14 17:37:09 +00:00
}
}
}
2022-03-07 18:10:55 +00:00
if len ( packConfig ) > 0 {
packJSON , err := json . Marshal ( packConfig )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , newOsqueryError ( "internal error: marshal pack JSON: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
config [ "packs" ] = json . RawMessage ( packJSON )
}
// Save interval values if they have been updated.
intervalsModified := false
intervals := fleet . HostOsqueryIntervals {
DistributedInterval : host . DistributedInterval ,
ConfigTLSRefresh : host . ConfigTLSRefresh ,
LoggerTLSPeriod : host . LoggerTLSPeriod ,
}
if options , ok := config [ "options" ] . ( map [ string ] interface { } ) ; ok {
distributedIntervalVal , ok := options [ "distributed_interval" ]
distributedInterval , err := cast . ToUintE ( distributedIntervalVal )
if ok && err == nil && intervals . DistributedInterval != distributedInterval {
intervals . DistributedInterval = distributedInterval
intervalsModified = true
}
loggerTLSPeriodVal , ok := options [ "logger_tls_period" ]
loggerTLSPeriod , err := cast . ToUintE ( loggerTLSPeriodVal )
if ok && err == nil && intervals . LoggerTLSPeriod != loggerTLSPeriod {
intervals . LoggerTLSPeriod = loggerTLSPeriod
intervalsModified = true
}
// Note config_tls_refresh can only be set in the osquery flags (and has
// also been deprecated in osquery for quite some time) so is ignored
// here.
configRefreshVal , ok := options [ "config_refresh" ]
configRefresh , err := cast . ToUintE ( configRefreshVal )
if ok && err == nil && intervals . ConfigTLSRefresh != configRefresh {
intervals . ConfigTLSRefresh = configRefresh
intervalsModified = true
}
}
// We are not doing deferred update host like in other places because the intervals
// are not modified often.
if intervalsModified {
if err := svc . ds . UpdateHostOsqueryIntervals ( ctx , host . ID , intervals ) ; err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , newOsqueryError ( "internal error: update host intervals: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
}
return config , nil
}
// AgentOptionsForHost gets the agent options for the provided host.
// The host information should be used for filtering based on team, platform, etc.
func ( svc * Service ) AgentOptionsForHost ( ctx context . Context , hostTeamID * uint , hostPlatform string ) ( json . RawMessage , error ) {
// Team agent options have priority over global options.
if hostTeamID != nil {
teamAgentOptions , err := svc . ds . TeamAgentOptions ( ctx , * hostTeamID )
if err != nil {
return nil , ctxerr . Wrap ( ctx , err , "load team agent options for host" )
}
if teamAgentOptions != nil && len ( * teamAgentOptions ) > 0 {
var options fleet . AgentOptions
if err := json . Unmarshal ( * teamAgentOptions , & options ) ; err != nil {
return nil , ctxerr . Wrap ( ctx , err , "unmarshal team agent options" )
}
return options . ForPlatform ( hostPlatform ) , nil
}
}
// Otherwise return the appropriate override for global options.
appConfig , err := svc . ds . AppConfig ( ctx )
if err != nil {
2023-10-11 18:20:06 +00:00
return nil , ctxerr . Wrap ( ctx , err , "load app config" )
2022-03-07 18:10:55 +00:00
}
var options fleet . AgentOptions
if appConfig . AgentOptions != nil {
if err := json . Unmarshal ( * appConfig . AgentOptions , & options ) ; err != nil {
return nil , ctxerr . Wrap ( ctx , err , "unmarshal global agent options" )
}
}
return options . ForPlatform ( hostPlatform ) , nil
}
////////////////////////////////////////////////////////////////////////////////
// Get Distributed Queries
////////////////////////////////////////////////////////////////////////////////
type getDistributedQueriesRequest struct {
NodeKey string ` json:"node_key" `
}
2022-03-09 21:13:56 +00:00
func ( r * getDistributedQueriesRequest ) hostNodeKey ( ) string {
return r . NodeKey
}
2022-03-07 18:10:55 +00:00
type getDistributedQueriesResponse struct {
Queries map [ string ] string ` json:"queries" `
2022-03-15 19:51:00 +00:00
Discovery map [ string ] string ` json:"discovery" `
2022-03-07 18:10:55 +00:00
Accelerate uint ` json:"accelerate,omitempty" `
Err error ` json:"error,omitempty" `
}
func ( r getDistributedQueriesResponse ) error ( ) error { return r . Err }
2022-12-27 14:26:59 +00:00
func getDistributedQueriesEndpoint ( ctx context . Context , request interface { } , svc fleet . Service ) ( errorer , error ) {
2022-03-15 19:51:00 +00:00
queries , discovery , accelerate , err := svc . GetDistributedQueries ( ctx )
2022-03-07 18:10:55 +00:00
if err != nil {
return getDistributedQueriesResponse { Err : err } , nil
}
2022-03-15 19:51:00 +00:00
return getDistributedQueriesResponse {
Queries : queries ,
Discovery : discovery ,
Accelerate : accelerate ,
} , nil
2022-03-07 18:10:55 +00:00
}
2022-03-15 19:51:00 +00:00
func ( svc * Service ) GetDistributedQueries ( ctx context . Context ) ( queries map [ string ] string , discovery map [ string ] string , accelerate uint , err error ) {
2022-03-07 18:10:55 +00:00
// skipauth: Authorization is currently for user endpoints only.
svc . authz . SkipAuthorization ( ctx )
host , ok := hostctx . FromContext ( ctx )
if ! ok {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , nil , 0 , newOsqueryError ( "internal error: missing host from request context" )
2022-03-07 18:10:55 +00:00
}
2022-03-15 19:51:00 +00:00
queries = make ( map [ string ] string )
discovery = make ( map [ string ] string )
2022-03-07 18:10:55 +00:00
2022-03-15 19:51:00 +00:00
detailQueries , detailDiscovery , err := svc . detailQueriesForHost ( ctx , host )
2022-03-07 18:10:55 +00:00
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , nil , 0 , newOsqueryError ( err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
for name , query := range detailQueries {
queries [ name ] = query
}
2022-03-15 19:51:00 +00:00
for name , query := range detailDiscovery {
discovery [ name ] = query
}
2022-03-07 18:10:55 +00:00
labelQueries , err := svc . labelQueriesForHost ( ctx , host )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , nil , 0 , newOsqueryError ( err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
for name , query := range labelQueries {
queries [ hostLabelQueryPrefix + name ] = query
}
if liveQueries , err := svc . liveQueryStore . QueriesForHost ( host . ID ) ; err != nil {
// If the live query store fails to fetch queries we still want the hosts
// to receive all the other queries (details, policies, labels, etc.),
// thus we just log the error.
level . Error ( svc . logger ) . Log ( "op" , "QueriesForHost" , "err" , err )
} else {
for name , query := range liveQueries {
queries [ hostDistributedQueryPrefix + name ] = query
}
}
2023-08-31 13:58:50 +00:00
policyQueries , noPolicies , err := svc . policyQueriesForHost ( ctx , host )
2022-03-07 18:10:55 +00:00
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return nil , nil , 0 , newOsqueryError ( err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
for name , query := range policyQueries {
queries [ hostPolicyQueryPrefix + name ] = query
}
2023-08-31 13:58:50 +00:00
if noPolicies {
// This is only set when it's time to re-run policies on the host,
// but the host doesn't have any policies assigned.
queries [ hostNoPoliciesWildcard ] = alwaysTrueQuery
}
2022-03-07 18:10:55 +00:00
2022-03-15 19:51:00 +00:00
accelerate = uint ( 0 )
2022-03-07 18:10:55 +00:00
if host . Hostname == "" || host . Platform == "" {
// Assume this host is just enrolling, and accelerate checkins
// (to allow for platform restricted labels to run quickly
// after platform is retrieved from details)
accelerate = 10
}
2022-03-15 19:51:00 +00:00
// The way osquery's distributed "discovery" queries work is:
// If len(discovery) > 0, then only those queries that have a "discovery"
// query and return more than one row are executed on the host.
//
// Thus, we set the alwaysTrueQuery for all queries, except for those where we set
// an explicit discovery query (e.g. orbit_info, google_chrome_profiles).
2023-12-14 15:38:54 +00:00
for name , query := range queries {
// there's a bug somewhere (Fleet, osquery or both?)
// that causes hosts to check-in in a loop if you send
// an empty query string.
//
// we previously fixed this for detail query overrides (see
// #14286, #14296) but I'm also adding this here as a safeguard
// for issues like #15524
if query == "" {
delete ( queries , name )
delete ( discovery , name )
continue
}
2022-03-15 19:51:00 +00:00
discoveryQuery := discovery [ name ]
if discoveryQuery == "" {
discoveryQuery = alwaysTrueQuery
}
discovery [ name ] = discoveryQuery
}
return queries , discovery , accelerate , nil
2022-03-07 18:10:55 +00:00
}
2022-03-15 19:51:00 +00:00
const alwaysTrueQuery = "SELECT 1"
2023-05-17 19:52:45 +00:00
// list of detail queries that are returned when only the critical queries
// should be returned (due to RefetchCriticalQueriesUntil timestamp being set).
var criticalDetailQueries = map [ string ] bool {
"mdm" : true ,
}
2022-03-07 18:10:55 +00:00
// detailQueriesForHost returns the map of detail+additional queries that should be executed by
// osqueryd to fill in the host details.
2022-03-15 19:51:00 +00:00
func ( svc * Service ) detailQueriesForHost ( ctx context . Context , host * fleet . Host ) ( queries map [ string ] string , discovery map [ string ] string , err error ) {
2023-05-17 19:52:45 +00:00
var criticalQueriesOnly bool
2022-03-07 18:10:55 +00:00
if ! svc . shouldUpdate ( host . DetailUpdatedAt , svc . config . Osquery . DetailUpdateInterval , host . ID ) && ! host . RefetchRequested {
2023-05-17 19:52:45 +00:00
// would not return anything, check if critical queries should be returned
if host . RefetchCriticalQueriesUntil != nil && host . RefetchCriticalQueriesUntil . After ( svc . clock . Now ( ) ) {
// return only those critical queries
criticalQueriesOnly = true
} else {
return nil , nil , nil
}
2022-03-07 18:10:55 +00:00
}
2023-02-08 14:49:42 +00:00
appConfig , err := svc . ds . AppConfig ( ctx )
if err != nil {
return nil , nil , ctxerr . Wrap ( ctx , err , "read app config" )
}
2022-08-30 11:13:09 +00:00
features , err := svc . HostFeatures ( ctx , host )
2022-03-07 18:10:55 +00:00
if err != nil {
2022-08-30 11:13:09 +00:00
return nil , nil , ctxerr . Wrap ( ctx , err , "read host features" )
2022-03-07 18:10:55 +00:00
}
2022-03-15 19:51:00 +00:00
queries = make ( map [ string ] string )
discovery = make ( map [ string ] string )
2023-02-08 14:49:42 +00:00
detailQueries := osquery_utils . GetDetailQueries ( ctx , svc . config , appConfig , features )
2022-03-07 18:10:55 +00:00
for name , query := range detailQueries {
2023-05-17 19:52:45 +00:00
if criticalQueriesOnly && ! criticalDetailQueries [ name ] {
continue
}
2022-03-07 18:10:55 +00:00
if query . RunsForPlatform ( host . Platform ) {
2022-03-15 19:51:00 +00:00
queryName := hostDetailQueryPrefix + name
queries [ queryName ] = query . Query
2023-11-30 12:17:07 +00:00
if query . QueryFunc != nil && query . Query == "" {
queries [ queryName ] = query . QueryFunc ( ctx , svc . logger , host , svc . ds )
}
2022-03-15 19:51:00 +00:00
discoveryQuery := query . Discovery
if discoveryQuery == "" {
discoveryQuery = alwaysTrueQuery
}
discovery [ queryName ] = discoveryQuery
2022-03-07 18:10:55 +00:00
}
}
2023-05-17 19:52:45 +00:00
if features . AdditionalQueries == nil || criticalQueriesOnly {
2022-03-07 18:10:55 +00:00
// No additional queries set
2022-03-15 19:51:00 +00:00
return queries , discovery , nil
2022-03-07 18:10:55 +00:00
}
var additionalQueries map [ string ] string
2022-08-30 11:13:09 +00:00
if err := json . Unmarshal ( * features . AdditionalQueries , & additionalQueries ) ; err != nil {
2022-03-15 19:51:00 +00:00
return nil , nil , ctxerr . Wrap ( ctx , err , "unmarshal additional queries" )
2022-03-07 18:10:55 +00:00
}
for name , query := range additionalQueries {
2022-03-15 19:51:00 +00:00
queryName := hostAdditionalQueryPrefix + name
queries [ queryName ] = query
discovery [ queryName ] = alwaysTrueQuery
2022-03-07 18:10:55 +00:00
}
2022-03-15 19:51:00 +00:00
return queries , discovery , nil
2022-03-07 18:10:55 +00:00
}
func ( svc * Service ) shouldUpdate ( lastUpdated time . Time , interval time . Duration , hostID uint ) bool {
svc . jitterMu . Lock ( )
defer svc . jitterMu . Unlock ( )
if svc . jitterH [ interval ] == nil {
svc . jitterH [ interval ] = newJitterHashTable ( int ( int64 ( svc . config . Osquery . MaxJitterPercent ) * int64 ( interval . Minutes ( ) ) / 100.0 ) )
level . Debug ( svc . logger ) . Log ( "jitter" , "created" , "bucketCount" , svc . jitterH [ interval ] . bucketCount )
}
jitter := svc . jitterH [ interval ] . jitterForHost ( hostID )
cutoff := svc . clock . Now ( ) . Add ( - ( interval + jitter ) )
return lastUpdated . Before ( cutoff )
}
func ( svc * Service ) labelQueriesForHost ( ctx context . Context , host * fleet . Host ) ( map [ string ] string , error ) {
labelReportedAt := svc . task . GetHostLabelReportedAt ( ctx , host )
if ! svc . shouldUpdate ( labelReportedAt , svc . config . Osquery . LabelUpdateInterval , host . ID ) && ! host . RefetchRequested {
return nil , nil
}
labelQueries , err := svc . ds . LabelQueriesForHost ( ctx , host )
if err != nil {
return nil , ctxerr . Wrap ( ctx , err , "retrieve label queries" )
}
return labelQueries , nil
}
2023-08-31 13:58:50 +00:00
// policyQueriesForHost returns policy queries if it's the time to re-run policies on the given host.
// It returns (nil, true, nil) if the interval is so that policies should be executed on the host, but there are no policies
// assigned to such host.
func ( svc * Service ) policyQueriesForHost ( ctx context . Context , host * fleet . Host ) ( policyQueries map [ string ] string , noPoliciesForHost bool , err error ) {
2022-03-07 18:10:55 +00:00
policyReportedAt := svc . task . GetHostPolicyReportedAt ( ctx , host )
if ! svc . shouldUpdate ( policyReportedAt , svc . config . Osquery . PolicyUpdateInterval , host . ID ) && ! host . RefetchRequested {
2023-08-31 13:58:50 +00:00
return nil , false , nil
2022-03-07 18:10:55 +00:00
}
2023-08-31 13:58:50 +00:00
policyQueries , err = svc . ds . PolicyQueriesForHost ( ctx , host )
2022-03-07 18:10:55 +00:00
if err != nil {
2023-08-31 13:58:50 +00:00
return nil , false , ctxerr . Wrap ( ctx , err , "retrieve policy queries" )
}
if len ( policyQueries ) == 0 {
return nil , true , nil
2022-03-07 18:10:55 +00:00
}
2023-08-31 13:58:50 +00:00
return policyQueries , false , nil
2022-03-07 18:10:55 +00:00
}
////////////////////////////////////////////////////////////////////////////////
// Write Distributed Query Results
////////////////////////////////////////////////////////////////////////////////
// When a distributed query has no results, the JSON schema is
// inconsistent, so we use this shim and massage into a consistent
// schema. For example (simplified from actual osqueryd 1.8.2 output):
// {
2022-08-30 11:13:09 +00:00
//
// "queries": {
// "query_with_no_results": "", // <- Note string instead of array
// "query_with_results": [{"foo":"bar","baz":"bang"}]
// },
//
2022-03-07 18:10:55 +00:00
// "node_key":"IGXCXknWQ1baTa8TZ6rF3kAPZ4\/aTsui"
// }
type submitDistributedQueryResultsRequestShim struct {
NodeKey string ` json:"node_key" `
Results map [ string ] json . RawMessage ` json:"queries" `
Statuses map [ string ] interface { } ` json:"statuses" `
Messages map [ string ] string ` json:"messages" `
2023-12-13 20:46:59 +00:00
Stats map [ string ] * fleet . Stats ` json:"stats" `
2022-03-07 18:10:55 +00:00
}
2022-03-09 21:13:56 +00:00
func ( shim * submitDistributedQueryResultsRequestShim ) hostNodeKey ( ) string {
return shim . NodeKey
}
2022-03-07 18:10:55 +00:00
func ( shim * submitDistributedQueryResultsRequestShim ) toRequest ( ctx context . Context ) ( * SubmitDistributedQueryResultsRequest , error ) {
results := fleet . OsqueryDistributedQueryResults { }
for query , raw := range shim . Results {
queryResults := [ ] map [ string ] string { }
// No need to handle error because the empty array is what we
// want if there was an error parsing the JSON (the error
// indicates that osquery sent us incosistently schemaed JSON)
_ = json . Unmarshal ( raw , & queryResults )
results [ query ] = queryResults
}
// Statuses were represented by strings in osquery < 3.0 and now
// integers in osquery > 3.0. Massage to string for compatibility with
// the service definition.
statuses := map [ string ] fleet . OsqueryStatus { }
for query , status := range shim . Statuses {
switch s := status . ( type ) {
case string :
sint , err := strconv . Atoi ( s )
if err != nil {
return nil , ctxerr . Wrap ( ctx , err , "parse status to int" )
}
statuses [ query ] = fleet . OsqueryStatus ( sint )
case float64 :
statuses [ query ] = fleet . OsqueryStatus ( s )
default :
return nil , ctxerr . Errorf ( ctx , "query status should be string or number, got %T" , s )
}
}
return & SubmitDistributedQueryResultsRequest {
NodeKey : shim . NodeKey ,
Results : results ,
Statuses : statuses ,
Messages : shim . Messages ,
2023-12-13 20:46:59 +00:00
Stats : shim . Stats ,
2022-03-07 18:10:55 +00:00
} , nil
}
type SubmitDistributedQueryResultsRequest struct {
NodeKey string ` json:"node_key" `
Results fleet . OsqueryDistributedQueryResults ` json:"queries" `
Statuses map [ string ] fleet . OsqueryStatus ` json:"statuses" `
Messages map [ string ] string ` json:"messages" `
2023-12-13 20:46:59 +00:00
Stats map [ string ] * fleet . Stats ` json:"stats" `
2022-03-07 18:10:55 +00:00
}
type submitDistributedQueryResultsResponse struct {
Err error ` json:"error,omitempty" `
}
func ( r submitDistributedQueryResultsResponse ) error ( ) error { return r . Err }
2022-12-27 14:26:59 +00:00
func submitDistributedQueryResultsEndpoint ( ctx context . Context , request interface { } , svc fleet . Service ) ( errorer , error ) {
2022-03-07 18:10:55 +00:00
shim := request . ( * submitDistributedQueryResultsRequestShim )
req , err := shim . toRequest ( ctx )
if err != nil {
return submitDistributedQueryResultsResponse { Err : err } , nil
}
2023-12-13 20:46:59 +00:00
err = svc . SubmitDistributedQueryResults ( ctx , req . Results , req . Statuses , req . Messages , req . Stats )
2022-03-07 18:10:55 +00:00
if err != nil {
return submitDistributedQueryResultsResponse { Err : err } , nil
}
return submitDistributedQueryResultsResponse { } , nil
}
const (
// hostLabelQueryPrefix is appended before the query name when a query is
// provided as a label query. This allows the results to be retrieved when
// osqueryd writes the distributed query results.
hostLabelQueryPrefix = "fleet_label_query_"
// hostDetailQueryPrefix is appended before the query name when a query is
// provided as a detail query.
hostDetailQueryPrefix = "fleet_detail_query_"
// hostAdditionalQueryPrefix is appended before the query name when a query is
// provided as an additional query (additional info for hosts to retrieve).
hostAdditionalQueryPrefix = "fleet_additional_query_"
// hostPolicyQueryPrefix is appended before the query name when a query is
// provided as a policy query. This allows the results to be retrieved when
// osqueryd writes the distributed query results.
hostPolicyQueryPrefix = "fleet_policy_query_"
2023-08-31 13:58:50 +00:00
// hostNoPoliciesWildcard is a query sent to hosts when it's time to run policy
// queries on a host, but such host does not have any policies assigned.
// When Fleet receives results from such query then it will update the host's
// policy_updated_at column.
//
// This is used to prevent hosts without policies assigned to continuously
// perform lookups in the policies table on every check in.
hostNoPoliciesWildcard = "fleet_no_policies_wildcard"
2022-03-07 18:10:55 +00:00
// hostDistributedQueryPrefix is appended before the query name when a query is
// run from a distributed query campaign
hostDistributedQueryPrefix = "fleet_distributed_query_"
)
func ( svc * Service ) SubmitDistributedQueryResults (
ctx context . Context ,
results fleet . OsqueryDistributedQueryResults ,
statuses map [ string ] fleet . OsqueryStatus ,
messages map [ string ] string ,
2023-12-13 20:46:59 +00:00
stats map [ string ] * fleet . Stats ,
2022-03-07 18:10:55 +00:00
) error {
// skipauth: Authorization is currently for user endpoints only.
svc . authz . SkipAuthorization ( ctx )
host , ok := hostctx . FromContext ( ctx )
if ! ok {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( "internal error: missing host from request context" )
2022-03-07 18:10:55 +00:00
}
detailUpdated := false
additionalResults := make ( fleet . OsqueryDistributedQueryResults )
additionalUpdated := false
labelResults := map [ uint ] * bool { }
policyResults := map [ uint ] * bool { }
2023-05-17 19:52:45 +00:00
refetchCriticalSet := host . RefetchCriticalQueriesUntil != nil
2022-03-07 18:10:55 +00:00
2023-12-13 20:46:59 +00:00
svc . maybeDebugHost ( ctx , host , results , statuses , messages , stats )
2022-03-07 18:10:55 +00:00
2024-09-16 16:01:21 +00:00
preProcessSoftwareResults ( host , & results , & statuses , & messages , osquery_utils . SoftwareOverrideQueries , svc . logger )
2024-03-14 19:33:12 +00:00
2023-08-31 13:58:50 +00:00
var hostWithoutPolicies bool
2022-03-07 18:10:55 +00:00
for query , rows := range results {
2023-08-31 13:58:50 +00:00
// When receiving this query in the results, we will update the host's
// policy_updated_at column.
if query == hostNoPoliciesWildcard {
hostWithoutPolicies = true
continue
}
2022-03-07 18:10:55 +00:00
// osquery docs say any nonzero (string) value for status indicates a query error
status , ok := statuses [ query ]
failed := ok && status != fleet . StatusOK
if failed && messages [ query ] != "" && ! noSuchTableRegexp . MatchString ( messages [ query ] ) {
2022-10-27 16:17:14 +00:00
ll := level . Debug ( svc . logger )
// We'd like to log these as error for troubleshooting and improving of distributed queries.
if messages [ query ] == "distributed query is denylisted" {
ll = level . Error ( svc . logger )
}
ll . Log ( "query" , query , "message" , messages [ query ] , "hostID" , host . ID )
2022-03-07 18:10:55 +00:00
}
2024-10-29 19:17:51 +00:00
queryStats := stats [ query ]
2022-03-07 18:10:55 +00:00
2022-12-21 20:37:40 +00:00
ingestedDetailUpdated , ingestedAdditionalUpdated , err := svc . ingestQueryResults (
2023-12-13 20:46:59 +00:00
ctx , query , host , rows , failed , messages , policyResults , labelResults , additionalResults , queryStats ,
2022-12-21 20:37:40 +00:00
)
2022-03-07 18:10:55 +00:00
if err != nil {
logging . WithErr ( ctx , ctxerr . New ( ctx , "error in query ingestion" ) )
logging . WithExtras ( ctx , "ingestion-err" , err )
}
2022-12-21 20:37:40 +00:00
detailUpdated = detailUpdated || ingestedDetailUpdated
additionalUpdated = additionalUpdated || ingestedAdditionalUpdated
2022-03-07 18:10:55 +00:00
}
ac , err := svc . ds . AppConfig ( ctx )
if err != nil {
return ctxerr . Wrap ( ctx , err , "getting app config" )
}
if len ( labelResults ) > 0 {
if err := svc . task . RecordLabelQueryExecutions ( ctx , host , labelResults , svc . clock . Now ( ) , ac . ServerSettings . DeferredSaveHost ) ; err != nil {
logging . WithErr ( ctx , err )
}
}
if len ( policyResults ) > 0 {
2022-03-21 19:16:47 +00:00
2024-03-19 16:05:48 +00:00
if err := processCalendarPolicies ( ctx , svc . ds , ac , host , policyResults , svc . logger ) ; err != nil {
logging . WithErr ( ctx , err )
}
2024-08-30 21:58:20 +00:00
if err := svc . processSoftwareForNewlyFailingPolicies ( ctx , host . ID , host . TeamID , host . Platform , host . OrbitNodeKey , policyResults ) ; err != nil {
2024-08-30 17:13:25 +00:00
logging . WithErr ( ctx , err )
}
2024-10-04 01:03:40 +00:00
if err := svc . processScriptsForNewlyFailingPolicies ( ctx , host . ID , host . TeamID , host . Platform , host . OrbitNodeKey , host . ScriptsEnabled , policyResults ) ; err != nil {
logging . WithErr ( ctx , err )
}
2022-03-21 19:16:47 +00:00
// filter policy results for webhooks
var policyIDs [ ] uint
2024-01-18 16:15:07 +00:00
if globalPolicyAutomationsEnabled ( ac . WebhookSettings , ac . Integrations ) {
2022-03-21 19:16:47 +00:00
policyIDs = append ( policyIDs , ac . WebhookSettings . FailingPoliciesWebhook . PolicyIDs ... )
}
if host . TeamID != nil {
team , err := svc . ds . Team ( ctx , * host . TeamID )
if err != nil {
logging . WithErr ( ctx , err )
2024-10-18 17:38:26 +00:00
} else if teamPolicyAutomationsEnabled ( team . Config . WebhookSettings , team . Config . Integrations ) {
policyIDs = append ( policyIDs , team . Config . WebhookSettings . FailingPoliciesWebhook . PolicyIDs ... )
2022-03-21 19:16:47 +00:00
}
}
filteredResults := filterPolicyResults ( policyResults , policyIDs )
if len ( filteredResults ) > 0 {
if failingPolicies , passingPolicies , err := svc . ds . FlippingPoliciesForHost ( ctx , host . ID , filteredResults ) ; err != nil {
2022-03-07 18:10:55 +00:00
logging . WithErr ( ctx , err )
} else {
// Register the flipped policies on a goroutine to not block the hosts on redis requests.
go func ( ) {
2022-10-08 12:57:46 +00:00
if err := svc . registerFlippedPolicies ( ctx , host . ID , host . Hostname , host . DisplayName ( ) , failingPolicies , passingPolicies ) ; err != nil {
2022-03-07 18:10:55 +00:00
logging . WithErr ( ctx , err )
}
} ( )
}
}
2024-08-30 17:13:25 +00:00
2022-03-07 18:10:55 +00:00
// NOTE(mna): currently, failing policies webhook wouldn't see the new
// flipped policies on the next run if async processing is enabled and the
// collection has not been done yet (not persisted in mysql). Should
// FlippingPoliciesForHost take pending redis data into consideration, or
// maybe we should impose restrictions between async collection interval
// and policy update interval?
if err := svc . task . RecordPolicyQueryExecutions ( ctx , host , policyResults , svc . clock . Now ( ) , ac . ServerSettings . DeferredSaveHost ) ; err != nil {
logging . WithErr ( ctx , err )
}
2024-10-18 17:38:26 +00:00
} else if hostWithoutPolicies {
// RecordPolicyQueryExecutions called with results=nil will still update the host's policy_updated_at column.
if err := svc . task . RecordPolicyQueryExecutions ( ctx , host , nil , svc . clock . Now ( ) , ac . ServerSettings . DeferredSaveHost ) ; err != nil {
logging . WithErr ( ctx , err )
2023-08-31 13:58:50 +00:00
}
2022-03-07 18:10:55 +00:00
}
if additionalUpdated {
additionalJSON , err := json . Marshal ( additionalResults )
if err != nil {
logging . WithErr ( ctx , err )
} else {
additional := json . RawMessage ( additionalJSON )
if err := svc . ds . SaveHostAdditional ( ctx , host . ID , & additional ) ; err != nil {
logging . WithErr ( ctx , err )
}
}
}
if detailUpdated {
host . DetailUpdatedAt = svc . clock . Now ( )
}
refetchRequested := host . RefetchRequested
if refetchRequested {
host . RefetchRequested = false
}
2023-05-17 19:52:45 +00:00
refetchCriticalCleared := refetchCriticalSet && host . RefetchCriticalQueriesUntil == nil
2024-02-06 22:53:43 +00:00
if refetchCriticalSet {
level . Debug ( svc . logger ) . Log ( "msg" , "refetch critical status on submit distributed query results" , "host_id" , host . ID , "refetch_requested" , refetchRequested , "refetch_critical_queries_until" , host . RefetchCriticalQueriesUntil , "refetch_critical_cleared" , refetchCriticalCleared )
}
2022-03-07 18:10:55 +00:00
2023-05-17 19:52:45 +00:00
if refetchRequested || detailUpdated || refetchCriticalCleared {
2022-03-07 18:10:55 +00:00
appConfig , err := svc . ds . AppConfig ( ctx )
if err != nil {
logging . WithErr ( ctx , err )
} else {
if appConfig . ServerSettings . DeferredSaveHost {
go svc . serialUpdateHost ( host )
} else {
if err := svc . ds . UpdateHost ( ctx , host ) ; err != nil {
logging . WithErr ( ctx , err )
}
}
}
}
return nil
}
2024-03-19 16:05:48 +00:00
func processCalendarPolicies (
ctx context . Context ,
ds fleet . Datastore ,
appConfig * fleet . AppConfig ,
host * fleet . Host ,
policyResults map [ uint ] * bool ,
logger log . Logger ,
) error {
if len ( appConfig . Integrations . GoogleCalendar ) == 0 || host . TeamID == nil {
return nil
}
team , err := ds . Team ( ctx , * host . TeamID )
if err != nil {
return ctxerr . Wrap ( ctx , err , "load host team" )
}
if team . Config . Integrations . GoogleCalendar == nil || ! team . Config . Integrations . GoogleCalendar . Enable {
return nil
}
hostCalendarEvent , calendarEvent , err := ds . GetHostCalendarEvent ( ctx , host . ID )
switch {
case err == nil :
if hostCalendarEvent . WebhookStatus != fleet . CalendarWebhookStatusPending {
return nil
}
case fleet . IsNotFound ( err ) :
return nil
default :
return ctxerr . Wrap ( ctx , err , "get host calendar event" )
}
now := time . Now ( )
if now . Before ( calendarEvent . StartTime ) {
level . Warn ( logger ) . Log ( "msg" , "results came too early" , "now" , now , "start_time" , calendarEvent . StartTime )
2024-04-02 21:03:51 +00:00
if err = ds . UpdateHostCalendarWebhookStatus ( context . Background ( ) , host . ID , fleet . CalendarWebhookStatusError ) ; err != nil {
level . Error ( logger ) . Log ( "msg" , "mark webhook as errored early" , "err" , err )
}
2024-03-19 16:05:48 +00:00
return nil
}
//
// TODO(lucas): Discuss.
//
2024-04-02 21:03:51 +00:00
const allowedTimeRelativeToEndTime = 5 * time . Minute // up to 5 minutes after the end_time to allow for short (0-time) event times
2024-03-19 16:05:48 +00:00
2024-04-02 21:03:51 +00:00
if now . After ( calendarEvent . EndTime . Add ( allowedTimeRelativeToEndTime ) ) {
2024-03-19 16:05:48 +00:00
level . Warn ( logger ) . Log ( "msg" , "results came too late" , "now" , now , "end_time" , calendarEvent . EndTime )
2024-04-02 21:03:51 +00:00
if err = ds . UpdateHostCalendarWebhookStatus ( context . Background ( ) , host . ID , fleet . CalendarWebhookStatusError ) ; err != nil {
level . Error ( logger ) . Log ( "msg" , "mark webhook as errored late" , "err" , err )
}
2024-03-19 16:05:48 +00:00
return nil
}
calendarPolicies , err := ds . GetCalendarPolicies ( ctx , * host . TeamID )
if err != nil {
return ctxerr . Wrap ( ctx , err , "get calendar policy ids" )
}
if len ( calendarPolicies ) == 0 {
return nil
}
failingCalendarPolicies := getFailingCalendarPolicies ( policyResults , calendarPolicies )
if len ( failingCalendarPolicies ) == 0 {
return nil
}
go func ( ) {
2024-04-05 17:44:56 +00:00
retryStrategy := backoff . NewExponentialBackOff ( )
retryStrategy . MaxElapsedTime = 30 * time . Minute
err := backoff . Retry (
func ( ) error {
if err := fleet . FireCalendarWebhook (
team . Config . Integrations . GoogleCalendar . WebhookURL ,
host . ID , host . HardwareSerial , host . DisplayName ( ) , failingCalendarPolicies , "" ,
) ; err != nil {
var statusCoder kithttp . StatusCoder
if errors . As ( err , & statusCoder ) && statusCoder . StatusCode ( ) == http . StatusTooManyRequests {
level . Debug ( logger ) . Log ( "msg" , "fire webhook" , "err" , err )
if err := ds . UpdateHostCalendarWebhookStatus (
context . Background ( ) , host . ID , fleet . CalendarWebhookStatusRetry ,
) ; err != nil {
level . Error ( logger ) . Log ( "msg" , "mark fired webhook as retry" , "err" , err )
}
return err
}
return backoff . Permanent ( err )
}
return nil
} , retryStrategy ,
)
nextStatus := fleet . CalendarWebhookStatusSent
if err != nil {
2024-03-19 16:05:48 +00:00
level . Error ( logger ) . Log ( "msg" , "fire webhook" , "err" , err )
2024-04-05 17:44:56 +00:00
nextStatus = fleet . CalendarWebhookStatusError
2024-03-19 16:05:48 +00:00
}
2024-04-05 17:44:56 +00:00
if err := ds . UpdateHostCalendarWebhookStatus ( context . Background ( ) , host . ID , nextStatus ) ; err != nil {
level . Error ( logger ) . Log ( "msg" , fmt . Sprintf ( "mark fired webhook as %v" , nextStatus ) , "err" , err )
2024-03-19 16:05:48 +00:00
}
} ( )
return nil
}
func getFailingCalendarPolicies ( policyResults map [ uint ] * bool , calendarPolicies [ ] fleet . PolicyCalendarData ) [ ] fleet . PolicyCalendarData {
var failingPolicies [ ] fleet . PolicyCalendarData
for _ , calendarPolicy := range calendarPolicies {
result , ok := policyResults [ calendarPolicy . ID ]
if ! ok || // ignore result of a policy that's not configured for calendar.
result == nil { // ignore policies that failed to execute.
continue
}
if ! * result {
failingPolicies = append ( failingPolicies , calendarPolicy )
}
}
return failingPolicies
}
2024-03-14 19:33:12 +00:00
// preProcessSoftwareResults will run pre-processing on the responses of the software queries.
// It will move the results from the software extra queries (e.g. software_vscode_extensions)
2024-05-30 16:10:16 +00:00
// into the main software query results (software_{macos|linux|windows}) as well as process
// any overrides that are set.
2024-03-14 19:33:12 +00:00
// We do this to not grow the main software queries and to ingest
// all software together (one direct ingest function for all software).
func preProcessSoftwareResults (
2024-09-16 16:01:21 +00:00
host * fleet . Host ,
2024-03-14 19:33:12 +00:00
results * fleet . OsqueryDistributedQueryResults ,
statuses * map [ string ] fleet . OsqueryStatus ,
messages * map [ string ] string ,
2024-05-30 16:10:16 +00:00
overrides map [ string ] osquery_utils . DetailQuery ,
2024-03-14 19:33:12 +00:00
logger log . Logger ,
) {
vsCodeExtensionsExtraQuery := hostDetailQueryPrefix + "software_vscode_extensions"
2024-09-16 16:01:21 +00:00
preProcessSoftwareExtraResults ( vsCodeExtensionsExtraQuery , host . ID , results , statuses , messages , osquery_utils . DetailQuery { } , logger )
2024-05-30 16:10:16 +00:00
for name , query := range overrides {
fullQueryName := hostDetailQueryPrefix + "software_" + name
2024-09-16 16:01:21 +00:00
preProcessSoftwareExtraResults ( fullQueryName , host . ID , results , statuses , messages , query , logger )
}
2024-10-29 16:16:09 +00:00
// Filter out python packages that are also deb packages on ubuntu/debian
2024-09-16 16:01:21 +00:00
pythonPackageFilter ( host . Platform , results , statuses )
}
2024-10-29 16:16:09 +00:00
// pythonPackageFilter filters out duplicate python_packages that are installed under deb_packages on Ubuntu and Debian.
2024-09-16 16:01:21 +00:00
// python_packages not matching a Debian package names are updated to "python3-packagename" to match OVAL definitions.
func pythonPackageFilter ( platform string , results * fleet . OsqueryDistributedQueryResults , statuses * map [ string ] fleet . OsqueryStatus ) {
const pythonPrefix = "python3-"
const pythonSource = "python_packages"
const debSource = "deb_packages"
const linuxSoftware = hostDetailQueryPrefix + "software_linux"
2024-10-29 16:16:09 +00:00
// Return early if platform is not Ubuntu or Debian
2024-09-16 16:01:21 +00:00
// We may need to add more platforms in the future
2024-10-29 16:16:09 +00:00
if platform != "ubuntu" && platform != "debian" {
2024-09-16 16:01:21 +00:00
return
}
// Check the 'software_linux' result and status
sw , ok := ( * results ) [ linuxSoftware ]
if ! ok {
return
}
if status , ok := ( * statuses ) [ linuxSoftware ] ; ! ok || status != fleet . StatusOK {
return
}
// Extract the Python and Debian packages from the software list for filtering
// pre-allocating space for 40 packages based on number of package found in
// a fresh ubuntu 24.04 install
pythonPackages := make ( map [ string ] int , 40 )
debPackages := make ( map [ string ] struct { } , 40 )
// Track indexes of rows to remove
indexesToRemove := [ ] int { }
for i , row := range sw {
switch row [ "source" ] {
case pythonSource :
loweredName := strings . ToLower ( row [ "name" ] )
pythonPackages [ loweredName ] = i
row [ "name" ] = loweredName
case debSource :
// Only append python3 deb packages
if strings . HasPrefix ( row [ "name" ] , pythonPrefix ) {
debPackages [ row [ "name" ] ] = struct { } { }
}
}
}
// Return early if there are no Python packages to process
if len ( pythonPackages ) == 0 {
return
}
// Loop through pythonPackages map to identify any that should be removed
for name , index := range pythonPackages {
convertedName := pythonPrefix + name
// Filter out Python packages that are also Debian packages
if _ , found := debPackages [ convertedName ] ; found {
indexesToRemove = append ( indexesToRemove , index )
} else {
// Update remaining Python package names to match OVAL definitions
sw [ index ] [ "name" ] = convertedName
}
}
// Sort indexes to remove in descending order
sort . Sort ( sort . Reverse ( sort . IntSlice ( indexesToRemove ) ) )
// Remove rows from sw in descending order of indexes
for _ , index := range indexesToRemove {
sw = append ( sw [ : index ] , sw [ index + 1 : ] ... )
2024-05-30 16:10:16 +00:00
}
2024-09-16 16:01:21 +00:00
// Store the updated software result back in the results map
( * results ) [ linuxSoftware ] = sw
2024-03-14 19:33:12 +00:00
}
func preProcessSoftwareExtraResults (
softwareExtraQuery string ,
hostID uint ,
results * fleet . OsqueryDistributedQueryResults ,
statuses * map [ string ] fleet . OsqueryStatus ,
messages * map [ string ] string ,
2024-05-30 16:10:16 +00:00
override osquery_utils . DetailQuery ,
2024-03-14 19:33:12 +00:00
logger log . Logger ,
) {
// We always remove the extra query and its results
// in case the main or extra software query failed to execute.
defer delete ( * results , softwareExtraQuery )
status , ok := ( * statuses ) [ softwareExtraQuery ]
if ! ok {
return // query did not execute, e.g. the table does not exist.
}
failed := status != fleet . StatusOK
if failed {
// extra query executed but with errors, so we return without changing anything.
level . Error ( logger ) . Log (
"query" , softwareExtraQuery ,
"message" , ( * messages ) [ softwareExtraQuery ] ,
"hostID" , hostID ,
)
return
}
// Extract the results of the extra query.
2024-10-29 19:17:51 +00:00
softwareExtraRows := ( * results ) [ softwareExtraQuery ]
2024-03-14 19:33:12 +00:00
if len ( softwareExtraRows ) == 0 {
return
}
// Append the results of the extra query to the main query.
for _ , query := range [ ] string {
// Only one of these execute in each host.
hostDetailQueryPrefix + "software_macos" ,
hostDetailQueryPrefix + "software_windows" ,
hostDetailQueryPrefix + "software_linux" ,
} {
if _ , ok := ( * results ) [ query ] ; ! ok {
continue
}
if status , ok := ( * statuses ) [ query ] ; ok && status != fleet . StatusOK {
// Do not append results if the main query failed to run.
continue
}
Add `team_identifier` to macOS software (#23766)
Changes to add `team_identifier` signing information to macOS
applications on the `/api/latest/fleet/hosts/:id/software` API endpoint.
Docs: https://github.com/fleetdm/fleet/pull/23743
- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/Committing-Changes.md#changes-files)
for more information.
- [X] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
- [X] Added/updated tests
- [X] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes
- [X] If database migrations are included, checked table schema to
confirm autoupdate
- For database migrations:
- [X] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [X] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [ X Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Orbit runs on macOS, Linux and Windows. Check if the orbit
feature/bugfix should only apply to one platform (`runtime.GOOS`).
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- [X] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).
---------
Co-authored-by: Tim Lee <timlee@fleetdm.com>
Co-authored-by: Ian Littman <iansltx@gmail.com>
2024-11-15 17:17:04 +00:00
if override . SoftwareProcessResults != nil {
( * results ) [ query ] = override . SoftwareProcessResults ( ( * results ) [ query ] , softwareExtraRows )
} else {
( * results ) [ query ] = removeOverrides ( ( * results ) [ query ] , override )
( * results ) [ query ] = append ( ( * results ) [ query ] , softwareExtraRows ... )
}
2024-03-14 19:33:12 +00:00
return
}
}
2024-05-30 16:10:16 +00:00
func removeOverrides ( rows [ ] map [ string ] string , override osquery_utils . DetailQuery ) [ ] map [ string ] string {
if override . SoftwareOverrideMatch != nil {
rows = slices . DeleteFunc ( rows , func ( row map [ string ] string ) bool {
return override . SoftwareOverrideMatch ( row )
} )
}
return rows
}
2024-01-18 16:15:07 +00:00
// globalPolicyAutomationsEnabled returns true if any of the global policy automations are enabled.
// globalPolicyAutomationsEnabled and teamPolicyAutomationsEnabled are effectively identical.
// We could not use Go generics because Go generics does not support accessing common struct fields right now.
// The umbrella Go issue tracking this: https://github.com/golang/go/issues/63940
func globalPolicyAutomationsEnabled ( webhookSettings fleet . WebhookSettings , integrations fleet . Integrations ) bool {
if webhookSettings . FailingPoliciesWebhook . Enable {
return true
}
for _ , j := range integrations . Jira {
if j . EnableFailingPolicies {
return true
}
}
for _ , z := range integrations . Zendesk {
if z . EnableFailingPolicies {
return true
}
}
return false
}
func teamPolicyAutomationsEnabled ( webhookSettings fleet . TeamWebhookSettings , integrations fleet . TeamIntegrations ) bool {
if webhookSettings . FailingPoliciesWebhook . Enable {
return true
}
for _ , j := range integrations . Jira {
if j . EnableFailingPolicies {
return true
}
}
for _ , z := range integrations . Zendesk {
if z . EnableFailingPolicies {
return true
}
}
return false
}
2022-12-21 20:37:40 +00:00
func ( svc * Service ) ingestQueryResults (
ctx context . Context ,
query string ,
host * fleet . Host ,
rows [ ] map [ string ] string ,
failed bool ,
messages map [ string ] string ,
policyResults map [ uint ] * bool ,
labelResults map [ uint ] * bool ,
additionalResults fleet . OsqueryDistributedQueryResults ,
2023-12-13 20:46:59 +00:00
stats * fleet . Stats ,
2022-12-21 20:37:40 +00:00
) ( bool , bool , error ) {
var detailUpdated , additionalUpdated bool
// live queries we do want to ingest even if the query had issues, because we want to inform the user of these
// issues
// same applies to policies, since it's a 3 state result, one of them being failure, and labels take this state
// into account as well
var err error
switch {
case strings . HasPrefix ( query , hostDistributedQueryPrefix ) :
2023-12-13 20:46:59 +00:00
err = svc . ingestDistributedQuery ( ctx , * host , query , rows , messages [ query ] , stats )
2022-12-21 20:37:40 +00:00
case strings . HasPrefix ( query , hostPolicyQueryPrefix ) :
err = ingestMembershipQuery ( hostPolicyQueryPrefix , query , rows , policyResults , failed )
case strings . HasPrefix ( query , hostLabelQueryPrefix ) :
err = ingestMembershipQuery ( hostLabelQueryPrefix , query , rows , labelResults , failed )
}
if failed {
// if a query failed, and it might be a detailed query or host additional, don't even try to ingest it
return false , false , err
}
switch {
case strings . HasPrefix ( query , hostDetailQueryPrefix ) :
trimmedQuery := strings . TrimPrefix ( query , hostDetailQueryPrefix )
var ingested bool
ingested , err = svc . directIngestDetailQuery ( ctx , host , trimmedQuery , rows )
if ! ingested && err == nil {
err = svc . ingestDetailQuery ( ctx , host , trimmedQuery , rows )
// No err != nil check here because ingestDetailQuery could have updated
// successfully some values of host.
detailUpdated = true
}
case strings . HasPrefix ( query , hostAdditionalQueryPrefix ) :
name := strings . TrimPrefix ( query , hostAdditionalQueryPrefix )
additionalResults [ name ] = rows
additionalUpdated = true
}
return detailUpdated , additionalUpdated , err
}
2022-03-07 18:10:55 +00:00
var noSuchTableRegexp = regexp . MustCompile ( ` ^no such table: \S+$ ` )
2022-12-21 20:37:40 +00:00
func ( svc * Service ) directIngestDetailQuery ( ctx context . Context , host * fleet . Host , name string , rows [ ] map [ string ] string ) ( ingested bool , err error ) {
2022-08-30 11:13:09 +00:00
features , err := svc . HostFeatures ( ctx , host )
2022-03-07 18:10:55 +00:00
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return false , newOsqueryError ( "ingest detail query: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
2023-02-08 14:49:42 +00:00
appConfig , err := svc . ds . AppConfig ( ctx )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return false , newOsqueryError ( "ingest detail query: " + err . Error ( ) )
2023-02-08 14:49:42 +00:00
}
detailQueries := osquery_utils . GetDetailQueries ( ctx , svc . config , appConfig , features )
2022-03-07 18:10:55 +00:00
query , ok := detailQueries [ name ]
if ! ok {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return false , newOsqueryError ( "unknown detail query " + name )
2022-03-07 18:10:55 +00:00
}
if query . DirectIngestFunc != nil {
2022-12-21 20:37:40 +00:00
err = query . DirectIngestFunc ( ctx , svc . logger , host , svc . ds , rows )
2022-03-07 18:10:55 +00:00
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return false , newOsqueryError ( fmt . Sprintf ( "ingesting query %s: %s" , name , err . Error ( ) ) )
2022-03-07 18:10:55 +00:00
}
return true , nil
2022-08-10 14:01:05 +00:00
} else if query . DirectTaskIngestFunc != nil {
2022-12-21 20:37:40 +00:00
err = query . DirectTaskIngestFunc ( ctx , svc . logger , host , svc . task , rows )
2022-08-10 14:01:05 +00:00
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return false , newOsqueryError ( fmt . Sprintf ( "ingesting query %s: %s" , name , err . Error ( ) ) )
2022-08-10 14:01:05 +00:00
}
return true , nil
2022-03-07 18:10:55 +00:00
}
return false , nil
}
// ingestDistributedQuery takes the results of a distributed query and modifies the
// provided fleet.Host appropriately.
2023-12-13 20:46:59 +00:00
func ( svc * Service ) ingestDistributedQuery (
ctx context . Context , host fleet . Host , name string , rows [ ] map [ string ] string , errMsg string , stats * fleet . Stats ,
) error {
2022-03-07 18:10:55 +00:00
trimmedQuery := strings . TrimPrefix ( name , hostDistributedQueryPrefix )
campaignID , err := strconv . Atoi ( osquery_utils . EmptyToZero ( trimmedQuery ) )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( "unable to parse campaign ID: " + trimmedQuery )
2022-03-07 18:10:55 +00:00
}
// Write the results to the pubsub store
res := fleet . DistributedQueryResult {
2024-10-18 17:38:26 +00:00
DistributedQueryCampaignID : uint ( campaignID ) , //nolint:gosec // dismiss G115
Reduce size of `DistributedQueryResult` to improve live query performance (#11882)
This was found while working on #10957.
When running a live query, a lot of unused host data is stored in Redis
and sent on every live query result message via websockets. The frontend
and fleetctl just need `id`, `hostname` and `display_name`. (This
becomes worse every time we add new fields to the `Host` struct.)
Sample of one websocket message result when running `SELECT * from
osquery_info;`:
size in `main`: 2234 bytes
```
a["{\"type\":\"result\",\"data\":{\"distributed_query_execution_id\":57,\"host\":
{\"created_at\":\"2023-05-22T12:14:11Z\",\"updated_at\":\"2023-05-23T12:31:51Z\",
\"software_updated_at\":\"0001-01-01T00:00:00Z\",\"id\":106,\"detail_updated_at\":\"2023-05-23T11:50:04Z\",
\"label_updated_at\":\"2023-05-23T11:50:04Z\",\"policy_updated_at\":\"1970-01-02T00:00:00Z\",
\"last_enrolled_at\":\"2023-05-22T12:14:12Z\",
\"seen_time\":\"2023-05-23T09:52:23.876311-03:00\",\"refetch_requested\":false,
\"hostname\":\"lucass-macbook-pro.local\",\"uuid\":\"BD4DFA10-E334-41D9-8136-D2163A8FE588\",\"platform\":\"darwin\",\"osquery_version\":\"5.8.2\",\"os_version\":\"macOS 13.3.1\",\"build\":\"22E261\",\"platform_like\":\"darwin\",\"code_name\":\"\",
\"uptime\":91125000000000,\"memory\":34359738368,\"cpu_type\":\"x86_64h\",\"cpu_subtype\":\"Intel x86-64h Haswell\",\"cpu_brand\":\"Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz\",\"cpu_physical_cores\":4,\"cpu_logical_cores\":8,\"hardware_vendor\":\"Apple Inc.\",\"hardware_model\":\"MacBookPro16,2\",\"hardware_version\":\"1.0\",
\"hardware_serial\":\"0DPQR4HMD1FZ\",
\"computer_name\":\"Lucas’s MacBook Pro\",\"public_ip\":\"\",
\"primary_ip\":\"192.168.0.230\",\"primary_mac\":\"68:2f:67:8e:b6:1f\",
\"distributed_interval\":1,\"config_tls_refresh\":60,\"logger_tls_period\":10,\"team_id\":null,
\"pack_stats\":null,\"team_name\":null,
\"gigs_disk_space_available\":386.23,\"percent_disk_space_available\":40,
\"issues\":{\"total_issues_count\":0,\"failing_policies_count\":0},
\"mdm\":{\"enrollment_status\":null,\"server_url\":null,\"name\":\"\",\"encryption_key_available\":false},
\"status\":\"online\",\"display_text\":\"lucass-macbook-pro.local\",\"display_name\":\"Lucas’s MacBook Pro\"},
\"rows\":[{\"build_distro\":\"10.14\",\"build_platform\":\"darwin\",
\"config_hash\":\"b7ee9363a7c686e76e99ffb122e9c5241a791e69\",\"config_valid\":\"1\",
\"extensions\":\"active\",\"host_display_name\":\"Lucas’s MacBook Pro\",
\"host_hostname\":\"lucass-macbook-pro.local\",\"instance_id\":\"cde5de81-344b-4c76-b1c5-dae964fdd4f2\",\"pid\":\"8370\",\"platform_mask\":\"21\",\"start_time\":\"1684757652\",
\"uuid\":\"BD4DFA10-E334-41D9-8136-D2163A8FE588\",
\"version\":\"5.8.2\",\"watcher\":\"8364\"}],\"error\":null}}"]
```
vs. size of the message result on this branch: 675 bytes
```
a["{\"type\":\"result\",\"data\":{\"distributed_query_execution_id\":59,
\"host\":{\"id\":106,\"hostname\":\"lucass-macbook-pro.local\",
\"display_name\":\"Lucas’s MacBook Pro\"},
\"rows\":[{\"build_distro\":\"10.14\",\"build_platform\":\"darwin\",
\"config_hash\":\"f80dee827635db39077a458243379b3ad63311fd\",
\"config_valid\":\"1\",\"extensions\":\"active\",\"host_display_name\":\"Lucas’s MacBook Pro\",
\"host_hostname\":\"lucass-macbook-pro.local\",
\"instance_id\":\"cde5de81-344b-4c76-b1c5-dae964fdd4f2\",\"pid\":\"8370\",\"platform_mask\":\"21\",
\"start_time\":\"1684757652\",\"uuid\":\"BD4DFA10-E334-41D9-8136-D2163A8FE588\",\"version\":\"5.8.2\",
\"watcher\":\"8364\"}]}}"]
```
Manual tests included running with an old fleetctl running with a new
fleet server, and vice-versa, a new fleetctl running against an old
fleet server.
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- ~For Orbit and Fleet Desktop changes:~
- ~[ ] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.~
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-05-25 11:11:53 +00:00
Host : fleet . ResultHostData {
ID : host . ID ,
Hostname : host . Hostname ,
DisplayName : host . DisplayName ( ) ,
} ,
2023-12-13 20:46:59 +00:00
Rows : rows ,
Stats : stats ,
2022-03-07 18:10:55 +00:00
}
2023-09-19 14:06:29 +00:00
if errMsg != "" {
2022-03-07 18:10:55 +00:00
res . Error = & errMsg
}
err = svc . resultStore . WriteResult ( res )
if err != nil {
var pse pubsub . Error
ok := errors . As ( err , & pse )
if ! ok || ! pse . NoSubscriber ( ) {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( "writing results: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
// If there are no subscribers, the campaign is "orphaned"
// and should be closed so that we don't continue trying to
// execute that query when we can't write to any subscriber
2024-10-18 17:38:26 +00:00
campaign , err := svc . ds . DistributedQueryCampaign ( ctx , uint ( campaignID ) ) //nolint:gosec // dismiss G115
2022-03-07 18:10:55 +00:00
if err != nil {
if err := svc . liveQueryStore . StopQuery ( strconv . Itoa ( campaignID ) ) ; err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( "stop orphaned campaign after load failure: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( "loading orphaned campaign: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
if campaign . CreatedAt . After ( svc . clock . Now ( ) . Add ( - 1 * time . Minute ) ) {
// Give the client a minute to connect before considering the
2023-06-01 19:11:55 +00:00
// campaign orphaned.
//
// Live queries work in two stages (asynchronous):
// 1. The campaign is created by a client. So the target devices checking in
// will start receiving the query corresponding to the campaign.
// 2. The client (UI/fleetctl) starts listenting for query results.
//
// This expected error can happen if:
// A. A device checked in and sent results back in between steps (1) and (2).
// B. The client stopped listening in (2) and devices continue to send results back.
return newOsqueryError ( fmt . Sprintf ( "campaignID=%d waiting for listener" , campaignID ) )
2022-03-07 18:10:55 +00:00
}
if campaign . Status != fleet . QueryComplete {
campaign . Status = fleet . QueryComplete
if err := svc . ds . SaveDistributedQueryCampaign ( ctx , campaign ) ; err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( "closing orphaned campaign: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
}
if err := svc . liveQueryStore . StopQuery ( strconv . Itoa ( campaignID ) ) ; err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( "stopping orphaned campaign: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
// No need to record query completion in this case
2023-06-01 19:11:55 +00:00
return newOsqueryError ( fmt . Sprintf ( "campaignID=%d stopped" , campaignID ) )
2022-03-07 18:10:55 +00:00
}
err = svc . liveQueryStore . QueryCompletedByHost ( strconv . Itoa ( campaignID ) , host . ID )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( "record query completion: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
return nil
}
// ingestMembershipQuery records the results of label queries run by a host
func ingestMembershipQuery (
prefix string ,
query string ,
rows [ ] map [ string ] string ,
results map [ uint ] * bool ,
failed bool ,
) error {
trimmedQuery := strings . TrimPrefix ( query , prefix )
trimmedQueryNum , err := strconv . Atoi ( osquery_utils . EmptyToZero ( trimmedQuery ) )
if err != nil {
return fmt . Errorf ( "converting query from string to int: %w" , err )
}
// A label/policy query matches if there is at least one result for that
// query. We must also store negative results.
if failed {
2024-10-18 17:38:26 +00:00
results [ uint ( trimmedQueryNum ) ] = nil //nolint:gosec // dismiss G115
2022-03-07 18:10:55 +00:00
} else {
2024-10-18 17:38:26 +00:00
results [ uint ( trimmedQueryNum ) ] = ptr . Bool ( len ( rows ) > 0 ) //nolint:gosec // dismiss G115
2022-03-07 18:10:55 +00:00
}
return nil
}
// ingestDetailQuery takes the results of a detail query and modifies the
// provided fleet.Host appropriately.
func ( svc * Service ) ingestDetailQuery ( ctx context . Context , host * fleet . Host , name string , rows [ ] map [ string ] string ) error {
2022-08-30 11:13:09 +00:00
features , err := svc . HostFeatures ( ctx , host )
2022-03-07 18:10:55 +00:00
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( "ingest detail query: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
}
2023-02-08 14:49:42 +00:00
appConfig , err := svc . ds . AppConfig ( ctx )
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( "ingest detail query: " + err . Error ( ) )
2023-02-08 14:49:42 +00:00
}
detailQueries := osquery_utils . GetDetailQueries ( ctx , svc . config , appConfig , features )
2022-03-07 18:10:55 +00:00
query , ok := detailQueries [ name ]
if ! ok {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( "unknown detail query " + name )
2022-03-07 18:10:55 +00:00
}
if query . IngestFunc != nil {
2022-03-21 16:29:52 +00:00
err = query . IngestFunc ( ctx , svc . logger , host , rows )
2022-03-07 18:10:55 +00:00
if err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
return newOsqueryError ( fmt . Sprintf ( "ingesting query %s: %s" , name , err . Error ( ) ) )
2022-03-07 18:10:55 +00:00
}
}
return nil
}
// filterPolicyResults filters out policies that aren't configured for webhook automation.
func filterPolicyResults ( incoming map [ uint ] * bool , webhookPolicies [ ] uint ) map [ uint ] * bool {
wp := make ( map [ uint ] struct { } )
for _ , policyID := range webhookPolicies {
wp [ policyID ] = struct { } { }
}
filtered := make ( map [ uint ] * bool )
for policyID , passes := range incoming {
if _ , ok := wp [ policyID ] ; ! ok {
continue
}
filtered [ policyID ] = passes
}
return filtered
}
2022-10-08 12:57:46 +00:00
func ( svc * Service ) registerFlippedPolicies ( ctx context . Context , hostID uint , hostname , displayName string , newFailing , newPassing [ ] uint ) error {
2022-03-07 18:10:55 +00:00
host := fleet . PolicySetHost {
2022-10-08 12:57:46 +00:00
ID : hostID ,
Hostname : hostname ,
DisplayName : displayName ,
2022-03-07 18:10:55 +00:00
}
for _ , policyID := range newFailing {
if err := svc . failingPolicySet . AddHost ( policyID , host ) ; err != nil {
return err
}
}
for _ , policyID := range newPassing {
if err := svc . failingPolicySet . RemoveHosts ( policyID , [ ] fleet . PolicySetHost { host } ) ; err != nil {
return err
}
}
return nil
}
2024-08-30 17:13:25 +00:00
func ( svc * Service ) processSoftwareForNewlyFailingPolicies (
ctx context . Context ,
hostID uint ,
hostTeamID * uint ,
hostPlatform string ,
2024-08-30 21:58:20 +00:00
hostOrbitNodeKey * string ,
2024-08-30 17:13:25 +00:00
incomingPolicyResults map [ uint ] * bool ,
) error {
2024-08-30 21:58:20 +00:00
if hostOrbitNodeKey == nil || * hostOrbitNodeKey == "" {
// We do not want to queue software installations on vanilla osquery hosts.
return nil
}
2024-09-12 17:23:25 +00:00
var policyTeamID uint
2024-08-30 17:13:25 +00:00
if hostTeamID == nil {
2024-09-12 17:23:25 +00:00
policyTeamID = fleet . PolicyNoTeamID
} else {
policyTeamID = * hostTeamID
2024-08-30 17:13:25 +00:00
}
// Filter out results that are not failures (we are only interested on failing policies,
// we don't care about passing policies or policies that failed to execute).
incomingFailingPolicies := make ( map [ uint ] * bool )
var incomingFailingPoliciesIDs [ ] uint
for policyID , policyResult := range incomingPolicyResults {
if policyResult != nil && ! * policyResult {
incomingFailingPolicies [ policyID ] = policyResult
incomingFailingPoliciesIDs = append ( incomingFailingPoliciesIDs , policyID )
}
}
if len ( incomingFailingPolicies ) == 0 {
return nil
}
// Get policies with associated installers for the team.
2024-09-12 17:23:25 +00:00
policiesWithInstaller , err := svc . ds . GetPoliciesWithAssociatedInstaller ( ctx , policyTeamID , incomingFailingPoliciesIDs )
2024-08-30 17:13:25 +00:00
if err != nil {
return ctxerr . Wrap ( ctx , err , "failed to get policies with installer" )
}
if len ( policiesWithInstaller ) == 0 {
return nil
}
// Filter out results of policies that are not associated to installers.
policiesWithInstallersMap := make ( map [ uint ] fleet . PolicySoftwareInstallerData )
for _ , policyWithInstaller := range policiesWithInstaller {
policiesWithInstallersMap [ policyWithInstaller . ID ] = policyWithInstaller
}
policyResultsOfPoliciesWithInstallers := make ( map [ uint ] * bool )
for policyID , passes := range incomingFailingPolicies {
if _ , ok := policiesWithInstallersMap [ policyID ] ; ! ok {
continue
}
policyResultsOfPoliciesWithInstallers [ policyID ] = passes
}
if len ( policyResultsOfPoliciesWithInstallers ) == 0 {
return nil
}
// Get the policies associated with installers that are flipping from passing to failing on this host.
policyIDsOfNewlyFailingPoliciesWithInstallers , _ , err := svc . ds . FlippingPoliciesForHost (
ctx , hostID , policyResultsOfPoliciesWithInstallers ,
)
if err != nil {
return ctxerr . Wrap ( ctx , err , "failed to get flipping policies for host" )
}
if len ( policyIDsOfNewlyFailingPoliciesWithInstallers ) == 0 {
return nil
}
policyIDsOfNewlyFailingPoliciesWithInstallersSet := make ( map [ uint ] struct { } )
for _ , policyID := range policyIDsOfNewlyFailingPoliciesWithInstallers {
policyIDsOfNewlyFailingPoliciesWithInstallersSet [ policyID ] = struct { } { }
}
// Finally filter out policies with installers that are not newly failing.
var failingPoliciesWithInstaller [ ] fleet . PolicySoftwareInstallerData
for _ , policyWithInstaller := range policiesWithInstaller {
if _ , ok := policyIDsOfNewlyFailingPoliciesWithInstallersSet [ policyWithInstaller . ID ] ; ok {
failingPoliciesWithInstaller = append ( failingPoliciesWithInstaller , policyWithInstaller )
}
}
for _ , failingPolicyWithInstaller := range failingPoliciesWithInstaller {
2024-10-09 23:15:56 +00:00
policyID := failingPolicyWithInstaller . ID
2024-08-30 17:13:25 +00:00
installerMetadata , err := svc . ds . GetSoftwareInstallerMetadataByID ( ctx , failingPolicyWithInstaller . InstallerID )
if err != nil {
return ctxerr . Wrap ( ctx , err , "get software installer metadata by id" )
}
logger := log . With ( svc . logger ,
"host_id" , hostID ,
"host_platform" , hostPlatform ,
"policy_id" , failingPolicyWithInstaller . ID ,
"software_installer_id" , failingPolicyWithInstaller . InstallerID ,
"software_title_id" , installerMetadata . TitleID ,
"software_installer_platform" , installerMetadata . Platform ,
)
if fleet . PlatformFromHost ( hostPlatform ) != installerMetadata . Platform {
level . Debug ( logger ) . Log ( "msg" , "installer platform does not match host platform" )
continue
}
hostLastInstall , err := svc . ds . GetHostLastInstallData ( ctx , hostID , installerMetadata . InstallerID )
if err != nil {
return ctxerr . Wrap ( ctx , err , "get host last install data" )
}
// hostLastInstall.Status == nil can happen when a software is installed by Fleet and later removed.
if hostLastInstall != nil && hostLastInstall . Status != nil &&
2024-09-04 21:46:48 +00:00
* hostLastInstall . Status == fleet . SoftwareInstallPending {
2024-08-30 17:13:25 +00:00
// There's a pending install for this host and installer,
// thus we do not queue another install request.
level . Debug ( svc . logger ) . Log (
"msg" , "found pending install request for this host and installer" ,
"pending_execution_id" , hostLastInstall . ExecutionID ,
)
continue
}
// NOTE(lucas): The user_id set in this software install will be NULL
// so this means that when generating the activity for this action
2024-10-09 23:15:56 +00:00
// (in SaveHostSoftwareInstallResult) the author will be set to Fleet.
2024-08-30 17:13:25 +00:00
installUUID , err := svc . ds . InsertSoftwareInstallRequest (
ctx , hostID ,
installerMetadata . InstallerID ,
false , // Set Self-service as false because this is triggered by Fleet.
2024-10-09 23:15:56 +00:00
& policyID ,
2024-08-30 17:13:25 +00:00
)
if err != nil {
return ctxerr . Wrapf ( ctx , err ,
"insert software install request: host_id=%d, software_installer_id=%d" ,
hostID , installerMetadata . InstallerID ,
)
}
level . Debug ( logger ) . Log (
"msg" , "install request sent" ,
"install_uuid" , installUUID ,
)
}
return nil
}
2024-10-04 01:03:40 +00:00
func ( svc * Service ) processScriptsForNewlyFailingPolicies (
ctx context . Context ,
hostID uint ,
hostTeamID * uint ,
hostPlatform string ,
hostOrbitNodeKey * string ,
hostScriptsEnabled * bool ,
incomingPolicyResults map [ uint ] * bool ,
) error {
if hostOrbitNodeKey == nil || * hostOrbitNodeKey == "" {
return nil // vanilla osquery hosts can't run scripts
}
// not logging here to avoid spamming logs on every policy failure for every no-scripts host even if the policy
// doesn't have a script attached
if hostScriptsEnabled != nil && ! * hostScriptsEnabled {
return nil
}
// Bail if scripts are disabled globally
cfg , err := svc . ds . AppConfig ( ctx )
if err != nil {
return err
}
if cfg . ServerSettings . ScriptsDisabled {
return nil
}
var policyTeamID uint
if hostTeamID == nil {
policyTeamID = fleet . PolicyNoTeamID
} else {
policyTeamID = * hostTeamID
}
// Filter out results that are not failures (we are only interested on failing policies,
// we don't care about passing policies or policies that failed to execute).
incomingFailingPolicies := make ( map [ uint ] * bool )
var incomingFailingPoliciesIDs [ ] uint
for policyID , policyResult := range incomingPolicyResults {
if policyResult != nil && ! * policyResult {
incomingFailingPolicies [ policyID ] = policyResult
incomingFailingPoliciesIDs = append ( incomingFailingPoliciesIDs , policyID )
}
}
if len ( incomingFailingPolicies ) == 0 {
return nil
}
// Get policies with associated scripts for the team.
policiesWithScript , err := svc . ds . GetPoliciesWithAssociatedScript ( ctx , policyTeamID , incomingFailingPoliciesIDs )
if err != nil {
return ctxerr . Wrap ( ctx , err , "failed to get policies with script" )
}
if len ( policiesWithScript ) == 0 {
return nil
}
// Filter out results of policies that are not associated to scripts.
policiesWithScriptsMap := make ( map [ uint ] fleet . PolicyScriptData )
for _ , policyWithScript := range policiesWithScript {
policiesWithScriptsMap [ policyWithScript . ID ] = policyWithScript
}
policyResultsOfPoliciesWithScripts := make ( map [ uint ] * bool )
for policyID , passes := range incomingFailingPolicies {
if _ , ok := policiesWithScriptsMap [ policyID ] ; ! ok {
continue
}
policyResultsOfPoliciesWithScripts [ policyID ] = passes
}
if len ( policyResultsOfPoliciesWithScripts ) == 0 {
return nil
}
// Get the policies associated with scripts that are flipping from passing to failing on this host.
policyIDsOfNewlyFailingPoliciesWithScripts , _ , err := svc . ds . FlippingPoliciesForHost (
ctx , hostID , policyResultsOfPoliciesWithScripts ,
)
if err != nil {
return ctxerr . Wrap ( ctx , err , "failed to get flipping policies for host" )
}
if len ( policyIDsOfNewlyFailingPoliciesWithScripts ) == 0 {
return nil
}
policyIDsOfNewlyFailingPoliciesWithScriptsSet := make ( map [ uint ] struct { } )
for _ , policyID := range policyIDsOfNewlyFailingPoliciesWithScripts {
policyIDsOfNewlyFailingPoliciesWithScriptsSet [ policyID ] = struct { } { }
}
// Finally filter out policies with scripts that are not newly failing.
var failingPoliciesWithScript [ ] fleet . PolicyScriptData
for _ , policyWithScript := range policiesWithScript {
if _ , ok := policyIDsOfNewlyFailingPoliciesWithScriptsSet [ policyWithScript . ID ] ; ok {
failingPoliciesWithScript = append ( failingPoliciesWithScript , policyWithScript )
}
}
for _ , failingPolicyWithScript := range failingPoliciesWithScript {
2024-10-08 20:45:31 +00:00
policyID := failingPolicyWithScript . ID
2024-10-04 01:03:40 +00:00
scriptMetadata , err := svc . ds . Script ( ctx , failingPolicyWithScript . ScriptID )
if err != nil {
return ctxerr . Wrap ( ctx , err , "get script metadata by id" )
}
logger := log . With ( svc . logger ,
"host_id" , hostID ,
"host_platform" , hostPlatform ,
2024-10-08 20:45:31 +00:00
"policy_id" , policyID ,
2024-10-04 01:03:40 +00:00
"script_id" , failingPolicyWithScript . ScriptID ,
"script_name" , scriptMetadata . Name ,
)
allScriptsExecutionPending , err := svc . ds . ListPendingHostScriptExecutions ( ctx , hostID )
if err != nil {
return ctxerr . Wrap ( ctx , err , "list host pending script executions" )
}
if len ( allScriptsExecutionPending ) > maxPendingScripts {
level . Warn ( logger ) . Log ( "msg" , "too many scripts pending for host" )
return nil
}
// skip incompatible scripts
hostPlatform := fleet . PlatformFromHost ( hostPlatform )
if ( hostPlatform == "windows" && strings . HasSuffix ( scriptMetadata . Name , ".sh" ) ) ||
( hostPlatform != "windows" && strings . HasSuffix ( scriptMetadata . Name , ".ps1" ) ) {
level . Info ( logger ) . Log ( "msg" , "script type does not match host platform" )
continue
}
// skip different-team scripts
var scriptTeamID uint
if scriptMetadata . TeamID != nil {
scriptTeamID = * scriptMetadata . TeamID
}
if policyTeamID != scriptTeamID { // this should not happen
level . Error ( logger ) . Log ( "msg" , "script team does not match host team" )
continue
}
scriptIsAlreadyPending , err := svc . ds . IsExecutionPendingForHost ( ctx , hostID , scriptMetadata . ID )
if err != nil {
return ctxerr . Wrap ( ctx , err , "check whether script is pending execution" )
}
if scriptIsAlreadyPending {
level . Debug ( logger ) . Log ( "msg" , "script is already pending on host" )
continue
}
contents , err := svc . ds . GetScriptContents ( ctx , scriptMetadata . ID )
if err != nil {
return ctxerr . Wrap ( ctx , err , "get script contents" )
}
runScriptRequest := fleet . HostScriptRequestPayload {
HostID : hostID ,
ScriptContents : string ( contents ) ,
ScriptContentID : scriptMetadata . ScriptContentID ,
ScriptID : & scriptMetadata . ID ,
TeamID : policyTeamID ,
2024-10-08 20:45:31 +00:00
PolicyID : & policyID ,
2024-10-04 01:03:40 +00:00
// no user ID as scripts are executed by Fleet
}
scriptResult , err := svc . ds . NewHostScriptExecutionRequest ( ctx , & runScriptRequest )
if err != nil {
return ctxerr . Wrapf ( ctx , err ,
"insert script run request; host_id=%d, script_id=%d" ,
hostID , scriptMetadata . ID ,
)
}
level . Debug ( logger ) . Log (
"msg" , "script run request sent" ,
"execution_id" , scriptResult . ExecutionID ,
)
}
return nil
}
2022-03-07 18:10:55 +00:00
func ( svc * Service ) maybeDebugHost (
ctx context . Context ,
host * fleet . Host ,
results fleet . OsqueryDistributedQueryResults ,
statuses map [ string ] fleet . OsqueryStatus ,
messages map [ string ] string ,
2023-12-13 20:46:59 +00:00
stats map [ string ] * fleet . Stats ,
2022-03-07 18:10:55 +00:00
) {
if svc . debugEnabledForHost ( ctx , host . ID ) {
hlogger := log . With ( svc . logger , "host-id" , host . ID )
logJSON ( hlogger , host , "host" )
logJSON ( hlogger , results , "results" )
logJSON ( hlogger , statuses , "statuses" )
logJSON ( hlogger , messages , "messages" )
2023-12-13 20:46:59 +00:00
logJSON ( hlogger , stats , "stats" )
2022-03-07 18:10:55 +00:00
}
}
////////////////////////////////////////////////////////////////////////////////
// Submit Logs
////////////////////////////////////////////////////////////////////////////////
type submitLogsRequest struct {
NodeKey string ` json:"node_key" `
LogType string ` json:"log_type" `
Data json . RawMessage ` json:"data" `
}
2022-03-09 21:13:56 +00:00
func ( r * submitLogsRequest ) hostNodeKey ( ) string {
return r . NodeKey
}
2022-03-07 18:10:55 +00:00
type submitLogsResponse struct {
Err error ` json:"error,omitempty" `
}
func ( r submitLogsResponse ) error ( ) error { return r . Err }
2022-12-27 14:26:59 +00:00
func submitLogsEndpoint ( ctx context . Context , request interface { } , svc fleet . Service ) ( errorer , error ) {
2022-03-07 18:10:55 +00:00
req := request . ( * submitLogsRequest )
var err error
switch req . LogType {
case "status" :
var statuses [ ] json . RawMessage
2023-10-10 12:44:03 +00:00
// NOTE(lucas): This unmarshal error is not being sent back to osquery (`if err :=` vs. `if err =`)
// Maybe there's a reason for it, we need to test such a change before fixing what appears
// to be a bug because the `err` is lost.
2022-03-07 18:10:55 +00:00
if err := json . Unmarshal ( req . Data , & statuses ) ; err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
err = newOsqueryError ( "unmarshalling status logs: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
break
}
err = svc . SubmitStatusLogs ( ctx , statuses )
if err != nil {
break
}
case "result" :
var results [ ] json . RawMessage
2023-10-10 12:44:03 +00:00
// NOTE(lucas): This unmarshal error is not being sent back to osquery (`if err :=` vs. `if err =`)
// Maybe there's a reason for it, we need to test such a change before fixing what appears
// to be a bug because the `err` is lost.
2022-03-07 18:10:55 +00:00
if err := json . Unmarshal ( req . Data , & results ) ; err != nil {
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
err = newOsqueryError ( "unmarshalling result logs: " + err . Error ( ) )
2022-03-07 18:10:55 +00:00
break
}
2024-03-04 18:10:10 +00:00
logging . WithExtras ( ctx , "results" , len ( results ) )
2023-10-10 12:44:03 +00:00
2023-10-11 18:20:06 +00:00
// We currently return errors to osqueryd if there are any issues submitting results
// to the configured external destinations.
2023-10-10 12:44:03 +00:00
if err = svc . SubmitResultLogs ( ctx , results ) ; err != nil {
2022-03-07 18:10:55 +00:00
break
}
default :
Add UUID to Fleet errors and clean up error msgs (#10411)
#8129
Apart from fixing the issue in #8129, this change also introduces UUIDs
to Fleet errors. To be able to match a returned error from the API to a
error in the Fleet logs. See
https://fleetdm.slack.com/archives/C019WG4GH0A/p1677780622769939 for
more context.
Samples with the changes in this PR:
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d ''
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "Expected JSON Body"
}
],
"uuid": "a01f6e10-354c-4ff0-b96e-1f64adb500b0"
}
```
```
curl -k -H "Authorization: Bearer $TEST_TOKEN" -H 'Content-Type:application/json' "https://localhost:8080/api/v1/fleet/sso" -d 'asd'
{
"message": "Bad request",
"errors": [
{
"name": "base",
"reason": "json decoder error"
}
],
"uuid": "5f716a64-7550-464b-a1dd-e6a505a9f89d"
}
```
```
curl -k -X GET -H "Authorization: Bearer badtoken" "https://localhost:8080/api/latest/fleet/teams"
{
"message": "Authentication required",
"errors": [
{
"name": "base",
"reason": "Authentication required"
}
],
"uuid": "efe45bc0-f956-4bf9-ba4f-aa9020a9aaaf"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Authorization header required",
"errors": [
{
"name": "base",
"reason": "Authorization header required"
}
],
"uuid": "57f78cd0-4559-464f-9df7-36c9ef7c89b3"
}
```
```
curl -k -X PATCH -H "Authorization: Bearer $TEST_TOKEN" "https://localhost:8080/api/latest/fleet/users/14" -d '{"name": "Manuel2", "password": "what", "new_password": "p4ssw0rd.12345"}'
{
"message": "Permission Denied",
"uuid": "7f0220ad-6de7-4faf-8b6c-8d7ff9d2ca06"
}
```
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- ~[ ] Documented any permissions changes~
- ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)~
- ~[ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.~
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [X] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- ~[ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-03-13 16:44:06 +00:00
err = newOsqueryError ( "unknown log type: " + req . LogType )
2022-03-07 18:10:55 +00:00
}
return submitLogsResponse { Err : err } , nil
}
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
// preProcessOsqueryResults will attempt to unmarshal `osqueryResults` and will return:
// - `unmarshaledResults` with each result unmarshaled to `fleet.ScheduledQueryResult`s, where if an item is `nil` it means the corresponding
// `osqueryResults` item could not be unmarshaled.
// - queriesDBData has the corresponding DB query to each unmarshalled result in `osqueryResults`.
//
// If queryReportsDisabled is true then it returns only t he `unmarshaledResults` without querying the DB.
func ( svc * Service ) preProcessOsqueryResults (
ctx context . Context ,
osqueryResults [ ] json . RawMessage ,
queryReportsDisabled bool ,
) ( unmarshaledResults [ ] * fleet . ScheduledQueryResult , queriesDBData map [ string ] * fleet . Query ) {
2023-10-11 18:20:06 +00:00
// skipauth: Authorization is currently for user endpoints only.
svc . authz . SkipAuthorization ( ctx )
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
lograw := func ( raw json . RawMessage ) string {
logr := raw
if len ( raw ) >= 64 {
logr = raw [ : 64 ]
}
return string ( logr )
}
2023-10-11 18:20:06 +00:00
for _ , raw := range osqueryResults {
var result * fleet . ScheduledQueryResult
if err := json . Unmarshal ( raw , & result ) ; err != nil {
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
level . Debug ( svc . logger ) . Log ( "msg" , "unmarshalling result" , "err" , err , "result" , lograw ( raw ) )
// Note that if err != nil we have two scenarios:
// - result == nil: which means the result could not be unmarshalled, e.g. not JSON.
// - result != nil: which means that the result was (partially) unmarshalled but some specific
// field could not be unmarshalled.
//
// In both scenarios we want to add `result` to `unmarshaledResults`.
2024-10-18 17:38:26 +00:00
} else if result != nil && result . QueryName == "" {
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
// If the unmarshaled result doesn't have a "name" field then we ignore the result.
2024-10-18 17:38:26 +00:00
level . Debug ( svc . logger ) . Log ( "msg" , "missing name field" , "result" , lograw ( raw ) )
result = nil
2023-10-11 18:20:06 +00:00
}
unmarshaledResults = append ( unmarshaledResults , result )
}
2023-10-25 22:20:27 +00:00
if queryReportsDisabled {
return unmarshaledResults , nil
}
2023-10-11 18:20:06 +00:00
queriesDBData = make ( map [ string ] * fleet . Query )
for _ , queryResult := range unmarshaledResults {
if queryResult == nil {
// These are results that could not be unmarshaled.
continue
}
teamID , queryName , err := getQueryNameAndTeamIDFromResult ( queryResult . QueryName )
if err != nil {
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
level . Debug ( svc . logger ) . Log ( "msg" , "querying name and team ID from result" , "err" , err )
2023-10-11 18:20:06 +00:00
continue
}
if _ , ok := queriesDBData [ queryResult . QueryName ] ; ok {
// Already loaded.
continue
}
query , err := svc . ds . QueryByName ( ctx , teamID , queryName )
if err != nil {
level . Debug ( svc . logger ) . Log ( "msg" , "loading query by name" , "err" , err , "team" , teamID , "name" , queryName )
continue
}
queriesDBData [ queryResult . QueryName ] = query
}
return unmarshaledResults , queriesDBData
}
2022-03-07 18:10:55 +00:00
func ( svc * Service ) SubmitStatusLogs ( ctx context . Context , logs [ ] json . RawMessage ) error {
// skipauth: Authorization is currently for user endpoints only.
svc . authz . SkipAuthorization ( ctx )
if err := svc . osqueryLogWriter . Status . Write ( ctx , logs ) ; err != nil {
2024-01-30 00:38:10 +00:00
osqueryErr := newOsqueryError ( "error writing status logs: " + err . Error ( ) )
// Attempting to write a large amount of data is the most likely explanation for this error.
osqueryErr . statusCode = http . StatusRequestEntityTooLarge
return osqueryErr
2022-03-07 18:10:55 +00:00
}
return nil
}
func ( svc * Service ) SubmitResultLogs ( ctx context . Context , logs [ ] json . RawMessage ) error {
// skipauth: Authorization is currently for user endpoints only.
svc . authz . SkipAuthorization ( ctx )
2023-10-11 18:20:06 +00:00
//
// We do not return errors to osqueryd when processing results because
// otherwise the results will never clear from its local DB and
// will keep retrying forever.
//
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
// We do return errors if we fail to write to the external logging destination,
// so that the logs are not lost and osquery retries on its next log interval.
//
2023-10-25 22:20:27 +00:00
var queryReportsDisabled bool
appConfig , err := svc . ds . AppConfig ( ctx )
if err != nil {
level . Error ( svc . logger ) . Log ( "msg" , "getting app config" , "err" , err )
// If we fail to load the app config we assume the flag to be disabled
// to not perform extra processing in that scenario.
queryReportsDisabled = true
} else {
queryReportsDisabled = appConfig . ServerSettings . QueryReportsDisabled
}
unmarshaledResults , queriesDBData := svc . preProcessOsqueryResults ( ctx , logs , queryReportsDisabled )
if ! queryReportsDisabled {
2024-06-14 15:24:01 +00:00
maxQueryReportRows := appConfig . ServerSettings . GetQueryReportCap ( )
svc . saveResultLogsToQueryReports ( ctx , unmarshaledResults , queriesDBData , maxQueryReportRows )
2023-10-25 22:20:27 +00:00
}
2023-10-11 18:20:06 +00:00
var filteredLogs [ ] json . RawMessage
for i , unmarshaledResult := range unmarshaledResults {
if unmarshaledResult == nil {
// Ignore results that could not be unmarshaled.
continue
}
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
2023-10-25 22:20:27 +00:00
if queryReportsDisabled {
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
// If query_reports_disabled=true we write the logs to the logging destination without any extra processing.
2023-10-25 22:20:27 +00:00
//
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
// If a query was recently configured with automations_enabled = 0 we may still write
// the results for it here. Eventually the query will be removed from the host schedule
// and thus Fleet won't receive any further results anymore.
2023-10-25 22:20:27 +00:00
filteredLogs = append ( filteredLogs , logs [ i ] )
continue
}
2023-10-11 18:20:06 +00:00
dbQuery , ok := queriesDBData [ unmarshaledResult . QueryName ]
if ! ok {
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
// If Fleet doesn't know of the query we write the logs to the logging destination
// without any extra processing. This is to support osquery nodes that load their
// config from elsewhere (e.g. using `--config_plugin=filesystem`).
//
// If a query was configured from Fleet but was recently removed, we may still write
// the results for it here. Eventually the query will be removed from the host schedule
// and thus Fleet won't receive any further results anymore.
filteredLogs = append ( filteredLogs , logs [ i ] )
2023-10-11 18:20:06 +00:00
continue
}
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
2023-10-11 18:20:06 +00:00
if ! dbQuery . AutomationsEnabled {
// Ignore results for queries that have automations disabled.
continue
}
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
2023-10-11 18:20:06 +00:00
filteredLogs = append ( filteredLogs , logs [ i ] )
}
2023-10-25 22:20:27 +00:00
if len ( filteredLogs ) == 0 {
return nil
}
2023-10-11 18:20:06 +00:00
if err := svc . osqueryLogWriter . Result . Write ( ctx , filteredLogs ) ; err != nil {
2024-01-30 00:38:10 +00:00
osqueryErr := newOsqueryError (
2023-12-21 18:15:25 +00:00
"error writing result logs " +
"(if the logging destination is down, you can reduce frequency/size of osquery logs by " +
"increasing logger_tls_period and decreasing logger_tls_max_lines): " + err . Error ( ) ,
)
2024-01-30 00:38:10 +00:00
// Attempting to write a large amount of data is the most likely explanation for this error.
osqueryErr . statusCode = http . StatusRequestEntityTooLarge
return osqueryErr
2022-03-07 18:10:55 +00:00
}
return nil
}
2023-10-10 12:44:03 +00:00
////////////////////////////////////////////////////////////////////////////////
// Query Reports
////////////////////////////////////////////////////////////////////////////////
2024-06-14 15:24:01 +00:00
func ( svc * Service ) saveResultLogsToQueryReports (
ctx context . Context ,
unmarshaledResults [ ] * fleet . ScheduledQueryResult ,
queriesDBData map [ string ] * fleet . Query ,
maxQueryReportRows int ,
) {
2023-10-10 12:44:03 +00:00
// skipauth: Authorization is currently for user endpoints only.
svc . authz . SkipAuthorization ( ctx )
2023-10-11 18:20:06 +00:00
host , ok := hostctx . FromContext ( ctx )
if ! ok {
level . Error ( svc . logger ) . Log ( "err" , "getting host from context" )
return
}
// Filter results to only the most recent for each query.
filtered := getMostRecentResults ( unmarshaledResults )
2023-10-10 12:44:03 +00:00
for _ , result := range filtered {
2023-10-11 18:20:06 +00:00
dbQuery , ok := queriesDBData [ result . QueryName ]
if ! ok {
// Means the query does not exist with such name anymore. Thus we ignore its result.
continue
}
2023-10-10 12:44:03 +00:00
2023-10-11 18:20:06 +00:00
if dbQuery . DiscardData || dbQuery . Logging != fleet . LoggingSnapshot {
// Ignore result if query is marked as discard data or if logging is not snapshot
continue
}
2023-10-10 12:44:03 +00:00
2024-05-03 20:37:55 +00:00
hostTeamID := uint ( 0 )
if host . TeamID != nil {
hostTeamID = * host . TeamID
}
if dbQuery . TeamID != nil && * dbQuery . TeamID != hostTeamID {
// The host was transferred to another team/global so we ignore the incoming results
// of this query that belong to a different team.
continue
}
2023-10-25 22:20:27 +00:00
// We first check the current query results count using the DB reader (also cached)
// to reduce the DB writer load of osquery/log requests when the host count is high.
count , err := svc . ds . ResultCountForQuery ( ctx , dbQuery . ID )
if err != nil {
level . Error ( svc . logger ) . Log ( "msg" , "get result count for query" , "err" , err , "query_id" , dbQuery . ID )
continue
}
2024-06-14 15:24:01 +00:00
if count >= maxQueryReportRows {
2023-10-25 22:20:27 +00:00
continue
}
2024-06-14 15:24:01 +00:00
if err := svc . overwriteResultRows ( ctx , result , dbQuery . ID , host . ID , maxQueryReportRows ) ; err != nil {
2023-10-11 18:20:06 +00:00
level . Error ( svc . logger ) . Log ( "msg" , "overwrite results" , "err" , err , "query_id" , dbQuery . ID , "host_id" , host . ID )
continue
}
2023-10-10 12:44:03 +00:00
}
}
2023-10-25 22:20:27 +00:00
// overwriteResultRows deletes existing and inserts the new results for a query and host.
//
// The "snapshot" array in a ScheduledQueryResult can contain multiple rows.
// Each row is saved as a separate ScheduledQueryResultRow, i.e. a result could contain
// many USB Devices or a result could contain all user accounts on a host.
2024-06-14 15:24:01 +00:00
func ( svc * Service ) overwriteResultRows ( ctx context . Context , result * fleet . ScheduledQueryResult , queryID , hostID uint , maxQueryReportRows int ) error {
2023-10-10 12:44:03 +00:00
fetchTime := time . Now ( )
rows := make ( [ ] * fleet . ScheduledQueryResultRow , 0 , len ( result . Snapshot ) )
2023-12-04 15:31:35 +00:00
// If the snapshot is empty, we still want to save a row with a null value
// to capture LastFetched.
if len ( result . Snapshot ) == 0 {
rows = append ( rows , & fleet . ScheduledQueryResultRow {
QueryID : queryID ,
HostID : hostID ,
Data : nil ,
LastFetched : fetchTime ,
} )
}
2023-10-10 12:44:03 +00:00
for _ , snapshotItem := range result . Snapshot {
row := & fleet . ScheduledQueryResultRow {
QueryID : queryID ,
HostID : hostID ,
Data : snapshotItem ,
LastFetched : fetchTime ,
}
rows = append ( rows , row )
}
2024-06-14 15:24:01 +00:00
if err := svc . ds . OverwriteQueryResultRows ( ctx , rows , maxQueryReportRows ) ; err != nil {
2023-10-10 12:44:03 +00:00
return ctxerr . Wrap ( ctx , err , "overwriting query result rows" )
}
return nil
}
// getMostRecentResults returns only the most recent result per query.
// Osquery can send multiple results for the same query (ie. if an agent loses
// network connectivity it will cache multiple results). Query Reports only
// save the most recent result for a given query.
2023-10-11 18:20:06 +00:00
func getMostRecentResults ( results [ ] * fleet . ScheduledQueryResult ) [ ] * fleet . ScheduledQueryResult {
2023-10-10 12:44:03 +00:00
// Use a map to track the most recent entry for each unique QueryName
2023-10-11 18:20:06 +00:00
latestResults := make ( map [ string ] * fleet . ScheduledQueryResult )
2023-10-10 12:44:03 +00:00
for _ , result := range results {
2023-10-11 18:20:06 +00:00
if result == nil {
// This is a result that failed to unmarshal.
continue
}
2023-10-10 12:44:03 +00:00
if existing , ok := latestResults [ result . QueryName ] ; ok {
// Compare the UnixTime time and update the map if the current result is more recent
if result . UnixTime > existing . UnixTime {
latestResults [ result . QueryName ] = result
}
} else {
latestResults [ result . QueryName ] = result
}
}
// Convert the map back to a slice
2023-10-11 18:20:06 +00:00
var filteredResults [ ] * fleet . ScheduledQueryResult
2023-10-10 12:44:03 +00:00
for _ , v := range latestResults {
filteredResults = append ( filteredResults , v )
}
return filteredResults
}
2024-01-18 15:41:06 +00:00
// findPackDelimiterString attempts to find the `pack_delimiter` string in the scheduled
// query name reported by osquery (note that `pack_delimiter` can contain multiple characters).
//
// The expected format for s is "pack<pack_delimiter>{Global|team-<team_id>}<pack_delimiter><query_name>"
//
// Returns "" if it failed to parse the pack_delimiter.
2024-05-01 15:42:03 +00:00
var (
dcounter = regexp . MustCompile ( ` (Global)|(team-\d+) ` )
pattern = regexp . MustCompile ( ` ^(.*)(?:(Global)|(team-\d+)) ` )
)
2024-01-18 15:41:06 +00:00
func findPackDelimiterString ( scheduledQueryName string ) string {
scheduledQueryName = scheduledQueryName [ 4 : ] // always starts with "pack"
2024-05-01 15:42:03 +00:00
count := dcounter . FindAllString ( scheduledQueryName , - 1 )
// If Global or team-<team_id> does not appear, then the
// pack_delimiter is invalid.
if len ( count ) == 0 {
return ""
}
if len ( count ) == 1 {
matches := pattern . FindStringSubmatch ( scheduledQueryName )
if len ( matches ) > 1 {
return matches [ 1 ]
2024-01-18 15:41:06 +00:00
}
}
2024-05-01 15:42:03 +00:00
// Handle edge cases where "Global" or "team-<team_id>"" appears multiple times in the query
// name. Regex is not pre-compiled, so it is a less performant operation.
// Go's regexp doesn't support backreferences so we have to perform some manual work.
if len ( count ) > 1 {
for l := 1 ; l < len ( scheduledQueryName ) ; l ++ {
sep := scheduledQueryName [ : l ]
rest := scheduledQueryName [ l : ]
pattern := fmt . Sprintf ( ` ^(?:(Global)|(team-\d+))%s.+ ` , regexp . QuoteMeta ( sep ) )
matched , _ := regexp . MatchString ( pattern , rest )
if matched {
return sep
}
}
}
2024-01-18 15:41:06 +00:00
return ""
}
// getQueryNameAndTeamIDFromResult attempts to parse the scheduled query name reported by osquery.
//
// The expected format of query names managed by Fleet is:
// "pack<pack_delimiter>{Global|team-<team_id>}<pack_delimiter><query_name>"
2023-10-10 12:44:03 +00:00
func getQueryNameAndTeamIDFromResult ( path string ) ( * uint , string , error ) {
2024-01-18 15:41:06 +00:00
if ! strings . HasPrefix ( path , "pack" ) || len ( path ) <= 4 {
return nil , "" , fmt . Errorf ( "unknown format: %q" , path )
}
sep := findPackDelimiterString ( path )
if sep == "" {
// If a pack_delimiter could not be parsed we return an error.
//
// 2017/legacy packs with the format "pack/<Pack name>/<Query name> are
// considered unknown format (they are not considered global or team
// scheduled queries).
return nil , "" , fmt . Errorf ( "unknown format: %q" , path )
}
2023-10-10 12:44:03 +00:00
// For pattern: pack/Global/Name
2024-01-18 15:41:06 +00:00
globalPattern := "pack" + sep + "Global" + sep
if strings . HasPrefix ( path , globalPattern ) {
2024-05-01 15:42:03 +00:00
name := strings . TrimPrefix ( path , globalPattern )
if name == "" {
return nil , "" , fmt . Errorf ( "parsing query name: %s" , path )
}
2024-01-18 15:41:06 +00:00
return nil , strings . TrimPrefix ( path , globalPattern ) , nil
2023-10-10 12:44:03 +00:00
}
// For pattern: pack/team-<ID>/Name
2024-01-18 15:41:06 +00:00
teamPattern := "pack" + sep + "team-"
if strings . HasPrefix ( path , teamPattern ) {
teamIDAndRest := strings . TrimPrefix ( path , teamPattern )
teamIDAndQueryNameParts := strings . SplitN ( teamIDAndRest , sep , 2 )
if len ( teamIDAndQueryNameParts ) != 2 {
return nil , "" , fmt . Errorf ( "parsing team number part: %s" , path )
}
2024-05-01 15:42:03 +00:00
if teamIDAndQueryNameParts [ 1 ] == "" {
return nil , "" , fmt . Errorf ( "parsing query name: %s" , path )
}
2024-01-18 15:41:06 +00:00
teamNumberUint , err := strconv . ParseUint ( teamIDAndQueryNameParts [ 0 ] , 10 , 32 )
2023-10-10 12:44:03 +00:00
if err != nil {
return nil , "" , fmt . Errorf ( "parsing team number: %w" , err )
}
teamNumber := uint ( teamNumberUint )
2024-01-18 15:41:06 +00:00
return & teamNumber , teamIDAndQueryNameParts [ 1 ] , nil
2023-10-10 12:44:03 +00:00
}
// If none of the above patterns match, return error
Fix osquery result logging when queries are configured outside of Fleet (#15393)
#15168
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests.
- [X] Manual QA for all new/changed functionality.
The issue can be reproduced by running `osqueryd` with
`--config_plugin=filesystem --config_path=/path/to/config.json`
This means the osquery config is fetched from a file rather than from
Fleet's agent settings.
The `/path/to/config.json` has the agent settings, e.g.:
```
{
"decorators": {
"load": [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;"
]
},
"options": {
"disable_distributed": false,
"distributed_interval": 10,
"distributed_plugin": "tls",
"distributed_tls_max_attempts": 3,
"logger_tls_endpoint": "/api/osquery/log",
"logger_tls_period": 10,
"pack_delimiter": "/"
},
"schedule": {
"USB devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 15
},
"OS version": {
"query": "SELECT * FROM os_version;",
"interval": 10
}
},
"packs": {
"Elsewhere": {
"queries": {
"Osquery Info": {
"query": "SELECT * FROM osquery_info;",
"interval": 30,
"platform": "",
"version": "",
"snapshot": true
}
}
}
}
}
```
The three queries should be logged to Fleet's configured result logging
destination (default is `filesystem`).
2023-12-04 14:18:49 +00:00
return nil , "" , fmt . Errorf ( "unknown format: %q" , path )
2023-10-10 12:44:03 +00:00
}
2024-11-13 17:01:08 +00:00
// Yara rules
func ( svc * Service ) YaraRuleByName ( ctx context . Context , name string ) ( * fleet . YaraRule , error ) {
return svc . ds . YaraRuleByName ( ctx , name )
}
type getYaraRequest struct {
NodeKey string ` json:"node_key" `
Name string ` url:"name" `
}
func ( r * getYaraRequest ) hostNodeKey ( ) string {
return r . NodeKey
}
type getYaraResponse struct {
Err error ` json:"error,omitempty" `
Content string
}
func ( r getYaraResponse ) error ( ) error { return r . Err }
func ( r getYaraResponse ) hijackRender ( ctx context . Context , w http . ResponseWriter ) {
w . Header ( ) . Set ( "Content-Type" , "text/plain; charset=utf-8" )
_ , _ = w . Write ( [ ] byte ( r . Content ) )
}
func getYaraEndpoint ( ctx context . Context , request interface { } , svc fleet . Service ) ( errorer , error ) {
r := request . ( * getYaraRequest )
rule , err := svc . YaraRuleByName ( ctx , r . Name )
if err != nil {
return getYaraResponse { Err : err } , nil
}
return getYaraResponse { Content : rule . Contents } , nil
}