Add host mdm disk encryption detail to host details API response (#14623)
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
- Updated `GET hosts/:id` API response to include additional detail for disk encryption in case of
|
||||
device client errors.
|
||||
@@ -254,31 +254,32 @@ WHERE
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) GetMDMWindowsBitLockerStatus(ctx context.Context, host *fleet.Host) (*fleet.DiskEncryptionStatus, error) {
|
||||
func (ds *Datastore) GetMDMWindowsBitLockerStatus(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
|
||||
hde := &fleet.HostMDMDiskEncryption{}
|
||||
if host == nil {
|
||||
return nil, errors.New("host cannot be nil")
|
||||
return hde, errors.New("host cannot be nil")
|
||||
}
|
||||
|
||||
if host.Platform != "windows" {
|
||||
// Generally, the caller should have already checked this, but just in case we log and
|
||||
// return nil
|
||||
level.Debug(ds.logger).Log("msg", "cannot get bitlocker status for non-windows host", "host_id", host.ID)
|
||||
return nil, nil
|
||||
return hde, nil
|
||||
}
|
||||
|
||||
if host.MDMInfo != nil && host.MDMInfo.IsServer {
|
||||
// It is currently expected that server hosts do not have a bitlocker status so we can skip
|
||||
// the query and return nil. We log for potential debugging in case this changes in the future.
|
||||
level.Debug(ds.logger).Log("msg", "no bitlocker status for server host", "host_id", host.ID)
|
||||
return nil, nil
|
||||
return hde, nil
|
||||
}
|
||||
|
||||
enabled, err := ds.getConfigEnableDiskEncryption(ctx, host.TeamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return hde, err
|
||||
}
|
||||
if !enabled {
|
||||
return nil, nil
|
||||
return hde, nil
|
||||
}
|
||||
|
||||
// Note action_required and removing_enforcement are not applicable to Windows hosts
|
||||
@@ -289,7 +290,8 @@ SELECT
|
||||
WHEN (%s) THEN '%s'
|
||||
WHEN (%s) THEN '%s'
|
||||
WHEN (%s) THEN '%s'
|
||||
END AS status
|
||||
END AS status,
|
||||
COALESCE(client_error, '') as detail
|
||||
FROM
|
||||
host_mdm hmdm
|
||||
LEFT JOIN host_disk_encryption_keys hdek ON hmdm.host_id = hdek.host_id
|
||||
@@ -306,17 +308,22 @@ WHERE
|
||||
fleet.DiskEncryptionFailed,
|
||||
)
|
||||
|
||||
var des fleet.DiskEncryptionStatus
|
||||
if err := sqlx.GetContext(ctx, ds.reader(ctx), &des, stmt, host.ID); err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
// At this point we know disk encryption is enabled so if we don't have a record for the
|
||||
// host then we treat it as enforcing and log for potential debugging
|
||||
level.Debug(ds.logger).Log("msg", "no bitlocker status found for host", "host_id", host.ID)
|
||||
des = fleet.DiskEncryptionEnforcing
|
||||
return &des, nil
|
||||
var dest struct {
|
||||
Status fleet.DiskEncryptionStatus `db:"status"`
|
||||
Detail string `db:"detail"`
|
||||
}
|
||||
if err := sqlx.GetContext(ctx, ds.reader(ctx), &dest, stmt, host.ID); err != nil {
|
||||
if err != sql.ErrNoRows {
|
||||
return &fleet.HostMDMDiskEncryption{}, err
|
||||
}
|
||||
return nil, err
|
||||
// At this point we know disk encryption is enabled so if there are no rows for the
|
||||
// host then we treat it as enforcing and log for potential debugging
|
||||
level.Debug(ds.logger).Log("msg", "no bitlocker status found for host", "host_id", host.ID)
|
||||
dest.Status = fleet.DiskEncryptionEnforcing
|
||||
}
|
||||
|
||||
return &des, nil
|
||||
return &fleet.HostMDMDiskEncryption{
|
||||
Status: &dest.Status,
|
||||
Detail: dest.Detail,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -133,7 +133,8 @@ func TestMDMWindowsDiskEncryption(t *testing.T) {
|
||||
bls, err := ds.GetMDMWindowsBitLockerStatus(ctx, h)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, bls)
|
||||
require.Equal(t, expected, *bls)
|
||||
require.NotNil(t, bls.Status)
|
||||
require.Equal(t, expected, *bls.Status)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1053,7 +1053,7 @@ type Datastore interface {
|
||||
//
|
||||
// Note that the returned status will be nil if the host is reported to be a Windows
|
||||
// server or if disk encryption is disabled for the host's team (or no team, as applicable).
|
||||
GetMDMWindowsBitLockerStatus(ctx context.Context, host *Host) (*DiskEncryptionStatus, error)
|
||||
GetMDMWindowsBitLockerStatus(ctx context.Context, host *Host) (*HostMDMDiskEncryption, error)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Host Script Results
|
||||
|
||||
+19
-4
@@ -376,6 +376,7 @@ type HostMDMOSSettings struct {
|
||||
|
||||
type HostMDMDiskEncryption struct {
|
||||
Status *DiskEncryptionStatus `json:"status" db:"-" csv:"-"`
|
||||
Detail string `json:"detail" db:"-" csv:"-"`
|
||||
}
|
||||
|
||||
type DiskEncryptionStatus string
|
||||
@@ -431,11 +432,14 @@ type HostMDMMacOSSetup struct {
|
||||
BootstrapPackageName string `db:"bootstrap_package_name" json:"bootstrap_package_name" csv:"-"`
|
||||
}
|
||||
|
||||
// DetermineMacOSDiskEncryptionStatus determines the disk encryption status for the
|
||||
// DetermineHostMDMDiskEncryptionMacOS determines the disk encryption status for the
|
||||
// host based on the file-vault profile in its list of profiles and whether its
|
||||
// disk encryption key is available and decryptable. The file-vault profile
|
||||
// identifier is received as argument to avoid a circular dependency.
|
||||
func (d *MDMHostData) DetermineMacOSDiskEncryptionStatus(profiles []HostMDMAppleProfile, fileVaultIdentifier string) {
|
||||
// disk encryption key is available and decryptable. It sets the status value in MacOSSettings on
|
||||
// the HostMDMData struct. It also returns a pointer to a newly populated HostMDMDiskEncryption
|
||||
// struct intended for use in the host details response.
|
||||
//
|
||||
// The file-vault profile identifier is received as argument to avoid a circular dependency.
|
||||
func (d *MDMHostData) DetermineHostMDMDiskEncryptionMacOS(profiles []HostMDMAppleProfile, fileVaultIdentifier string) *HostMDMDiskEncryption {
|
||||
var settings MDMHostMacOSSettings
|
||||
|
||||
var fvprof *HostMDMAppleProfile
|
||||
@@ -503,6 +507,17 @@ func (d *MDMHostData) DetermineMacOSDiskEncryptionStatus(profiles []HostMDMApple
|
||||
}
|
||||
}
|
||||
d.MacOSSettings = &settings
|
||||
|
||||
var status *DiskEncryptionStatus
|
||||
if settings.DiskEncryption != nil {
|
||||
status = settings.DiskEncryption
|
||||
}
|
||||
var detail string
|
||||
if fvprof != nil {
|
||||
detail = fvprof.Detail
|
||||
}
|
||||
|
||||
return &HostMDMDiskEncryption{Status: status, Detail: detail}
|
||||
}
|
||||
|
||||
func (d *MDMHostData) ProfileStatusFromDiskEncryptionState(currStatus *MDMAppleDeliveryStatus) *MDMAppleDeliveryStatus {
|
||||
|
||||
@@ -690,7 +690,7 @@ type MDMWindowsDeleteEnrolledDeviceWithDeviceIDFunc func(ctx context.Context, md
|
||||
|
||||
type GetMDMWindowsBitLockerSummaryFunc func(ctx context.Context, teamID *uint) (*fleet.MDMWindowsBitLockerSummary, error)
|
||||
|
||||
type GetMDMWindowsBitLockerStatusFunc func(ctx context.Context, host *fleet.Host) (*fleet.DiskEncryptionStatus, error)
|
||||
type GetMDMWindowsBitLockerStatusFunc func(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error)
|
||||
|
||||
type NewHostScriptExecutionRequestFunc func(ctx context.Context, request *fleet.HostScriptRequestPayload) (*fleet.HostScriptResult, error)
|
||||
|
||||
@@ -4114,7 +4114,7 @@ func (s *DataStore) GetMDMWindowsBitLockerSummary(ctx context.Context, teamID *u
|
||||
return s.GetMDMWindowsBitLockerSummaryFunc(ctx, teamID)
|
||||
}
|
||||
|
||||
func (s *DataStore) GetMDMWindowsBitLockerStatus(ctx context.Context, host *fleet.Host) (*fleet.DiskEncryptionStatus, error) {
|
||||
func (s *DataStore) GetMDMWindowsBitLockerStatus(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
|
||||
s.mu.Lock()
|
||||
s.GetMDMWindowsBitLockerStatusFuncInvoked = true
|
||||
s.mu.Unlock()
|
||||
|
||||
@@ -924,11 +924,11 @@ func (svc *Service) getHostDetails(ctx context.Context, host *fleet.Host, opts f
|
||||
switch host.Platform {
|
||||
case "windows":
|
||||
if ac.MDM.WindowsEnabledAndConfigured && license.IsPremium(ctx) {
|
||||
bls, err := svc.ds.GetMDMWindowsBitLockerStatus(ctx, host)
|
||||
hde, err := svc.ds.GetMDMWindowsBitLockerStatus(ctx, host)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "get host mdm bitlocker status")
|
||||
}
|
||||
host.MDM.OSSettings.DiskEncryption.Status = bls
|
||||
host.MDM.OSSettings.DiskEncryption = *hde
|
||||
}
|
||||
case "darwin":
|
||||
if ac.MDM.EnabledAndConfigured {
|
||||
@@ -939,8 +939,8 @@ func (svc *Service) getHostDetails(ctx context.Context, host *fleet.Host, opts f
|
||||
|
||||
// determine disk encryption and action required here based on profiles and
|
||||
// raw decryptable key status.
|
||||
host.MDM.DetermineMacOSDiskEncryptionStatus(profs, mobileconfig.FleetFileVaultPayloadIdentifier)
|
||||
host.MDM.OSSettings.DiskEncryption.Status = host.MDM.MacOSSettings.DiskEncryption
|
||||
hde := host.MDM.DetermineHostMDMDiskEncryptionMacOS(profs, mobileconfig.FleetFileVaultPayloadIdentifier)
|
||||
host.MDM.OSSettings.DiskEncryption = *hde
|
||||
|
||||
for _, p := range profs {
|
||||
if p.Identifier == mobileconfig.FleetFileVaultPayloadIdentifier {
|
||||
|
||||
@@ -228,6 +228,7 @@ func TestHostDetailsMDMAppleDiskEncryption(t *testing.T) {
|
||||
Identifier: mobileconfig.FleetFileVaultPayloadIdentifier,
|
||||
Status: &fleet.MDMAppleDeliveryFailed,
|
||||
OperationType: fleet.MDMAppleOperationTypeInstall,
|
||||
Detail: "some mdm profile install error",
|
||||
},
|
||||
fleet.DiskEncryptionFailed,
|
||||
"",
|
||||
@@ -280,6 +281,7 @@ func TestHostDetailsMDMAppleDiskEncryption(t *testing.T) {
|
||||
Identifier: mobileconfig.FleetFileVaultPayloadIdentifier,
|
||||
Status: &fleet.MDMAppleDeliveryFailed,
|
||||
OperationType: fleet.MDMAppleOperationTypeRemove,
|
||||
Detail: "some mdm profile removal error",
|
||||
},
|
||||
fleet.DiskEncryptionFailed,
|
||||
"",
|
||||
@@ -327,11 +329,13 @@ func TestHostDetailsMDMAppleDiskEncryption(t *testing.T) {
|
||||
if c.wantState == "" {
|
||||
require.Nil(t, hostDetail.MDM.MacOSSettings.DiskEncryption)
|
||||
require.Nil(t, hostDetail.MDM.OSSettings.DiskEncryption.Status)
|
||||
require.Empty(t, hostDetail.MDM.OSSettings.DiskEncryption.Detail)
|
||||
} else {
|
||||
require.NotNil(t, hostDetail.MDM.MacOSSettings.DiskEncryption)
|
||||
require.Equal(t, c.wantState, *hostDetail.MDM.MacOSSettings.DiskEncryption)
|
||||
require.NotNil(t, hostDetail.MDM.OSSettings.DiskEncryption.Status)
|
||||
require.Equal(t, c.wantState, *hostDetail.MDM.OSSettings.DiskEncryption.Status)
|
||||
require.Equal(t, c.fvProf.Detail, hostDetail.MDM.OSSettings.DiskEncryption.Detail)
|
||||
}
|
||||
if c.wantAction == "" {
|
||||
require.Nil(t, hostDetail.MDM.MacOSSettings.ActionRequired)
|
||||
@@ -343,6 +347,7 @@ func TestHostDetailsMDMAppleDiskEncryption(t *testing.T) {
|
||||
require.NotNil(t, hostDetail.MDM.Profiles)
|
||||
profs := *hostDetail.MDM.Profiles
|
||||
require.Equal(t, c.wantStatus, profs[0].Status)
|
||||
require.Equal(t, c.fvProf.Detail, profs[0].Detail)
|
||||
} else {
|
||||
require.Nil(t, *hostDetail.MDM.Profiles)
|
||||
}
|
||||
@@ -396,11 +401,11 @@ func TestHostDetailsOSSettings(t *testing.T) {
|
||||
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
|
||||
return &fleet.AppConfig{MDM: fleet.MDM{EnabledAndConfigured: true, WindowsEnabledAndConfigured: true}}, nil
|
||||
}
|
||||
ds.GetMDMWindowsBitLockerStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.DiskEncryptionStatus, error) {
|
||||
ds.GetMDMWindowsBitLockerStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
|
||||
if c.wantStatus == "" {
|
||||
return nil, nil
|
||||
}
|
||||
return &c.wantStatus, nil
|
||||
return &fleet.HostMDMDiskEncryption{Status: &c.wantStatus, Detail: ""}, nil
|
||||
}
|
||||
ds.GetHostMDMProfilesFunc = func(ctx context.Context, uuid string) ([]fleet.HostMDMAppleProfile, error) {
|
||||
return nil, nil
|
||||
@@ -469,9 +474,9 @@ func TestHostDetailsOSSettingsWindowsOnly(t *testing.T) {
|
||||
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
|
||||
return &fleet.AppConfig{MDM: fleet.MDM{WindowsEnabledAndConfigured: true}}, nil
|
||||
}
|
||||
ds.GetMDMWindowsBitLockerStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.DiskEncryptionStatus, error) {
|
||||
ds.GetMDMWindowsBitLockerStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
|
||||
verified := fleet.DiskEncryptionVerified
|
||||
return &verified, nil
|
||||
return &fleet.HostMDMDiskEncryption{Status: &verified, Detail: ""}, nil
|
||||
}
|
||||
ds.GetHostMDMProfilesFunc = func(ctx context.Context, uuid string) ([]fleet.HostMDMAppleProfile, error) {
|
||||
return nil, nil
|
||||
|
||||
Reference in New Issue
Block a user