mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
Add MDM detection for windows and mdm endpoints (#8479)
This commit is contained in:
parent
1aaee2b5de
commit
baa1ddc0f2
1
changes/7860-mdm-windows
Normal file
1
changes/7860-mdm-windows
Normal file
@ -0,0 +1 @@
|
||||
* Detect Windows MDM solutions and add mdm endpoints.
|
@ -1675,8 +1675,10 @@ None.
|
||||
- [Transfer hosts to a team by filter](#transfer-hosts-to-a-team-by-filter)
|
||||
- [Bulk delete hosts by filter or ids](#bulk-delete-hosts-by-filter-or-ids)
|
||||
- [Get host's Google Chrome profiles](#get-hosts-google-chrome-profiles)
|
||||
- [Get host's mobile device management (MDM) and Munki information](#get-hosts-mobile-device-management-mdm-and-munki-information)
|
||||
- [Get aggregated host's mobile device management (MDM) and Munki information](#get-aggregated-hosts-mobile-device-management-mdm-and-munki-information)
|
||||
- [Get host's mobile device management (MDM) information](#get-hosts-mobile-device-management-mdm-information)
|
||||
- [Get mobile device management (MDM) summary](#get-mobile-device-management-mdm-summary)
|
||||
- [Get host's macadmin mobile device management (MDM) and Munki information](#get-hosts-macadmin-mobile-device-management-mdm-and-munki-information)
|
||||
- [Get aggregated host's mobile device management (MDM) and Munki information](#get-aggregated-hosts-macadmin-mobile-device-management-mdm-and-munki-information)
|
||||
- [Get host OS versions](#get-host-os-versions)
|
||||
- [Get hosts report in CSV](#get-hosts-report-in-csv)
|
||||
|
||||
@ -2538,7 +2540,94 @@ user by email.
|
||||
|
||||
---
|
||||
|
||||
### Get host's mobile device management (MDM) and Munki information
|
||||
### Get host's mobile device management (MDM) information
|
||||
|
||||
Currently supports Windows and MacOS. On MacOS this requires the [macadmins osquery
|
||||
extension](https://github.com/macadmins/osquery-extension) which comes bundled
|
||||
in [Fleet's osquery installers](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).
|
||||
|
||||
Retrieves a host's MDM enrollment status and MDM server URL.
|
||||
|
||||
`GET /api/v1/fleet/hosts/{id}/mdm`
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | In | Description |
|
||||
| ------- | ------- | ---- | -------------------------------------------------------------------------------- |
|
||||
| id | integer | path | **Required** The id of the host to get the details for |
|
||||
|
||||
#### Example
|
||||
|
||||
`GET /api/v1/fleet/hosts/32/mdm`
|
||||
|
||||
##### Default response
|
||||
|
||||
`Status: 200`
|
||||
|
||||
```json
|
||||
{
|
||||
"enrollment_status": "Enrolled (automated)",
|
||||
"server_url": "some.mdm.com",
|
||||
"name": "Some MDM",
|
||||
"id": 3
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Get mobile device management (MDM) summary
|
||||
|
||||
Currently supports Windows and MacOS. On MacOS this requires the [macadmins osquery
|
||||
extension](https://github.com/macadmins/osquery-extension) which comes bundled
|
||||
in [Fleet's osquery installers](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).
|
||||
|
||||
Retrieves MDM enrollment summary.
|
||||
|
||||
`GET /api/v1/fleet/hosts/summary/mdm`
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | In | Description |
|
||||
| -------- | ------- | ----- | -------------------------------------------------------------------------------- |
|
||||
| team_id | integer | query | Filter by team |
|
||||
| platform | string | query | Filter by platform ("windows" or "darwin") |
|
||||
|
||||
#### Example
|
||||
|
||||
`GET /api/v1/fleet/hosts/summary/mdm?team_id=1&platform=windows`
|
||||
|
||||
##### Default response
|
||||
|
||||
`Status: 200`
|
||||
|
||||
```json
|
||||
{
|
||||
"mobile_device_management_enrollment_status": {
|
||||
"enrolled_manual_hosts_count": 0,
|
||||
"enrolled_automated_hosts_count": 2,
|
||||
"unenrolled_hosts_count": 0,
|
||||
"hosts_count": 2
|
||||
},
|
||||
"mobile_device_management_solution": [
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Solution1",
|
||||
"server_url": "solution1.com",
|
||||
"hosts_count": 1
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Solution2",
|
||||
"server_url": "solution2.com",
|
||||
"hosts_count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Get host's macadmin mobile device management (MDM) and Munki information
|
||||
|
||||
Requires the [macadmins osquery
|
||||
extension](https://github.com/macadmins/osquery-extension) which comes bundled
|
||||
@ -2596,7 +2685,7 @@ Retrieves a host's MDM enrollment status, MDM server URL, and Munki version.
|
||||
|
||||
---
|
||||
|
||||
### Get aggregated host's mobile device management (MDM) and Munki information
|
||||
### Get aggregated host's macadmin mobile device management (MDM) and Munki information
|
||||
|
||||
Requires the [macadmins osquery
|
||||
extension](https://github.com/macadmins/osquery-extension) which comes bundled
|
||||
|
@ -2113,8 +2113,8 @@ func (ds *Datastore) getOrInsertMunkiIssues(ctx context.Context, errors, warning
|
||||
return msgToID, nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) SetOrUpdateMDMData(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool) error {
|
||||
mdmID, err := ds.getOrInsertMDMSolution(ctx, serverURL)
|
||||
func (ds *Datastore) SetOrUpdateMDMData(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool, name string) error {
|
||||
mdmID, err := ds.getOrInsertMDMSolution(ctx, serverURL, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -2147,9 +2147,10 @@ func (ds *Datastore) SetOrUpdateHostOrbitInfo(ctx context.Context, hostID uint,
|
||||
)
|
||||
}
|
||||
|
||||
func (ds *Datastore) getOrInsertMDMSolution(ctx context.Context, serverURL string) (mdmID uint, err error) {
|
||||
mdmName := fleet.MDMNameFromServerURL(serverURL)
|
||||
|
||||
func (ds *Datastore) getOrInsertMDMSolution(ctx context.Context, serverURL string, mdmName string) (mdmID uint, err error) {
|
||||
if mdmName == "" {
|
||||
mdmName = fleet.MDMNameFromServerURL(serverURL)
|
||||
}
|
||||
readStmt := ¶meterizedStmt{
|
||||
Statement: `SELECT id FROM mobile_device_management_solutions WHERE name = ? AND server_url = ?`,
|
||||
Args: []interface{}{mdmName, serverURL},
|
||||
@ -2313,7 +2314,7 @@ func (ds *Datastore) AggregatedMunkiIssues(ctx context.Context, teamID *uint) ([
|
||||
return result, resultJSON.UpdatedAt, nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) AggregatedMDMStatus(ctx context.Context, teamID *uint) (fleet.AggregatedMDMStatus, time.Time, error) {
|
||||
func (ds *Datastore) AggregatedMDMStatus(ctx context.Context, teamID *uint, platform string) (fleet.AggregatedMDMStatus, time.Time, error) {
|
||||
id := uint(0)
|
||||
|
||||
if teamID != nil {
|
||||
@ -2327,8 +2328,8 @@ func (ds *Datastore) AggregatedMDMStatus(ctx context.Context, teamID *uint) (fle
|
||||
}
|
||||
err := sqlx.GetContext(
|
||||
ctx, ds.reader, &statusJson,
|
||||
`select json_value, updated_at from aggregated_stats where id = ? and type = 'mdm_status'`,
|
||||
id,
|
||||
`select json_value, updated_at from aggregated_stats where id = ? and type = ?`,
|
||||
id, platformKey("mdm_status", platform),
|
||||
)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
@ -2343,7 +2344,14 @@ func (ds *Datastore) AggregatedMDMStatus(ctx context.Context, teamID *uint) (fle
|
||||
return status, statusJson.UpdatedAt, nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) AggregatedMDMSolutions(ctx context.Context, teamID *uint) ([]fleet.AggregatedMDMSolutions, time.Time, error) {
|
||||
func platformKey(key string, platform string) string {
|
||||
if platform == "" {
|
||||
return key
|
||||
}
|
||||
return key + "_" + platform
|
||||
}
|
||||
|
||||
func (ds *Datastore) AggregatedMDMSolutions(ctx context.Context, teamID *uint, platform string) ([]fleet.AggregatedMDMSolutions, time.Time, error) {
|
||||
id := uint(0)
|
||||
|
||||
if teamID != nil {
|
||||
@ -2357,8 +2365,8 @@ func (ds *Datastore) AggregatedMDMSolutions(ctx context.Context, teamID *uint) (
|
||||
}
|
||||
err := sqlx.GetContext(
|
||||
ctx, ds.reader, &resultJSON,
|
||||
`SELECT json_value, updated_at FROM aggregated_stats WHERE id = ? AND type = 'mdm_solutions'`,
|
||||
id,
|
||||
`SELECT json_value, updated_at FROM aggregated_stats WHERE id = ? AND type = ?`,
|
||||
id, platformKey("mdm_solutions", platform),
|
||||
)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
@ -2374,7 +2382,11 @@ func (ds *Datastore) AggregatedMDMSolutions(ctx context.Context, teamID *uint) (
|
||||
}
|
||||
|
||||
func (ds *Datastore) GenerateAggregatedMunkiAndMDM(ctx context.Context) error {
|
||||
var ids []uint
|
||||
var (
|
||||
platforms = []string{"", "darwin", "windows"}
|
||||
ids []uint
|
||||
)
|
||||
|
||||
if err := sqlx.SelectContext(ctx, ds.reader, &ids, `SELECT id FROM teams`); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "list teams")
|
||||
}
|
||||
@ -2386,11 +2398,13 @@ func (ds *Datastore) GenerateAggregatedMunkiAndMDM(ctx context.Context) error {
|
||||
if err := ds.generateAggregatedMunkiIssues(ctx, &id); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "generating aggregated munki issues")
|
||||
}
|
||||
if err := ds.generateAggregatedMDMStatus(ctx, &id); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "generating aggregated mdm status")
|
||||
}
|
||||
if err := ds.generateAggregatedMDMSolutions(ctx, &id); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "generating aggregated mdm solutions")
|
||||
for _, platform := range platforms {
|
||||
if err := ds.generateAggregatedMDMStatus(ctx, &id, platform); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "generating aggregated mdm status")
|
||||
}
|
||||
if err := ds.generateAggregatedMDMSolutions(ctx, &id, platform); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "generating aggregated mdm solutions")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2400,11 +2414,13 @@ func (ds *Datastore) GenerateAggregatedMunkiAndMDM(ctx context.Context) error {
|
||||
if err := ds.generateAggregatedMunkiIssues(ctx, nil); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "generating aggregated munki issues")
|
||||
}
|
||||
if err := ds.generateAggregatedMDMStatus(ctx, nil); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "generating aggregated mdm status")
|
||||
}
|
||||
if err := ds.generateAggregatedMDMSolutions(ctx, nil); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "generating aggregated mdm solutions")
|
||||
for _, platform := range platforms {
|
||||
if err := ds.generateAggregatedMDMStatus(ctx, nil, platform); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "generating aggregated mdm status")
|
||||
}
|
||||
if err := ds.generateAggregatedMDMSolutions(ctx, nil, platform); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "generating aggregated mdm solutions")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -2496,10 +2512,12 @@ ON DUPLICATE KEY UPDATE
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) generateAggregatedMDMStatus(ctx context.Context, teamID *uint) error {
|
||||
id := uint(0)
|
||||
func (ds *Datastore) generateAggregatedMDMStatus(ctx context.Context, teamID *uint, platform string) error {
|
||||
var (
|
||||
id = uint(0)
|
||||
status fleet.AggregatedMDMStatus
|
||||
)
|
||||
|
||||
var status fleet.AggregatedMDMStatus
|
||||
query := `SELECT
|
||||
COUNT(DISTINCT host_id) as hosts_count,
|
||||
COALESCE(SUM(CASE WHEN NOT enrolled THEN 1 ELSE 0 END), 0) as unenrolled_hosts_count,
|
||||
@ -2508,10 +2526,19 @@ func (ds *Datastore) generateAggregatedMDMStatus(ctx context.Context, teamID *ui
|
||||
FROM host_mdm hm
|
||||
`
|
||||
args := []interface{}{}
|
||||
if teamID != nil || platform != "" {
|
||||
query += ` JOIN hosts h ON (h.id = hm.host_id) `
|
||||
}
|
||||
whereAnd := "WHERE"
|
||||
if teamID != nil {
|
||||
args = append(args, *teamID)
|
||||
query += ` JOIN hosts h ON (h.id = hm.host_id) WHERE h.team_id = ?`
|
||||
query += ` WHERE h.team_id = ? `
|
||||
id = *teamID
|
||||
whereAnd = "AND"
|
||||
}
|
||||
if platform != "" {
|
||||
args = append(args, platform)
|
||||
query += whereAnd + " h.platform = ? "
|
||||
}
|
||||
err := sqlx.GetContext(ctx, ds.reader, &status, query, args...)
|
||||
if err != nil {
|
||||
@ -2531,7 +2558,7 @@ ON DUPLICATE KEY UPDATE
|
||||
json_value = VALUES(json_value),
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
`,
|
||||
id, "mdm_status", statusJson,
|
||||
id, platformKey("mdm_status", platform), statusJson,
|
||||
)
|
||||
if err != nil {
|
||||
return ctxerr.Wrapf(ctx, err, "inserting stats for mdm_status id %d", id)
|
||||
@ -2539,10 +2566,12 @@ ON DUPLICATE KEY UPDATE
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) generateAggregatedMDMSolutions(ctx context.Context, teamID *uint) error {
|
||||
id := uint(0)
|
||||
|
||||
var results []fleet.AggregatedMDMSolutions
|
||||
func (ds *Datastore) generateAggregatedMDMSolutions(ctx context.Context, teamID *uint, platform string) error {
|
||||
var (
|
||||
id = uint(0)
|
||||
results []fleet.AggregatedMDMSolutions
|
||||
whereAnd = "WHERE"
|
||||
)
|
||||
query := `SELECT
|
||||
mdms.id,
|
||||
mdms.server_url,
|
||||
@ -2553,10 +2582,18 @@ func (ds *Datastore) generateAggregatedMDMSolutions(ctx context.Context, teamID
|
||||
ON hm.mdm_id = mdms.id
|
||||
`
|
||||
args := []interface{}{}
|
||||
if teamID != nil || platform != "" {
|
||||
query += ` JOIN hosts h ON (h.id = hm.host_id) `
|
||||
}
|
||||
if teamID != nil {
|
||||
args = append(args, *teamID)
|
||||
query += ` JOIN hosts h ON (h.id = hm.host_id) WHERE h.team_id = ?`
|
||||
query += ` WHERE h.team_id = ? `
|
||||
id = *teamID
|
||||
whereAnd = "AND"
|
||||
}
|
||||
if platform != "" {
|
||||
args = append(args, platform)
|
||||
query += whereAnd + ` h.platform = ? `
|
||||
}
|
||||
query += ` GROUP BY id, server_url, name`
|
||||
err := sqlx.SelectContext(ctx, ds.reader, &results, query, args...)
|
||||
@ -2577,7 +2614,7 @@ ON DUPLICATE KEY UPDATE
|
||||
json_value = VALUES(json_value),
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
`,
|
||||
id, "mdm_solutions", resultsJSON,
|
||||
id, platformKey("mdm_solutions", platform), resultsJSON,
|
||||
)
|
||||
if err != nil {
|
||||
return ctxerr.Wrapf(ctx, err, "inserting stats for mdm_solutions id %d", id)
|
||||
|
@ -890,13 +890,13 @@ func testHostsListMDM(t *testing.T, ds *Datastore) {
|
||||
}
|
||||
|
||||
const simpleMDM, kandji, unknown = "https://simplemdm.com", "https://kandji.io", "https://url.com"
|
||||
err := ds.SetOrUpdateMDMData(ctx, hostIDs[0], true, simpleMDM, true) // enrollment: automatic
|
||||
err := ds.SetOrUpdateMDMData(ctx, hostIDs[0], true, simpleMDM, true, "") // enrollment: automatic
|
||||
require.NoError(t, err)
|
||||
err = ds.SetOrUpdateMDMData(ctx, hostIDs[1], true, kandji, true) // enrollment: automatic
|
||||
err = ds.SetOrUpdateMDMData(ctx, hostIDs[1], true, kandji, true, "") // enrollment: automatic
|
||||
require.NoError(t, err)
|
||||
err = ds.SetOrUpdateMDMData(ctx, hostIDs[2], true, unknown, false) // enrollment: manual
|
||||
err = ds.SetOrUpdateMDMData(ctx, hostIDs[2], true, unknown, false, "") // enrollment: manual
|
||||
require.NoError(t, err)
|
||||
err = ds.SetOrUpdateMDMData(ctx, hostIDs[3], false, simpleMDM, false) // enrollment: unenrolled
|
||||
err = ds.SetOrUpdateMDMData(ctx, hostIDs[3], false, simpleMDM, false, "") // enrollment: unenrolled
|
||||
require.NoError(t, err)
|
||||
|
||||
var simpleMDMID uint
|
||||
@ -3907,7 +3907,7 @@ func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
||||
_, err = ds.GetHostMDM(context.Background(), 432)
|
||||
require.True(t, fleet.IsNotFound(err), err)
|
||||
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 432, true, "url", false))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 432, true, "url", false, ""))
|
||||
|
||||
hmdm, err := ds.GetHostMDM(context.Background(), 432)
|
||||
require.NoError(t, err)
|
||||
@ -3919,8 +3919,8 @@ func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
||||
urlMDMID := *hmdm.MDMID
|
||||
assert.Equal(t, fleet.UnknownMDMName, hmdm.Name)
|
||||
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://kandji.io", true)) // kandji mdm name
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 432, false, "url3", true))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://kandji.io", true, "")) // kandji mdm name
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 432, false, "url3", true, ""))
|
||||
|
||||
hmdm, err = ds.GetHostMDM(context.Background(), 432)
|
||||
require.NoError(t, err)
|
||||
@ -3954,7 +3954,7 @@ func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
||||
require.ErrorIs(t, err, sql.ErrNoRows)
|
||||
|
||||
// switch to simplemdm in an update
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://simplemdm.com", false)) // now simplemdm name
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://simplemdm.com", false, "")) // now simplemdm name
|
||||
|
||||
hmdm, err = ds.GetHostMDM(context.Background(), 455)
|
||||
require.NoError(t, err)
|
||||
@ -3966,7 +3966,7 @@ func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
||||
assert.Equal(t, fleet.WellKnownMDMSimpleMDM, hmdm.Name)
|
||||
|
||||
// switch back to "url"
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, false, "url", false))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, false, "url", false, ""))
|
||||
|
||||
hmdm, err = ds.GetHostMDM(context.Background(), 455)
|
||||
require.NoError(t, err)
|
||||
@ -3979,7 +3979,7 @@ func testHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
||||
|
||||
// switch to a different Kandji server URL, will have a different MDM ID as
|
||||
// even though this is another Kandji, the URL is different.
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://kandji.io/2", false))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://kandji.io/2", false, ""))
|
||||
|
||||
hmdm, err = ds.GetHostMDM(context.Background(), 455)
|
||||
require.NoError(t, err)
|
||||
@ -4065,11 +4065,19 @@ func testAggregatedHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, issues, 0)
|
||||
require.Zero(t, updatedAt)
|
||||
status, updatedAt, err := ds.AggregatedMDMStatus(context.Background(), nil)
|
||||
status, updatedAt, err := ds.AggregatedMDMStatus(context.Background(), nil, "")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, status)
|
||||
require.Zero(t, updatedAt)
|
||||
solutions, updatedAt, err := ds.AggregatedMDMSolutions(context.Background(), nil)
|
||||
solutions, updatedAt, err := ds.AggregatedMDMSolutions(context.Background(), nil, "")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, solutions, 0)
|
||||
require.Zero(t, updatedAt)
|
||||
status, updatedAt, err = ds.AggregatedMDMStatus(context.Background(), nil, "windows")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, status)
|
||||
require.Zero(t, updatedAt)
|
||||
solutions, updatedAt, err = ds.AggregatedMDMSolutions(context.Background(), nil, "windows")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, solutions, 0)
|
||||
require.Zero(t, updatedAt)
|
||||
@ -4088,11 +4096,19 @@ func testAggregatedHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, issues)
|
||||
require.NotZero(t, updatedAt)
|
||||
status, updatedAt, err = ds.AggregatedMDMStatus(context.Background(), nil)
|
||||
status, updatedAt, err = ds.AggregatedMDMStatus(context.Background(), nil, "")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, status)
|
||||
require.NotZero(t, updatedAt)
|
||||
solutions, updatedAt, err = ds.AggregatedMDMSolutions(context.Background(), nil)
|
||||
solutions, updatedAt, err = ds.AggregatedMDMSolutions(context.Background(), nil, "")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, solutions, 0)
|
||||
require.NotZero(t, updatedAt)
|
||||
status, updatedAt, err = ds.AggregatedMDMStatus(context.Background(), nil, "windows")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, status)
|
||||
require.NotZero(t, updatedAt)
|
||||
solutions, updatedAt, err = ds.AggregatedMDMSolutions(context.Background(), nil, "windows")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, solutions, 0)
|
||||
require.NotZero(t, updatedAt)
|
||||
@ -4149,23 +4165,23 @@ func testAggregatedHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 432, true, "url", false))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 123, true, "url", false))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 124, true, "url", false))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://simplemdm.com", true))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 999, false, "https://kandji.io", true))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 875, false, "https://kandji.io", true))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 432, true, "url", false, ""))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 123, true, "url", false, ""))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 124, true, "url", false, ""))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 455, true, "https://simplemdm.com", true, ""))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 999, false, "https://kandji.io", true, ""))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), 875, false, "https://kandji.io", true, ""))
|
||||
|
||||
require.NoError(t, ds.GenerateAggregatedMunkiAndMDM(context.Background()))
|
||||
|
||||
status, _, err = ds.AggregatedMDMStatus(context.Background(), nil)
|
||||
status, _, err = ds.AggregatedMDMStatus(context.Background(), nil, "")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 6, status.HostsCount)
|
||||
assert.Equal(t, 2, status.UnenrolledHostsCount)
|
||||
assert.Equal(t, 3, status.EnrolledManualHostsCount)
|
||||
assert.Equal(t, 1, status.EnrolledAutomatedHostsCount)
|
||||
|
||||
solutions, _, err = ds.AggregatedMDMSolutions(context.Background(), nil)
|
||||
solutions, _, err = ds.AggregatedMDMSolutions(context.Background(), nil, "")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, solutions, 3) // 3 different urls
|
||||
for _, sol := range solutions {
|
||||
@ -4196,16 +4212,16 @@ func testAggregatedHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
h1 := test.NewHost(t, ds, "h1"+t.Name(), "192.168.1.10", "1", "1", time.Now())
|
||||
h2 := test.NewHost(t, ds, "h2"+t.Name(), "192.168.1.11", "2", "2", time.Now())
|
||||
h3 := test.NewHost(t, ds, "h3"+t.Name(), "192.168.1.11", "3", "3", time.Now())
|
||||
h1 := test.NewHost(t, ds, "h1"+t.Name(), "192.168.1.10", "1", "1", time.Now(), test.WithPlatform("windows"))
|
||||
h2 := test.NewHost(t, ds, "h2"+t.Name(), "192.168.1.11", "2", "2", time.Now(), test.WithPlatform("darwin"))
|
||||
h3 := test.NewHost(t, ds, "h3"+t.Name(), "192.168.1.11", "3", "3", time.Now(), test.WithPlatform("darwin"))
|
||||
|
||||
require.NoError(t, ds.AddHostsToTeam(context.Background(), &team1.ID, []uint{h1.ID}))
|
||||
require.NoError(t, ds.AddHostsToTeam(context.Background(), &team2.ID, []uint{h2.ID}))
|
||||
require.NoError(t, ds.AddHostsToTeam(context.Background(), &team1.ID, []uint{h3.ID}))
|
||||
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), h1.ID, true, "https://simplemdm.com", false))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), h2.ID, true, "url", false))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), h1.ID, true, "https://simplemdm.com", false, ""))
|
||||
require.NoError(t, ds.SetOrUpdateMDMData(context.Background(), h2.ID, true, "url", false, ""))
|
||||
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), h1.ID, "1.2.3", []string{"d"}, nil))
|
||||
require.NoError(t, ds.SetOrUpdateMunkiInfo(context.Background(), h2.ID, "1.2.3", []string{"d"}, []string{"e"}))
|
||||
|
||||
@ -4252,14 +4268,41 @@ func testAggregatedHostMDMAndMunki(t *testing.T, ds *Datastore) {
|
||||
})
|
||||
require.True(t, updatedAt.After(firstUpdatedAt))
|
||||
|
||||
status, _, err = ds.AggregatedMDMStatus(context.Background(), &team1.ID)
|
||||
status, _, err = ds.AggregatedMDMStatus(context.Background(), &team1.ID, "")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, status.HostsCount)
|
||||
assert.Equal(t, 0, status.UnenrolledHostsCount)
|
||||
assert.Equal(t, 1, status.EnrolledManualHostsCount)
|
||||
assert.Equal(t, 0, status.EnrolledAutomatedHostsCount)
|
||||
|
||||
solutions, updatedAt, err = ds.AggregatedMDMSolutions(context.Background(), &team1.ID)
|
||||
solutions, updatedAt, err = ds.AggregatedMDMSolutions(context.Background(), &team1.ID, "")
|
||||
require.True(t, updatedAt.After(firstUpdatedAt))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, solutions, 1)
|
||||
assert.Equal(t, "https://simplemdm.com", solutions[0].ServerURL)
|
||||
assert.Equal(t, fleet.WellKnownMDMSimpleMDM, solutions[0].Name)
|
||||
assert.Equal(t, 1, solutions[0].HostsCount)
|
||||
|
||||
status, _, err = ds.AggregatedMDMStatus(context.Background(), &team1.ID, "darwin")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 0, status.HostsCount)
|
||||
assert.Equal(t, 0, status.UnenrolledHostsCount)
|
||||
assert.Equal(t, 0, status.EnrolledManualHostsCount)
|
||||
assert.Equal(t, 0, status.EnrolledAutomatedHostsCount)
|
||||
|
||||
solutions, updatedAt, err = ds.AggregatedMDMSolutions(context.Background(), &team1.ID, "darwin")
|
||||
require.True(t, updatedAt.After(firstUpdatedAt))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, solutions, 0)
|
||||
|
||||
status, _, err = ds.AggregatedMDMStatus(context.Background(), &team1.ID, "windows")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, status.HostsCount)
|
||||
assert.Equal(t, 0, status.UnenrolledHostsCount)
|
||||
assert.Equal(t, 1, status.EnrolledManualHostsCount)
|
||||
assert.Equal(t, 0, status.EnrolledAutomatedHostsCount)
|
||||
|
||||
solutions, updatedAt, err = ds.AggregatedMDMSolutions(context.Background(), &team1.ID, "windows")
|
||||
require.True(t, updatedAt.After(firstUpdatedAt))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, solutions, 1)
|
||||
@ -4871,7 +4914,7 @@ func testHostsDeleteHosts(t *testing.T, ds *Datastore) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, ds.RecordPolicyQueryExecutions(context.Background(), host, map[uint]*bool{policy.ID: ptr.Bool(true)}, time.Now(), false))
|
||||
// Update host_mdm.
|
||||
err = ds.SetOrUpdateMDMData(context.Background(), host.ID, false, "", false)
|
||||
err = ds.SetOrUpdateMDMData(context.Background(), host.ID, false, "", false, "")
|
||||
require.NoError(t, err)
|
||||
// Update host_munki_info.
|
||||
err = ds.SetOrUpdateMunkiInfo(context.Background(), host.ID, "42", []string{"a"}, []string{"b"})
|
||||
|
@ -254,8 +254,8 @@ type Datastore interface {
|
||||
|
||||
AggregatedMunkiVersion(ctx context.Context, teamID *uint) ([]AggregatedMunkiVersion, time.Time, error)
|
||||
AggregatedMunkiIssues(ctx context.Context, teamID *uint) ([]AggregatedMunkiIssue, time.Time, error)
|
||||
AggregatedMDMStatus(ctx context.Context, teamID *uint) (AggregatedMDMStatus, time.Time, error)
|
||||
AggregatedMDMSolutions(ctx context.Context, teamID *uint) ([]AggregatedMDMSolutions, time.Time, error)
|
||||
AggregatedMDMStatus(ctx context.Context, teamID *uint, platform string) (AggregatedMDMStatus, time.Time, error)
|
||||
AggregatedMDMSolutions(ctx context.Context, teamID *uint, platform string) ([]AggregatedMDMSolutions, time.Time, error)
|
||||
GenerateAggregatedMunkiAndMDM(ctx context.Context) error
|
||||
|
||||
GetMunkiIssue(ctx context.Context, munkiIssueID uint) (*MunkiIssue, error)
|
||||
@ -605,7 +605,7 @@ type Datastore interface {
|
||||
SaveHostAdditional(ctx context.Context, hostID uint, additional *json.RawMessage) error
|
||||
|
||||
SetOrUpdateMunkiInfo(ctx context.Context, hostID uint, version string, errors, warnings []string) error
|
||||
SetOrUpdateMDMData(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool) error
|
||||
SetOrUpdateMDMData(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool, name string) error
|
||||
SetOrUpdateHostDisksSpace(ctx context.Context, hostID uint, gigsAvailable, percentAvailable float64) error
|
||||
// SetOrUpdateHostOrbitInfo inserts of updates the orbit info for a host
|
||||
SetOrUpdateHostOrbitInfo(ctx context.Context, hostID uint, version string) error
|
||||
|
@ -486,6 +486,12 @@ type AggregatedMDMStatus struct {
|
||||
HostsCount int `json:"hosts_count" db:"hosts_count"`
|
||||
}
|
||||
|
||||
// AggregatedMDMData contains aggregated data from mdm installations.
|
||||
type AggregatedMDMData struct {
|
||||
MDMStatus AggregatedMDMStatus `json:"mobile_device_management_enrollment_status"`
|
||||
MDMSolutions []AggregatedMDMSolutions `json:"mobile_device_management_solution"`
|
||||
}
|
||||
|
||||
// MDMSolution represents a single MDM solution, as returned by the list hosts
|
||||
// endpoint when an MDM Solution ID is provided as filter.
|
||||
type MDMSolution struct {
|
||||
|
@ -315,7 +315,9 @@ type Service interface {
|
||||
DisableAuthForPing(ctx context.Context)
|
||||
|
||||
MacadminsData(ctx context.Context, id uint) (*MacadminsData, error)
|
||||
MDMData(ctx context.Context, id uint) (*HostMDM, error)
|
||||
AggregatedMacadminsData(ctx context.Context, teamID *uint) (*AggregatedMacadminsData, error)
|
||||
AggregatedMDMData(ctx context.Context, id *uint, platform string) (AggregatedMDMData, error)
|
||||
GetMDMSolution(ctx context.Context, mdmID uint) (*MDMSolution, error)
|
||||
GetMunkiIssue(ctx context.Context, munkiIssueID uint) (*MunkiIssue, error)
|
||||
|
||||
|
@ -203,9 +203,9 @@ type AggregatedMunkiVersionFunc func(ctx context.Context, teamID *uint) ([]fleet
|
||||
|
||||
type AggregatedMunkiIssuesFunc func(ctx context.Context, teamID *uint) ([]fleet.AggregatedMunkiIssue, time.Time, error)
|
||||
|
||||
type AggregatedMDMStatusFunc func(ctx context.Context, teamID *uint) (fleet.AggregatedMDMStatus, time.Time, error)
|
||||
type AggregatedMDMStatusFunc func(ctx context.Context, teamID *uint, platform string) (fleet.AggregatedMDMStatus, time.Time, error)
|
||||
|
||||
type AggregatedMDMSolutionsFunc func(ctx context.Context, teamID *uint) ([]fleet.AggregatedMDMSolutions, time.Time, error)
|
||||
type AggregatedMDMSolutionsFunc func(ctx context.Context, teamID *uint, platform string) ([]fleet.AggregatedMDMSolutions, time.Time, error)
|
||||
|
||||
type GenerateAggregatedMunkiAndMDMFunc func(ctx context.Context) error
|
||||
|
||||
@ -437,7 +437,7 @@ type SaveHostAdditionalFunc func(ctx context.Context, hostID uint, additional *j
|
||||
|
||||
type SetOrUpdateMunkiInfoFunc func(ctx context.Context, hostID uint, version string, errors []string, warnings []string) error
|
||||
|
||||
type SetOrUpdateMDMDataFunc func(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool) error
|
||||
type SetOrUpdateMDMDataFunc func(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool, name string) error
|
||||
|
||||
type SetOrUpdateHostDisksSpaceFunc func(ctx context.Context, hostID uint, gigsAvailable float64, percentAvailable float64) error
|
||||
|
||||
@ -1700,14 +1700,14 @@ func (s *DataStore) AggregatedMunkiIssues(ctx context.Context, teamID *uint) ([]
|
||||
return s.AggregatedMunkiIssuesFunc(ctx, teamID)
|
||||
}
|
||||
|
||||
func (s *DataStore) AggregatedMDMStatus(ctx context.Context, teamID *uint) (fleet.AggregatedMDMStatus, time.Time, error) {
|
||||
func (s *DataStore) AggregatedMDMStatus(ctx context.Context, teamID *uint, platform string) (fleet.AggregatedMDMStatus, time.Time, error) {
|
||||
s.AggregatedMDMStatusFuncInvoked = true
|
||||
return s.AggregatedMDMStatusFunc(ctx, teamID)
|
||||
return s.AggregatedMDMStatusFunc(ctx, teamID, platform)
|
||||
}
|
||||
|
||||
func (s *DataStore) AggregatedMDMSolutions(ctx context.Context, teamID *uint) ([]fleet.AggregatedMDMSolutions, time.Time, error) {
|
||||
func (s *DataStore) AggregatedMDMSolutions(ctx context.Context, teamID *uint, platform string) ([]fleet.AggregatedMDMSolutions, time.Time, error) {
|
||||
s.AggregatedMDMSolutionsFuncInvoked = true
|
||||
return s.AggregatedMDMSolutionsFunc(ctx, teamID)
|
||||
return s.AggregatedMDMSolutionsFunc(ctx, teamID, platform)
|
||||
}
|
||||
|
||||
func (s *DataStore) GenerateAggregatedMunkiAndMDM(ctx context.Context) error {
|
||||
@ -2285,9 +2285,9 @@ func (s *DataStore) SetOrUpdateMunkiInfo(ctx context.Context, hostID uint, versi
|
||||
return s.SetOrUpdateMunkiInfoFunc(ctx, hostID, version, errors, warnings)
|
||||
}
|
||||
|
||||
func (s *DataStore) SetOrUpdateMDMData(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool) error {
|
||||
func (s *DataStore) SetOrUpdateMDMData(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool, name string) error {
|
||||
s.SetOrUpdateMDMDataFuncInvoked = true
|
||||
return s.SetOrUpdateMDMDataFunc(ctx, hostID, enrolled, serverURL, installedFromDep)
|
||||
return s.SetOrUpdateMDMDataFunc(ctx, hostID, enrolled, serverURL, installedFromDep, name)
|
||||
}
|
||||
|
||||
func (s *DataStore) SetOrUpdateHostDisksSpace(ctx context.Context, hostID uint, gigsAvailable float64, percentAvailable float64) error {
|
||||
|
@ -343,6 +343,9 @@ func attachFleetAPIRoutes(r *mux.Router, svc fleet.Service, config config.FleetC
|
||||
ue.GET("/api/_version_/fleet/hosts/report", hostsReportEndpoint, hostsReportRequest{})
|
||||
ue.GET("/api/_version_/fleet/os_versions", osVersionsEndpoint, osVersionsRequest{})
|
||||
|
||||
ue.GET("/api/_version_/fleet/hosts/summary/mdm", getHostMDMSummary, getHostMDMSummaryRequest{})
|
||||
ue.GET("/api/_version_/fleet/hosts/{id:[0-9]+}/mdm", getHostMDM, getHostMDMRequest{})
|
||||
|
||||
ue.POST("/api/_version_/fleet/labels", createLabelEndpoint, createLabelRequest{})
|
||||
ue.PATCH("/api/_version_/fleet/labels/{id:[0-9]+}", modifyLabelEndpoint, modifyLabelRequest{})
|
||||
ue.GET("/api/_version_/fleet/labels/{id:[0-9]+}", getLabelEndpoint, getLabelRequest{})
|
||||
|
@ -889,6 +889,50 @@ func (svc *Service) ListHostDeviceMapping(ctx context.Context, id uint) ([]*flee
|
||||
return svc.ds.ListHostDeviceMapping(ctx, id)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// MDM
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type getHostMDMRequest struct {
|
||||
ID uint `url:"id"`
|
||||
}
|
||||
|
||||
type getHostMDMResponse struct {
|
||||
Err error `json:"error,omitempty"`
|
||||
*fleet.HostMDM
|
||||
}
|
||||
|
||||
func getHostMDM(ctx context.Context, request interface{}, svc fleet.Service) (interface{}, error) {
|
||||
req := request.(*getHostMDMRequest)
|
||||
mdm, err := svc.MDMData(ctx, req.ID)
|
||||
if err != nil {
|
||||
return getHostMDMResponse{Err: err}, nil
|
||||
}
|
||||
return getHostMDMResponse{HostMDM: mdm}, nil
|
||||
}
|
||||
|
||||
type getHostMDMSummaryResponse struct {
|
||||
fleet.AggregatedMDMData
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type getHostMDMSummaryRequest struct {
|
||||
TeamID *uint `query:"team_id,optional"`
|
||||
Platform string `query:"platform,optional"`
|
||||
}
|
||||
|
||||
func getHostMDMSummary(ctx context.Context, request interface{}, svc fleet.Service) (interface{}, error) {
|
||||
req := request.(*getHostMDMSummaryRequest)
|
||||
resp := getHostMDMSummaryResponse{}
|
||||
var err error
|
||||
|
||||
resp.AggregatedMDMData, err = svc.AggregatedMDMData(ctx, req.TeamID, req.Platform)
|
||||
if err != nil {
|
||||
return getHostMDMSummaryResponse{Err: err}, nil
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Macadmins
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -1016,18 +1060,15 @@ func (svc *Service) AggregatedMacadminsData(ctx context.Context, teamID *uint) (
|
||||
}
|
||||
agg.MunkiIssues = issues
|
||||
|
||||
status, mdmUpdatedAt, err := svc.ds.AggregatedMDMStatus(ctx, teamID)
|
||||
var mdmUpdatedAt, mdmSolutionsUpdatedAt time.Time
|
||||
agg.MDMStatus, mdmUpdatedAt, err = svc.ds.AggregatedMDMStatus(ctx, teamID, "darwin")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
agg.MDMStatus = status
|
||||
|
||||
solutions, mdmSolutionsUpdatedAt, err := svc.ds.AggregatedMDMSolutions(ctx, teamID)
|
||||
agg.MDMSolutions, mdmSolutionsUpdatedAt, err = svc.ds.AggregatedMDMSolutions(ctx, teamID, "darwin")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
agg.MDMSolutions = solutions
|
||||
|
||||
agg.CountsUpdatedAt = munkiUpdatedAt
|
||||
if munkiIssUpdatedAt.After(agg.CountsUpdatedAt) {
|
||||
agg.CountsUpdatedAt = munkiIssUpdatedAt
|
||||
@ -1042,6 +1083,48 @@ func (svc *Service) AggregatedMacadminsData(ctx context.Context, teamID *uint) (
|
||||
return agg, nil
|
||||
}
|
||||
|
||||
func (svc *Service) MDMData(ctx context.Context, id uint) (*fleet.HostMDM, error) {
|
||||
if err := svc.authz.Authorize(ctx, &fleet.Host{}, fleet.ActionList); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
host, err := svc.ds.HostLite(ctx, id)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "find host for MDMData")
|
||||
}
|
||||
|
||||
if err := svc.authz.Authorize(ctx, host, fleet.ActionRead); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var mdm *fleet.HostMDM
|
||||
switch hmdm, err := svc.ds.GetHostMDM(ctx, id); {
|
||||
case err != nil && !fleet.IsNotFound(err):
|
||||
return nil, err
|
||||
case err == nil:
|
||||
mdm = hmdm
|
||||
}
|
||||
return mdm, nil
|
||||
}
|
||||
|
||||
func (svc *Service) AggregatedMDMData(ctx context.Context, teamID *uint, platform string) (fleet.AggregatedMDMData, error) {
|
||||
if err := svc.authz.Authorize(ctx, &fleet.Host{TeamID: teamID}, fleet.ActionList); err != nil {
|
||||
return fleet.AggregatedMDMData{}, err
|
||||
}
|
||||
|
||||
var err error
|
||||
data := fleet.AggregatedMDMData{}
|
||||
data.MDMStatus, _, err = svc.ds.AggregatedMDMStatus(ctx, teamID, platform)
|
||||
if err != nil {
|
||||
return fleet.AggregatedMDMData{}, err
|
||||
}
|
||||
data.MDMSolutions, _, err = svc.ds.AggregatedMDMSolutions(ctx, teamID, platform)
|
||||
if err != nil {
|
||||
return fleet.AggregatedMDMData{}, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Hosts Report in CSV downloadable file
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -932,7 +932,7 @@ func (s *integrationTestSuite) TestHostsCount() {
|
||||
require.Equal(t, 0, resp.Count)
|
||||
|
||||
// set MDM information on a host
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(context.Background(), hosts[1].ID, true, "https://simplemdm.com", false))
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(context.Background(), hosts[1].ID, true, "https://simplemdm.com", false, ""))
|
||||
var mdmID uint
|
||||
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error {
|
||||
return sqlx.GetContext(context.Background(), q, &mdmID,
|
||||
@ -1119,7 +1119,7 @@ func (s *integrationTestSuite) TestListHosts() {
|
||||
assert.Nil(t, resp.MunkiIssue)
|
||||
|
||||
// set MDM information on a host
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(context.Background(), host.ID, true, "https://simplemdm.com", false))
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(context.Background(), host.ID, true, "https://simplemdm.com", false, ""))
|
||||
var mdmID uint
|
||||
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error {
|
||||
return sqlx.GetContext(context.Background(), q, &mdmID,
|
||||
@ -2542,6 +2542,7 @@ func (s *integrationTestSuite) TestGetMacadminsData() {
|
||||
PrimaryIP: "192.168.1.1",
|
||||
PrimaryMac: "30-65-EC-6F-C4-58",
|
||||
OsqueryHostID: "1",
|
||||
Platform: "darwin",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, hostAll)
|
||||
@ -2557,6 +2558,7 @@ func (s *integrationTestSuite) TestGetMacadminsData() {
|
||||
PrimaryIP: "192.168.1.2",
|
||||
PrimaryMac: "30-65-EC-6F-C4-59",
|
||||
OsqueryHostID: "2",
|
||||
Platform: "darwin",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, hostNothing)
|
||||
@ -2572,6 +2574,7 @@ func (s *integrationTestSuite) TestGetMacadminsData() {
|
||||
PrimaryIP: "192.168.1.3",
|
||||
PrimaryMac: "30-65-EC-6F-C4-5F",
|
||||
OsqueryHostID: "3",
|
||||
Platform: "darwin",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, hostOnlyMunki)
|
||||
@ -2587,6 +2590,7 @@ func (s *integrationTestSuite) TestGetMacadminsData() {
|
||||
PrimaryIP: "192.168.1.4",
|
||||
PrimaryMac: "30-65-EC-6F-C4-5A",
|
||||
OsqueryHostID: "4",
|
||||
Platform: "darwin",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, hostOnlyMDM)
|
||||
@ -2602,6 +2606,7 @@ func (s *integrationTestSuite) TestGetMacadminsData() {
|
||||
PrimaryIP: "192.168.1.5",
|
||||
PrimaryMac: "30-65-EC-6F-D5-5A",
|
||||
OsqueryHostID: "5",
|
||||
Platform: "darwin",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, hostMDMNoID)
|
||||
@ -2614,7 +2619,7 @@ func (s *integrationTestSuite) TestGetMacadminsData() {
|
||||
return err
|
||||
})
|
||||
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(ctx, hostAll.ID, true, "url", false))
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(ctx, hostAll.ID, true, "url", false, ""))
|
||||
require.NoError(t, s.ds.SetOrUpdateMunkiInfo(ctx, hostAll.ID, "1.3.0", []string{"error1"}, []string{"warning1"}))
|
||||
|
||||
macadminsData := macadminsDataResponse{}
|
||||
@ -2641,7 +2646,7 @@ func (s *integrationTestSuite) TestGetMacadminsData() {
|
||||
assert.False(t, macadminsData.Macadmins.MunkiIssues[1].HostIssueCreatedAt.IsZero())
|
||||
assert.Equal(t, "warning", macadminsData.Macadmins.MunkiIssues[1].IssueType)
|
||||
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(ctx, hostAll.ID, true, "https://simplemdm.com", true))
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(ctx, hostAll.ID, true, "https://simplemdm.com", true, ""))
|
||||
require.NoError(t, s.ds.SetOrUpdateMunkiInfo(ctx, hostAll.ID, "1.5.0", []string{"error1"}, nil))
|
||||
|
||||
macadminsData = macadminsDataResponse{}
|
||||
@ -2657,7 +2662,7 @@ func (s *integrationTestSuite) TestGetMacadminsData() {
|
||||
require.Len(t, macadminsData.Macadmins.MunkiIssues, 1)
|
||||
assert.Equal(t, "error1", macadminsData.Macadmins.MunkiIssues[0].Name)
|
||||
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(ctx, hostAll.ID, false, "url2", false))
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(ctx, hostAll.ID, false, "url2", false, ""))
|
||||
|
||||
macadminsData = macadminsDataResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/macadmins", hostAll.ID), nil, http.StatusOK, &macadminsData)
|
||||
@ -2685,7 +2690,7 @@ func (s *integrationTestSuite) TestGetMacadminsData() {
|
||||
assert.Equal(t, "warning1", macadminsData.Macadmins.MunkiIssues[0].Name)
|
||||
|
||||
// only mdm returns null on munki info
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(ctx, hostOnlyMDM.ID, true, "https://kandji.io", true))
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(ctx, hostOnlyMDM.ID, true, "https://kandji.io", true, ""))
|
||||
macadminsData = macadminsDataResponse{}
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/macadmins", hostOnlyMDM.ID), nil, http.StatusOK, &macadminsData)
|
||||
require.NotNil(t, macadminsData.Macadmins)
|
||||
|
@ -29,7 +29,7 @@ func (s *integrationTestSuite) TestDeviceAuthenticatedEndpoints() {
|
||||
{HostID: hosts[0].ID, Email: "a@b.c", Source: "google_chrome_profiles"},
|
||||
{HostID: hosts[0].ID, Email: "b@b.c", Source: "google_chrome_profiles"},
|
||||
})
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(context.Background(), hosts[0].ID, true, "url", false))
|
||||
require.NoError(t, s.ds.SetOrUpdateMDMData(context.Background(), hosts[0].ID, true, "url", false, ""))
|
||||
require.NoError(t, s.ds.SetOrUpdateMunkiInfo(context.Background(), hosts[0].ID, "1.3.0", nil, nil))
|
||||
// create a battery for hosts[0]
|
||||
require.NoError(t, s.ds.ReplaceHostBatteries(context.Background(), hosts[0].ID, []*fleet.HostBattery{
|
||||
|
@ -560,11 +560,11 @@ func TestHostDetailQueries(t *testing.T) {
|
||||
|
||||
queries, discovery, err = svc.detailQueriesForHost(context.Background(), &host)
|
||||
require.NoError(t, err)
|
||||
// 2 - 4 = -2
|
||||
// 2 - 5 = -3
|
||||
// └───┼────┼─► additional queries: bim, foobar
|
||||
// └────┼─► windows specific queries: os_windows, os_version_windows, network_interface_windows, disk_space_windows
|
||||
// └─► net difference
|
||||
require.Equal(t, len(expectedDetailQueries)-2, len(queries), distQueriesMapKeys(queries))
|
||||
require.Equal(t, len(expectedDetailQueries)-3, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
for name := range queries {
|
||||
assert.True(t,
|
||||
@ -744,8 +744,8 @@ func TestLabelQueries(t *testing.T) {
|
||||
// should be turned on so that we can quickly fill labels)
|
||||
queries, discovery, acc, err := svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// -4 windows specific queries: disk_space_windows, network_interface_windows, os_windows, os_version_windows
|
||||
require.Equal(t, len(expectedDetailQueries)-4, len(queries), distQueriesMapKeys(queries))
|
||||
// -5 windows specific queries: disk_space_windows, network_interface_windows, os_windows, os_version_windows
|
||||
require.Equal(t, len(expectedDetailQueries)-5, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
assert.NotZero(t, acc)
|
||||
|
||||
@ -835,8 +835,8 @@ func TestLabelQueries(t *testing.T) {
|
||||
ctx = hostctx.NewContext(ctx, host)
|
||||
queries, discovery, acc, err = svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// +3 for label queries, but -4 windows specific queries
|
||||
require.Equal(t, len(expectedDetailQueries)-1, len(queries), distQueriesMapKeys(queries))
|
||||
// +3 for label queries, but -5 windows specific queries
|
||||
require.Equal(t, len(expectedDetailQueries)-2, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
assert.Zero(t, acc)
|
||||
|
||||
@ -1051,8 +1051,8 @@ func TestDetailQueriesWithEmptyStrings(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
// somehow confusingly, the query response above changed the host's platform
|
||||
// from windows to darwin
|
||||
// -4 windows queries
|
||||
require.Equal(t, len(expectedDetailQueries)-4, len(queries), distQueriesMapKeys(queries))
|
||||
// -5 windows queries
|
||||
require.Equal(t, len(expectedDetailQueries)-5, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
assert.Zero(t, acc)
|
||||
}
|
||||
@ -1080,7 +1080,7 @@ func TestDetailQueries(t *testing.T) {
|
||||
ds.PolicyQueriesForHostFunc = func(ctx context.Context, host *fleet.Host) (map[string]string, error) {
|
||||
return map[string]string{}, nil
|
||||
}
|
||||
ds.SetOrUpdateMDMDataFunc = func(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool) error {
|
||||
ds.SetOrUpdateMDMDataFunc = func(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool, name string) error {
|
||||
require.True(t, enrolled)
|
||||
require.False(t, installedFromDep)
|
||||
require.Equal(t, "hi.com", serverURL)
|
||||
@ -1115,8 +1115,8 @@ func TestDetailQueries(t *testing.T) {
|
||||
// queries)
|
||||
queries, discovery, acc, err := svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// -3 macos queries, -4 windows quries, +1 for software inventory
|
||||
if !assert.Equal(t, len(expectedDetailQueries)-6, len(queries)) {
|
||||
// -3 macos queries, -5 windows quries, +1 for software inventory
|
||||
if !assert.Equal(t, len(expectedDetailQueries)-3-5+1, len(queries)) {
|
||||
// this is just to print the diff between the expected and actual query
|
||||
// keys when the count assertion fails, to help debugging - they are not
|
||||
// expected to match.
|
||||
@ -1373,8 +1373,8 @@ func TestDetailQueries(t *testing.T) {
|
||||
|
||||
queries, discovery, acc, err = svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// -4 windows queries, +1 software inventory
|
||||
require.Equal(t, len(expectedDetailQueries)-3, len(queries), distQueriesMapKeys(queries))
|
||||
// -5 windows queries, +1 software inventory
|
||||
require.Equal(t, len(expectedDetailQueries)-4, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
assert.Zero(t, acc)
|
||||
}
|
||||
@ -2339,8 +2339,8 @@ func TestPolicyQueries(t *testing.T) {
|
||||
|
||||
queries, discovery, _, err := svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// all queries -4 windows only queries +2 policy queries
|
||||
require.Equal(t, len(expectedDetailQueries)-2, len(queries), distQueriesMapKeys(queries))
|
||||
// all queries -5 windows only queries +2 policy queries
|
||||
require.Equal(t, len(expectedDetailQueries)-3, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
|
||||
checkPolicyResults := func(queries map[string]string) {
|
||||
@ -2396,8 +2396,8 @@ func TestPolicyQueries(t *testing.T) {
|
||||
ctx = hostctx.NewContext(context.Background(), host)
|
||||
queries, discovery, _, err = svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// all standard queries -4 windows only queries
|
||||
require.Equal(t, len(expectedDetailQueries)-4, len(queries), distQueriesMapKeys(queries))
|
||||
// all standard queries -5 windows only queries
|
||||
require.Equal(t, len(expectedDetailQueries)-5, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
noPolicyResults(queries)
|
||||
|
||||
@ -2406,8 +2406,8 @@ func TestPolicyQueries(t *testing.T) {
|
||||
|
||||
queries, discovery, _, err = svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// all standard queries -4 windows only queries +2 policy queries
|
||||
require.Equal(t, len(expectedDetailQueries)-2, len(queries), distQueriesMapKeys(queries))
|
||||
// all standard queries -5 windows only queries +2 policy queries
|
||||
require.Equal(t, len(expectedDetailQueries)-3, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
checkPolicyResults(queries)
|
||||
|
||||
@ -2435,8 +2435,8 @@ func TestPolicyQueries(t *testing.T) {
|
||||
ctx = hostctx.NewContext(context.Background(), host)
|
||||
queries, discovery, _, err = svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// all standard queries -4 windows only queries
|
||||
require.Equal(t, len(expectedDetailQueries)-4, len(queries), distQueriesMapKeys(queries))
|
||||
// all standard queries -5 windows only queries
|
||||
require.Equal(t, len(expectedDetailQueries)-5, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
noPolicyResults(queries)
|
||||
|
||||
@ -2445,8 +2445,8 @@ func TestPolicyQueries(t *testing.T) {
|
||||
ctx = hostctx.NewContext(context.Background(), host)
|
||||
queries, discovery, _, err = svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// all standard queries -4 windows only queries +2 policy queries
|
||||
require.Equal(t, len(expectedDetailQueries)-2, len(queries), distQueriesMapKeys(queries))
|
||||
// all standard queries -5 windows only queries +2 policy queries
|
||||
require.Equal(t, len(expectedDetailQueries)-3, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
checkPolicyResults(queries)
|
||||
|
||||
@ -2476,8 +2476,8 @@ func TestPolicyQueries(t *testing.T) {
|
||||
ctx = hostctx.NewContext(context.Background(), host)
|
||||
queries, discovery, _, err = svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// all standard queries -4 windows only queries
|
||||
require.Equal(t, len(expectedDetailQueries)-4, len(queries), distQueriesMapKeys(queries))
|
||||
// all standard queries -5 windows only queries
|
||||
require.Equal(t, len(expectedDetailQueries)-5, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
noPolicyResults(queries)
|
||||
}
|
||||
@ -2542,8 +2542,8 @@ func TestPolicyWebhooks(t *testing.T) {
|
||||
|
||||
queries, discovery, _, err := svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// all queries -4 windows only, +3 for policies
|
||||
require.Equal(t, len(expectedDetailQueries)-1, len(queries), distQueriesMapKeys(queries))
|
||||
// all queries -5 windows only, +3 for policies
|
||||
require.Equal(t, len(expectedDetailQueries)-2, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
|
||||
checkPolicyResults := func(queries map[string]string) {
|
||||
@ -2656,8 +2656,8 @@ func TestPolicyWebhooks(t *testing.T) {
|
||||
ctx = hostctx.NewContext(context.Background(), host)
|
||||
queries, discovery, _, err = svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// all queries -4 windows only queries
|
||||
require.Equal(t, len(expectedDetailQueries)-4, len(queries), distQueriesMapKeys(queries))
|
||||
// all queries -5 windows only queries
|
||||
require.Equal(t, len(expectedDetailQueries)-5, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
noPolicyResults(queries)
|
||||
|
||||
@ -2666,8 +2666,8 @@ func TestPolicyWebhooks(t *testing.T) {
|
||||
|
||||
queries, discovery, _, err = svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// all queries -4 windows only queries, +3 for policies
|
||||
require.Equal(t, len(expectedDetailQueries)-1, len(queries), distQueriesMapKeys(queries))
|
||||
// all queries -5 windows only queries, +3 for policies
|
||||
require.Equal(t, len(expectedDetailQueries)-2, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
checkPolicyResults(queries)
|
||||
|
||||
@ -2791,7 +2791,7 @@ func TestLiveQueriesFailing(t *testing.T) {
|
||||
queries, discovery, _, err := svc.GetDistributedQueries(ctx)
|
||||
require.NoError(t, err)
|
||||
// all standard queries minus windows only queries
|
||||
require.Equal(t, len(expectedDetailQueries)-4, len(queries), distQueriesMapKeys(queries))
|
||||
require.Equal(t, len(expectedDetailQueries)-5, len(queries), distQueriesMapKeys(queries))
|
||||
verifyDiscovery(t, queries, discovery)
|
||||
|
||||
logs, err := io.ReadAll(buf)
|
||||
|
@ -440,10 +440,24 @@ func ingestKubequeryInfo(ctx context.Context, logger log.Logger, host *fleet.Hos
|
||||
var extraDetailQueries = map[string]DetailQuery{
|
||||
"mdm": {
|
||||
Query: `select enrolled, server_url, installed_from_dep from mdm;`,
|
||||
DirectIngestFunc: directIngestMDM,
|
||||
DirectIngestFunc: directIngestMDMMac,
|
||||
Platforms: []string{"darwin"},
|
||||
Discovery: discoveryTable("mdm"),
|
||||
},
|
||||
"mdm_windows": {
|
||||
Query: `
|
||||
SELECT provid.providerID, url.discoveryServiceURL, autopilot.autopilot FROM (
|
||||
SELECT data providerID FROM registry WHERE path LIKE 'HKEY_LOCAL_MACHINE\Software\Microsoft\Enrollments\%\ProviderID'
|
||||
) provid, (
|
||||
SELECT data discoveryServiceURL FROM registry WHERE path LIKE 'HKEY_LOCAL_MACHINE\Software\Microsoft\Enrollments\%\DiscoveryServiceFullURL'
|
||||
) url, ( SELECT EXISTS (
|
||||
SELECT 1 FROM registry WHERE KEY LIKE 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\AutopilotPolicyCache'
|
||||
) autopilot
|
||||
) autopilot;
|
||||
`,
|
||||
DirectIngestFunc: directIngestMDMWindows,
|
||||
Platforms: []string{"windows"},
|
||||
},
|
||||
"munki_info": {
|
||||
Query: `select version, errors, warnings from munki_info;`,
|
||||
DirectIngestFunc: directIngestMunkiInfo,
|
||||
@ -1179,7 +1193,7 @@ func directIngestUsers(ctx context.Context, logger log.Logger, host *fleet.Host,
|
||||
return nil
|
||||
}
|
||||
|
||||
func directIngestMDM(ctx context.Context, logger log.Logger, host *fleet.Host, ds fleet.Datastore, rows []map[string]string, failed bool) error {
|
||||
func directIngestMDMMac(ctx context.Context, logger log.Logger, host *fleet.Host, ds fleet.Datastore, rows []map[string]string, failed bool) error {
|
||||
if len(rows) == 0 || failed {
|
||||
// assume the extension is not there
|
||||
return nil
|
||||
@ -1205,7 +1219,27 @@ func directIngestMDM(ctx context.Context, logger log.Logger, host *fleet.Host, d
|
||||
}
|
||||
}
|
||||
|
||||
return ds.SetOrUpdateMDMData(ctx, host.ID, enrolled, rows[0]["server_url"], installedFromDep)
|
||||
return ds.SetOrUpdateMDMData(ctx, host.ID, enrolled, rows[0]["server_url"], installedFromDep, "")
|
||||
}
|
||||
|
||||
func directIngestMDMWindows(ctx context.Context, logger log.Logger, host *fleet.Host, ds fleet.Datastore, rows []map[string]string, failed bool) error {
|
||||
if failed {
|
||||
level.Error(logger).Log("op", "directIngestMDMWindows", "err", "failed")
|
||||
return nil
|
||||
}
|
||||
if len(rows) > 1 {
|
||||
logger.Log("component", "service", "method", "ingestMDMWindows", "warn",
|
||||
fmt.Sprintf("mdm_windows expected single result got %d", len(rows)))
|
||||
}
|
||||
if len(rows) == 0 {
|
||||
return ds.SetOrUpdateMDMData(ctx, host.ID, false, "", false, "")
|
||||
}
|
||||
autoPilot, err := strconv.ParseBool(rows[0]["autopilot"])
|
||||
if err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "parsing autopilot")
|
||||
}
|
||||
|
||||
return ds.SetOrUpdateMDMData(ctx, host.ID, true, rows[0]["discoveryServiceURL"], autoPilot, rows[0]["providerID"])
|
||||
}
|
||||
|
||||
func directIngestMunkiInfo(ctx context.Context, logger log.Logger, host *fleet.Host, ds fleet.Datastore, rows []map[string]string, failed bool) error {
|
||||
|
@ -235,7 +235,6 @@ func sortedKeysCompare(t *testing.T, m map[string]DetailQuery, expectedKeys []st
|
||||
|
||||
func TestGetDetailQueries(t *testing.T) {
|
||||
queriesNoConfig := GetDetailQueries(config.FleetConfig{}, nil)
|
||||
require.Len(t, queriesNoConfig, 19)
|
||||
|
||||
baseQueries := []string{
|
||||
"network_interface_unix",
|
||||
@ -249,6 +248,7 @@ func TestGetDetailQueries(t *testing.T) {
|
||||
"disk_space_unix",
|
||||
"disk_space_windows",
|
||||
"mdm",
|
||||
"mdm_windows",
|
||||
"munki_info",
|
||||
"google_chrome_profiles",
|
||||
"battery",
|
||||
@ -258,19 +258,22 @@ func TestGetDetailQueries(t *testing.T) {
|
||||
"kubequery_info",
|
||||
"orbit_info",
|
||||
}
|
||||
|
||||
require.Len(t, queriesNoConfig, len(baseQueries))
|
||||
sortedKeysCompare(t, queriesNoConfig, baseQueries)
|
||||
|
||||
queriesWithoutWinOSVuln := GetDetailQueries(config.FleetConfig{Vulnerabilities: config.VulnerabilitiesConfig{DisableWinOSVulnerabilities: true}}, nil)
|
||||
require.Len(t, queriesWithoutWinOSVuln, 18)
|
||||
require.Len(t, queriesWithoutWinOSVuln, 19)
|
||||
|
||||
queriesWithUsers := GetDetailQueries(config.FleetConfig{App: config.AppConfig{EnableScheduledQueryStats: true}}, &fleet.Features{EnableHostUsers: true})
|
||||
require.Len(t, queriesWithUsers, 21)
|
||||
sortedKeysCompare(t, queriesWithUsers, append(baseQueries, "users", "scheduled_query_stats"))
|
||||
qs := append(baseQueries, "users", "scheduled_query_stats")
|
||||
require.Len(t, queriesWithUsers, len(qs))
|
||||
sortedKeysCompare(t, queriesWithUsers, qs)
|
||||
|
||||
queriesWithUsersAndSoftware := GetDetailQueries(config.FleetConfig{App: config.AppConfig{EnableScheduledQueryStats: true}}, &fleet.Features{EnableHostUsers: true, EnableSoftwareInventory: true})
|
||||
require.Len(t, queriesWithUsersAndSoftware, 24)
|
||||
sortedKeysCompare(t, queriesWithUsersAndSoftware,
|
||||
append(baseQueries, "users", "software_macos", "software_linux", "software_windows", "scheduled_query_stats"))
|
||||
qs = append(baseQueries, "users", "software_macos", "software_linux", "software_windows", "scheduled_query_stats")
|
||||
require.Len(t, queriesWithUsersAndSoftware, len(qs))
|
||||
sortedKeysCompare(t, queriesWithUsersAndSoftware, qs)
|
||||
}
|
||||
|
||||
func TestDetailQueriesOSVersionUnixLike(t *testing.T) {
|
||||
@ -402,9 +405,9 @@ func TestDetailQueriesOSVersionWindows(t *testing.T) {
|
||||
assert.Equal(t, "Windows 10 Enterprise LTSC 1809", host.OSVersion)
|
||||
}
|
||||
|
||||
func TestDirectIngestMDM(t *testing.T) {
|
||||
func TestDirectIngestMDMMac(t *testing.T) {
|
||||
ds := new(mock.Store)
|
||||
ds.SetOrUpdateMDMDataFunc = func(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool) error {
|
||||
ds.SetOrUpdateMDMDataFunc = func(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool, name string) error {
|
||||
require.False(t, enrolled)
|
||||
require.False(t, installedFromDep)
|
||||
require.Empty(t, serverURL)
|
||||
@ -413,11 +416,11 @@ func TestDirectIngestMDM(t *testing.T) {
|
||||
|
||||
var host fleet.Host
|
||||
|
||||
err := directIngestMDM(context.Background(), log.NewNopLogger(), &host, ds, []map[string]string{}, true)
|
||||
err := directIngestMDMMac(context.Background(), log.NewNopLogger(), &host, ds, []map[string]string{}, true)
|
||||
require.NoError(t, err)
|
||||
require.False(t, ds.SetOrUpdateMDMDataFuncInvoked)
|
||||
|
||||
err = directIngestMDM(context.Background(), log.NewNopLogger(), &host, ds, []map[string]string{
|
||||
err = directIngestMDMMac(context.Background(), log.NewNopLogger(), &host, ds, []map[string]string{
|
||||
{
|
||||
"enrolled": "false",
|
||||
"installed_from_dep": "",
|
||||
@ -428,6 +431,31 @@ func TestDirectIngestMDM(t *testing.T) {
|
||||
require.True(t, ds.SetOrUpdateMDMDataFuncInvoked)
|
||||
}
|
||||
|
||||
func TestDirectIngestMDMWindows(t *testing.T) {
|
||||
ds := new(mock.Store)
|
||||
ds.SetOrUpdateMDMDataFunc = func(ctx context.Context, hostID uint, enrolled bool, serverURL string, installedFromDep bool, name string) error {
|
||||
require.True(t, enrolled)
|
||||
require.True(t, installedFromDep)
|
||||
require.NotEmpty(t, serverURL)
|
||||
return nil
|
||||
}
|
||||
|
||||
var host fleet.Host
|
||||
err := directIngestMDMWindows(context.Background(), log.NewNopLogger(), &host, ds, []map[string]string{}, true)
|
||||
require.NoError(t, err)
|
||||
require.False(t, ds.SetOrUpdateMDMDataFuncInvoked)
|
||||
|
||||
err = directIngestMDMWindows(context.Background(), log.NewNopLogger(), &host, ds, []map[string]string{
|
||||
{
|
||||
"discoveryServiceURL": "some url",
|
||||
"autopilot": "true",
|
||||
"providerID": "1337",
|
||||
},
|
||||
}, false)
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.SetOrUpdateMDMDataFuncInvoked)
|
||||
}
|
||||
|
||||
func TestDirectIngestChromeProfiles(t *testing.T) {
|
||||
ds := new(mock.Store)
|
||||
ds.ReplaceHostDeviceMappingFunc = func(ctx context.Context, hostID uint, mapping []*fleet.HostDeviceMapping) error {
|
||||
|
@ -108,6 +108,12 @@ func WithComputerName(s string) NewHostOption {
|
||||
}
|
||||
}
|
||||
|
||||
func WithPlatform(s string) NewHostOption {
|
||||
return func(h *fleet.Host) {
|
||||
h.Platform = s
|
||||
}
|
||||
}
|
||||
|
||||
func NewHost(tb testing.TB, ds fleet.Datastore, name, ip, key, uuid string, now time.Time, options ...NewHostOption) *fleet.Host {
|
||||
osqueryHostID, _ := server.GenerateRandomText(10)
|
||||
h := &fleet.Host{
|
||||
|
Loading…
Reference in New Issue
Block a user