import React, { useContext, useState } from "react"; import { Tab, Tabs, TabList, TabPanel } from "react-tabs"; import { useQuery } from "react-query"; import FileSaver from "file-saver"; import { NotificationContext } from "context/notification"; import { AppContext } from "context/app"; // @ts-ignore import { stringToClipboard } from "utilities/copy_text"; import configAPI from "services/entities/config"; import Button from "components/buttons/Button"; 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 { isValidPemCertificate } from "../../../pages/hosts/ManageHostsPage/helpers"; import CopyIcon from "../../../../assets/images/icon-copy-clipboard-fleet-blue-20x20@2x.png"; import DownloadIcon from "../../../../assets/images/icon-download-12x12@2x.png"; 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: "Advanced", type: "advanced", }, ]; interface IPlatformWrapperProps { enrollSecret: string; onCancel: () => void; } const baseClass = "platform-wrapper"; const PlatformWrapper = ({ enrollSecret, onCancel, }: IPlatformWrapperProps): JSX.Element => { const { config, isPreviewMode } = useContext(AppContext); const { renderFlash } = useContext(NotificationContext); const [copyMessage, setCopyMessage] = useState>({}); const [includeFleetDesktop, setIncludeFleetDesktop] = useState(true); const [showPlainOsquery, setShowPlainOsquery] = useState(false); const { data: certificate, error: fetchCertificateError, isFetching: isFetchingCertificate, } = useQuery( ["certificate"], () => configAPI.loadCertificate(), { enabled: !isPreviewMode, refetchOnWindowFocus: false, } ); 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=2000000`; 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:
)} Download download

) : (

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 = (platform: string) => { return platform === "advanced" ? `fleetctl package --type=rpm --fleet-url=${config?.server_settings.server_url} --enroll-secret=${enrollSecret} --fleet-certificate=PATH_TO_YOUR_CERTIFICATE/fleet.pem` : `fleetctl package --type=${platform} ${ includeFleetDesktop ? "--fleet-desktop " : "" }--fleet-url=${ config?.server_settings.server_url } --enroll-secret=${enrollSecret}`; }; const renderLabel = (platform: string, installerString: string) => { const onCopyInstaller = (evt: React.MouseEvent) => { evt.preventDefault(); stringToClipboard(installerString) .then(() => setCopyMessage((prev) => ({ ...prev, [platform]: "Copied!" })) ) .catch(() => setCopyMessage((prev) => ({ ...prev, [platform]: "Copy failed" })) ); // Clear message after 1 second setTimeout( () => setCopyMessage((prev) => ({ ...prev, [platform]: "" })), 1000 ); return false; }; return ( <> {platform === "plain-osquery" ? ( <>

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

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

) : ( With the{" "} Fleet command-line tool {" "} installed: )}{" "} {copyMessage[platform] && ( {`${copyMessage[platform]} `} )} ); }; const renderTab = (platform: string) => { if (platform === "advanced") { return (
{renderFleetCertificateBlock("tooltip")}

Generates an installer that your devices will use to connect to Fleet.

setShowPlainOsquery((prev) => !prev)} /> {showPlainOsquery && ( <>

Download your enroll secret:

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

{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} ) : ( Download download icon )}

)}
); } return ( <> setIncludeFleetDesktop(value)} value={includeFleetDesktop} > <> Include  Lightweight application that allows end users to see information about their device.

" } > Fleet Desktop
Generates an installer that your devices will use to connect to Fleet. ); }; return (
{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;