fleet/frontend/pages/hosts/details/OSSettingsModal/OSSettingsTable/OSSettingsTableConfig.tsx
jacobshandling 096d67dd5a
Linux disk encryption: frontend changes, backend missing private key errors, remove disk encryption endpoints dependence on MDM being enabled (#23714)
## Addresses #22702,  #23713, #23756, #23746, #23747, and #23876
_-Note that much of this code as is will render as expected only once
integrated with the backend or if manipulated manually for testing
purposes_

**Frontend**:
- Update banners on my device page, tests
- Build new logic for calling endpoint to trigger linux key escrow on
clicking `Create key`
- Add `CreateLinuxKeyModal` to inform user of next steps after clicking
`Create key`
- Update banners on host details page, tests
- Update the Controls > OS settings section with new logic related to
linux disk encryption
- Expect and include counts of Linux hosts in aggregate disk encryption
stats UI
- Add "Linux" column to the disk encryption table
- Show disk encryption related UI for supported Linux platforms
- TODO: confirm platform string matching functionality in manual e2e
testing
- Expand capabilities of `SectionHeader` component, apply to new UI
- Flash "missing private key" error, with clickable link, when trying to
update disk encryption enabled while no server private key is present.
- TODO: QA this once other endpoints on Controls > Disk encryption are
enabled even when MDM not turned on
- Update Disk encryption key modal copy


-Other TODO:
  - Confirm when integrated with API:
    - Aggregate disk encryption counts
    - Disk encryption table Linux column
    - Show disk encryption key action on host details page when expected
    - Opens Disk encryption key modal, displays key as expected
  
**Backend**:
- For "No team" and teams, error when trying to update disk encryption
enabled while no server private key is present.
- Remove requirement of mdm being enabled for use of various endpoints
related to Linux disk encryption
- Update tests


_________
**Host details and my device page banners**

![banners](https://github.com/user-attachments/assets/b76fbfbd-0969-40eb-b8b1-9fd0d4fd0f4f)

**Create key modal**
<img width="1799" alt="create-key-modal"
src="https://github.com/user-attachments/assets/81a55ccb-b6b9-4eb6-b2ff-a463c60724c0">

**Enabling disk encryption**

![turning-on-enforcement](https://github.com/user-attachments/assets/005010b9-2238-46f8-9579-f07823898a78)

**Disk encryption: Fleet free**
<img width="1912" alt="free"
src="https://github.com/user-attachments/assets/9f9cace3-8955-47c2-87d9-24ff9387ac1a">

**Custom settings: turn on MDM**
<img width="1912" alt="turn on mdm"
src="https://github.com/user-attachments/assets/4d3ad47b-4035-4d93-86f0-dc2691b38bb4">

**Device status indicators**

![host-status-indicators](https://github.com/user-attachments/assets/5fc72c1e-816b-45b3-a650-5c1fcc48f09e)

**Encryption key action and modal**

![de-key-action-and-modal](https://github.com/user-attachments/assets/632f7b2c-c07e-4e30-87ef-e6437ae42a78)



- [x] Changes file added for user-visible changes in `changes/`
- [x] Added/updated tests
- [x] Manual QA for all new/changed functionality
  - [ ] Full e2e testing to do when integrated with backend

---------

Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
Co-authored-by: Ian Littman <iansltx@gmail.com>
2024-11-20 11:58:47 -08:00

193 lines
4.9 KiB
TypeScript

import React from "react";
import { Column } from "react-table";
import { IStringCellProps } from "interfaces/datatable_config";
import { IHostMdmData } from "interfaces/host";
import {
FLEET_FILEVAULT_PROFILE_DISPLAY_NAME,
// FLEET_FILEVAULT_PROFILE_IDENTIFIER,
IHostMdmProfile,
MdmDDMProfileStatus,
MdmProfileStatus,
isLinuxDiskEncryptionStatus,
isWindowsDiskEncryptionStatus,
} from "interfaces/mdm";
import { isDiskEncryptionSupportedLinuxPlatform } from "interfaces/platform";
import TooltipTruncatedTextCell from "components/TableContainer/DataTable/TooltipTruncatedTextCell";
import OSSettingStatusCell from "./OSSettingStatusCell";
import {
generateLinuxDiskEncryptionSetting,
generateWinDiskEncryptionSetting,
} from "../../helpers";
import OSSettingsErrorCell from "./OSSettingsErrorCell";
export const isMdmProfileStatus = (
status: string
): status is MdmProfileStatus => {
return status !== "action_required";
};
export interface IHostMdmProfileWithAddedStatus
extends Omit<IHostMdmProfile, "status"> {
status: OsSettingsTableStatusValue;
}
type ITableColumnConfig = Column<IHostMdmProfileWithAddedStatus>;
type ITableStringCellProps = IStringCellProps<IHostMdmProfileWithAddedStatus>;
/** Non DDM profiles can have an `action_required` as a profile status. DDM
* Profiles will never have this status.
*/
export type INonDDMProfileStatus = MdmProfileStatus | "action_required";
export type OsSettingsTableStatusValue =
| MdmDDMProfileStatus
| INonDDMProfileStatus;
const generateTableConfig = (
hostId: number,
canResendProfiles: boolean,
onProfileResent?: () => void
): ITableColumnConfig[] => {
return [
{
Header: "Name",
disableSortBy: true,
accessor: "name",
Cell: (cellProps: ITableStringCellProps) => {
return (
<TooltipTruncatedTextCell
value={cellProps.cell.value}
className="os-settings-name-cell"
/>
);
},
},
{
Header: "Status",
disableSortBy: true,
accessor: "status",
Cell: (cellProps: ITableStringCellProps) => {
return (
<OSSettingStatusCell
status={cellProps.row.original.status}
operationType={cellProps.row.original.operation_type}
profileName={cellProps.row.original.name}
hostPlatform={cellProps.row.original.platform}
/>
);
},
},
{
Header: "Error",
disableSortBy: true,
accessor: "detail",
Cell: (cellProps: ITableStringCellProps) => (
<OSSettingsErrorCell
canResendProfiles={canResendProfiles}
hostId={hostId}
profile={cellProps.row.original}
onProfileResent={onProfileResent}
/>
),
},
];
};
const makeWindowsRows = ({ profiles, os_settings }: IHostMdmData) => {
const rows: IHostMdmProfileWithAddedStatus[] = [];
if (profiles) {
rows.push(...profiles);
}
if (
os_settings?.disk_encryption?.status &&
isWindowsDiskEncryptionStatus(os_settings.disk_encryption.status)
) {
rows.push(
generateWinDiskEncryptionSetting(
os_settings.disk_encryption.status,
os_settings.disk_encryption.detail
)
);
}
if (rows.length === 0 && !profiles) {
return null;
}
return rows;
};
const makeLinuxRows = ({ profiles, os_settings }: IHostMdmData) => {
const rows: IHostMdmProfileWithAddedStatus[] = [];
if (profiles) {
rows.push(...profiles);
}
if (
os_settings?.disk_encryption?.status &&
isLinuxDiskEncryptionStatus(os_settings.disk_encryption.status)
) {
rows.push(
generateLinuxDiskEncryptionSetting(
os_settings.disk_encryption.status,
os_settings.disk_encryption.detail
)
);
}
if (rows.length === 0 && !profiles) {
return null;
}
return rows;
};
const makeDarwinRows = ({ profiles, macos_settings }: IHostMdmData) => {
if (!profiles) {
return null;
}
let rows: IHostMdmProfileWithAddedStatus[] = profiles;
if (macos_settings?.disk_encryption === "action_required") {
rows = profiles.map((p) => {
// TODO: this is a brittle check for the filevault profile
// it would be better to match on the identifier but it is not
// currently available in the API response
if (p.name === FLEET_FILEVAULT_PROFILE_DISPLAY_NAME) {
return { ...p, status: "action_required" || p.status };
}
return p;
});
}
return rows;
};
export const generateTableData = (
hostMDMData: IHostMdmData,
platform: string
) => {
switch (platform) {
case "windows":
return makeWindowsRows(hostMDMData);
case "darwin":
return makeDarwinRows(hostMDMData);
case "ubuntu":
return makeLinuxRows(hostMDMData);
case "rhel":
return makeLinuxRows(hostMDMData);
case "ios":
return hostMDMData.profiles;
case "ipados":
return hostMDMData.profiles;
default:
return null;
}
};
export default generateTableConfig;