= {
atom_packages: "Package (Atom)", // Atom packages were removed from software inventory. Mapping is maintained for backwards compatibility. (2023-12-04)
python_packages: "Package (Python)",
apps: "Application (macOS)",
- ios: "Application (iOS)",
- ipados: "Application (iPadOS)",
+ ios_apps: "Application (iOS)",
+ ipados_apps: "Application (iPadOS)",
chrome_extensions: "Browser plugin", // chrome_extensions can include any chrome-based browser (e.g., edge), so we rely instead on the `browser` field computed by Fleet server and fallback to this value if it is not present.
firefox_addons: "Browser plugin (Firefox)",
safari_extensions: "Browser plugin (Safari)",
diff --git a/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx b/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx
index 54bce326b1..c0f81ef72d 100644
--- a/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx
+++ b/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx
@@ -4,7 +4,10 @@ import { formatDistanceToNowStrict } from "date-fns";
import { ActivityType, IActivity, IActivityDetails } from "interfaces/activity";
import { getInstallStatusPredicate } from "interfaces/software";
-import { AppleDisplayPlatform } from "interfaces/platform";
+import {
+ AppleDisplayPlatform,
+ PLATFORM_DISPLAY_NAMES,
+} from "interfaces/platform";
import {
addGravatarUrlToResource,
@@ -882,10 +885,13 @@ const TAGGED_TEMPLATES = {
);
},
addedAppStoreApp: (activity: IActivity) => {
+ const { software_title: swTitle, platform: swPlatform } =
+ activity.details || {};
return (
<>
{" "}
- added {activity.details?.software_title} to{" "}
+ added {swTitle}{" "}
+ {swPlatform ? `(${PLATFORM_DISPLAY_NAMES[swPlatform]}) ` : ""}to{" "}
{activity.details?.team_name ? (
<>
{" "}
@@ -898,10 +904,13 @@ const TAGGED_TEMPLATES = {
);
},
deletedAppStoreApp: (activity: IActivity) => {
+ const { software_title: swTitle, platform: swPlatform } =
+ activity.details || {};
return (
<>
{" "}
- deleted {activity.details?.software_title} from{" "}
+ deleted {swTitle}{" "}
+ {swPlatform ? `(${PLATFORM_DISPLAY_NAMES[swPlatform]}) ` : ""}from{" "}
{activity.details?.team_name ? (
<>
{" "}
diff --git a/frontend/pages/DashboardPage/cards/OperatingSystems/OperatingSystemsTableConfig.tsx b/frontend/pages/DashboardPage/cards/OperatingSystems/OperatingSystemsTableConfig.tsx
index f5a5292217..80df2741ac 100644
--- a/frontend/pages/DashboardPage/cards/OperatingSystems/OperatingSystemsTableConfig.tsx
+++ b/frontend/pages/DashboardPage/cards/OperatingSystems/OperatingSystemsTableConfig.tsx
@@ -108,7 +108,7 @@ const generateDefaultTableHeaders = (
Cell: (cellProps: IVulnCellProps) => {
const platform = cellProps.row.original.platform;
if (platform !== "darwin" && platform !== "windows") {
- return ;
+ return ;
}
return ;
},
diff --git a/frontend/pages/NoAccessPage/NoAccessPage.tsx b/frontend/pages/NoAccessPage/NoAccessPage.tsx
index 017ea3f8b4..1c7a83dd99 100644
--- a/frontend/pages/NoAccessPage/NoAccessPage.tsx
+++ b/frontend/pages/NoAccessPage/NoAccessPage.tsx
@@ -4,6 +4,8 @@ import React, { useEffect } from "react";
import { InjectedRouter } from "react-router";
import PATHS from "router/paths";
+import { CONTACT_FLEET_LINK } from "utilities/constants";
+
import Button from "components/buttons/Button/Button";
// @ts-ignore
import StackedWhiteBoxes from "components/StackedWhiteBoxes";
@@ -48,7 +50,7 @@ const NoAccessPage = ({ router, orgContactUrl }: INoAccessPageProps) => {
To get access,{" "}
.
diff --git a/frontend/pages/SoftwarePage/SoftwareOSDetailsPage/SoftwareOSDetailsPage.tsx b/frontend/pages/SoftwarePage/SoftwareOSDetailsPage/SoftwareOSDetailsPage.tsx
index 3a1b01adfa..125dab201a 100644
--- a/frontend/pages/SoftwarePage/SoftwareOSDetailsPage/SoftwareOSDetailsPage.tsx
+++ b/frontend/pages/SoftwarePage/SoftwareOSDetailsPage/SoftwareOSDetailsPage.tsx
@@ -11,64 +11,34 @@ import useTeamIdParam from "hooks/useTeamIdParam";
import { AppContext } from "context/app";
import { ignoreAxiosError } from "interfaces/errors";
+import {
+ isLinuxLike,
+ Platform,
+ VULN_SUPPORTED_PLATFORMS,
+} from "interfaces/platform";
import osVersionsAPI, {
IOSVersionResponse,
IGetOsVersionQueryKey,
} from "services/entities/operating_systems";
import { IOperatingSystemVersion } from "interfaces/operating_system";
-import { isLinuxLike } from "interfaces/platform";
-import { DEFAULT_USE_QUERY_OPTIONS, SUPPORT_LINK } from "utilities/constants";
+import {
+ DEFAULT_USE_QUERY_OPTIONS,
+ PLATFORM_DISPLAY_NAMES,
+} from "utilities/constants";
import Spinner from "components/Spinner";
import MainContent from "components/MainContent";
-import EmptyTable from "components/EmptyTable";
-import CustomLink from "components/CustomLink";
import TeamsHeader from "components/TeamsHeader";
import Card from "components/Card";
import SoftwareDetailsSummary from "../components/SoftwareDetailsSummary";
import SoftwareVulnerabilitiesTable from "../components/SoftwareVulnerabilitiesTable";
import DetailsNoHosts from "../components/DetailsNoHosts";
+import { VulnsNotSupported } from "../components/SoftwareVulnerabilitiesTable/SoftwareVulnerabilitiesTable";
const baseClass = "software-os-details-page";
-interface INotSupportedVulnProps {
- platform: string;
-}
-
-const platformDisplayName = (platform: string) => {
- if (isLinuxLike(platform)) {
- return "Linux hosts";
- }
-
- switch (platform) {
- case "chrome":
- return "Chromebooks";
- case "ios":
- return "iPhones";
- case "ipados":
- return "iPads";
- default:
- return "this operating system";
- }
-};
-
-const NotSupportedVuln = ({ platform }: INotSupportedVulnProps) => {
- return (
-
- Interested in vulnerability management for{" "}
- {platformDisplayName(platform)}?{" "}
-
- >
- }
- />
- );
-};
-
interface ISoftwareOSDetailsRouteParams {
id: string;
team_id?: string;
@@ -145,10 +115,13 @@ const SoftwareOSDetailsPage = ({
}
if (
- osVersionDetails.platform !== "darwin" &&
- osVersionDetails.platform !== "windows"
+ // TODO - detangle platform typing here
+ !VULN_SUPPORTED_PLATFORMS.includes(osVersionDetails.platform as Platform)
) {
- return ;
+ const supportInterestText = isLinuxLike(osVersionDetails.platform)
+ ? "Linux"
+ : PLATFORM_DISPLAY_NAMES[osVersionDetails.platform];
+ return ;
}
return (
diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsPage.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsPage.tsx
index e721379b34..b545171ea3 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsPage.tsx
+++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsPage.tsx
@@ -202,6 +202,9 @@ const SoftwareTitleDetailsPage = ({
data={softwareTitle.versions ?? []}
isLoading={isSoftwareTitleLoading}
teamIdForApi={teamIdForApi}
+ isIPadOSOrIOSApp={["ios_apps", "ipados_apps"].includes(
+ softwareTitle.source
+ )}
/>
>
diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsTable/SoftwareTitleDetailsTable.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsTable/SoftwareTitleDetailsTable.tsx
index 99587e2b9c..a348b501b0 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsTable/SoftwareTitleDetailsTable.tsx
+++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsTable/SoftwareTitleDetailsTable.tsx
@@ -44,6 +44,7 @@ interface ISoftwareTitleDetailsTableProps {
data: ISoftwareTitleVersion[];
isLoading: boolean;
teamIdForApi?: number;
+ isIPadOSOrIOSApp: boolean;
}
interface IRowProps extends Row {
@@ -57,6 +58,7 @@ const SoftwareTitleDetailsTable = ({
data,
isLoading,
teamIdForApi,
+ isIPadOSOrIOSApp,
}: ISoftwareTitleDetailsTableProps) => {
const handleRowSelect = (row: IRowProps) => {
const hostsBySoftwareParams = {
@@ -74,8 +76,12 @@ const SoftwareTitleDetailsTable = ({
const softwareTableHeaders = useMemo(
() =>
- generateSoftwareTitleDetailsTableConfig({ router, teamId: teamIdForApi }),
- [router, teamIdForApi]
+ generateSoftwareTitleDetailsTableConfig({
+ router,
+ teamId: teamIdForApi,
+ isIPadOSOrIOSApp,
+ }),
+ [router, teamIdForApi, isIPadOSOrIOSApp]
);
const renderVersionsCount = () => (
diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsTable/SoftwareTitleDetailsTableConfig.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsTable/SoftwareTitleDetailsTableConfig.tsx
index e5990b58a6..705249e14a 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsTable/SoftwareTitleDetailsTableConfig.tsx
+++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwareTitleDetailsTable/SoftwareTitleDetailsTableConfig.tsx
@@ -17,6 +17,7 @@ import VulnerabilitiesCell from "../../components/VulnerabilitiesCell";
interface ISoftwareTitleDetailsTableConfigProps {
router: InjectedRouter;
teamId?: number;
+ isIPadOSOrIOSApp: boolean;
}
interface ICellProps {
cell: {
@@ -48,6 +49,7 @@ interface IVulnCellProps extends ICellProps {
const generateSoftwareTitleDetailsTableConfig = ({
router,
teamId,
+ isIPadOSOrIOSApp,
}: ISoftwareTitleDetailsTableConfigProps) => {
const tableHeaders = [
{
@@ -90,10 +92,13 @@ const generateSoftwareTitleDetailsTableConfig = ({
// With the versions data, we can sum up the vulnerabilities to get the
// total number of vulnerabilities for the software title
accessor: "vulnerabilities",
- Cell: (cellProps: IVulnCellProps): JSX.Element => (
-
+ Cell: (cellProps: IVulnCellProps): JSX.Element => {
+ if (isIPadOSOrIOSApp) {
+ return ;
+ }
+ return ;
// TODO: tooltip
- ),
+ },
},
{
title: "Hosts",
diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/helpers.ts b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/helpers.ts
index 9e7ece8cf7..b662f30556 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/helpers.ts
+++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/helpers.ts
@@ -3,6 +3,7 @@ import {
ISoftwareTitleDetails,
isSoftwarePackage,
} from "interfaces/software";
+import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
/**
* Generates the data needed to render the package card.
@@ -18,9 +19,10 @@ export const getPackageCardInfo = (softwareTitle: ISoftwareTitleDetails) => {
return {
softwarePackage: isSoftwarePackage(packageData) ? packageData : undefined,
name: softwareTitle.name,
- version: isSoftwarePackage(packageData)
- ? packageData.version
- : packageData.latest_version,
+ version:
+ (isSoftwarePackage(packageData)
+ ? packageData.version
+ : packageData.latest_version) || DEFAULT_EMPTY_CELL_VALUE,
uploadedAt: isSoftwarePackage(packageData) ? packageData.uploaded_at : "",
status: packageData.status,
isSelfService: isSoftwarePackage(packageData)
diff --git a/frontend/pages/SoftwarePage/SoftwareTitles/SoftwareTable/SoftwareTitlesTableConfig.tsx b/frontend/pages/SoftwarePage/SoftwareTitles/SoftwareTable/SoftwareTitlesTableConfig.tsx
index 0e303c918c..213cc1ec46 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitles/SoftwareTable/SoftwareTitlesTableConfig.tsx
+++ b/frontend/pages/SoftwarePage/SoftwareTitles/SoftwareTable/SoftwareTitlesTableConfig.tsx
@@ -2,13 +2,7 @@ import React from "react";
import { CellProps, Column } from "react-table";
import { InjectedRouter } from "react-router";
-import {
- IAppStoreApp,
- ISoftware,
- ISoftwarePackage,
- ISoftwareTitle,
- formatSoftwareType,
-} from "interfaces/software";
+import { ISoftwareTitle, formatSoftwareType } from "interfaces/software";
import PATHS from "router/paths";
import { buildQueryStringFromParams } from "utilities/url";
@@ -123,14 +117,6 @@ const generateTableHeaders = (
},
sortType: "caseInsensitive",
},
- {
- Header: "Type",
- disableSortBy: true,
- accessor: "source",
- Cell: (cellProps: ITableStringCellProps) => (
-
- ),
- },
{
Header: "Version",
disableSortBy: true,
@@ -139,6 +125,14 @@ const generateTableHeaders = (
),
},
+ {
+ Header: "Type",
+ disableSortBy: true,
+ accessor: "source",
+ Cell: (cellProps: ITableStringCellProps) => (
+
+ ),
+ },
// the "vulnerabilities" accessor is used but the data is actually coming
// from the version attribute. We do this as we already have a "versions"
// attribute used for the "Version" column and we cannot reuse. This is a
@@ -149,6 +143,11 @@ const generateTableHeaders = (
Header: "Vulnerabilities",
disableSortBy: true,
Cell: (cellProps: IVulnerabilitiesCellProps) => {
+ if (
+ ["ios_apps", "ipados_apps"].includes(cellProps.row.original.source)
+ ) {
+ return ;
+ }
const vulnerabilities = getVulnerabilities(
cellProps.row.original.versions ?? []
);
diff --git a/frontend/pages/SoftwarePage/SoftwareTitles/SoftwareTable/SoftwareVersionsTableConfig.tsx b/frontend/pages/SoftwarePage/SoftwareTitles/SoftwareTable/SoftwareVersionsTableConfig.tsx
index d22aab9e86..0be57bf962 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitles/SoftwareTable/SoftwareVersionsTableConfig.tsx
+++ b/frontend/pages/SoftwarePage/SoftwareTitles/SoftwareTable/SoftwareVersionsTableConfig.tsx
@@ -63,14 +63,6 @@ const generateTableHeaders = (
},
sortType: "caseInsensitive",
},
- {
- Header: "Type",
- disableSortBy: true,
- accessor: "source",
- Cell: (cellProps: ITableStringCellProps) => (
-
- ),
- },
{
Header: "Version",
disableSortBy: true,
@@ -79,13 +71,26 @@ const generateTableHeaders = (
),
},
+ {
+ Header: "Type",
+ disableSortBy: true,
+ accessor: "source",
+ Cell: (cellProps: ITableStringCellProps) => (
+
+ ),
+ },
{
Header: "Vulnerabilities",
disableSortBy: true,
accessor: "vulnerabilities",
- Cell: (cellProps: IVulnerabilitiesCellProps) => (
-
- ),
+ Cell: (cellProps: IVulnerabilitiesCellProps) => {
+ if (
+ ["ipados_apps", "ios_apps"].includes(cellProps.row.original.source)
+ ) {
+ return ;
+ }
+ return ;
+ },
},
{
Header: (cellProps: ITableHeaderProps) => (
diff --git a/frontend/pages/SoftwarePage/SoftwareVersionDetailsPage/SoftwareVersionDetailsPage.tsx b/frontend/pages/SoftwarePage/SoftwareVersionDetailsPage/SoftwareVersionDetailsPage.tsx
index 328713f78c..8ee1118aef 100644
--- a/frontend/pages/SoftwarePage/SoftwareVersionDetailsPage/SoftwareVersionDetailsPage.tsx
+++ b/frontend/pages/SoftwarePage/SoftwareVersionDetailsPage/SoftwareVersionDetailsPage.tsx
@@ -31,6 +31,7 @@ import Card from "components/Card";
import SoftwareDetailsSummary from "../components/SoftwareDetailsSummary";
import SoftwareVulnerabilitiesTable from "../components/SoftwareVulnerabilitiesTable";
import DetailsNoHosts from "../components/DetailsNoHosts";
+import { VulnsNotSupported } from "../components/SoftwareVulnerabilitiesTable/SoftwareVulnerabilitiesTable";
const baseClass = "software-version-details-page";
@@ -112,6 +113,23 @@ const SoftwareVersionDetailsPage = ({
[handleTeamChange]
);
+ const renderVulnTable = (swVersion: ISoftwareVersion) => {
+ if (["ios_apps", "ipados_apps"].includes(swVersion.source)) {
+ const supportInterestText =
+ swVersion.source === "ios_apps" ? "iOS" : "iPadOS";
+ return ;
+ }
+ return (
+
+ );
+ };
+
const renderContent = () => {
if (isSoftwareVersionLoading) {
return ;
@@ -157,13 +175,7 @@ const SoftwareVersionDetailsPage = ({
className={`${baseClass}__vulnerabilities-section`}
>
Vulnerabilities
-
+ {renderVulnTable(softwareVersion)}
>
)}
diff --git a/frontend/pages/SoftwarePage/components/AppStoreVpp/AppStoreVpp.tsx b/frontend/pages/SoftwarePage/components/AppStoreVpp/AppStoreVpp.tsx
index 1a1fc02ad0..65d19bcefd 100644
--- a/frontend/pages/SoftwarePage/components/AppStoreVpp/AppStoreVpp.tsx
+++ b/frontend/pages/SoftwarePage/components/AppStoreVpp/AppStoreVpp.tsx
@@ -10,6 +10,8 @@ import mdmAppleAPI, {
} from "services/entities/mdm_apple";
import { DEFAULT_USE_QUERY_OPTIONS } from "utilities/constants";
+import { PLATFORM_DISPLAY_NAMES } from "interfaces/platform";
+
import Card from "components/Card";
import CustomLink from "components/CustomLink";
import Spinner from "components/Spinner";
@@ -29,7 +31,7 @@ const EnableVppCard = () => {
- Volume Purchasing Program (VPP) isn’t enabled.
+ Volume Purchasing Program (VPP) isn't enabled
To add App Store apps, first enable VPP.
@@ -66,6 +68,11 @@ const VppAppListItem = ({ app, selected, onSelect }: IVppAppListItemProps) => {
name="vppApp"
onChange={() => onSelect(app)}
/>
+ {app.platform && (
+
+ {PLATFORM_DISPLAY_NAMES[app.platform]}
+
+ )}
);
};
@@ -76,40 +83,20 @@ interface IVppAppListProps {
onSelect: (app: IVppApp) => void;
}
-const VppAppList = ({ apps, selectedApp, onSelect }: IVppAppListProps) => {
- const renderContent = () => {
- if (apps.length === 0) {
- return (
-
-
- You don't have any App Store apps
-
-
- You must purchase apps in ABM. App Store apps that are already added
- to this team are not listed.
-
-
- );
- }
-
- return (
-
- {apps.map((app) => (
-
- ))}
-
- );
- };
-
- return (
-
{renderContent()}
- );
-};
+const VppAppList = ({ apps, selectedApp, onSelect }: IVppAppListProps) => (
+
+
+ {apps.map((app) => (
+
+ ))}
+
+
+);
interface IAppStoreVppProps {
teamId: number;
@@ -193,20 +180,41 @@ const AppStoreVpp = ({ teamId, router, onExit }: IAppStoreVppProps) => {
return
;
}
- return vppApps ? (
-
- ) : null;
+ if (vppApps) {
+ if (vppApps.length === 0) {
+ return (
+
+
+ You don't have any App Store apps
+
+
+ Add apps in{" "}
+ {" "}
+ Apps that are already added to this team are not listed.
+
+
+ );
+ }
+ return (
+ <>
+
+
+ These apps were added in Apple Business Manager (ABM). To add more
+ apps, head to{" "}
+
+
+ >
+ );
+ }
+ return null;
};
return (
-
- Apple App Store apps purchased via Apple Business Manager.
-
{renderContent()}