Add UI for Fleet Sandbox to download prepackaged installers (#6721)
BIN
assets/images/icon-apple-black-24x24@2x.png
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
assets/images/icon-apple-vibrant-blue-24x24@2x.png
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
assets/images/icon-circle-check-blue-48x48@2x.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
assets/images/icon-linux-black-24x24@2x.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/images/icon-linux-vibrant-blue-24x24@2x.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/images/icon-windows-black-24x24@2x.png
Normal file
|
After Width: | Height: | Size: 517 B |
BIN
assets/images/icon-windows-vibrant-blue-24x24@2x.png
Normal file
|
After Width: | Height: | Size: 527 B |
1
changes/issue-5757-download-orbit-installer-sandbox
Normal file
|
|
@ -0,0 +1 @@
|
|||
- Added Fleet Sandbox UI to download pre-packaged installers
|
||||
|
|
@ -409,7 +409,8 @@ awslocal kinesis get-records --shard-iterator AAAAAAAAAAERtiUrWGI0sq99TtpKnmDu6h
|
|||
|
||||
Pre-built installers are kept in a blob storage like AWS S3. As part of your your local development there's a [MinIO](https://min.io/) instance running on http://localhost:9000. To test the pre-built installers functionality locally:
|
||||
|
||||
1. Build the installers you want using `fleetctl package`.
|
||||
1. Build the installers you want using `fleetctl package`. Be sure to include the `--insecure` flag
|
||||
for local testing.
|
||||
2. Use the [installerstore](../../tools/installerstore/README.md) tool to upload them to your MinIO instance.
|
||||
3. Configure your fleet server setting `FLEET_PACKAGING_GLOBAL_ENROLL_SECRET` to match your global enroll secret.
|
||||
4. Set `FLEET_DEMO=1`, as the endpoint to retrieve the installer is only available in the sandbox.
|
||||
|
|
@ -418,4 +419,7 @@ Pre-built installers are kept in a blob storage like AWS S3. As part of your you
|
|||
FLEET_DEMO=1 FLEET_PACKAGING_GLOBAL_ENROLL_SECRET=xyz ./build/fleet serve --dev
|
||||
```
|
||||
|
||||
Be sure to replace the `FLEET_PACKAGING_GLOBAL_ENROLL_SECRET` value above with the global enroll
|
||||
secret from the `fleetctl package` command used to build the installers.
|
||||
|
||||
MinIO also offers a web interface at http://localhost:9001. Credentials are `minio` / `minio123!`.
|
||||
|
|
|
|||
|
|
@ -1,24 +1,52 @@
|
|||
import React from "react";
|
||||
|
||||
import { ITeamSummary } from "interfaces/team";
|
||||
import DataError from "components/DataError";
|
||||
import Modal from "components/Modal";
|
||||
import { ITeam } from "interfaces/team";
|
||||
import { IEnrollSecret } from "interfaces/enroll_secret";
|
||||
import Spinner from "components/Spinner";
|
||||
|
||||
import PlatformWrapper from "./PlatformWrapper/PlatformWrapper";
|
||||
import DownloadInstallers from "./DownloadInstallers/DownloadInstallers";
|
||||
|
||||
const baseClass = "add-hosts-modal";
|
||||
|
||||
interface IAddHostsModal {
|
||||
currentTeam?: ITeamSummary;
|
||||
enrollSecret?: string;
|
||||
isLoading: boolean;
|
||||
isSandboxMode?: boolean;
|
||||
onCancel: () => void;
|
||||
selectedTeam: ITeam | { name: string; secrets: IEnrollSecret[] | null };
|
||||
}
|
||||
|
||||
const AddHostsModal = ({
|
||||
currentTeam,
|
||||
enrollSecret,
|
||||
isLoading,
|
||||
isSandboxMode,
|
||||
onCancel,
|
||||
selectedTeam,
|
||||
}: IAddHostsModal): JSX.Element => {
|
||||
const renderModalContent = () => {
|
||||
if (isLoading) {
|
||||
return <Spinner />;
|
||||
}
|
||||
if (!enrollSecret) {
|
||||
return <DataError />;
|
||||
}
|
||||
|
||||
// TODO: Currently, prepacked installers in Fleet Sandbox use the global enroll secret,
|
||||
// and Fleet Sandbox runs Fleet Free so the currentTeam check here is an
|
||||
// additional precaution/reminder to revisit this in connection with future changes.
|
||||
// See https://github.com/fleetdm/fleet/issues/4970#issuecomment-1187679407.
|
||||
return isSandboxMode && !currentTeam ? (
|
||||
<DownloadInstallers onCancel={onCancel} enrollSecret={enrollSecret} />
|
||||
) : (
|
||||
<PlatformWrapper onCancel={onCancel} enrollSecret={enrollSecret} />
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal onExit={onCancel} title={"Add hosts"} className={baseClass}>
|
||||
<PlatformWrapper onCancel={onCancel} selectedTeam={selectedTeam} />
|
||||
{renderModalContent()}
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,185 @@
|
|||
import React, { useState } from "react";
|
||||
import FileSaver from "file-saver";
|
||||
|
||||
import {
|
||||
IInstallerPlatform,
|
||||
IInstallerType,
|
||||
INSTALLER_PLATFORM_BY_TYPE,
|
||||
INSTALLER_TYPE_BY_PLATFORM,
|
||||
} from "interfaces/installer";
|
||||
import installerAPI from "services/entities/installers";
|
||||
|
||||
import Button from "components/buttons/Button";
|
||||
import Checkbox from "components/forms/fields/Checkbox";
|
||||
import DataError from "components/DataError";
|
||||
import Spinner from "components/Spinner";
|
||||
import TooltipWrapper from "components/TooltipWrapper";
|
||||
|
||||
import AppleIcon from "./../../../../assets/images/icon-apple-black-24x24@2x.png";
|
||||
import AppleIconVibrant from "./../../../../assets/images/icon-apple-vibrant-blue-24x24@2x.png";
|
||||
import LinuxIcon from "./../../../../assets/images/icon-linux-black-24x24@2x.png";
|
||||
import LinuxIconVibrant from "./../../../../assets/images/icon-linux-vibrant-blue-24x24@2x.png";
|
||||
import WindowsIcon from "./../../../../assets/images/icon-windows-black-24x24@2x.png";
|
||||
import WindowsIconVibrant from "./../../../../assets/images/icon-windows-vibrant-blue-24x24@2x.png";
|
||||
import SuccessIcon from "./../../../../assets/images/icon-circle-check-blue-48x48@2x.png";
|
||||
|
||||
interface IDownloadInstallersProps {
|
||||
enrollSecret: string;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
const baseClass = "download-installers";
|
||||
|
||||
const displayOrder = [
|
||||
"macOS",
|
||||
"Windows",
|
||||
"Linux (RPM)",
|
||||
"Linux (deb)",
|
||||
] as const;
|
||||
|
||||
const displayIcon = (platform: IInstallerPlatform, isSelected: boolean) => {
|
||||
switch (platform) {
|
||||
case "Linux (RPM)":
|
||||
case "Linux (deb)":
|
||||
return (
|
||||
<img src={isSelected ? LinuxIconVibrant : LinuxIcon} alt={platform} />
|
||||
);
|
||||
case "macOS":
|
||||
return (
|
||||
<img src={isSelected ? AppleIconVibrant : AppleIcon} alt={platform} />
|
||||
);
|
||||
case "Windows":
|
||||
return (
|
||||
<img
|
||||
src={isSelected ? WindowsIconVibrant : WindowsIcon}
|
||||
alt={platform}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const DownloadInstallers = ({
|
||||
enrollSecret,
|
||||
onCancel,
|
||||
}: IDownloadInstallersProps): JSX.Element => {
|
||||
const [includeDesktop, setIncludeDesktop] = useState(true);
|
||||
const [isDownloadError, setIsDownloadError] = useState(false);
|
||||
const [isDownloading, setIsDownloading] = useState(false);
|
||||
const [isDownloadSuccess, setIsDownloadSuccess] = useState(false);
|
||||
const [selectedInstaller, setSelectedInstaller] = useState<
|
||||
IInstallerType | undefined
|
||||
>();
|
||||
|
||||
const downloadInstaller = async (installerType?: IInstallerType) => {
|
||||
if (!installerType) {
|
||||
// do nothing
|
||||
return;
|
||||
}
|
||||
setIsDownloading(true);
|
||||
try {
|
||||
const blob: BlobPart = await installerAPI.downloadInstaller({
|
||||
enrollSecret,
|
||||
installerType,
|
||||
includeDesktop,
|
||||
});
|
||||
const filename = `fleet-osquery.${installerType}`;
|
||||
const file = new global.window.File([blob], filename, {
|
||||
type: "application/octet-stream",
|
||||
});
|
||||
FileSaver.saveAs(file);
|
||||
setIsDownloadSuccess(true);
|
||||
} catch {
|
||||
setIsDownloadError(true);
|
||||
} finally {
|
||||
setIsDownloading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onClickSelector = (type: IInstallerType) => {
|
||||
if (isDownloading) {
|
||||
// do nothing
|
||||
return;
|
||||
}
|
||||
if (type === selectedInstaller) {
|
||||
setSelectedInstaller(undefined);
|
||||
return;
|
||||
}
|
||||
setSelectedInstaller(type);
|
||||
};
|
||||
|
||||
if (isDownloadError) {
|
||||
return (
|
||||
<div className={`${baseClass}__error`}>
|
||||
<DataError />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isDownloadSuccess) {
|
||||
const installerPlatform =
|
||||
(selectedInstaller &&
|
||||
`${INSTALLER_PLATFORM_BY_TYPE[selectedInstaller]} `) ||
|
||||
"";
|
||||
return (
|
||||
<div className={`${baseClass}__success`}>
|
||||
<img src={SuccessIcon} alt="download successful" />
|
||||
<h2>You’re almost there</h2>
|
||||
<p>{`Run the installer on a ${installerPlatform}laptop, workstation, or sever to add it to Fleet.`}</p>
|
||||
<Button onClick={onCancel}>Got it</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`${baseClass}`}>
|
||||
<p>Which platform is your host running?</p>
|
||||
<div className={`${baseClass}__select-installer`}>
|
||||
{displayOrder.map((platform) => {
|
||||
const installerType = INSTALLER_TYPE_BY_PLATFORM[platform];
|
||||
const isSelected = selectedInstaller === installerType;
|
||||
return (
|
||||
<div
|
||||
key={installerType}
|
||||
className={`${baseClass}__selector ${
|
||||
isSelected ? `${baseClass}__selector--selected` : ""
|
||||
}`}
|
||||
onClick={() => onClickSelector(installerType)}
|
||||
>
|
||||
<span>
|
||||
{displayIcon(platform, isSelected)}
|
||||
{platform}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<Checkbox
|
||||
name="include-fleet-desktop"
|
||||
onChange={(value: boolean) => setIncludeDesktop(value)}
|
||||
value={includeDesktop}
|
||||
>
|
||||
<>
|
||||
Include
|
||||
<TooltipWrapper
|
||||
tipContent={
|
||||
"<p>Lightweight application that allows end users to see information about their device.</p>"
|
||||
}
|
||||
>
|
||||
Fleet Desktop
|
||||
</TooltipWrapper>
|
||||
</>
|
||||
</Checkbox>
|
||||
<Button
|
||||
className={`${baseClass}__button--download`}
|
||||
disabled={!selectedInstaller}
|
||||
onClick={() => downloadInstaller(selectedInstaller)}
|
||||
>
|
||||
{isDownloading ? <Spinner /> : "Download installer"}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DownloadInstallers;
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
.download-installers {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
padding-bottom: 20px;
|
||||
|
||||
p {
|
||||
padding-top: $pad-small;
|
||||
padding-bottom: $pad-medium;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.component__tooltip-wrapper__tip-text {
|
||||
p {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.form-field.form-field--checkbox {
|
||||
padding-bottom: $pad-large;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&__select-installer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
padding-bottom: $pad-large;
|
||||
}
|
||||
|
||||
&__selector {
|
||||
cursor: pointer;
|
||||
font-size: $small;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
gap: 16px;
|
||||
width: 286px;
|
||||
|
||||
border: 1px solid #c5c7d1;
|
||||
border-radius: 4px;
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
img {
|
||||
height: 24px;
|
||||
width: auto;
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: $core-vibrant-blue;
|
||||
}
|
||||
|
||||
&--selected {
|
||||
color: $core-vibrant-blue;
|
||||
background-color: $ui-vibrant-blue-10;
|
||||
border-color: $core-vibrant-blue;
|
||||
}
|
||||
}
|
||||
|
||||
&__button--download {
|
||||
width: 154px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
&__success {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 48px 0 70px;
|
||||
|
||||
img {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
padding: 16px 0 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&__error {
|
||||
.data-error__inner {
|
||||
margin: 0;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,23 +53,21 @@ const platformSubNav: IPlatformSubNav[] = [
|
|||
},
|
||||
];
|
||||
|
||||
interface IPlatformWrapperProp {
|
||||
selectedTeam: ITeam | { name: string; secrets: IEnrollSecret[] | null };
|
||||
interface IPlatformWrapperProps {
|
||||
enrollSecret: string;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
const baseClass = "platform-wrapper";
|
||||
|
||||
const PlatformWrapper = ({
|
||||
selectedTeam,
|
||||
enrollSecret,
|
||||
onCancel,
|
||||
}: IPlatformWrapperProp): JSX.Element => {
|
||||
}: IPlatformWrapperProps): JSX.Element => {
|
||||
const { config, isPreviewMode } = useContext(AppContext);
|
||||
const { renderFlash } = useContext(NotificationContext);
|
||||
const [copyMessage, setCopyMessage] = useState<Record<string, string>>({});
|
||||
const [includeFleetDesktop, setIncludeFleetDesktop] = useState<boolean>(
|
||||
false
|
||||
);
|
||||
const [includeFleetDesktop, setIncludeFleetDesktop] = useState<boolean>(true);
|
||||
const [showPlainOsquery, setShowPlainOsquery] = useState<boolean>(false);
|
||||
|
||||
const {
|
||||
|
|
@ -127,11 +125,6 @@ const PlatformWrapper = ({
|
|||
--carver_continue_endpoint=/api/v1/osquery/carve/block
|
||||
--carver_block_size=2000000`;
|
||||
|
||||
let enrollSecret: string;
|
||||
if (selectedTeam.secrets) {
|
||||
enrollSecret = selectedTeam.secrets[0].secret;
|
||||
}
|
||||
|
||||
const onDownloadEnrollSecret = (evt: React.MouseEvent) => {
|
||||
evt.preventDefault();
|
||||
|
||||
|
|
@ -407,7 +400,7 @@ const PlatformWrapper = ({
|
|||
<>
|
||||
<Checkbox
|
||||
name="include-fleet-desktop"
|
||||
onChange={() => setIncludeFleetDesktop(!includeFleetDesktop)}
|
||||
onChange={(value: boolean) => setIncludeFleetDesktop(value)}
|
||||
value={includeFleetDesktop}
|
||||
>
|
||||
<>
|
||||
|
|
|
|||
27
frontend/interfaces/installer.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
export type IInstallerType = "pkg" | "msi" | "rpm" | "deb";
|
||||
|
||||
export type IInstallerPlatform =
|
||||
| "Windows"
|
||||
| "macOS"
|
||||
| "Linux (RPM)"
|
||||
| "Linux (deb)";
|
||||
|
||||
export const INSTALLER_TYPE_BY_PLATFORM: Record<
|
||||
IInstallerPlatform,
|
||||
IInstallerType
|
||||
> = {
|
||||
macOS: "pkg",
|
||||
Windows: "msi",
|
||||
"Linux (RPM)": "rpm",
|
||||
"Linux (deb)": "deb",
|
||||
} as const;
|
||||
|
||||
export const INSTALLER_PLATFORM_BY_TYPE: Record<
|
||||
IInstallerType,
|
||||
IInstallerPlatform
|
||||
> = {
|
||||
pkg: "macOS",
|
||||
msi: "Windows",
|
||||
rpm: "Linux (RPM)",
|
||||
deb: "Linux (deb)",
|
||||
} as const;
|
||||
|
|
@ -16,7 +16,7 @@ export default PropTypes.shape({
|
|||
});
|
||||
|
||||
/**
|
||||
* The id, name, and optional description for a team entity
|
||||
* The id, name, description, and host count for a team entity
|
||||
*/
|
||||
export interface ITeamSummary {
|
||||
id: number;
|
||||
|
|
|
|||
|
|
@ -487,11 +487,15 @@ const TeamDetailsWrapper = ({
|
|||
</TabsWrapper>
|
||||
{showAddHostsModal && (
|
||||
<AddHostsModal
|
||||
currentTeam={currentTeam}
|
||||
enrollSecret={teamSecrets?.[0]?.secret}
|
||||
isLoading={isLoadingTeams}
|
||||
// TODO: Currently, prepacked installers in Fleet Sandbox use the global enroll secret,
|
||||
// and Fleet Sandbox runs Fleet Free so explicitly setting isSandboxMode here is an
|
||||
// additional precaution/reminder to revisit this in connection with future changes.
|
||||
// See https://github.com/fleetdm/fleet/issues/4970#issuecomment-1187679407.
|
||||
isSandboxMode={false}
|
||||
onCancel={toggleAddHostsModal}
|
||||
selectedTeam={{
|
||||
name: currentTeam.name,
|
||||
secrets: teamSecrets || null,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{showManageEnrollSecretsModal && (
|
||||
|
|
|
|||
|
|
@ -314,13 +314,6 @@ const ManageHostsPage = ({
|
|||
}
|
||||
);
|
||||
|
||||
const addHostsTeam = currentTeam
|
||||
? { name: currentTeam.name, secrets: teamSecrets || null }
|
||||
: {
|
||||
name: "No team",
|
||||
secrets: globalSecrets || null,
|
||||
};
|
||||
|
||||
const {
|
||||
data: teams,
|
||||
isLoading: isLoadingTeams,
|
||||
|
|
@ -1187,9 +1180,25 @@ const ManageHostsPage = ({
|
|||
/>
|
||||
);
|
||||
|
||||
const renderAddHostsModal = () => (
|
||||
<AddHostsModal onCancel={toggleAddHostsModal} selectedTeam={addHostsTeam} />
|
||||
);
|
||||
const renderAddHostsModal = () => {
|
||||
const enrollSecret =
|
||||
// TODO: Currently, prepacked installers in Fleet Sandbox use the global enroll secret,
|
||||
// and Fleet Sandbox runs Fleet Free so the isSandboxMode check here is an
|
||||
// additional precaution/reminder to revisit this in connection with future changes.
|
||||
// See https://github.com/fleetdm/fleet/issues/4970#issuecomment-1187679407.
|
||||
currentTeam && !isSandboxMode
|
||||
? teamSecrets?.[0].secret
|
||||
: globalSecrets?.[0].secret;
|
||||
return (
|
||||
<AddHostsModal
|
||||
currentTeam={currentTeam}
|
||||
enrollSecret={enrollSecret}
|
||||
isLoading={isLoadingTeams || isGlobalSecretsLoading}
|
||||
isSandboxMode={!!isSandboxMode}
|
||||
onCancel={toggleAddHostsModal}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const renderTransferHostModal = () => {
|
||||
if (!teams) {
|
||||
|
|
@ -1344,7 +1353,9 @@ const ManageHostsPage = ({
|
|||
isHostCountLoading ? "count-loading" : ""
|
||||
}`}
|
||||
>
|
||||
<span>{`${count} host${count === 1 ? "" : "s"}`}</span>
|
||||
{count !== undefined && (
|
||||
<span>{`${count} host${count === 1 ? "" : "s"}`}</span>
|
||||
)}
|
||||
{count ? (
|
||||
<Button
|
||||
className={`${baseClass}__export-btn`}
|
||||
|
|
|
|||
25
frontend/services/entities/installers.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { IInstallerType } from "interfaces/installer";
|
||||
import sendRequest from "services";
|
||||
import ENDPOINTS from "utilities/endpoints";
|
||||
|
||||
export interface IDownloadInstallerRequestParams {
|
||||
enrollSecret: string;
|
||||
includeDesktop: boolean;
|
||||
installerType: IInstallerType;
|
||||
}
|
||||
|
||||
export default {
|
||||
downloadInstaller: ({
|
||||
enrollSecret,
|
||||
includeDesktop,
|
||||
installerType,
|
||||
}: IDownloadInstallerRequestParams): Promise<BlobPart> => {
|
||||
const path = `${ENDPOINTS.DOWNLOAD_INSTALLER}/${encodeURIComponent(
|
||||
enrollSecret
|
||||
)}/${installerType}?desktop=${includeDesktop}`;
|
||||
console.log("path: ", path);
|
||||
|
||||
return sendRequest("GET", path, undefined, "blob");
|
||||
},
|
||||
};
|
||||
|
|
@ -1,11 +1,16 @@
|
|||
import axios, { AxiosError, AxiosResponse } from "axios";
|
||||
import axios, {
|
||||
AxiosError,
|
||||
AxiosResponse,
|
||||
ResponseType as AxiosResponseType,
|
||||
} from "axios";
|
||||
import local from "utilities/local";
|
||||
import URL_PREFIX from "router/url_prefix";
|
||||
|
||||
const sendRequest = async (
|
||||
method: "GET" | "POST" | "PATCH" | "DELETE",
|
||||
path: string,
|
||||
data?: unknown
|
||||
data?: unknown,
|
||||
responseType: AxiosResponseType = "json"
|
||||
): Promise<any> => {
|
||||
const { origin } = global.window.location;
|
||||
|
||||
|
|
@ -17,6 +22,7 @@ const sendRequest = async (
|
|||
method,
|
||||
url,
|
||||
data,
|
||||
responseType,
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export default {
|
|||
return `/${API_VERSION}/fleet/email/change/${token}`;
|
||||
},
|
||||
DEVICE_USER_DETAILS: `/${API_VERSION}/fleet/device`,
|
||||
DOWNLOAD_INSTALLER: `/${API_VERSION}/fleet/download_installer`,
|
||||
ENABLE_USER: (id: number): string => {
|
||||
return `/${API_VERSION}/fleet/users/${id}/enable`;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ GLOBAL OPTIONS:
|
|||
### Example
|
||||
|
||||
To upload a file for testing to your local MinIO server, you can run this
|
||||
command from the root of the repo:
|
||||
command from the root of the repo (be sure to replace the `--enroll-secret`
|
||||
string with the value you wish to test and set the `--fleet-desktop` boolean
|
||||
to your desired value):
|
||||
|
||||
```
|
||||
go run tools/installerstore/main.go \
|
||||
|
|
@ -46,6 +48,7 @@ go run tools/installerstore/main.go \
|
|||
--disable-ssl=true \
|
||||
--force-s3-path-style=true \
|
||||
--create-bucket=true \
|
||||
--fleet-desktop=true \
|
||||
fleet-osquery.pkg
|
||||
```
|
||||
|
||||
|
|
|
|||