Feat UI windows automatic enrollment (#12988)
relates to #12606 Implementation of the Windows automatic enrollment Fleet UI pages. This includes implementation of card for windows automatic enrollment, the setup page for windows automatic enrollment, and terms and conditions page for windows (This is currently still being worked on as our current solution is not working). **windows mdm auto enrollment card**  **windows auto enrollment setup page**  - [x] Changes file added for user-visible changes in `changes/` or `orbit/changes/`. See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information. - [x] Manual QA for all new/changed functionality --------- Co-authored-by: Marcos Oviedo <marcos@fleetdm.com>
This commit is contained in:
co-authored by
Marcos Oviedo
parent
6d186602cd
commit
6555d8def4
@@ -0,0 +1 @@
|
||||
- add windows mdmd automatic enrollment setup pages to fleet UI
|
||||
@@ -3,7 +3,11 @@ import PropTypes from "prop-types";
|
||||
import classnames from "classnames";
|
||||
import { noop, pick } from "lodash";
|
||||
|
||||
import { stringToClipboard } from "utilities/copy_text";
|
||||
|
||||
import FormField from "components/forms/FormField";
|
||||
import Button from "components/buttons/Button";
|
||||
import Icon from "components/Icon";
|
||||
|
||||
const baseClass = "input-field";
|
||||
|
||||
@@ -34,6 +38,7 @@ class InputField extends Component {
|
||||
PropTypes.arrayOf(PropTypes.string),
|
||||
PropTypes.object,
|
||||
]),
|
||||
enableCopy: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
@@ -50,6 +55,7 @@ class InputField extends Component {
|
||||
parseTarget: false,
|
||||
tooltip: "",
|
||||
hint: "",
|
||||
enableCopy: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
@@ -110,6 +116,12 @@ class InputField extends Component {
|
||||
"tooltip",
|
||||
]);
|
||||
|
||||
const copyValue = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
stringToClipboard(value);
|
||||
};
|
||||
|
||||
if (type === "textarea") {
|
||||
return (
|
||||
<FormField
|
||||
@@ -135,25 +147,42 @@ class InputField extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
const inputContainerClasses = classnames(`${baseClass}__input-container`, {
|
||||
"copy-enabled": this.props.enableCopy,
|
||||
});
|
||||
|
||||
return (
|
||||
<FormField {...formFieldProps} type="input" className={inputWrapperClass}>
|
||||
<input
|
||||
disabled={disabled}
|
||||
name={name}
|
||||
id={name}
|
||||
onChange={onInputChange}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
className={inputClasses}
|
||||
placeholder={placeholder}
|
||||
ref={(r) => {
|
||||
this.input = r;
|
||||
}}
|
||||
type={type}
|
||||
{...inputOptions}
|
||||
value={value}
|
||||
autoComplete={blockAutoComplete ? "new-password" : ""}
|
||||
/>
|
||||
<div className={inputContainerClasses}>
|
||||
<input
|
||||
disabled={disabled}
|
||||
name={name}
|
||||
id={name}
|
||||
onChange={onInputChange}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
className={inputClasses}
|
||||
placeholder={placeholder}
|
||||
ref={(r) => {
|
||||
this.input = r;
|
||||
}}
|
||||
type={type}
|
||||
{...inputOptions}
|
||||
value={value}
|
||||
autoComplete={blockAutoComplete ? "new-password" : ""}
|
||||
/>
|
||||
<div className={`${baseClass}__copy-wrapper`}>
|
||||
{this.props.enableCopy && (
|
||||
<Button
|
||||
variant="text-icon"
|
||||
onClick={copyValue}
|
||||
className={`${baseClass}__copy-value-button`}
|
||||
>
|
||||
<Icon name="copy" /> Copy
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</FormField>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,12 @@
|
||||
font-family: "SourceCodePro", $monospace;
|
||||
}
|
||||
}
|
||||
|
||||
&__input-container.copy-enabled {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $pad-medium;
|
||||
}
|
||||
}
|
||||
|
||||
// Removes arrows on Firefox number fields
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
import InputFieldHiddenContent from ".";
|
||||
|
||||
const meta: Meta<typeof InputFieldHiddenContent> = {
|
||||
component: InputFieldHiddenContent,
|
||||
title: "Components/FormFields/InputFieldHiddenContent",
|
||||
args: {
|
||||
value: "test value",
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof InputFieldHiddenContent>;
|
||||
|
||||
export const Default: Story = {};
|
||||
+1
-1
@@ -64,7 +64,7 @@ const AutomaticEnrollment = ({ router }: IAutomaticEnrollment) => {
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<div className={`${baseClass}__section`}>
|
||||
<AppleBusinessManagerSection />
|
||||
<AppleBusinessManagerSection router={router} />
|
||||
</div>
|
||||
<div className={`${baseClass}__section`}>
|
||||
<IdpSection />
|
||||
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
import React, { useContext } from "react";
|
||||
|
||||
import PATHS from "router/paths";
|
||||
import { AppContext } from "context/app";
|
||||
|
||||
// @ts-ignore
|
||||
import InputField from "components/forms/fields/InputField";
|
||||
import BackLink from "components/BackLink";
|
||||
import MainContent from "components/MainContent";
|
||||
import CustomLink from "components/CustomLink/CustomLink";
|
||||
|
||||
const generateMdmTermsOfUseUrl = (domain: string) => {
|
||||
return `${domain}/api/mdm/microsoft/tos`;
|
||||
};
|
||||
|
||||
const generateMdmDiscoveryUrl = (domain: string) => {
|
||||
return `${domain}/api/mdm/microsoft/discovery`;
|
||||
};
|
||||
|
||||
const baseClass = "windows-automatic-enrollment-page";
|
||||
|
||||
const WindowsAutomaticEnrollmentPage = () => {
|
||||
const { config } = useContext(AppContext);
|
||||
|
||||
return (
|
||||
<MainContent className={baseClass}>
|
||||
<>
|
||||
<BackLink
|
||||
text="Back to automatic enrollment"
|
||||
path={PATHS.ADMIN_INTEGRATIONS_AUTOMATIC_ENROLLMENT}
|
||||
className={`${baseClass}__back-to-automatic-enrollment`}
|
||||
/>
|
||||
<h1>Azure Active Directory</h1>
|
||||
<p>
|
||||
The end user will see Microsoft's default initial setup. You can
|
||||
further simplify the initial device setup with Autopilot, which is
|
||||
similar to Apple's Automated Device Enrollment (DEP).{" "}
|
||||
<CustomLink
|
||||
newTab
|
||||
text="Learn more"
|
||||
url="https://fleetdm.com/docs/using-fleet/windows-mdm-setup"
|
||||
/>
|
||||
</p>
|
||||
<ol className={`${baseClass}__setup-list`}>
|
||||
<li>
|
||||
<CustomLink
|
||||
newTab
|
||||
text="Sign in to Azure portal"
|
||||
url="https://azure.microsoft.com/en-gb/get-started/azure-portal"
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
Select <b>Azure Active Directory > Custom domain names</b>, then
|
||||
select <b>+ Add custom domain</b>, type your organization's
|
||||
domain name (e.g. acme.com), and select <b>Add domain</b>.
|
||||
</li>
|
||||
<li>
|
||||
Use the information presented in Azure AD to create a new TXT/MX
|
||||
record with your domain registrar, then select <b>Verify</b>.
|
||||
</li>
|
||||
<li>
|
||||
Select <b>Azure Active Directory > Mobility (MDM and MAM)</b> (or
|
||||
search for “Mobility” at the top of the page).
|
||||
</li>
|
||||
<li>
|
||||
Select <b>+ Add application</b>, then select{" "}
|
||||
<b>+ Create your own application</b>.
|
||||
</li>
|
||||
<li>
|
||||
Enter “Fleet” as the name of your application and select{" "}
|
||||
<b>Create</b>.
|
||||
</li>
|
||||
<li>
|
||||
Set MDM user scope to <b>All</b>, then copy the URLs below, paste
|
||||
them in Azure AD, and select <b>Save</b>.
|
||||
<div className={`${baseClass}__url-inputs-wrapper`}>
|
||||
<InputField
|
||||
inputWrapperClass={`${baseClass}__url-input`}
|
||||
label="MDM terms of use URL"
|
||||
name="mdmTermsOfUseUrl"
|
||||
tooltip="The terms of use URL is used to display the terms of service to end users
|
||||
before turning on MDM their host. The terms of use text informs users about
|
||||
policies that will be enforced on the host."
|
||||
value={generateMdmTermsOfUseUrl(
|
||||
config?.server_settings.server_url || ""
|
||||
)}
|
||||
enableCopy
|
||||
/>
|
||||
<InputField
|
||||
inputWrapperClass={`${baseClass}__url-input`}
|
||||
label="MDM discovery URL"
|
||||
name="mdmDiscoveryUrl"
|
||||
tooltip="The enrollment URL is used to connect hosts with the MDM service."
|
||||
value={generateMdmDiscoveryUrl(
|
||||
config?.server_settings.server_url || ""
|
||||
)}
|
||||
enableCopy
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
Go back to <b>Mobility (MDM and MAM)</b>, refresh the page, then
|
||||
open newly created app and select{" "}
|
||||
<b>On-premises MDM application settings</b>.
|
||||
</li>
|
||||
<li>
|
||||
Select the link under <b>Application ID URI</b>, then select{" "}
|
||||
<b>Edit</b> button next to the Application ID URI input.
|
||||
</li>
|
||||
<li>
|
||||
Use your organization's domain you added in the first step, and
|
||||
select <b>Save</b>.
|
||||
</li>
|
||||
<li>
|
||||
Select <b>API permissions</b> from the sidebar, then select{" "}
|
||||
<b>+ Add permissions</b>.
|
||||
</li>
|
||||
<li>
|
||||
Select <b>Microsoft Graph</b>, then select{" "}
|
||||
<b>Delegated permissions</b>, and select{" "}
|
||||
<b>Group > Group.Read.All</b> and{" "}
|
||||
<b>Group > Group.ReadWrite.All</b>.
|
||||
</li>
|
||||
<li>
|
||||
Select <b>Application permissions</b>, then select following:
|
||||
<ul className={`${baseClass}__permissions-list`}>
|
||||
<li>Device.Read.All</li>
|
||||
<li>Device > Device.ReadWrite.All</li>
|
||||
<li>Directory > Directory.Read.All</li>
|
||||
<li>Group > Group.Read.All</li>
|
||||
<li>User > User.Read.All</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
Select <b>Add permissions</b>.
|
||||
</li>
|
||||
<li>
|
||||
Select <b>Grant admin consent for <your tenant name></b>, and
|
||||
confirm.
|
||||
</li>
|
||||
<li>
|
||||
You're ready to automatically enroll Windows hosts to Fleet.
|
||||
</li>
|
||||
</ol>
|
||||
</>
|
||||
</MainContent>
|
||||
);
|
||||
};
|
||||
|
||||
export default WindowsAutomaticEnrollmentPage;
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
.windows-automatic-enrollment-page {
|
||||
&__back-to-automatic-enrollment {
|
||||
margin-bottom: $pad-xlarge;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: $pad-xxlarge;
|
||||
font-size: $x-large;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: $x-small;
|
||||
margin: 0 0 $pad-large;
|
||||
}
|
||||
|
||||
&__setup-list {
|
||||
font-size: $x-small;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $pad-large;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
max-width: 660px;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
&__url-inputs-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $pad-icon;
|
||||
margin-top: $pad-large;
|
||||
}
|
||||
|
||||
&__url-input {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&__permissions-list {
|
||||
margin-top: $pad-large;
|
||||
list-style: disc;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $pad-medium;
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export { default } from "./WindowsAutomaticEnrollmentPage";
|
||||
+21
-1
@@ -2,11 +2,14 @@ import React, { useContext, useState } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { AxiosError } from "axios";
|
||||
import FileSaver from "file-saver";
|
||||
import { InjectedRouter } from "react-router";
|
||||
|
||||
import PATHS from "router/paths";
|
||||
import { IMdmAppleBm } from "interfaces/mdm";
|
||||
import mdmAppleBmAPI from "services/entities/mdm_apple_bm";
|
||||
import { readableDate } from "utilities/helpers";
|
||||
import { NotificationContext } from "context/notification";
|
||||
import { AppContext } from "context/app";
|
||||
|
||||
import Icon from "components/Icon";
|
||||
import Button from "components/buttons/Button";
|
||||
@@ -16,6 +19,7 @@ import DataError from "components/DataError";
|
||||
import Spinner from "components/Spinner/Spinner";
|
||||
|
||||
import EditTeamModal from "../EditTeamModal";
|
||||
import WindowsAutomaticEnrollmentCard from "./components/WindowsAutomaticEnrollmentCard/WindowsAutomaticEnrollmentCard";
|
||||
|
||||
const baseClass = "apple-business-manager-section";
|
||||
|
||||
@@ -24,10 +28,17 @@ interface IABMKeys {
|
||||
decodedPrivate: string;
|
||||
}
|
||||
|
||||
const AppleBusinessManagerSection = () => {
|
||||
interface IAppleBusinessManagerSectionProps {
|
||||
router: InjectedRouter;
|
||||
}
|
||||
|
||||
const AppleBusinessManagerSection = ({
|
||||
router,
|
||||
}: IAppleBusinessManagerSectionProps) => {
|
||||
const [showEditTeamModal, setShowEditTeamModal] = useState(false);
|
||||
const [defaultTeamName, setDefaultTeamName] = useState("No team");
|
||||
const { renderFlash } = useContext(NotificationContext);
|
||||
const { config } = useContext(AppContext);
|
||||
|
||||
const {
|
||||
data: mdmAppleBm,
|
||||
@@ -58,6 +69,10 @@ const AppleBusinessManagerSection = () => {
|
||||
setShowEditTeamModal(!showEditTeamModal);
|
||||
};
|
||||
|
||||
const navigateToWindowsAutomaticEnrollment = () => {
|
||||
router.push(PATHS.ADMIN_INTEGRATIONS_AUTOMATIC_ENROLLMENT_WINDOWS);
|
||||
};
|
||||
|
||||
const onDownloadKeys = (evt: React.MouseEvent) => {
|
||||
evt.preventDefault();
|
||||
|
||||
@@ -219,6 +234,11 @@ const AppleBusinessManagerSection = () => {
|
||||
<div className={baseClass}>
|
||||
<h2>Apple Business Manager</h2>
|
||||
{isLoadingMdmAppleBm ? <Spinner /> : renderAppleBMInfo()}
|
||||
{config?.mdm_enabled && (
|
||||
<WindowsAutomaticEnrollmentCard
|
||||
viewDetails={navigateToWindowsAutomaticEnrollment}
|
||||
/>
|
||||
)}
|
||||
{showEditTeamModal && (
|
||||
<EditTeamModal
|
||||
onCancel={toggleEditTeamModal}
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import React from "react";
|
||||
import { noop } from "lodash";
|
||||
|
||||
import Card from "components/Card";
|
||||
import Button from "components/buttons/Button";
|
||||
import Icon from "components/Icon/Icon";
|
||||
|
||||
const baseClass = "windows-automatic-enrollment-card";
|
||||
|
||||
interface IWindowsAutomaticEnrollmentCardProps {
|
||||
viewDetails: () => void;
|
||||
}
|
||||
|
||||
const WindowsAutomaticEnrollmentCard = ({
|
||||
viewDetails,
|
||||
}: IWindowsAutomaticEnrollmentCardProps) => {
|
||||
return (
|
||||
<Card className={baseClass} color="gray">
|
||||
<div>
|
||||
<h3>Windows automatic enrollment</h3>
|
||||
<p>
|
||||
To use automatic enrollment for Windows hosts and Windows Autopilot
|
||||
you need to connect Fleet to Azure AD first.
|
||||
</p>
|
||||
</div>
|
||||
<Button onClick={viewDetails} variant="text-icon">
|
||||
Details{" "}
|
||||
<Icon name="chevron" direction="right" color="core-fleet-blue" />
|
||||
</Button>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default WindowsAutomaticEnrollmentCard;
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
.windows-automatic-enrollment-card {
|
||||
margin-top: $pad-xxxlarge;
|
||||
font-size: $x-small;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
h3 {
|
||||
font-size: $x-small;
|
||||
font-weight: $bold;
|
||||
margin: 0 0 $pad-xsmall;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
max-width: 520px;
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export { default } from "./WindowsAutomaticEnrollmentCard";
|
||||
@@ -55,6 +55,7 @@ import MacOSSettings from "pages/ManageControlsPage/MacOSSettings";
|
||||
import MacOSSetup from "pages/ManageControlsPage/MacOSSetup/MacOSSetup";
|
||||
import WindowsMdmPage from "pages/admin/IntegrationsPage/cards/MdmSettings/WindowsMdmPage";
|
||||
import MacOSMdmPage from "pages/admin/IntegrationsPage/cards/MdmSettings/MacOSMdmPage";
|
||||
import WindowsAutomaticEnrollmentPage from "pages/admin/IntegrationsPage/cards/AutomaticEnrollment/WindowsAutomaticEnrollmentPage";
|
||||
|
||||
import PATHS from "router/paths";
|
||||
|
||||
@@ -141,6 +142,10 @@ const routes = (
|
||||
</Route>
|
||||
<Route path="integrations/mdm/windows" component={WindowsMdmPage} />
|
||||
<Route path="integrations/mdm/apple" component={MacOSMdmPage} />
|
||||
<Route
|
||||
path="integrations/automatic-enrollment/windows"
|
||||
component={WindowsAutomaticEnrollmentPage}
|
||||
/>
|
||||
<Route path="teams" component={TeamDetailsWrapper}>
|
||||
<Route path="members" component={MembersPage} />
|
||||
<Route path="options" component={AgentOptionsPage} />
|
||||
|
||||
@@ -17,6 +17,8 @@ export default {
|
||||
DASHBOARD_MAC: `${URL_PREFIX}/dashboard/mac`,
|
||||
DASHBOARD_WINDOWS: `${URL_PREFIX}/dashboard/windows`,
|
||||
DASHBOARD_CHROME: `${URL_PREFIX}/dashboard/chrome`,
|
||||
|
||||
// Admin pages
|
||||
ADMIN_USERS: `${URL_PREFIX}/settings/users`,
|
||||
ADMIN_INTEGRATIONS: `${URL_PREFIX}/settings/integrations`,
|
||||
ADMIN_INTEGRATIONS_TICKET_DESTINATIONS: `${URL_PREFIX}/settings/integrations/ticket-destinations`,
|
||||
@@ -24,6 +26,7 @@ export default {
|
||||
ADMIN_INTEGRATIONS_MDM_MAC: `${URL_PREFIX}/settings/integrations/mdm/apple`,
|
||||
ADMIN_INTEGRATIONS_MDM_WINDOWS: `${URL_PREFIX}/settings/integrations/mdm/windows`,
|
||||
ADMIN_INTEGRATIONS_AUTOMATIC_ENROLLMENT: `${URL_PREFIX}/settings/integrations/automatic-enrollment`,
|
||||
ADMIN_INTEGRATIONS_AUTOMATIC_ENROLLMENT_WINDOWS: `${URL_PREFIX}/settings/integrations/automatic-enrollment/windows`,
|
||||
ADMIN_TEAMS: `${URL_PREFIX}/settings/teams`,
|
||||
ADMIN_SETTINGS: `${URL_PREFIX}/settings`,
|
||||
ADMIN_SETTINGS_INFO: `${URL_PREFIX}/settings/organization/info`,
|
||||
@@ -35,6 +38,7 @@ export default {
|
||||
ADMIN_SETTINGS_STATISTICS: `${URL_PREFIX}/settings/organization/statistics`,
|
||||
ADMIN_SETTINGS_ADVANCED: `${URL_PREFIX}/settings/organization/advanced`,
|
||||
ADMIN_SETTINGS_FLEET_DESKTOP: `${URL_PREFIX}/settings/organization/fleet-desktop`,
|
||||
|
||||
EDIT_PACK: (packId: number): string => {
|
||||
return `${URL_PREFIX}/packs/${packId}/edit`;
|
||||
},
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
<!-- This is the html page for a user accepting the terms of service during the
|
||||
windows mdm enrollment flow. -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mdm-windows-sso-callback-page {
|
||||
font-family: "Inter", sans-serif;
|
||||
height: 100vh;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.eula-wrapper {
|
||||
width: 80vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.eula {
|
||||
font-size: 18px;
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.eula ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.eula ol {
|
||||
padding: 0;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
margin-top: 0;
|
||||
margin-bottom: 42px;
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
background-color: #192147;
|
||||
margin-top: 16px;
|
||||
padding: 8px 16px;
|
||||
font-size: 18px;
|
||||
width: 341px;
|
||||
height: 78px;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
const agreeToTerms = () => {
|
||||
window.location =
|
||||
"{{.RedirectURL}}" + "?IsAccepted=true&OpaqueBlob={{.ClientData}}";
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-content">
|
||||
<div class="mdm-windows-sso-callback-page">
|
||||
<div class="eula-wrapper">
|
||||
<h1>Terms and conditions</h1>
|
||||
<div class="eula">
|
||||
<p>
|
||||
Fleet is open-source software for managing computers. Your
|
||||
organization is using it to manage and secure this computer.
|
||||
</p>
|
||||
<p>Fleet does NOT have access to:</p>
|
||||
<ul>
|
||||
<li>⌨️ Keystrokes</li>
|
||||
<li>🖱 Mouse movements</li>
|
||||
<li>🎙 Webcams & mic</li>
|
||||
<li>🖥 Screen content</li>
|
||||
</ul>
|
||||
<p>
|
||||
To read the source code running on your device, visit
|
||||
github.com/fleetdm/fleet.
|
||||
</p>
|
||||
<p>
|
||||
The people who contribute to Fleet are helpful, kind, and
|
||||
dedicated to clarity through open-source software. If you run into
|
||||
issues or would like to contribute, let us know at fleetdm.com.
|
||||
</p>
|
||||
<p>And now, the End User License Agreement:</p>
|
||||
<p>
|
||||
This copy of Fleet (“the Software Product”) and accompanying
|
||||
documentation is licensed and not sold. Fleet Device Management,
|
||||
Inc (“Fleet”) owns intellectual property rights in the Software
|
||||
Product that are protected by laws and treaties pertaining to
|
||||
copyright and other forms of intellectual property. The
|
||||
Licensee's (“you” or “your”) license to download, use, copy,
|
||||
or change the Software Product is subject to these rights and to
|
||||
all the terms and conditions of this End User License Agreement
|
||||
(“Agreement”). These Terms are subject to change by Fleet Device
|
||||
Management, Inc without prior written notice at any time, and in
|
||||
Fleet's sole discretion.
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Acceptance<br />
|
||||
<p>
|
||||
You accept and agree to be bound by the terms of this
|
||||
agreement by selecting the “accept” option and downloading the
|
||||
software product or by installing, using or copying the
|
||||
software product. You must agree to all of the terms of this
|
||||
agreement before downloading or installing the software
|
||||
product.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
License Grant<br />
|
||||
<p>
|
||||
Subject to the terms and conditions of this Agreement, Fleet
|
||||
hereby grants to End User, and End User&s authorized users
|
||||
who have been registered with Fleet, a non-exclusive and
|
||||
nontransferable license, during the term of your contract, to
|
||||
access and use the Software Product. End User agrees that its
|
||||
purchase of subscription(s) for the Software Product is
|
||||
neither contingent upon the delivery of any future
|
||||
functionality or features nor dependent upon any oral or
|
||||
written public comments made by Fleet with respect to future
|
||||
functionality or features, unless specifically documented in a
|
||||
statement of work or other agreement. Upon expiration or
|
||||
termination of your contract, the rights and licenses granted
|
||||
hereunder will automatically terminate, and End Users may
|
||||
continue to use the free version of the Software Product but
|
||||
will lose functionality associated with paid features.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Restrictions on Transfer<br />
|
||||
<p>
|
||||
Without first obtaining the express written consent of Fleet
|
||||
Device Management Inc., you may not assign your rights and
|
||||
obligations under this Agreement, or redistribute, encumber,
|
||||
sell, rent, lease, sublicense, or otherwise transfer your
|
||||
rights to the Software Product.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Restrictions on Use<br />
|
||||
<p>
|
||||
You may not use, copy, or install the Software Product on more
|
||||
hosts than the number permitted by license.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
No Warranties<br />
|
||||
<p>
|
||||
To the maximum extent permitted by applicable law, Fleet
|
||||
expressly disclaims any warranty for the Software Product. The
|
||||
Software Product and any related documentation are provided
|
||||
"as is" without warranty of any kind, either express or
|
||||
implied, including, without limitation, the implied warranties
|
||||
of merchantability or fitness for a particular purpose. Fleet
|
||||
makes no warranty that the Software Product will meet your
|
||||
requirements or operate under your specific conditions of use.
|
||||
Fleet makes no warranty that operation of the Software Product
|
||||
will be secure, error free, or free from interruption. The
|
||||
entire risk arising out of use or performance of the Software
|
||||
Product remains with you.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
No Liability for Consequential Damages<br />
|
||||
<p>
|
||||
To the maximum extent permitted by applicable law, in no event
|
||||
shall Fleet, its directors, officers, employees, agents or its
|
||||
suppliers be liable for any damages whatsoever (including,
|
||||
without limitation, damages for loss of business profit,
|
||||
business interruption, loss of business information, or any
|
||||
other pecuniary loss) arising out of the use of, or inability
|
||||
to use, this Fleet product, even if Fleet has been advised of
|
||||
the possibility of such damages. Because some
|
||||
states/jurisdictions do not allow the exclusion or limitation
|
||||
of liability for consequential or incidental damages, the
|
||||
above limitation may not apply to you.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Limitation of Remedies and Damages<br />
|
||||
<p>
|
||||
Your remedy for a breach of this Agreement or of any warranty
|
||||
included in this Agreement is the correction or replacement of
|
||||
the Software Product. Selection of whether to correct or
|
||||
replace shall be solely at the discretion of Fleet. If Fleet
|
||||
is unable to provide a replacement or substitute Software
|
||||
Product or corrections to the Software Product, your sole
|
||||
alternate remedy shall be a refund of the purchase price for
|
||||
the Software Product.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Governing Law<br />
|
||||
<p>
|
||||
This Agreement is governed by the laws of the State of
|
||||
California, without regard to its conflict of law provisions.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Termination<br />
|
||||
<p>
|
||||
Without prejudice to any other rights, Fleet may terminate
|
||||
this Agreement if you fail to comply with the terms and
|
||||
conditions of this EULA.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Severability<br />
|
||||
<p>
|
||||
If any provision of this Agreement shall be held to be invalid
|
||||
or unenforceable, the remainder of this Agreement shall remain
|
||||
in full force and effect. To the extent any express or implied
|
||||
restrictions are not permitted by applicable laws, these
|
||||
express or implied restrictions shall remain in force and
|
||||
effect to the maximum extent permitted by such applicable
|
||||
laws.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Export Restrictions<br />
|
||||
<p>
|
||||
You agree that neither you nor your customers intend to or
|
||||
will, directly or indirectly, export or transmit the Software
|
||||
Product or related documentation and technical data, or
|
||||
process, or service that is the direct product of the Software
|
||||
Product to any country to which such export or transmission is
|
||||
restricted by any applicable U.S. regulation or statute,
|
||||
without the prior written consent, if required, of the Bureau
|
||||
of Export Administration of the U.S. Department of Commerce,
|
||||
or such other governmental entity as may have jurisdiction
|
||||
over such export or transmission.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<button onClick="agreeToTerms()">Agree and continue</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Vendored
+5
@@ -16,3 +16,8 @@ declare module "*.gif" {
|
||||
const value: string;
|
||||
export = value;
|
||||
}
|
||||
|
||||
declare module "*.pdf" {
|
||||
const value: string;
|
||||
export = value;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"html/template"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
)
|
||||
|
||||
@@ -17,7 +18,7 @@ type InviteMailer struct {
|
||||
}
|
||||
|
||||
func (i *InviteMailer) Message() ([]byte, error) {
|
||||
t, err := getTemplate("server/mail/templates/invite_token.html")
|
||||
t, err := server.GetTemplate("server/mail/templates/invite_token.html", "email_template")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+2
-16
@@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/bindata"
|
||||
"github.com/fleetdm/fleet/v4/server"
|
||||
"github.com/fleetdm/fleet/v4/server/config"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
)
|
||||
@@ -266,7 +266,7 @@ type SMTPTestMailer struct {
|
||||
}
|
||||
|
||||
func (m *SMTPTestMailer) Message() ([]byte, error) {
|
||||
t, err := getTemplate("server/mail/templates/smtp_setup.html")
|
||||
t, err := server.GetTemplate("server/mail/templates/smtp_setup.html", "email_template")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -278,17 +278,3 @@ func (m *SMTPTestMailer) Message() ([]byte, error) {
|
||||
|
||||
return msg.Bytes(), nil
|
||||
}
|
||||
|
||||
func getTemplate(templatePath string) (*template.Template, error) {
|
||||
templateData, err := bindata.Asset(templatePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := template.New("email_template").Parse(string(templateData))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package mail
|
||||
import (
|
||||
"bytes"
|
||||
"html/template"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server"
|
||||
)
|
||||
|
||||
type ChangeEmailMailer struct {
|
||||
@@ -12,7 +14,7 @@ type ChangeEmailMailer struct {
|
||||
}
|
||||
|
||||
func (cem *ChangeEmailMailer) Message() ([]byte, error) {
|
||||
t, err := getTemplate("server/mail/templates/change_email_confirmation.html")
|
||||
t, err := server.GetTemplate("server/mail/templates/change_email_confirmation.html", "email_template")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -34,7 +36,7 @@ type PasswordResetMailer struct {
|
||||
}
|
||||
|
||||
func (r PasswordResetMailer) Message() ([]byte, error) {
|
||||
t, err := getTemplate("server/mail/templates/password_reset.html")
|
||||
t, err := server.GetTemplate("server/mail/templates/password_reset.html", "email_template")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/logging"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
@@ -1165,34 +1166,7 @@ func (svc *Service) GetMDMWindowsManagementResponse(ctx context.Context, reqSync
|
||||
|
||||
// GetMDMWindowsTOSContent returns valid TOC content
|
||||
func (svc *Service) GetMDMWindowsTOSContent(ctx context.Context, redirectUri string, reqID string) (string, error) {
|
||||
tmpl, err := template.New("").Parse(`
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
button {
|
||||
background-color: #008CBA;
|
||||
color: white;
|
||||
padding: 10px 60px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<img src="https://fleetdm.com/images/logo-blue-162x92@2x.png">
|
||||
<br>
|
||||
<h2>Terms and conditions</h2>
|
||||
<br> Terms and Conditions PDF content should go here <center>
|
||||
<br>
|
||||
<button type="button" onClick="acceptBtn()">Accept</button>
|
||||
<script>
|
||||
function acceptBtn() {
|
||||
window.location = "{{.RedirectURL}}" + "?IsAccepted=true&OpaqueBlob={{.ClientData}}";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>`)
|
||||
tmpl, err := server.GetTemplate("frontend/templates/windowsTOS.html", "windows-tos")
|
||||
if err != nil {
|
||||
return "", ctxerr.Wrap(ctx, err, "issue generating TOS content")
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -18,6 +19,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
|
||||
"github.com/fleetdm/fleet/v4/server/bindata"
|
||||
)
|
||||
|
||||
// GenerateRandomText return a string generated by filling in keySize bytes with
|
||||
@@ -119,3 +121,20 @@ func DecodePrivateKeyPEM(encoded []byte) (*rsa.PrivateKey, error) {
|
||||
|
||||
return x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
}
|
||||
|
||||
// GetTemplate takes a path to a template file and a template name and will
|
||||
// include the template file in the build binary. It then returns a pointer to
|
||||
// the template.
|
||||
func GetTemplate(templatePath string, templateName string) (*template.Template, error) {
|
||||
templateData, err := bindata.Asset(templatePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := template.New(templateName).Parse(string(templateData))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user