mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
UI/Docs changes to rotate keys using Escrow Buddy (#20843)
UI portion for #13157 # Checklist for submitter If some of the following don't apply, delete the relevant line. <!-- Note that API documentation changes are now addressed by the product design team. --> - [x] Added/updated tests - [x] Manual QA for all new/changed functionality
This commit is contained in:
parent
fa529e47f9
commit
42ff57d059
10 changed files with 9 additions and 192 deletions
|
|
@ -2755,27 +2755,6 @@ Signals the Fleet server to send a webbook request with the device UUID and seri
|
|||
|
||||
---
|
||||
|
||||
#### Trigger FileVault key escrow
|
||||
|
||||
Sends a signal to Fleet Desktop to initiate a FileVault key escrow. This is useful for setting the escrow key initially as well as in scenarios where a token rotation is required. **Requires Fleet Premium license**
|
||||
|
||||
`POST /api/v1/fleet/device/{token}/rotate_encryption_key`
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Type | In | Description |
|
||||
| ----- | ------ | ---- | ---------------------------------- |
|
||||
| token | string | path | The device's authentication token. |
|
||||
|
||||
##### Example
|
||||
|
||||
`POST /api/v1/fleet/device/abcdef012456789/rotate_encryption_key`
|
||||
|
||||
##### Default response
|
||||
|
||||
`Status: 204`
|
||||
|
||||
|
||||
### Report an agent error
|
||||
|
||||
Notifies the server about an agent error, resulting in two outcomes:
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ import PolicyDetailsModal from "../cards/Policies/HostPoliciesTable/PolicyDetail
|
|||
import AutoEnrollMdmModal from "./AutoEnrollMdmModal";
|
||||
import ManualEnrollMdmModal from "./ManualEnrollMdmModal";
|
||||
import OSSettingsModal from "../OSSettingsModal";
|
||||
import ResetKeyModal from "./ResetKeyModal";
|
||||
import BootstrapPackageModal from "../HostDetailsPage/modals/BootstrapPackageModal";
|
||||
import { parseHostSoftwareQueryParams } from "../cards/Software/HostSoftware";
|
||||
import SelfService from "../cards/Software/SelfService";
|
||||
|
|
@ -90,7 +89,6 @@ const DeviceUserPage = ({
|
|||
const [isPremiumTier, setIsPremiumTier] = useState(false);
|
||||
const [showInfoModal, setShowInfoModal] = useState(false);
|
||||
const [showEnrollMdmModal, setShowEnrollMdmModal] = useState(false);
|
||||
const [showResetKeyModal, setShowResetKeyModal] = useState(false);
|
||||
const [refetchStartTime, setRefetchStartTime] = useState<number | null>(null);
|
||||
const [showRefetchSpinner, setShowRefetchSpinner] = useState(false);
|
||||
const [orgLogoURL, setOrgLogoURL] = useState("");
|
||||
|
|
@ -248,10 +246,6 @@ const DeviceUserPage = ({
|
|||
setShowEnrollMdmModal(!showEnrollMdmModal);
|
||||
}, [showEnrollMdmModal, setShowEnrollMdmModal]);
|
||||
|
||||
const toggleResetKeyModal = useCallback(() => {
|
||||
setShowResetKeyModal(!showResetKeyModal);
|
||||
}, [showResetKeyModal, setShowResetKeyModal]);
|
||||
|
||||
const togglePolicyDetailsModal = useCallback(
|
||||
(policy: IHostPolicy) => {
|
||||
setShowPolicyDetailsModal(!showPolicyDetailsModal);
|
||||
|
|
@ -361,7 +355,6 @@ const DeviceUserPage = ({
|
|||
host.mdm.macos_settings?.action_required ?? null
|
||||
}
|
||||
onTurnOnMdm={toggleEnrollMdmModal}
|
||||
onResetKey={toggleResetKeyModal}
|
||||
/>
|
||||
<HostSummaryCard
|
||||
summaryData={summaryData}
|
||||
|
|
@ -448,12 +441,6 @@ const DeviceUserPage = ({
|
|||
</TabsWrapper>
|
||||
{showInfoModal && <InfoModal onCancel={toggleInfoModal} />}
|
||||
{showEnrollMdmModal && renderEnrollMdmModal()}
|
||||
{showResetKeyModal && (
|
||||
<ResetKeyModal
|
||||
onClose={toggleResetKeyModal}
|
||||
deviceAuthToken={deviceAuthToken}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{!!host && showPolicyDetailsModal && (
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
import Button from "components/buttons/Button";
|
||||
import Modal from "components/Modal";
|
||||
import mdmAPI from "services/entities/mdm";
|
||||
import { useQuery } from "react-query";
|
||||
import Spinner from "components/Spinner";
|
||||
import DataError from "components/DataError";
|
||||
|
||||
interface IResetKeyModalProps {
|
||||
onClose: () => void;
|
||||
deviceAuthToken: string;
|
||||
}
|
||||
|
||||
const baseClass = "reset-key-modal";
|
||||
|
||||
const ResetKeyModal = ({
|
||||
onClose,
|
||||
deviceAuthToken,
|
||||
}: IResetKeyModalProps): JSX.Element => {
|
||||
const { isLoading: isLoadingResetDEKey, error: errorResetDEKey } = useQuery(
|
||||
["resetDEkey", deviceAuthToken],
|
||||
() => mdmAPI.resetEncryptionKey(deviceAuthToken),
|
||||
{ refetchOnWindowFocus: false }
|
||||
);
|
||||
|
||||
const renderModalBody = () => {
|
||||
if (isLoadingResetDEKey) {
|
||||
return <Spinner />;
|
||||
}
|
||||
if (errorResetDEKey) {
|
||||
return <DataError />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ol>
|
||||
<li>
|
||||
Wait 30 seconds for the <b>Reset disk encryption key</b> pop up to
|
||||
open.
|
||||
</li>
|
||||
<li>
|
||||
In the popup, enter the password you use to login to your Mac.
|
||||
</li>
|
||||
<li>
|
||||
Close this window and select <b>Refetch</b> on your My device page.
|
||||
This tells your organization that you reset your key.
|
||||
</li>
|
||||
</ol>
|
||||
<div className="modal-cta-wrap">
|
||||
<Button type="button" onClick={onClose} variant="brand">
|
||||
Done
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<Modal
|
||||
title="Reset key"
|
||||
onExit={onClose}
|
||||
className={baseClass}
|
||||
width="medium"
|
||||
>
|
||||
{renderModalBody()}
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResetKeyModal;
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
.reset-key-modal {
|
||||
ol {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: $pad-large;
|
||||
list-style: number inside;
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from "./ResetKeyModal";
|
||||
|
|
@ -6,8 +6,7 @@ import DeviceUserBanners from "./DeviceUserBanners";
|
|||
|
||||
describe("Device User Banners", () => {
|
||||
const turnOnMdmExpcetedText = /Mobile device management \(MDM\) is off\./;
|
||||
const logoutDiskEncryptExpectedText = /Disk encryption: Log out of your device or restart to turn on disk encryption\./;
|
||||
const resetKeyDiskEncryptExpcetedText = /Disk encryption: Reset your disk encryption key\./;
|
||||
const resetKeyDiskEncryptExpcetedText = /Disk encryption: Log out of your device or restart it to safeguard your data in case your device is lost or stolen\./;
|
||||
|
||||
it("renders the turn on mdm banner correctly", () => {
|
||||
render(
|
||||
|
|
@ -19,28 +18,11 @@ describe("Device User Banners", () => {
|
|||
diskEncryptionStatus={null}
|
||||
diskEncryptionActionRequired={null}
|
||||
onTurnOnMdm={noop}
|
||||
onResetKey={noop}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText(turnOnMdmExpcetedText)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the logout for disk encrpytion banner correctly", () => {
|
||||
render(
|
||||
<DeviceUserBanners
|
||||
hostPlatform="darwin"
|
||||
mdmEnrollmentStatus="On (automatic)"
|
||||
mdmEnabledAndConfigured
|
||||
mdmConnectedToFleet
|
||||
diskEncryptionStatus="action_required"
|
||||
diskEncryptionActionRequired="log_out"
|
||||
onTurnOnMdm={noop}
|
||||
onResetKey={noop}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText(logoutDiskEncryptExpectedText)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the reset key for disk encryption banner correctly", () => {
|
||||
render(
|
||||
<DeviceUserBanners
|
||||
|
|
@ -51,7 +33,6 @@ describe("Device User Banners", () => {
|
|||
diskEncryptionStatus="action_required"
|
||||
diskEncryptionActionRequired="rotate_key"
|
||||
onTurnOnMdm={noop}
|
||||
onResetKey={noop}
|
||||
/>
|
||||
);
|
||||
expect(
|
||||
|
|
@ -59,28 +40,6 @@ describe("Device User Banners", () => {
|
|||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders only one banner in a priority order", () => {
|
||||
// set up to render logout disk encryption banner, which is 2nd in priority
|
||||
render(
|
||||
<DeviceUserBanners
|
||||
hostPlatform="darwin"
|
||||
mdmEnrollmentStatus="On (automatic)"
|
||||
mdmEnabledAndConfigured
|
||||
mdmConnectedToFleet
|
||||
diskEncryptionStatus="action_required"
|
||||
diskEncryptionActionRequired="log_out"
|
||||
onTurnOnMdm={noop}
|
||||
onResetKey={noop}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(screen.queryByText(turnOnMdmExpcetedText)).not.toBeInTheDocument();
|
||||
expect(screen.getByText(logoutDiskEncryptExpectedText)).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByText(resetKeyDiskEncryptExpcetedText)
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders no banner correctly", () => {
|
||||
// setup so mdm is not enabled and configured.
|
||||
render(
|
||||
|
|
@ -92,13 +51,12 @@ describe("Device User Banners", () => {
|
|||
diskEncryptionStatus={null}
|
||||
diskEncryptionActionRequired={null}
|
||||
onTurnOnMdm={noop}
|
||||
onResetKey={noop}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(screen.queryByText(turnOnMdmExpcetedText)).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByText(logoutDiskEncryptExpectedText)
|
||||
screen.queryByText(resetKeyDiskEncryptExpcetedText)
|
||||
).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByText(resetKeyDiskEncryptExpcetedText)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ interface IDeviceUserBannersProps {
|
|||
diskEncryptionStatus: DiskEncryptionStatus | null;
|
||||
diskEncryptionActionRequired: MacDiskEncryptionActionRequired | null;
|
||||
onTurnOnMdm: () => void;
|
||||
onResetKey: () => void;
|
||||
}
|
||||
|
||||
const DeviceUserBanners = ({
|
||||
|
|
@ -26,7 +25,6 @@ const DeviceUserBanners = ({
|
|||
diskEncryptionStatus,
|
||||
diskEncryptionActionRequired,
|
||||
onTurnOnMdm,
|
||||
onResetKey,
|
||||
}: IDeviceUserBannersProps) => {
|
||||
const isMdmUnenrolled =
|
||||
mdmEnrollmentStatus === "Off" || mdmEnrollmentStatus === null;
|
||||
|
|
@ -37,11 +35,6 @@ const DeviceUserBanners = ({
|
|||
const showTurnOnMdmBanner =
|
||||
hostPlatform === "darwin" && isMdmUnenrolled && mdmEnabledAndConfigured;
|
||||
|
||||
const showDiskEncryptionLogoutRestart =
|
||||
diskEncryptionBannersEnabled &&
|
||||
diskEncryptionStatus === "action_required" &&
|
||||
diskEncryptionActionRequired === "log_out";
|
||||
|
||||
const showDiskEncryptionKeyResetRequired =
|
||||
diskEncryptionBannersEnabled &&
|
||||
diskEncryptionStatus === "action_required" &&
|
||||
|
|
@ -53,12 +46,6 @@ const DeviceUserBanners = ({
|
|||
</Button>
|
||||
);
|
||||
|
||||
const resetKeyButton = (
|
||||
<Button variant="unstyled" onClick={onResetKey}>
|
||||
<b>Reset key</b>
|
||||
</Button>
|
||||
);
|
||||
|
||||
const renderBanner = () => {
|
||||
if (showTurnOnMdmBanner) {
|
||||
return (
|
||||
|
|
@ -68,19 +55,14 @@ const DeviceUserBanners = ({
|
|||
your device up to date so you don't have to.
|
||||
</InfoBanner>
|
||||
);
|
||||
} else if (showDiskEncryptionLogoutRestart) {
|
||||
}
|
||||
|
||||
if (showDiskEncryptionKeyResetRequired) {
|
||||
return (
|
||||
<InfoBanner color="yellow">
|
||||
Disk encryption: Log out of your device or restart to turn on disk
|
||||
encryption. Then, select <strong>Refetch</strong>. This prevents
|
||||
unauthorized access to the information on your device.
|
||||
</InfoBanner>
|
||||
);
|
||||
} else if (showDiskEncryptionKeyResetRequired) {
|
||||
return (
|
||||
<InfoBanner color="yellow" cta={resetKeyButton}>
|
||||
Disk encryption: Reset your disk encryption key. This lets your
|
||||
organization help you unlock your device if you forget your password.
|
||||
Disk encryption: Log out of your device or restart it to safeguard
|
||||
your data in case your device is lost or stolen. After, select{" "}
|
||||
<strong>Refetch</strong> to clear this banner.
|
||||
</InfoBanner>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,8 +79,7 @@ const HostDetailsBanners = ({
|
|||
{showDiskEncryptionUserActionRequired && (
|
||||
<InfoBanner color="yellow">
|
||||
Disk encryption: Requires action from the end user. Ask the end user
|
||||
to follow <b>Disk encryption</b> instructions on their{" "}
|
||||
<b>My device</b> page.
|
||||
to log out of their device or restart it.
|
||||
</InfoBanner>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -83,10 +83,6 @@ export interface IGetMdmCommandResultsResponse {
|
|||
}
|
||||
|
||||
const mdmService = {
|
||||
resetEncryptionKey: (token: string) => {
|
||||
const { DEVICE_USER_RESET_ENCRYPTION_KEY } = endpoints;
|
||||
return sendRequest("POST", DEVICE_USER_RESET_ENCRYPTION_KEY(token));
|
||||
},
|
||||
unenrollHostFromMdm: (hostId: number, timeout?: number) => {
|
||||
const { HOST_MDM_UNENROLL } = endpoints;
|
||||
return sendRequest(
|
||||
|
|
|
|||
|
|
@ -31,9 +31,6 @@ export default {
|
|||
`/${API_VERSION}/fleet/device/${token}/software`,
|
||||
DEVICE_SOFTWARE_INSTALL: (token: string, softwareTitleId: number) =>
|
||||
`/${API_VERSION}/fleet/device/${token}/software/install/${softwareTitleId}`,
|
||||
DEVICE_USER_RESET_ENCRYPTION_KEY: (token: string): string => {
|
||||
return `/${API_VERSION}/fleet/device/${token}/rotate_encryption_key`;
|
||||
},
|
||||
DEVICE_USER_MDM_ENROLLMENT_PROFILE: (token: string): string => {
|
||||
return `/${API_VERSION}/fleet/device/${token}/mdm/apple/manual_enrollment_profile`;
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue