Skip to content

Commit

Permalink
Cherry-Pick: Include Linux disk encryption status in configuration pr…
Browse files Browse the repository at this point in the history
…ofiles aggregate status response when applicable, fix disk encryption/MDM configuration order-of-operations issues, add integration tests for LUKS (#24124)

Cherry-pick of #24114, for #24112, #24116, #23587

Co-authored-by: jacobshandling <[email protected]>
Co-authored-by: Jacob Shandling <[email protected]>
  • Loading branch information
3 people authored Nov 25, 2024
1 parent e18729c commit be15eec
Show file tree
Hide file tree
Showing 18 changed files with 293 additions and 35 deletions.
18 changes: 6 additions & 12 deletions ee/server/service/teams.go
Original file line number Diff line number Diff line change
Expand Up @@ -1516,15 +1516,15 @@ func unmarshalWithGlobalDefaults(b *json.RawMessage) (fleet.Features, error) {
}

func (svc *Service) updateTeamMDMDiskEncryption(ctx context.Context, tm *fleet.Team, enable *bool) error {
var didUpdate, didUpdateMacOSDiskEncryption bool
var didUpdate bool
if enable != nil {
if svc.config.Server.PrivateKey == "" {
return ctxerr.New(ctx, "Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
}
if tm.Config.MDM.EnableDiskEncryption != *enable {
if *enable && svc.config.Server.PrivateKey == "" {
return ctxerr.New(ctx, "Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
}

tm.Config.MDM.EnableDiskEncryption = *enable
didUpdate = true
didUpdateMacOSDiskEncryption = true
}
}

Expand All @@ -1537,13 +1537,7 @@ func (svc *Service) updateTeamMDMDiskEncryption(ctx context.Context, tm *fleet.T
if err != nil {
return err
}

// macOS-specific stuff. For legacy reasons we check if apple is configured
// via `appCfg.MDM.EnabledAndConfigured`
//
// TODO: is there a missing bitlocker activity feed item? (see same TODO on
// other methods that deal with disk encryption)
if appCfg.MDM.EnabledAndConfigured && didUpdateMacOSDiskEncryption {
if appCfg.MDM.EnabledAndConfigured {
var act fleet.ActivityDetails
if tm.Config.MDM.EnableDiskEncryption {
act = fleet.ActivityTypeEnabledMacosDiskEncryption{TeamID: &tm.ID, TeamName: &tm.Name}
Expand Down
2 changes: 1 addition & 1 deletion frontend/services/entities/mdm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ const mdmService = {
},

getProfilesStatusSummary: (teamId: number) => {
let { MDM_PROFILES_STATUS_SUMMARY: path } = endpoints;
let { PROFILES_STATUS_SUMMARY: path } = endpoints;

if (teamId) {
path = `${path}?${buildQueryStringFromParams({ team_id: teamId })}`;
Expand Down
2 changes: 1 addition & 1 deletion frontend/utilities/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export default {
MDM_PROFILE: (id: string) => `/${API_VERSION}/fleet/mdm/profiles/${id}`,

MDM_UPDATE_APPLE_SETTINGS: `/${API_VERSION}/fleet/mdm/apple/settings`,
MDM_PROFILES_STATUS_SUMMARY: `/${API_VERSION}/fleet/mdm/profiles/summary`,
PROFILES_STATUS_SUMMARY: `/${API_VERSION}/fleet/configuration_profiles/summary`,
MDM_DISK_ENCRYPTION_SUMMARY: `/${API_VERSION}/fleet/mdm/disk_encryption/summary`,
MDM_APPLE_SSO: `/${API_VERSION}/fleet/mdm/sso`,
MDM_APPLE_ENROLLMENT_PROFILE: (token: string, ref?: string) => {
Expand Down
2 changes: 1 addition & 1 deletion server/datastore/mysql/app_configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ func (ds *Datastore) AggregateEnrollSecretPerTeam(ctx context.Context) ([]*fleet
return secrets, nil
}

func (ds *Datastore) getConfigEnableDiskEncryption(ctx context.Context, teamID *uint) (bool, error) {
func (ds *Datastore) GetConfigEnableDiskEncryption(ctx context.Context, teamID *uint) (bool, error) {
if teamID != nil && *teamID > 0 {
tc, err := ds.TeamMDMConfig(ctx, *teamID)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions server/datastore/mysql/app_configs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ func testGetConfigEnableDiskEncryption(t *testing.T, ds *Datastore) {
require.NoError(t, err)
require.False(t, ac.MDM.EnableDiskEncryption.Value)

enabled, err := ds.getConfigEnableDiskEncryption(ctx, nil)
enabled, err := ds.GetConfigEnableDiskEncryption(ctx, nil)
require.NoError(t, err)
require.False(t, enabled)

Expand All @@ -461,7 +461,7 @@ func testGetConfigEnableDiskEncryption(t *testing.T, ds *Datastore) {
require.NoError(t, err)
require.True(t, ac.MDM.EnableDiskEncryption.Value)

enabled, err = ds.getConfigEnableDiskEncryption(ctx, nil)
enabled, err = ds.GetConfigEnableDiskEncryption(ctx, nil)
require.NoError(t, err)
require.True(t, enabled)

Expand All @@ -474,7 +474,7 @@ func testGetConfigEnableDiskEncryption(t *testing.T, ds *Datastore) {
require.NotNil(t, tm)
require.False(t, tm.Config.MDM.EnableDiskEncryption)

enabled, err = ds.getConfigEnableDiskEncryption(ctx, &team1.ID)
enabled, err = ds.GetConfigEnableDiskEncryption(ctx, &team1.ID)
require.NoError(t, err)
require.False(t, enabled)

Expand Down
3 changes: 2 additions & 1 deletion server/datastore/mysql/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,7 @@ func (ds *Datastore) applyHostFilters(
return "", nil, ctxerr.Wrap(ctx, err, "building query to filter macOS settings status")
}
sqlStmt, whereParams = filterHostsByMacOSDiskEncryptionStatus(sqlStmt, opt, whereParams)
if enableDiskEncryption, err := ds.getConfigEnableDiskEncryption(ctx, opt.TeamFilter); err != nil {
if enableDiskEncryption, err := ds.GetConfigEnableDiskEncryption(ctx, opt.TeamFilter); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return "", nil, ctxerr.Wrap(
ctx, &fleet.BadRequestError{
Expand Down Expand Up @@ -4547,6 +4547,7 @@ func (ds *Datastore) HostLite(ctx context.Context, id uint) (*fleet.Host, error)
"hardware_model",
"computer_name",
"platform",
"os_version",
"team_id",
"distributed_interval",
"logger_tls_period",
Expand Down
2 changes: 1 addition & 1 deletion server/datastore/mysql/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ func (ds *Datastore) applyHostLabelFilters(ctx context.Context, filter fleet.Tea
}
query, whereParams = filterHostsByMacOSDiskEncryptionStatus(query, opt, whereParams)
query, whereParams = filterHostsByMDMBootstrapPackageStatus(query, opt, whereParams)
if enableDiskEncryption, err := ds.getConfigEnableDiskEncryption(ctx, opt.TeamFilter); err != nil {
if enableDiskEncryption, err := ds.GetConfigEnableDiskEncryption(ctx, opt.TeamFilter); err != nil {
return "", nil, err
} else if opt.OSSettingsFilter.IsValid() {
query, whereParams, err = ds.filterHostsByOSSettingsStatus(query, opt, whereParams, enableDiskEncryption)
Expand Down
6 changes: 3 additions & 3 deletions server/datastore/mysql/microsoft_mdm.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ AND (
}

func (ds *Datastore) GetMDMWindowsBitLockerSummary(ctx context.Context, teamID *uint) (*fleet.MDMWindowsBitLockerSummary, error) {
enabled, err := ds.getConfigEnableDiskEncryption(ctx, teamID)
enabled, err := ds.GetConfigEnableDiskEncryption(ctx, teamID)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -655,7 +655,7 @@ func (ds *Datastore) GetMDMWindowsBitLockerStatus(ctx context.Context, host *fle
return nil, nil
}

enabled, err := ds.getConfigEnableDiskEncryption(ctx, host.TeamID)
enabled, err := ds.GetConfigEnableDiskEncryption(ctx, host.TeamID)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -887,7 +887,7 @@ func subqueryHostsMDMWindowsOSSettingsStatusVerified() (string, []interface{}, e
}

func (ds *Datastore) GetMDMWindowsProfilesSummary(ctx context.Context, teamID *uint) (*fleet.MDMProfilesSummary, error) {
includeBitLocker, err := ds.getConfigEnableDiskEncryption(ctx, teamID)
includeBitLocker, err := ds.GetConfigEnableDiskEncryption(ctx, teamID)
if err != nil {
return nil, err
}
Expand Down
1 change: 1 addition & 0 deletions server/fleet/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,7 @@ type Datastore interface {
GetHostEmails(ctx context.Context, hostUUID string, source string) ([]string, error)
SetOrUpdateHostDisksSpace(ctx context.Context, hostID uint, gigsAvailable, percentAvailable, gigsTotal float64) error

GetConfigEnableDiskEncryption(ctx context.Context, teamID *uint) (bool, error)
SetOrUpdateHostDisksEncryption(ctx context.Context, hostID uint, encrypted bool) error
// SetOrUpdateHostDiskEncryptionKey sets the base64, encrypted key for
// a host
Expand Down
4 changes: 2 additions & 2 deletions server/fleet/mdm.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,8 @@ type MDMDiskEncryptionSummary struct {
RemovingEnforcement MDMPlatformsCounts `db:"removing_enforcement" json:"removing_enforcement"`
}

// MDMProfilesSummary reports the number of hosts being managed with MDM configuration
// profiles. Each host may be counted in only one of four mutually-exclusive categories:
// MDMProfilesSummary reports the number of hosts being managed with configuration
// profiles and/or disk encryption. Each host may be counted in only one of four mutually-exclusive categories:
// Failed, Pending, Verifying, or Verified.
type MDMProfilesSummary struct {
// Verified includes each host where Fleet has verified the installation of all of the
Expand Down
5 changes: 5 additions & 0 deletions server/fleet/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,11 @@ type Service interface {
// Returns empty status if the host is not a supported Linux host
LinuxHostDiskEncryptionStatus(ctx context.Context, host Host) (HostMDMDiskEncryption, error)

// GetMDMLinuxProfilesSummary summarizes the current status of Linux disk encryption for
// the provided team (or hosts without a team if teamId is nil), or returns zeroes if disk
// encryption is not enforced on the selected team
GetMDMLinuxProfilesSummary(ctx context.Context, teamId *uint) (MDMProfilesSummary, error)

///////////////////////////////////////////////////////////////////////////////
// Common MDM

Expand Down
12 changes: 12 additions & 0 deletions server/mock/datastore_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,8 @@ type GetHostEmailsFunc func(ctx context.Context, hostUUID string, source string)

type SetOrUpdateHostDisksSpaceFunc func(ctx context.Context, hostID uint, gigsAvailable float64, percentAvailable float64, gigsTotal float64) error

type GetConfigEnableDiskEncryptionFunc func(ctx context.Context, teamID *uint) (bool, error)

type SetOrUpdateHostDisksEncryptionFunc func(ctx context.Context, hostID uint, encrypted bool) error

type SetOrUpdateHostDiskEncryptionKeyFunc func(ctx context.Context, hostID uint, encryptedBase64Key string, clientError string, decryptable *bool) error
Expand Down Expand Up @@ -2085,6 +2087,9 @@ type DataStore struct {
SetOrUpdateHostDisksSpaceFunc SetOrUpdateHostDisksSpaceFunc
SetOrUpdateHostDisksSpaceFuncInvoked bool

GetConfigEnableDiskEncryptionFunc GetConfigEnableDiskEncryptionFunc
GetConfigEnableDiskEncryptionFuncInvoked bool

SetOrUpdateHostDisksEncryptionFunc SetOrUpdateHostDisksEncryptionFunc
SetOrUpdateHostDisksEncryptionFuncInvoked bool

Expand Down Expand Up @@ -5029,6 +5034,13 @@ func (s *DataStore) SetOrUpdateHostDisksSpace(ctx context.Context, hostID uint,
return s.SetOrUpdateHostDisksSpaceFunc(ctx, hostID, gigsAvailable, percentAvailable, gigsTotal)
}

func (s *DataStore) GetConfigEnableDiskEncryption(ctx context.Context, teamID *uint) (bool, error) {
s.mu.Lock()
s.GetConfigEnableDiskEncryptionFuncInvoked = true
s.mu.Unlock()
return s.GetConfigEnableDiskEncryptionFunc(ctx, teamID)
}

func (s *DataStore) SetOrUpdateHostDisksEncryption(ctx context.Context, hostID uint, encrypted bool) error {
s.mu.Lock()
s.SetOrUpdateHostDisksEncryptionFuncInvoked = true
Expand Down
2 changes: 1 addition & 1 deletion server/service/appconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ func (svc *Service) ModifyAppConfig(ctx context.Context, p []byte, applyOpts fle
// 1. To get the JSON value from the database
// 2. To update fields with the incoming values
if newAppConfig.MDM.EnableDiskEncryption.Valid {
if svc.config.Server.PrivateKey == "" {
if newAppConfig.MDM.EnableDiskEncryption.Value && svc.config.Server.PrivateKey == "" {
return nil, ctxerr.New(ctx, "Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
}
appConfig.MDM.EnableDiskEncryption = newAppConfig.MDM.EnableDiskEncryption
Expand Down
9 changes: 6 additions & 3 deletions server/service/apple_mdm.go
Original file line number Diff line number Diff line change
Expand Up @@ -2143,20 +2143,23 @@ func (svc *Service) updateAppConfigMDMDiskEncryption(ctx context.Context, enable
return err
}

var didUpdate, didUpdateMacOSDiskEncryption bool
var didUpdate bool
if enabled != nil {
if ac.MDM.EnableDiskEncryption.Value != *enabled {
if *enabled && svc.config.Server.PrivateKey == "" {
return ctxerr.New(ctx, "Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
}

ac.MDM.EnableDiskEncryption = optjson.SetBool(*enabled)
didUpdate = true
didUpdateMacOSDiskEncryption = true
}
}

if didUpdate {
if err := svc.ds.SaveAppConfig(ctx, ac); err != nil {
return err
}
if didUpdateMacOSDiskEncryption {
if ac.MDM.EnabledAndConfigured { // if macOS MDM is configured, set up FileVault escrow
var act fleet.ActivityDetails
if ac.MDM.EnableDiskEncryption.Value {
act = fleet.ActivityTypeEnabledMacosDiskEncryption{}
Expand Down
7 changes: 6 additions & 1 deletion server/service/integration_core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8638,6 +8638,11 @@ func (s *integrationTestSuite) TestGetHostDiskEncryption() {
require.Equal(t, hostLin.ID, getHostResp.Host.ID)
require.True(t, *getHostResp.Host.DiskEncryptionEnabled)

// should succeed as we no longer require MDM to access this endpoint, as Linux encryption doesn't require MDM
var profiles getMDMProfilesSummaryResponse
s.DoJSON("GET", "/api/latest/fleet/configuration_profiles/summary", getMDMProfilesSummaryRequest{}, http.StatusOK, &profiles)
s.DoJSON("GET", "/api/latest/fleet/mdm/profiles/summary", getMDMProfilesSummaryRequest{}, http.StatusOK, &profiles)

// set unencrypted for all hosts
require.NoError(t, s.ds.SetOrUpdateHostDisksEncryption(context.Background(), hostWin.ID, false))
require.NoError(t, s.ds.SetOrUpdateHostDisksEncryption(context.Background(), hostMac.ID, false))
Expand All @@ -8653,7 +8658,7 @@ func (s *integrationTestSuite) TestGetHostDiskEncryption() {
require.Equal(t, hostMac.ID, getHostResp.Host.ID)
require.False(t, *getHostResp.Host.DiskEncryptionEnabled)

// Linux does not return false, it omits the field when false
// Linux may omit the field when false
getHostResp = getHostResponse{}
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d", hostLin.ID), nil, http.StatusOK, &getHostResp)
require.Equal(t, hostLin.ID, getHostResp.Host.ID)
Expand Down
Loading

0 comments on commit be15eec

Please sign in to comment.