import React, { useContext, useState } from "react"; import { Tab, Tabs, TabList, TabPanel } from "react-tabs"; import FileSaver from "file-saver"; import { NotificationContext } from "context/notification"; import { IConfig } from "interfaces/config"; import { LEARN_MORE_ABOUT_BASE_LINK } from "utilities/constants"; import Button from "components/buttons/Button"; import Icon from "components/Icon/Icon"; import RevealButton from "components/buttons/RevealButton"; // @ts-ignore import InputField from "components/forms/fields/InputField"; import TooltipWrapper from "components/TooltipWrapper"; import TabNav from "components/TabNav"; import InfoBanner from "components/InfoBanner/InfoBanner"; import CustomLink from "components/CustomLink/CustomLink"; import Radio from "components/forms/fields/Radio"; import TabText from "components/TabText"; import { isValidPemCertificate } from "../../../pages/hosts/ManageHostsPage/helpers"; import IosIpadosPanel from "./IosIpadosPanel"; import AndroidPanel from "./AndroidPanel"; interface IPlatformSubNav { name: string; type: string; } const platformSubNav: IPlatformSubNav[] = [ { name: "macOS", type: "pkg", }, { name: "Windows", type: "msi", }, { name: "Linux", type: "deb", }, { name: "ChromeOS", type: "chromeos", }, { name: "iOS & iPadOS", type: "ios-ipados", }, { name: "Android", type: "android", }, { name: "Advanced", type: "advanced", }, ]; interface IPlatformWrapperProps { enrollSecret: string; onCancel: () => void; certificate: any; isFetchingCertificate: boolean; fetchCertificateError: any; config: IConfig | null; } const baseClass = "platform-wrapper"; const PlatformWrapper = ({ enrollSecret, onCancel, certificate, isFetchingCertificate, fetchCertificateError, config, }: IPlatformWrapperProps): JSX.Element => { const { renderFlash } = useContext(NotificationContext); const [hostType, setHostType] = useState<"workstation" | "server">( "workstation" ); const [showPlainOsquery, setShowPlainOsquery] = useState(false); const [selectedTabIndex, setSelectedTabIndex] = useState(0); // External link requires control in state let tlsHostname = config?.server_settings.server_url || ""; try { const serverUrl = new URL(config?.server_settings.server_url || ""); tlsHostname = serverUrl.hostname; if (serverUrl.port) { tlsHostname += `:${serverUrl.port}`; } } catch (e) { if (!(e instanceof TypeError)) { throw e; } } const flagfileContent = `# Server --tls_hostname=${tlsHostname} --tls_server_certs=fleet.pem # Enrollment --host_identifier=instance --enroll_secret_path=secret.txt --enroll_tls_endpoint=/api/osquery/enroll # Configuration --config_plugin=tls --config_tls_endpoint=/api/v1/osquery/config --config_refresh=10 # Live query --disable_distributed=false --distributed_plugin=tls --distributed_interval=10 --distributed_tls_max_attempts=3 --distributed_tls_read_endpoint=/api/v1/osquery/distributed/read --distributed_tls_write_endpoint=/api/v1/osquery/distributed/write # Logging --logger_plugin=tls --logger_tls_endpoint=/api/v1/osquery/log --logger_tls_period=10 # File carving --disable_carver=false --carver_start_endpoint=/api/v1/osquery/carve/begin --carver_continue_endpoint=/api/v1/osquery/carve/block --carver_block_size=8000000`; const onDownloadEnrollSecret = (evt: React.MouseEvent) => { evt.preventDefault(); const filename = "secret.txt"; const file = new global.window.File([enrollSecret], filename); FileSaver.saveAs(file); return false; }; const onDownloadFlagfile = (evt: React.MouseEvent) => { evt.preventDefault(); const filename = "flagfile.txt"; const file = new global.window.File([flagfileContent], filename); FileSaver.saveAs(file); return false; }; const onDownloadCertificate = (evt: React.MouseEvent) => { evt.preventDefault(); if (certificate && isValidPemCertificate(certificate)) { const filename = "fleet.pem"; const file = new global.window.File([certificate], filename, { type: "application/x-pem-file", }); FileSaver.saveAs(file); } else { renderFlash( "error", "Your certificate could not be downloaded. Please check your Fleet configuration." ); } return false; }; const renderFleetCertificateBlock = (type: "plain" | "tooltip") => { return (
{type === "plain" ? (
Download your Fleet certificate
) : (
Download your{" "} Fleet certificate:
)} {isFetchingCertificate && (

Loading your certificate

)} {!isFetchingCertificate && (certificate ? (

{type === "plain" && ( <> Prove the TLS certificate used by the Fleet server to enable secure connections from osquery:
)}

) : (

Fleet failed to load your certificate. If you're able to access Fleet at a private or secure (HTTPS) IP address, please log into Fleet at this address to load your certificate.

))}
); }; const renderInstallerString = (packageType: string) => { return packageType === "advanced" ? `fleetctl package --type=YOUR_TYPE --fleet-url=${config?.server_settings.server_url} --enroll-secret=${enrollSecret} --fleet-certificate=PATH_TO_YOUR_CERTIFICATE/fleet.pem` : `fleetctl package --type=${packageType} ${ config && !config.server_settings.scripts_disabled ? "--enable-scripts " : "" }${hostType === "workstation" ? "--fleet-desktop " : ""}--fleet-url=${ config?.server_settings.server_url } --enroll-secret=${enrollSecret}`; }; const renderLabel = (packageType: string) => { return ( <> {packageType !== "plain-osquery" && ( Use this command to generate Fleet's agent.{" "} )} ); }; const renderPanel = (packageType: string) => { const CHROME_OS_INFO = { extensionId: "fleeedmmihkfkeemmipgmhhjemlljidg", installationUrl: "https://chrome.fleetdm.com/updates.xml", policyForExtension: `{ "fleet_url": { "Value": "${config?.server_settings.server_url}" }, "enroll_secret": { "Value": "${enrollSecret}" } }`, }; let packageTypeHelpText; if (packageType === "deb") { packageTypeHelpText = ( <> Run this on your computer, then deploy the generated package to your hosts. For CentOS, Red Hat, and Fedora Linux, use{" "} --type=rpm. For Arch Linux, use{" "} --type=pkg.tar.zst. For ARM, use{" "} --arch=arm64 ); } else if (packageType === "msi") { packageTypeHelpText = ( <> Run this on your computer, then deploy the generated package to your hosts. For ARM, use --arch=arm64 ); } else if (packageType === "pkg") { packageTypeHelpText = "Run this on your computer, then deploy the generated package to your hosts."; } else { packageTypeHelpText = ""; } if (packageType === "chromeos") { return ( <>

In Google Admin:

Add the extension for the relevant users & browsers using the information below.

For a step-by-step guide, see the documentation page for 
); } if (packageType === "ios-ipados") { return ; } if (packageType === "android") { return ; } if (packageType === "advanced") { return ( <> {renderFleetCertificateBlock("tooltip")}
This works for macOS, Windows, and Linux hosts. To add Chromebooks,  .
setShowPlainOsquery((prev) => !prev)} /> {showPlainOsquery && ( <>

Download your enroll secret:

Osquery uses an enroll secret to authenticate with the Fleet server.

{renderFleetCertificateBlock("plain")}

Download your flagfile:

If using the enroll secret and server certificate downloaded above, use the generated flagfile. In some configurations, modifications may need to be made.
{fetchCertificateError ? ( {fetchCertificateError} ) : ( )}

With{" "} {" "} installed:

Run osquery from the directory containing the above files (may require sudo or Run as Administrator privileges):

)} ); } return ( // "form" className applies the global form styling
{packageType !== "pkg" && ( // Windows & Linux
Type
setHostType("workstation")} /> setHostType("server")} />
)}
); }; return (
setSelectedTabIndex(index)} selectedIndex={selectedTabIndex} > {platformSubNav.map((navItem) => { // Bolding text when the tab is active causes a layout shift // so we add a hidden pseudo element with the same text string return ( {navItem.name} ); })} {platformSubNav.map((navItem) => { // Bolding text when the tab is active causes a layout shift // so we add a hidden pseudo element with the same text string return (
{renderPanel(navItem.type)}
); })}
); }; export default PlatformWrapper;