mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #40809 **Orbit agent: key rotation replaces decrypt-then-re-encrypt:** - When the disk is already encrypted, orbit now adds a new Fleet-managed recovery key protector, removes old ones, and escrows the new key. The disk is never decrypted. - If key escrow fails, the rotated key is cached in memory and retried on subsequent ticks without rotating again. - Removes `DecryptVolume` and `decrypt()` (no longer called from production code). **Server: osquery query returns both protection_status and conversion_status:** - The `disk_encryption_windows` query now returns both columns instead of just checking `protection_status = 1`. This lets the server correctly identify a disk as encrypted via `conversion_status = 1` even when `protection_status = 0`. - New `directIngestDiskEncryptionWindows` function parses both values, handles parse errors, and normalizes `protection_status = 2` (unknown) to NULL. **Server: new `bitlocker_protection_status` column and status logic:** - Adds `bitlocker_protection_status` column to `host_disks` (DB migration). - When a disk is encrypted and key is escrowed but protection is off, the host shows "Action required" with a detail message explaining the issue, instead of misleadingly showing "Verified." - `protection_status = 2` (unknown) and `NULL` (older orbit hosts) are treated as protection on for backward compatibility. - The `profiles_verified` and `profiles_verifying` branches in the combined profiles+BitLocker summary now handle `bitlocker_action_required`, counting those hosts as "pending". Contributor docs updates: https://github.com/fleetdm/fleet/pull/43241 Public docs updates: https://github.com/fleetdm/fleet/pull/43243/changes # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually ## Database migrations - [x] Checked schema for all modified table for columns that will auto-update timestamps during migration. ## fleetd/orbit/Fleet Desktop - [x] Verified compatibility with the latest released version of Fleet (see [Must rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md)) - [x] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes - [x] Verified that fleetd runs on macOS, Linux and Windows - [x] Verified auto-update works from the released version of component to the new version (see [tools/tuf/test](../tools/tuf/test/README.md)) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Fixed Windows BitLocker encryption/decryption request loop on systems with secondary drives and auto-unlock. * **New Features** * Added BitLocker recovery key rotation capability, allowing safe key updates without full disk re-encryption. * Enhanced BitLocker protection status tracking to correctly display "Action required" when protection is disabled. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
77 lines
3.2 KiB
Go
77 lines
3.2 KiB
Go
package bitlocker
|
|
|
|
// Volume encryption/decryption status.
|
|
//
|
|
// Values and their meanings were taken from:
|
|
// https://learn.microsoft.com/en-us/windows/win32/secprov/getconversionstatus-win32-encryptablevolume
|
|
const (
|
|
ConversionStatusFullyDecrypted int32 = 0
|
|
ConversionStatusFullyEncrypted int32 = 1
|
|
ConversionStatusEncryptionInProgress int32 = 2
|
|
ConversionStatusDecryptionInProgress int32 = 3
|
|
ConversionStatusEncryptionPaused int32 = 4
|
|
ConversionStatusDecryptionPaused int32 = 5
|
|
)
|
|
|
|
const (
|
|
// Error codes from Win32_EncryptableVolume WMI methods. The Microsoft docs
|
|
// define these as uint32, but the COM VARIANT transport delivers them as
|
|
// VT_I4 (signed 32-bit), which go-ole surfaces as int32. The bit patterns
|
|
// are identical (e.g., 0x80310019 as uint32 == -2144272327 as int32).
|
|
ErrorCodeInvalidArg int32 = -2147024809 // E_INVALIDARG: encryption flags conflict with Group Policy
|
|
ErrorCodeIODevice int32 = -2147023779
|
|
ErrorCodeDriveIncompatibleVolume int32 = -2144272206
|
|
ErrorCodeNoTPMWithPassphrase int32 = -2144272212
|
|
ErrorCodePassphraseTooLong int32 = -2144272214
|
|
ErrorCodePolicyPassphraseNotAllowed int32 = -2144272278
|
|
ErrorCodeNotDecrypted int32 = -2144272327
|
|
ErrorCodeInvalidPasswordFormat int32 = -2144272331
|
|
ErrorCodeBootableCDOrDVD int32 = -2144272336
|
|
ErrorCodeProtectorExists int32 = -2144272335
|
|
)
|
|
|
|
// EncryptionError represents an error that occurs during the encryption
|
|
// process.
|
|
type EncryptionError struct {
|
|
msg string // msg is the error message describing what went wrong.
|
|
code int32 // code is the Bitlocker-specific error code.
|
|
}
|
|
|
|
func NewEncryptionError(msg string, code int32) *EncryptionError {
|
|
return &EncryptionError{
|
|
msg: msg,
|
|
code: code,
|
|
}
|
|
}
|
|
|
|
// Error returns the error message of the EncryptionError.
|
|
// This method makes EncryptionError compatible with the Go built-in error
|
|
// interface.
|
|
func (e *EncryptionError) Error() string {
|
|
return e.msg
|
|
}
|
|
|
|
// Code returns the Bitlocker-specific error code.
|
|
// These codes are defined by Microsoft and are used to identify specific types
|
|
// of encryption errors.
|
|
func (e *EncryptionError) Code() int32 {
|
|
return e.code
|
|
}
|
|
|
|
// EncryptionStatus represents the encryption status of a volume as returned by
|
|
// the GetConversionStatus method of the Win32_EncryptableVolume class.
|
|
type EncryptionStatus struct {
|
|
ProtectionStatus int32 // indicates whether the volume and its encryption key are secured.
|
|
ConversionStatus int32 // represents the encryption or decryption status of the volume.
|
|
EncryptionPercentage string // percentage of the volume that is encrypted.
|
|
EncryptionFlags string // flags describing the encryption behavior.
|
|
WipingStatus int32 // status of the free space wiping on the volume.
|
|
WipingPercentage string // percentage of free space that has been wiped.
|
|
}
|
|
|
|
// VolumeStatus provides the encryption status for a specific drive volume.
|
|
// It ties a volume (identified by its drive letter) to its EncryptionStatus.
|
|
type VolumeStatus struct {
|
|
DriveVolume string // driveVolume is the identifier of the drive (e.g., "C:").
|
|
Status *EncryptionStatus // status holds the encryption status of the volume.
|
|
}
|