import React, { useContext, useState } from "react"; import { Tab, Tabs, TabList, TabPanel } from "react-tabs"; import FileSaver from "file-saver"; import { NotificationContext } from "context/notification"; // @ts-ignore import { stringToClipboard } from "utilities/copy_text"; import { IConfig } from "interfaces/config"; 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 Checkbox from "components/forms/fields/Checkbox"; import TooltipWrapper from "components/TooltipWrapper"; import TabsWrapper from "components/TabsWrapper"; import InfoBanner from "components/InfoBanner/InfoBanner"; import CustomLink from "components/CustomLink/CustomLink"; import { isValidPemCertificate } from "../../../pages/hosts/ManageHostsPage/helpers"; interface IPlatformSubNav { name: string; type: string; } const platformSubNav: IPlatformSubNav[] = [ { name: "macOS", type: "pkg", }, { name: "Windows", type: "msi", }, { name: "Linux (RPM)", type: "rpm", }, { name: "Linux (deb)", type: "deb", }, { name: "ChromeOS", type: "chromeos", }, { 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 [copyMessage, setCopyMessage] = useState>({}); const [includeFleetDesktop, setIncludeFleetDesktop] = useState(true); 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} ${ includeFleetDesktop ? "--fleet-desktop " : "" }--fleet-url=${ config?.server_settings.server_url } --enroll-secret=${enrollSecret}`; }; const renderLabel = (packageType: string, installerString: string) => { const onCopyInstaller = (evt: React.MouseEvent) => { evt.preventDefault(); stringToClipboard(installerString) .then(() => setCopyMessage((prev) => ({ ...prev, [packageType]: "Copied!" })) ) .catch(() => setCopyMessage((prev) => ({ ...prev, [packageType]: "Copy failed" })) ); // Clear message after 1 second setTimeout( () => setCopyMessage((prev) => ({ ...prev, [packageType]: "" })), 1000 ); return false; }; return ( <> {packageType === "plain-osquery" ? ( <>

With{" "} osquery {" "} installed:

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

) : ( Run this command with the{" "} Fleet command-line tool {" "} installed: )}{" "} {copyMessage[packageType] && ( {`${copyMessage[packageType]} `} )} ); }; const renderChromeOSLabel = (label: string, value: string) => { const onCopyChromeOSLabel = (evt: React.MouseEvent) => { evt.preventDefault(); stringToClipboard(value) .then(() => setCopyMessage((prev) => ({ ...prev, [label]: "Copied!" }))) .catch(() => setCopyMessage((prev) => ({ ...prev, [label]: "Copy failed", })) ); // Clear message after 1 second setTimeout( () => setCopyMessage((prev) => ({ ...prev, [label]: "" })), 1000 ); return false; }; return ( <> {label} {copyMessage[label] && ( Copied! )} ); }; const renderTab = (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}" } }`, }; 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 === "advanced") { return (
{renderFleetCertificateBlock("tooltip")}

Distribute your package to add hosts to Fleet.

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} ) : ( )}

)}
); } return ( <> {packageType !== "pkg" && ( setIncludeFleetDesktop(value)} value={includeFleetDesktop} > <> Include  Fleet Desktop )} Distribute your package to add hosts to Fleet. ); }; 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 ( {renderTab(navItem.type)} ); })}
); }; export default PlatformWrapper;