diff --git a/ee/server/service/mdm.go b/ee/server/service/mdm.go index 354ae1e322..674329d9e4 100644 --- a/ee/server/service/mdm.go +++ b/ee/server/service/mdm.go @@ -1013,10 +1013,16 @@ func (svc *Service) GetMDMDiskEncryptionSummary(ctx context.Context, teamID *uin windows = *w } + linux, err := svc.ds.GetLinuxDiskEncryptionSummary(ctx, teamID) + if err != nil { + return nil, ctxerr.Wrap(ctx, err, "getting linux disk encryption summary") + } + return &fleet.MDMDiskEncryptionSummary{ Verified: fleet.MDMPlatformsCounts{ MacOS: macOS.Verified, Windows: windows.Verified, + Linux: linux.Verified, }, Verifying: fleet.MDMPlatformsCounts{ MacOS: macOS.Verifying, @@ -1025,6 +1031,7 @@ func (svc *Service) GetMDMDiskEncryptionSummary(ctx context.Context, teamID *uin ActionRequired: fleet.MDMPlatformsCounts{ MacOS: macOS.ActionRequired, Windows: windows.ActionRequired, + Linux: linux.ActionRequired, }, Enforcing: fleet.MDMPlatformsCounts{ MacOS: macOS.Enforcing, @@ -1033,6 +1040,7 @@ func (svc *Service) GetMDMDiskEncryptionSummary(ctx context.Context, teamID *uin Failed: fleet.MDMPlatformsCounts{ MacOS: macOS.Failed, Windows: windows.Failed, + Linux: linux.Failed, }, RemovingEnforcement: fleet.MDMPlatformsCounts{ MacOS: macOS.RemovingEnforcement, diff --git a/server/datastore/mysql/hosts.go b/server/datastore/mysql/hosts.go index 27f1b778c1..eff646172c 100644 --- a/server/datastore/mysql/hosts.go +++ b/server/datastore/mysql/hosts.go @@ -3921,7 +3921,7 @@ func (ds *Datastore) GetHostDiskEncryptionKey(ctx context.Context, hostID uint) var key fleet.HostDiskEncryptionKey err := sqlx.GetContext(ctx, ds.reader(ctx), &key, ` SELECT - host_id, base64_encrypted, decryptable, updated_at + host_id, base64_encrypted, decryptable, updated_at, client_error FROM host_disk_encryption_keys WHERE host_id = ?`, hostID) diff --git a/server/datastore/mysql/linux_mdm.go b/server/datastore/mysql/linux_mdm.go new file mode 100644 index 0000000000..2cd88843ef --- /dev/null +++ b/server/datastore/mysql/linux_mdm.go @@ -0,0 +1,69 @@ +package mysql + +import ( + "context" + "fmt" + + "github.com/fleetdm/fleet/v4/server/fleet" + "github.com/jmoiron/sqlx" +) + +func (ds *Datastore) GetLinuxDiskEncryptionSummary(ctx context.Context, teamID *uint) (fleet.MDMLinuxDiskEncryptionSummary, error) { + var args []interface{} + var teamFilter string + if teamID != nil { + teamFilter = "AND h.team_id = ?" + args = append(args, *teamID) + } else { + teamFilter = "AND h.team_id IS NULL" + } + + stmt := fmt.Sprintf(`SELECT + CASE WHEN hdek.base64_encrypted IS NOT NULL + AND hdek.base64_encrypted != '' + AND hdek.client_error = '' THEN + 'verified' + WHEN hdek.client_error IS NOT NULL + AND hdek.client_error != '' THEN + 'failed' + WHEN hdek.base64_encrypted IS NULL + OR (hdek.base64_encrypted = '' + AND hdek.client_error = '') THEN + 'action_required' + END AS status, + COUNT(h.id) AS host_count + FROM + hosts h + LEFT JOIN host_disk_encryption_keys hdek ON h.id = hdek.host_id + WHERE + (h.os_version LIKE '%%fedora%%' + OR h.platform LIKE 'ubuntu') + %s + GROUP BY + status`, teamFilter) + + type countRow struct { + Status string `db:"status"` + HostCount uint `db:"host_count"` + } + + var counts []countRow + summary := fleet.MDMLinuxDiskEncryptionSummary{} + + if err := sqlx.SelectContext(ctx, ds.reader(ctx), &counts, stmt, args...); err != nil { + return summary, err + } + + for _, count := range counts { + switch count.Status { + case "verified": + summary.Verified = count.HostCount + case "action_required": + summary.ActionRequired = count.HostCount + case "failed": + summary.Failed = count.HostCount + } + } + + return summary, nil +} diff --git a/server/datastore/mysql/linux_mdm_test.go b/server/datastore/mysql/linux_mdm_test.go new file mode 100644 index 0000000000..d0cecb405b --- /dev/null +++ b/server/datastore/mysql/linux_mdm_test.go @@ -0,0 +1,146 @@ +package mysql + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/fleetdm/fleet/v4/server/fleet" + "github.com/fleetdm/fleet/v4/server/test" + "github.com/stretchr/testify/require" +) + +func TestLinuxDiskEncryptionSummary(t *testing.T) { + ds := CreateMySQLDS(t) + ctx := context.Background() + + // 5 new ubuntu hosts + var ubuntuHosts []*fleet.Host + for i := 0; i < 5; i++ { + h := test.NewHost(t, ds, fmt.Sprintf("foo.local.%d", i), "1.1.1.1", + fmt.Sprintf("%d", i), fmt.Sprintf("%d", i), time.Now(), test.WithPlatform("ubuntu")) + ubuntuHosts = append(ubuntuHosts, h) + } + + // 5 new fedora hosts + var fedoraHosts []*fleet.Host + for i := 5; i < 10; i++ { + h := test.NewHost(t, ds, fmt.Sprintf("foo.local.%d", i), "1.1.1.1", + fmt.Sprintf("%d", i), fmt.Sprintf("%d", i), time.Now(), + test.WithOSVersion("Fedora Linux 38.0.0"), test.WithPlatform("rhel")) + fedoraHosts = append(fedoraHosts, h) + } + + // 5 macos hosts + var macosHosts []*fleet.Host + for i := 10; i < 15; i++ { + h := test.NewHost(t, ds, fmt.Sprintf("foo.local.%d", i), "1.1.1.1", + fmt.Sprintf("%d", i), fmt.Sprintf("%d", i), time.Now(), test.WithPlatform("darwin")) + macosHosts = append(macosHosts, h) + } + + // no teams tests ===== + summary, err := ds.GetLinuxDiskEncryptionSummary(ctx, nil) + require.NoError(t, err) + + require.Equal(t, uint(0), summary.Verified) + require.Equal(t, uint(10), summary.ActionRequired) + require.Equal(t, uint(0), summary.Failed) + + // Add disk encryption keys + + // ubuntu + err = ds.SetOrUpdateHostDiskEncryptionKey(ctx, ubuntuHosts[0].ID, "base64_encrypted", "", nil) + require.NoError(t, err) + // fedora + err = ds.SetOrUpdateHostDiskEncryptionKey(ctx, fedoraHosts[0].ID, "base64_encrypted", "", nil) + require.NoError(t, err) + // macos + err = ds.SetOrUpdateHostDiskEncryptionKey(ctx, macosHosts[0].ID, "base64_encrypted", "", nil) + require.NoError(t, err) + + summary, err = ds.GetLinuxDiskEncryptionSummary(ctx, nil) + require.NoError(t, err) + + require.Equal(t, uint(2), summary.Verified) + require.Equal(t, uint(8), summary.ActionRequired) + require.Equal(t, uint(0), summary.Failed) + + // update ubuntu with key and client error + err = ds.SetOrUpdateHostDiskEncryptionKey(ctx, ubuntuHosts[0].ID, "base64_encrypted", "client error", nil) + require.NoError(t, err) + + summary, err = ds.GetLinuxDiskEncryptionSummary(ctx, nil) + require.NoError(t, err) + + require.Equal(t, uint(1), summary.Verified) + require.Equal(t, uint(8), summary.ActionRequired) + require.Equal(t, uint(1), summary.Failed) + + // add ubuntu with no key and client error + err = ds.SetOrUpdateHostDiskEncryptionKey(ctx, ubuntuHosts[1].ID, "", "client error", nil) + require.NoError(t, err) + + summary, err = ds.GetLinuxDiskEncryptionSummary(ctx, nil) + require.NoError(t, err) + + require.Equal(t, uint(1), summary.Verified) + require.Equal(t, uint(7), summary.ActionRequired) + require.Equal(t, uint(2), summary.Failed) + + // move verified fedora host to team will remove existing key + team, err := ds.NewTeam(ctx, &fleet.Team{Name: "team1"}) + require.NoError(t, err) + + err = ds.AddHostsToTeam(ctx, &team.ID, []uint{fedoraHosts[0].ID}) + require.NoError(t, err) + + // team summary + summary, err = ds.GetLinuxDiskEncryptionSummary(ctx, &team.ID) + require.NoError(t, err) + + require.Equal(t, uint(0), summary.Verified) + require.Equal(t, uint(1), summary.ActionRequired) + require.Equal(t, uint(0), summary.Failed) + + // no team summary + summary, err = ds.GetLinuxDiskEncryptionSummary(ctx, nil) + require.NoError(t, err) + + require.Equal(t, uint(0), summary.Verified) + require.Equal(t, uint(7), summary.ActionRequired) + require.Equal(t, uint(2), summary.Failed) + + // move all hosts to team + for _, h := range ubuntuHosts { + err = ds.AddHostsToTeam(ctx, &team.ID, []uint{h.ID}) + require.NoError(t, err) + } + + for _, h := range fedoraHosts { + err = ds.AddHostsToTeam(ctx, &team.ID, []uint{h.ID}) + require.NoError(t, err) + } + + for _, h := range macosHosts { + err = ds.AddHostsToTeam(ctx, &team.ID, []uint{h.ID}) + require.NoError(t, err) + } + + // team summary + summary, err = ds.GetLinuxDiskEncryptionSummary(ctx, &team.ID) + require.NoError(t, err) + + require.Equal(t, uint(0), summary.Verified) + require.Equal(t, uint(10), summary.ActionRequired) + require.Equal(t, uint(0), summary.Failed) + + // no team summary + summary, err = ds.GetLinuxDiskEncryptionSummary(ctx, nil) + require.NoError(t, err) + + require.Equal(t, uint(0), summary.Verified) + require.Equal(t, uint(0), summary.ActionRequired) + require.Equal(t, uint(0), summary.Failed) +} diff --git a/server/fleet/datastore.go b/server/fleet/datastore.go index 12aeeacf2f..b1bcc4b7b2 100644 --- a/server/fleet/datastore.go +++ b/server/fleet/datastore.go @@ -1513,6 +1513,14 @@ type Datastore interface { // GetHostMDMProfileInstallStatus returns the status of the profile for the host. GetHostMDMProfileInstallStatus(ctx context.Context, hostUUID string, profileUUID string) (MDMDeliveryStatus, error) + /////////////////////////////////////////////////////////////////////////////// + // Linux MDM + + // GetLinuxDiskEncryptionSummary summarizes the current state of Linux disk encryption on + // each Linux host in the specified team (or, if no team is specified, each host that is not assigned + // to any team). + GetLinuxDiskEncryptionSummary(ctx context.Context, teamID *uint) (MDMLinuxDiskEncryptionSummary, error) + /////////////////////////////////////////////////////////////////////////////// // MDM Commands diff --git a/server/fleet/hosts.go b/server/fleet/hosts.go index 407af288f8..95ce9ee268 100644 --- a/server/fleet/hosts.go +++ b/server/fleet/hosts.go @@ -1179,6 +1179,7 @@ type HostDiskEncryptionKey struct { Decryptable *bool `json:"-" db:"decryptable"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` DecryptedValue string `json:"key" db:"-"` + ClientError string `json:"-" db:"client_error"` } // HostSoftwareInstalledPath represents where in the file system a software on a host was installed diff --git a/server/fleet/linux_mdm.go b/server/fleet/linux_mdm.go new file mode 100644 index 0000000000..7a9a5544e1 --- /dev/null +++ b/server/fleet/linux_mdm.go @@ -0,0 +1,7 @@ +package fleet + +type MDMLinuxDiskEncryptionSummary struct { + Verified uint `json:"verified"` + ActionRequired uint `json:"action_required"` + Failed uint `json:"failed"` +} diff --git a/server/fleet/mdm.go b/server/fleet/mdm.go index 7f717eeb14..55e28bc7b9 100644 --- a/server/fleet/mdm.go +++ b/server/fleet/mdm.go @@ -298,6 +298,7 @@ type MDMCommandFilters struct { type MDMPlatformsCounts struct { MacOS uint `db:"macos" json:"macos"` Windows uint `db:"windows" json:"windows"` + Linux uint `db:"linux" json:"linux"` } type MDMDiskEncryptionSummary struct { diff --git a/server/fleet/service.go b/server/fleet/service.go index 79b3f19222..902ecad0d1 100644 --- a/server/fleet/service.go +++ b/server/fleet/service.go @@ -1052,6 +1052,13 @@ type Service interface { assumeEnabled *bool, ) error + /////////////////////////////////////////////////////////////////////////////// + // Linux MDM + + // LinuxHostDiskEncryptionStatus returns the current disk encryption status of the specified Linux host + // Returns empty status if the host is not a supported Linux host + LinuxHostDiskEncryptionStatus(ctx context.Context, host Host) (HostMDMDiskEncryption, error) + /////////////////////////////////////////////////////////////////////////////// // Common MDM diff --git a/server/mock/datastore_mock.go b/server/mock/datastore_mock.go index 169e64cde4..d793428ad7 100644 --- a/server/mock/datastore_mock.go +++ b/server/mock/datastore_mock.go @@ -987,6 +987,8 @@ type ResendHostMDMProfileFunc func(ctx context.Context, hostUUID string, profile type GetHostMDMProfileInstallStatusFunc func(ctx context.Context, hostUUID string, profileUUID string) (fleet.MDMDeliveryStatus, error) +type GetLinuxDiskEncryptionSummaryFunc func(ctx context.Context, teamID *uint) (fleet.MDMLinuxDiskEncryptionSummary, error) + type GetMDMCommandPlatformFunc func(ctx context.Context, commandUUID string) (string, error) type ListMDMCommandsFunc func(ctx context.Context, tmFilter fleet.TeamFilter, listOpts *fleet.MDMCommandListOptions) ([]*fleet.MDMCommand, error) @@ -2611,6 +2613,9 @@ type DataStore struct { GetHostMDMProfileInstallStatusFunc GetHostMDMProfileInstallStatusFunc GetHostMDMProfileInstallStatusFuncInvoked bool + GetLinuxDiskEncryptionSummaryFunc GetLinuxDiskEncryptionSummaryFunc + GetLinuxDiskEncryptionSummaryFuncInvoked bool + GetMDMCommandPlatformFunc GetMDMCommandPlatformFunc GetMDMCommandPlatformFuncInvoked bool @@ -6256,6 +6261,13 @@ func (s *DataStore) GetHostMDMProfileInstallStatus(ctx context.Context, hostUUID return s.GetHostMDMProfileInstallStatusFunc(ctx, hostUUID, profileUUID) } +func (s *DataStore) GetLinuxDiskEncryptionSummary(ctx context.Context, teamID *uint) (fleet.MDMLinuxDiskEncryptionSummary, error) { + s.mu.Lock() + s.GetLinuxDiskEncryptionSummaryFuncInvoked = true + s.mu.Unlock() + return s.GetLinuxDiskEncryptionSummaryFunc(ctx, teamID) +} + func (s *DataStore) GetMDMCommandPlatform(ctx context.Context, commandUUID string) (string, error) { s.mu.Lock() s.GetMDMCommandPlatformFuncInvoked = true diff --git a/server/service/hosts.go b/server/service/hosts.go index b2ee905999..4af625c202 100644 --- a/server/service/hosts.go +++ b/server/service/hosts.go @@ -1242,6 +1242,20 @@ func (svc *Service) getHostDetails(ctx context.Context, host *fleet.Host, opts f } host.MDM.Profiles = &profiles + if host.IsLUKSSupported() { + status, err := svc.LinuxHostDiskEncryptionStatus(ctx, *host) + if err != nil { + return nil, ctxerr.Wrap(ctx, err, "get host disk encryption status") + } + host.MDM.OSSettings = &fleet.HostMDMOSSettings{ + DiskEncryption: status, + } + + if status.Status != nil && *status.Status == fleet.DiskEncryptionVerified { + host.MDM.EncryptionKeyAvailable = true + } + } + var macOSSetup *fleet.HostMDMMacOSSetup if ac.MDM.EnabledAndConfigured && license.IsPremium(ctx) { macOSSetup, err = svc.ds.GetHostMDMMacOSSetup(ctx, host.ID) diff --git a/server/service/hosts_test.go b/server/service/hosts_test.go index ebca688f3f..035a552486 100644 --- a/server/service/hosts_test.go +++ b/server/service/hosts_test.go @@ -400,6 +400,10 @@ func TestHostDetailsOSSettings(t *testing.T) { return &fleet.HostLockWipeStatus{}, nil } + ds.GetHostDiskEncryptionKeyFunc = func(ctx context.Context, hostID uint) (*fleet.HostDiskEncryptionKey, error) { + return &fleet.HostDiskEncryptionKey{}, nil + } + type testCase struct { name string host *fleet.Host @@ -1316,7 +1320,8 @@ func TestHostEncryptionKey(t *testing.T) { } ds.GetAllMDMConfigAssetsByNameFunc = func(ctx context.Context, assetNames []fleet.MDMAssetName, - _ sqlx.QueryerContext) (map[fleet.MDMAssetName]fleet.MDMConfigAsset, error) { + _ sqlx.QueryerContext, + ) (map[fleet.MDMAssetName]fleet.MDMConfigAsset, error) { return map[fleet.MDMAssetName]fleet.MDMConfigAsset{ fleet.MDMAssetCACert: {Name: fleet.MDMAssetCACert, Value: testCertPEM}, fleet.MDMAssetCAKey: {Name: fleet.MDMAssetCAKey, Value: testKeyPEM}, @@ -1369,7 +1374,8 @@ func TestHostEncryptionKey(t *testing.T) { return nil, keyErr } ds.GetAllMDMConfigAssetsByNameFunc = func(ctx context.Context, assetNames []fleet.MDMAssetName, - _ sqlx.QueryerContext) (map[fleet.MDMAssetName]fleet.MDMConfigAsset, error) { + _ sqlx.QueryerContext, + ) (map[fleet.MDMAssetName]fleet.MDMConfigAsset, error) { return map[fleet.MDMAssetName]fleet.MDMConfigAsset{ fleet.MDMAssetCACert: {Name: fleet.MDMAssetCACert, Value: testCertPEM}, fleet.MDMAssetCAKey: {Name: fleet.MDMAssetCAKey, Value: testKeyPEM}, @@ -1430,7 +1436,8 @@ func TestHostEncryptionKey(t *testing.T) { return nil } ds.GetAllMDMConfigAssetsByNameFunc = func(ctx context.Context, assetNames []fleet.MDMAssetName, - _ sqlx.QueryerContext) (map[fleet.MDMAssetName]fleet.MDMConfigAsset, error) { + _ sqlx.QueryerContext, + ) (map[fleet.MDMAssetName]fleet.MDMConfigAsset, error) { return map[fleet.MDMAssetName]fleet.MDMConfigAsset{ fleet.MDMAssetCACert: {Name: fleet.MDMAssetCACert, Value: testCertPEM}, fleet.MDMAssetCAKey: {Name: fleet.MDMAssetCAKey, Value: testKeyPEM}, diff --git a/server/service/linux_mdm.go b/server/service/linux_mdm.go new file mode 100644 index 0000000000..d4ae8da27e --- /dev/null +++ b/server/service/linux_mdm.go @@ -0,0 +1,44 @@ +package service + +import ( + "context" + + "github.com/fleetdm/fleet/v4/server/fleet" +) + +func (svc *Service) LinuxHostDiskEncryptionStatus(ctx context.Context, host fleet.Host) (fleet.HostMDMDiskEncryption, error) { + if !host.IsLUKSSupported() { + return fleet.HostMDMDiskEncryption{}, nil + } + + actionRequired := fleet.DiskEncryptionActionRequired + verified := fleet.DiskEncryptionVerified + failed := fleet.DiskEncryptionFailed + + key, err := svc.ds.GetHostDiskEncryptionKey(ctx, host.ID) + if err != nil { + if fleet.IsNotFound(err) { + return fleet.HostMDMDiskEncryption{ + Status: &actionRequired, + }, nil + } + return fleet.HostMDMDiskEncryption{}, err + } + + if key.ClientError != "" { + return fleet.HostMDMDiskEncryption{ + Status: &failed, + Detail: key.ClientError, + }, nil + } + + if key.Base64Encrypted == "" { + return fleet.HostMDMDiskEncryption{ + Status: &actionRequired, + }, nil + } + + return fleet.HostMDMDiskEncryption{ + Status: &verified, + }, nil +} diff --git a/server/service/linux_mdm_test.go b/server/service/linux_mdm_test.go new file mode 100644 index 0000000000..05809eb4fc --- /dev/null +++ b/server/service/linux_mdm_test.go @@ -0,0 +1,118 @@ +package service + +import ( + "context" + "testing" + "time" + + "github.com/fleetdm/fleet/v4/server/fleet" + "github.com/fleetdm/fleet/v4/server/mock" + "github.com/fleetdm/fleet/v4/server/ptr" + "github.com/stretchr/testify/assert" +) + +func TestLinuxHostDiskEncryptionStatus(t *testing.T) { + ds := new(mock.Store) + svc, ctx := newTestService(t, ds, nil, nil) + + actionRequired := fleet.DiskEncryptionActionRequired + verified := fleet.DiskEncryptionVerified + failed := fleet.DiskEncryptionFailed + + testcases := []struct { + name string + host fleet.Host + keyExists bool + clientErrorExists bool + status fleet.HostMDMDiskEncryption + notFound bool + }{ + { + name: "no key", + host: fleet.Host{ID: 1, Platform: "ubuntu"}, + keyExists: false, + clientErrorExists: false, + status: fleet.HostMDMDiskEncryption{ + Status: &actionRequired, + }, + }, + { + name: "key exists", + host: fleet.Host{ID: 1, Platform: "ubuntu"}, + keyExists: true, + clientErrorExists: false, + status: fleet.HostMDMDiskEncryption{ + Status: &verified, + }, + }, + { + name: "key exists && client error", + host: fleet.Host{ID: 1, Platform: "ubuntu"}, + keyExists: true, + clientErrorExists: true, + status: fleet.HostMDMDiskEncryption{ + Status: &failed, + Detail: "client error", + }, + }, + { + name: "no key && client error", + host: fleet.Host{ID: 1, Platform: "ubuntu"}, + keyExists: false, + clientErrorExists: true, + status: fleet.HostMDMDiskEncryption{ + Status: &failed, + Detail: "client error", + }, + }, + { + name: "key not found", + host: fleet.Host{ID: 1, Platform: "ubuntu"}, + keyExists: false, + clientErrorExists: false, + status: fleet.HostMDMDiskEncryption{ + Status: &actionRequired, + }, + notFound: true, + }, + { + name: "unsupported platform", + host: fleet.Host{ID: 1, Platform: "amzn"}, + status: fleet.HostMDMDiskEncryption{}, + }, + } + + for _, tt := range testcases { + t.Run(tt.name, func(t *testing.T) { + ds.GetHostDiskEncryptionKeyFunc = func(ctx context.Context, hostID uint) (*fleet.HostDiskEncryptionKey, error) { + var encrypted string + if tt.keyExists { + encrypted = "encrypted" + } + + var clientError string + if tt.clientErrorExists { + clientError = "client error" + } + + var nfe notFoundError + if tt.notFound { + return nil, &nfe + } + + return &fleet.HostDiskEncryptionKey{ + HostID: hostID, + Base64Encrypted: encrypted, + Decryptable: ptr.Bool(true), + UpdatedAt: time.Now(), + ClientError: clientError, + }, nil + } + + status, err := svc.LinuxHostDiskEncryptionStatus(ctx, tt.host) + assert.Nil(t, err) + + assert.Equal(t, tt.status, status) + }) + } +} diff --git a/server/service/mdm_test.go b/server/service/mdm_test.go index 59ea63c8b4..e763cf6c05 100644 --- a/server/service/mdm_test.go +++ b/server/service/mdm_test.go @@ -606,6 +606,11 @@ func TestMDMCommonAuthorization(t *testing.T) { ds.GetMDMWindowsProfilesSummaryFunc = func(ctx context.Context, teamID *uint) (*fleet.MDMProfilesSummary, error) { return &fleet.MDMProfilesSummary{}, nil } + + ds.GetLinuxDiskEncryptionSummaryFunc = func(ctx context.Context, teamID *uint) (fleet.MDMLinuxDiskEncryptionSummary, error) { + return fleet.MDMLinuxDiskEncryptionSummary{}, nil + } + ds.AreHostsConnectedToFleetMDMFunc = func(ctx context.Context, hosts []*fleet.Host) (map[string]bool, error) { res := make(map[string]bool, len(hosts)) for _, h := range hosts { @@ -874,6 +879,11 @@ func TestGetMDMDiskEncryptionSummary(t *testing.T) { return res, nil } + ds.GetLinuxDiskEncryptionSummaryFunc = func(ctx context.Context, teamID *uint) (fleet.MDMLinuxDiskEncryptionSummary, error) { + require.Nil(t, teamID) + return fleet.MDMLinuxDiskEncryptionSummary{Verified: 1, ActionRequired: 2, Failed: 3}, nil + } + // Test that the summary properly combines the results of the two methods des, err := svc.GetMDMDiskEncryptionSummary(ctx, nil) require.NoError(t, err) @@ -882,6 +892,7 @@ func TestGetMDMDiskEncryptionSummary(t *testing.T) { Verified: fleet.MDMPlatformsCounts{ MacOS: 1, Windows: 7, + Linux: 1, }, Verifying: fleet.MDMPlatformsCounts{ MacOS: 2, @@ -890,10 +901,12 @@ func TestGetMDMDiskEncryptionSummary(t *testing.T) { ActionRequired: fleet.MDMPlatformsCounts{ MacOS: 3, Windows: 0, + Linux: 2, }, Failed: fleet.MDMPlatformsCounts{ MacOS: 4, Windows: 8, + Linux: 3, }, Enforcing: fleet.MDMPlatformsCounts{ MacOS: 5, diff --git a/server/test/new_objects.go b/server/test/new_objects.go index 8a285783e5..f56496faea 100644 --- a/server/test/new_objects.go +++ b/server/test/new_objects.go @@ -217,6 +217,12 @@ func WithPlatform(s string) NewHostOption { } } +func WithOSVersion(s string) NewHostOption { + return func(h *fleet.Host) { + h.OSVersion = s + } +} + func WithTeamID(teamID uint) NewHostOption { return func(h *fleet.Host) { h.TeamID = &teamID