From 6a268f173c3ccc572d8f4b47bdc28e257e2f7086 Mon Sep 17 00:00:00 2001 From: Scott Gress Date: Wed, 6 Aug 2025 13:13:36 -0500 Subject: [PATCH] Add banners for Windows hosts that need to set BitLocker PIN (#31453) for #31196 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. Will add changelog when feature is complete. ## Testing > Note - to enable the "require bitlocker pin" ui, compile front end with: ``` SHOW_BITLOCKER_PIN_OPTION=true NODE_ENV=development yarn run webpack --progress --watch ``` - [X] Added/updated automated tests - [X] QA'd all new/changed functionality manually I had to add/remove the `tpm_pin_set` flag in the db manually, but by doing that I was able to get the banners to appear, when running https://github.com/fleetdm/fleet/pull/31451. image --- image --- image --------- Co-authored-by: Gabriel Hernandez --- .../details/DeviceUserPage/DeviceUserPage.tsx | 40 +++++++++++++++++++ .../DeviceUserBanners.tests.tsx | 28 +++++++++++++ .../DeviceUserBanners/DeviceUserBanners.tsx | 22 ++++++++++ .../HostDetailsBanners/HostDetailsBanners.tsx | 27 ++++++++----- 4 files changed, 108 insertions(+), 9 deletions(-) diff --git a/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx b/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx index b1a66c5fab..c9b46316a5 100644 --- a/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx +++ b/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx @@ -4,6 +4,7 @@ import { useQuery } from "react-query"; import { Tab, Tabs, TabList, TabPanel } from "react-tabs"; import { pick } from "lodash"; +import Modal from "components/Modal"; import { NotificationContext } from "context/notification"; @@ -123,6 +124,7 @@ const DeviceUserPage = ({ NotificationContext ); + const [showBitLockerPINModal, setShowBitLockerPINModal] = useState(false); const [showInfoModal, setShowInfoModal] = useState(false); const [showEnrollMdmModal, setShowEnrollMdmModal] = useState(false); const [refetchStartTime, setRefetchStartTime] = useState(null); @@ -466,6 +468,7 @@ const DeviceUserPage = ({ host.mdm.macos_settings?.action_required ?? null } onTurnOnMdm={toggleEnrollMdmModal} + onClickCreatePIN={() => setShowBitLockerPINModal(true)} onTriggerEscrowLinuxKey={onTriggerEscrowLinuxKey} diskEncryptionOSSetting={host.mdm.os_settings?.disk_encryption} diskIsEncrypted={host.disk_encryption_enabled} @@ -611,6 +614,43 @@ const DeviceUserPage = ({ token={deviceAuthToken} /> ))} + {showBitLockerPINModal && ( + setShowBitLockerPINModal(false)} + onEnter={() => setShowBitLockerPINModal(false)} + className={baseClass} + width="large" + > +
+

+

    +
  1. +

    + Open the Start menu. +

    +
  2. +
  3. +

    Type “Manage BitLocker” and launch.

    +
  4. +
  5. +

    + Choose Enter a PIN (recommended) and follow the + prompts to create a PIN. +

    +
  6. +
  7. +

    + Close this window and select Refetch on your{" "} + My device page. This informs your organization + that you have set a BitLocker PIN. +

    +
  8. +
+

+
+
+ )} )} {!!host && showPolicyDetailsModal && ( diff --git a/frontend/pages/hosts/details/DeviceUserPage/components/DeviceUserBanners/DeviceUserBanners.tests.tsx b/frontend/pages/hosts/details/DeviceUserPage/components/DeviceUserBanners/DeviceUserBanners.tests.tsx index 0341ad8f00..b96389211a 100644 --- a/frontend/pages/hosts/details/DeviceUserPage/components/DeviceUserBanners/DeviceUserBanners.tests.tsx +++ b/frontend/pages/hosts/details/DeviceUserPage/components/DeviceUserBanners/DeviceUserBanners.tests.tsx @@ -8,6 +8,7 @@ describe("Device User Banners", () => { const turnOnMdmExpcetedText = /Mobile device management \(MDM\) is off\./; const resetNonLinuxDiskEncryptKeyExpectedText = /Disk encryption: Log out of your device or restart it to safeguard your data in case your device is lost or stolen\./; const createNewLinuxDiskEncryptKeyExpectedText = /Disk encryption: Create a new disk encryption key\. This lets your organization help you unlock your device if you forget your passphrase\./; + const createPINExepectedText = /Disk encryption: Create a BitLocker PIN to safeguard your data/; it("renders the turn on mdm banner correctly", () => { render( @@ -20,6 +21,7 @@ describe("Device User Banners", () => { diskEncryptionActionRequired={null} onTurnOnMdm={noop} onTriggerEscrowLinuxKey={noop} + onClickCreatePIN={noop} /> ); expect(screen.getByText(turnOnMdmExpcetedText)).toBeInTheDocument(); @@ -36,6 +38,7 @@ describe("Device User Banners", () => { diskEncryptionActionRequired="rotate_key" onTurnOnMdm={noop} onTriggerEscrowLinuxKey={noop} + onClickCreatePIN={noop} /> ); expect( @@ -57,6 +60,7 @@ describe("Device User Banners", () => { diskEncryptionActionRequired={null} onTurnOnMdm={noop} onTriggerEscrowLinuxKey={noop} + onClickCreatePIN={noop} /> ); expect( @@ -79,6 +83,7 @@ describe("Device User Banners", () => { diskEncryptionActionRequired={null} onTurnOnMdm={noop} onTriggerEscrowLinuxKey={noop} + onClickCreatePIN={noop} /> ); expect( @@ -86,6 +91,27 @@ describe("Device User Banners", () => { ).toBeInTheDocument(); }); + it("renders the create PIN banner correctly for Windows", () => { + render( + + ); + expect(screen.getByText(createPINExepectedText)).toBeInTheDocument(); + }); + it("renders no banner correctly for a mac that is verifying its disk encryption", () => { render( { onTurnOnMdm={noop} onTriggerEscrowLinuxKey={noop} diskEncryptionOSSetting={{ status: "verifying", detail: "" }} + onClickCreatePIN={noop} /> ); @@ -121,6 +148,7 @@ describe("Device User Banners", () => { diskEncryptionActionRequired={null} onTurnOnMdm={noop} onTriggerEscrowLinuxKey={noop} + onClickCreatePIN={noop} /> ); diff --git a/frontend/pages/hosts/details/DeviceUserPage/components/DeviceUserBanners/DeviceUserBanners.tsx b/frontend/pages/hosts/details/DeviceUserPage/components/DeviceUserBanners/DeviceUserBanners.tsx index bcc40a131f..2178c5a8a4 100644 --- a/frontend/pages/hosts/details/DeviceUserPage/components/DeviceUserBanners/DeviceUserBanners.tsx +++ b/frontend/pages/hosts/details/DeviceUserPage/components/DeviceUserBanners/DeviceUserBanners.tsx @@ -13,6 +13,7 @@ interface IDeviceUserBannersProps extends IHostBannersBaseProps { mdmEnabledAndConfigured: boolean; diskEncryptionActionRequired: MacDiskEncryptionActionRequired | null; onTurnOnMdm: () => void; + onClickCreatePIN: () => void; onTriggerEscrowLinuxKey: () => void; } @@ -25,6 +26,7 @@ const DeviceUserBanners = ({ macDiskEncryptionStatus, diskEncryptionActionRequired, onTurnOnMdm, + onClickCreatePIN, diskEncryptionOSSetting, diskIsEncrypted, diskEncryptionKeyAvailable, @@ -123,6 +125,26 @@ const DeviceUserBanners = ({ } } + if ( + hostPlatform === "windows" && + diskEncryptionOSSetting?.status === "action_required" + ) { + return ( + + Create PIN + + } + > + Disk encryption: Create a BitLocker PIN to safeguard your data in case + your device is lost or stolen. After, select Refetch{" "} + to clear this banner. + + ); + } + return null; }; diff --git a/frontend/pages/hosts/details/HostDetailsPage/components/HostDetailsBanners/HostDetailsBanners.tsx b/frontend/pages/hosts/details/HostDetailsPage/components/HostDetailsBanners/HostDetailsBanners.tsx index 5f3d0f12b6..fadbe84ee1 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/components/HostDetailsBanners/HostDetailsBanners.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/components/HostDetailsBanners/HostDetailsBanners.tsx @@ -55,6 +55,16 @@ const HostDetailsBanners = ({ connectedToFleetMdm && macDiskEncryptionStatus === "action_required"; + const actionRequiredBanner = ( +
+ + Disk encryption: Requires action from the end user. Ask the user to + follow Disk encryption instructions on their My device{" "} + page. + +
+ ); + if (showTurnOnMdmInfoBanner) { return (
@@ -108,17 +118,16 @@ const HostDetailsBanners = ({ // linux host's disk is encrypted, but Fleet doesn't yet have a disk // encryption key escrowed (note that this state is also possible for Windows hosts, which we // don't show this banner for currently) - return ( -
- - Disk encryption: Requires action from the end user. Ask the user to - follow Disk encryption instructions on their My device{" "} - page. - -
- ); + return actionRequiredBanner; } } + if ( + hostPlatform === "windows" && + diskEncryptionOSSetting?.status === "action_required" + ) { + return actionRequiredBanner; + } + return null; };