fleet/frontend/pages/admin/IntegrationsPage/cards/ConditionalAccess/ConditionalAccess.tsx

419 lines
13 KiB
TypeScript
Raw Normal View History

UI: Conditional access - Microsoft Entra (#27982) _Note - currently feature flagged. Build frontend with `ALLOW_CONDITIONAL_ACCESS=true NODE_ENV=development yarn run webpack --progress --watch` to enable this feature. Also, all of this functionality depends on the new `config.license.managed_cloud` being true, so you'll need to mock that data somehow. [This branch](https://github.com/fleetdm/fleet/tree/27043-fake-data) has the appropriate fake data for testing_ ## For #27043, #27864 ### Build front end for Fleet's integration with Microsoft Entra, allowing conditional preventtion of single sign-on for hosts failing any policies on a team #### Trigger the integration ![trigger](https://github.com/user-attachments/assets/4578568a-f64a-4390-83d9-fbec751d4b14) #### Triggered, but configuration still not verified <img width="1348" alt="√ not-verified-return-to-prefilled-form" src="https://github.com/user-attachments/assets/44d0c21f-2554-40a8-9158-d1107cff2d09" /> #### Verified, short and long tenant ids: ![ezgif-75f82492180d28](https://github.com/user-attachments/assets/015f3605-81e8-463a-be74-07bab99d9724) #### Verified –> Deleted ![√ verified - delete - deleted](https://github.com/user-attachments/assets/44b8ba70-49c9-43e7-be54-8474756a5b50) #### Enable for policies of a team ![√ enable-for-team](https://github.com/user-attachments/assets/9454b0da-059d-4991-a3ff-14e74257a3a7) #### Activities <img width="886" alt="√ activities" src="https://github.com/user-attachments/assets/d21e6185-c2f2-40b2-9c69-9b92fab58766" /> #### Unavailable for self-hosted Fleet instances: ![no-access-self-hosted](https://github.com/user-attachments/assets/56213522-b721-472f-9174-c8dac0df61f3) #### Premium only ![√ premium-only](https://github.com/user-attachments/assets/97373960-6b38-458b-be37-4c3868469182) - [x] Changes file added for user-visible changes in `changes/` - [x] Added/updated automated tests - [x] A detailed QA plan exists on the associated ticket (if it isn't there, work with the product group's QA engineer to add it) - [ ] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2025-04-15 20:55:07 +00:00
import React, { useContext, useEffect, useState } from "react";
import { size } from "lodash";
import paths from "router/paths";
import { NotificationContext } from "context/notification";
import conditionalAccessAPI, {
ConfirmMSConditionalAccessResponse,
} from "services/entities/conditional_access";
import configAPI from "services/entities/config";
// @ts-ignore
import InputField from "components/forms/fields/InputField";
import CustomLink from "components/CustomLink";
import SectionHeader from "components/SectionHeader";
import {
DEFAULT_USE_QUERY_OPTIONS,
LEARN_MORE_ABOUT_BASE_LINK,
} from "utilities/constants";
import Button from "components/buttons/Button";
import { IInputFieldParseTarget } from "interfaces/form_field";
UI: Conditional access - Microsoft Entra (#27982) _Note - currently feature flagged. Build frontend with `ALLOW_CONDITIONAL_ACCESS=true NODE_ENV=development yarn run webpack --progress --watch` to enable this feature. Also, all of this functionality depends on the new `config.license.managed_cloud` being true, so you'll need to mock that data somehow. [This branch](https://github.com/fleetdm/fleet/tree/27043-fake-data) has the appropriate fake data for testing_ ## For #27043, #27864 ### Build front end for Fleet's integration with Microsoft Entra, allowing conditional preventtion of single sign-on for hosts failing any policies on a team #### Trigger the integration ![trigger](https://github.com/user-attachments/assets/4578568a-f64a-4390-83d9-fbec751d4b14) #### Triggered, but configuration still not verified <img width="1348" alt="√ not-verified-return-to-prefilled-form" src="https://github.com/user-attachments/assets/44d0c21f-2554-40a8-9158-d1107cff2d09" /> #### Verified, short and long tenant ids: ![ezgif-75f82492180d28](https://github.com/user-attachments/assets/015f3605-81e8-463a-be74-07bab99d9724) #### Verified –> Deleted ![√ verified - delete - deleted](https://github.com/user-attachments/assets/44b8ba70-49c9-43e7-be54-8474756a5b50) #### Enable for policies of a team ![√ enable-for-team](https://github.com/user-attachments/assets/9454b0da-059d-4991-a3ff-14e74257a3a7) #### Activities <img width="886" alt="√ activities" src="https://github.com/user-attachments/assets/d21e6185-c2f2-40b2-9c69-9b92fab58766" /> #### Unavailable for self-hosted Fleet instances: ![no-access-self-hosted](https://github.com/user-attachments/assets/56213522-b721-472f-9174-c8dac0df61f3) #### Premium only ![√ premium-only](https://github.com/user-attachments/assets/97373960-6b38-458b-be37-4c3868469182) - [x] Changes file added for user-visible changes in `changes/` - [x] Added/updated automated tests - [x] A detailed QA plan exists on the associated ticket (if it isn't there, work with the product group's QA engineer to add it) - [ ] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2025-04-15 20:55:07 +00:00
import { AppContext } from "context/app";
import Spinner from "components/Spinner";
import PremiumFeatureMessage from "components/PremiumFeatureMessage";
import InfoBanner from "components/InfoBanner";
import Icon from "components/Icon";
import TooltipTruncatedText from "components/TooltipTruncatedText";
import { useQuery } from "react-query";
import DataError from "components/DataError";
import Modal from "components/Modal";
import { IConfig } from "interfaces/config";
const baseClass = "conditional-access";
const MSETID = "microsoft_entra_tenant_id";
interface IDeleteConditionalAccessModal {
toggleDeleteConditionalAccessModal: () => void;
onDelete: () => void;
}
const DeleteConditionalAccessModal = ({
toggleDeleteConditionalAccessModal,
onDelete,
}: IDeleteConditionalAccessModal) => {
const { renderFlash } = useContext(NotificationContext);
const [isDeleting, setIsDeleting] = useState(false);
const handleDelete = async () => {
setIsDeleting(true);
try {
await conditionalAccessAPI.deleteMicrosoftConditionalAccess();
renderFlash("success", "Successfully disconnected from Microsoft Entra.");
toggleDeleteConditionalAccessModal();
onDelete();
} catch {
renderFlash(
"error",
"Could not disconnect from Microsoft Entra, please try again."
);
}
setIsDeleting(false);
};
UI: Conditional access - Microsoft Entra (#27982) _Note - currently feature flagged. Build frontend with `ALLOW_CONDITIONAL_ACCESS=true NODE_ENV=development yarn run webpack --progress --watch` to enable this feature. Also, all of this functionality depends on the new `config.license.managed_cloud` being true, so you'll need to mock that data somehow. [This branch](https://github.com/fleetdm/fleet/tree/27043-fake-data) has the appropriate fake data for testing_ ## For #27043, #27864 ### Build front end for Fleet's integration with Microsoft Entra, allowing conditional preventtion of single sign-on for hosts failing any policies on a team #### Trigger the integration ![trigger](https://github.com/user-attachments/assets/4578568a-f64a-4390-83d9-fbec751d4b14) #### Triggered, but configuration still not verified <img width="1348" alt="√ not-verified-return-to-prefilled-form" src="https://github.com/user-attachments/assets/44d0c21f-2554-40a8-9158-d1107cff2d09" /> #### Verified, short and long tenant ids: ![ezgif-75f82492180d28](https://github.com/user-attachments/assets/015f3605-81e8-463a-be74-07bab99d9724) #### Verified –> Deleted ![√ verified - delete - deleted](https://github.com/user-attachments/assets/44b8ba70-49c9-43e7-be54-8474756a5b50) #### Enable for policies of a team ![√ enable-for-team](https://github.com/user-attachments/assets/9454b0da-059d-4991-a3ff-14e74257a3a7) #### Activities <img width="886" alt="√ activities" src="https://github.com/user-attachments/assets/d21e6185-c2f2-40b2-9c69-9b92fab58766" /> #### Unavailable for self-hosted Fleet instances: ![no-access-self-hosted](https://github.com/user-attachments/assets/56213522-b721-472f-9174-c8dac0df61f3) #### Premium only ![√ premium-only](https://github.com/user-attachments/assets/97373960-6b38-458b-be37-4c3868469182) - [x] Changes file added for user-visible changes in `changes/` - [x] Added/updated automated tests - [x] A detailed QA plan exists on the associated ticket (if it isn't there, work with the product group's QA engineer to add it) - [ ] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2025-04-15 20:55:07 +00:00
return (
<Modal
title="Delete"
onExit={toggleDeleteConditionalAccessModal}
onEnter={onDelete}
>
<>
<p>
Fleet will be disconnected from Microsoft Entra and will stop blocking
end users from logging in with single sign-on.
</p>
<div className="modal-cta-wrap">
<Button
type="button"
variant="alert"
onClick={handleDelete}
isLoading={isDeleting}
disabled={isDeleting}
UI: Conditional access - Microsoft Entra (#27982) _Note - currently feature flagged. Build frontend with `ALLOW_CONDITIONAL_ACCESS=true NODE_ENV=development yarn run webpack --progress --watch` to enable this feature. Also, all of this functionality depends on the new `config.license.managed_cloud` being true, so you'll need to mock that data somehow. [This branch](https://github.com/fleetdm/fleet/tree/27043-fake-data) has the appropriate fake data for testing_ ## For #27043, #27864 ### Build front end for Fleet's integration with Microsoft Entra, allowing conditional preventtion of single sign-on for hosts failing any policies on a team #### Trigger the integration ![trigger](https://github.com/user-attachments/assets/4578568a-f64a-4390-83d9-fbec751d4b14) #### Triggered, but configuration still not verified <img width="1348" alt="√ not-verified-return-to-prefilled-form" src="https://github.com/user-attachments/assets/44d0c21f-2554-40a8-9158-d1107cff2d09" /> #### Verified, short and long tenant ids: ![ezgif-75f82492180d28](https://github.com/user-attachments/assets/015f3605-81e8-463a-be74-07bab99d9724) #### Verified –> Deleted ![√ verified - delete - deleted](https://github.com/user-attachments/assets/44b8ba70-49c9-43e7-be54-8474756a5b50) #### Enable for policies of a team ![√ enable-for-team](https://github.com/user-attachments/assets/9454b0da-059d-4991-a3ff-14e74257a3a7) #### Activities <img width="886" alt="√ activities" src="https://github.com/user-attachments/assets/d21e6185-c2f2-40b2-9c69-9b92fab58766" /> #### Unavailable for self-hosted Fleet instances: ![no-access-self-hosted](https://github.com/user-attachments/assets/56213522-b721-472f-9174-c8dac0df61f3) #### Premium only ![√ premium-only](https://github.com/user-attachments/assets/97373960-6b38-458b-be37-4c3868469182) - [x] Changes file added for user-visible changes in `changes/` - [x] Added/updated automated tests - [x] A detailed QA plan exists on the associated ticket (if it isn't there, work with the product group's QA engineer to add it) - [ ] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2025-04-15 20:55:07 +00:00
>
Delete
</Button>
<Button
onClick={toggleDeleteConditionalAccessModal}
variant="inverse-alert"
disabled={isDeleting}
UI: Conditional access - Microsoft Entra (#27982) _Note - currently feature flagged. Build frontend with `ALLOW_CONDITIONAL_ACCESS=true NODE_ENV=development yarn run webpack --progress --watch` to enable this feature. Also, all of this functionality depends on the new `config.license.managed_cloud` being true, so you'll need to mock that data somehow. [This branch](https://github.com/fleetdm/fleet/tree/27043-fake-data) has the appropriate fake data for testing_ ## For #27043, #27864 ### Build front end for Fleet's integration with Microsoft Entra, allowing conditional preventtion of single sign-on for hosts failing any policies on a team #### Trigger the integration ![trigger](https://github.com/user-attachments/assets/4578568a-f64a-4390-83d9-fbec751d4b14) #### Triggered, but configuration still not verified <img width="1348" alt="√ not-verified-return-to-prefilled-form" src="https://github.com/user-attachments/assets/44d0c21f-2554-40a8-9158-d1107cff2d09" /> #### Verified, short and long tenant ids: ![ezgif-75f82492180d28](https://github.com/user-attachments/assets/015f3605-81e8-463a-be74-07bab99d9724) #### Verified –> Deleted ![√ verified - delete - deleted](https://github.com/user-attachments/assets/44b8ba70-49c9-43e7-be54-8474756a5b50) #### Enable for policies of a team ![√ enable-for-team](https://github.com/user-attachments/assets/9454b0da-059d-4991-a3ff-14e74257a3a7) #### Activities <img width="886" alt="√ activities" src="https://github.com/user-attachments/assets/d21e6185-c2f2-40b2-9c69-9b92fab58766" /> #### Unavailable for self-hosted Fleet instances: ![no-access-self-hosted](https://github.com/user-attachments/assets/56213522-b721-472f-9174-c8dac0df61f3) #### Premium only ![√ premium-only](https://github.com/user-attachments/assets/97373960-6b38-458b-be37-4c3868469182) - [x] Changes file added for user-visible changes in `changes/` - [x] Added/updated automated tests - [x] A detailed QA plan exists on the associated ticket (if it isn't there, work with the product group's QA engineer to add it) - [ ] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2025-04-15 20:55:07 +00:00
>
Cancel
</Button>
</div>
</>
</Modal>
);
};
// conditions > UI phases:
// - no config.tenant id > "form"
// - config.tenant id:
// - and config.confirmed > "configured"
// - not config.confirmed > "confirming-configured", hit confirmation endpoint
// - confirmation endpoint returns false > "form", prefilled with current tid
// - confirmation endpoint returns true > "configured"
// - conf ep returns error > DataError, under header
// - form submitted > "form-submitted", new tab to MS stuff
//
interface IFormData {
[MSETID]: string;
}
interface IFormErrors {
[MSETID]?: string | null;
}
enum Phase {
Form = "form",
FormSubmitted = "form-submitted",
ConfirmingConfigured = "confirming-configured",
ConfirmationError = "confirmation-error",
Configured = "configured",
}
const validate = (formData: IFormData) => {
const errs: IFormErrors = {};
if (!formData[MSETID]) {
errs[MSETID] = "Tenant ID must be present";
}
return errs;
};
const ConditionalAccess = () => {
// HOOKS
const { renderFlash } = useContext(NotificationContext);
const { isPremiumTier, setConfig, config: contextConfig } = useContext(
AppContext
);
const [phase, setPhase] = useState<Phase>(Phase.Form);
const [isUpdating, setIsUpdating] = useState(false);
// this page is unique in that it triggers a server process that will result in an update to
// config, but via an endpoint (conditional access) other than the usual PATCH config, so we want
// to both reference config context AND conditionally (when `isUpdating` from the Configured
// phase) access `refetchConfig` and associated useQuery capability
// see frontend/docs/patterns.md > ### Reading and updating configs for why this is atypical
const { refetch: refetchConfig } = useQuery<IConfig, Error, IConfig>(
["config"],
() => configAPI.loadAll(),
{
select: (data: IConfig) => data,
enabled: isUpdating && phase === Phase.Configured,
onSuccess: (_config) => {
if (
!_config?.conditional_access?.microsoft_entra_connection_configured
) {
setPhase(Phase.Form);
}
setConfig(_config);
setIsUpdating(false);
},
...DEFAULT_USE_QUERY_OPTIONS,
}
);
const [formData, setFormData] = useState<IFormData>({
[MSETID]:
contextConfig?.conditional_access?.microsoft_entra_tenant_id || "",
});
const [formErrors, setFormErrors] = useState<IFormErrors>({});
const [
showDeleteConditionalAccessModal,
setShowDeleteConditionalAccessModal,
] = useState(false);
// "loading" state here is encompassed by phase === Phase.ConfirmingConfigured state, don't need
// to use useQuery's
// "error" state handled by onError callback
// success state handled by onSuccess callback
useQuery<
ConfirmMSConditionalAccessResponse,
Error,
ConfirmMSConditionalAccessResponse
>(["confirmAccess"], conditionalAccessAPI.confirmMicrosoftConditionalAccess, {
...DEFAULT_USE_QUERY_OPTIONS,
// only make this call at the appropriate UI phase
enabled: phase === Phase.ConfirmingConfigured && isPremiumTier,
onSuccess: ({ configuration_completed, setup_error }) => {
UI: Conditional access - Microsoft Entra (#27982) _Note - currently feature flagged. Build frontend with `ALLOW_CONDITIONAL_ACCESS=true NODE_ENV=development yarn run webpack --progress --watch` to enable this feature. Also, all of this functionality depends on the new `config.license.managed_cloud` being true, so you'll need to mock that data somehow. [This branch](https://github.com/fleetdm/fleet/tree/27043-fake-data) has the appropriate fake data for testing_ ## For #27043, #27864 ### Build front end for Fleet's integration with Microsoft Entra, allowing conditional preventtion of single sign-on for hosts failing any policies on a team #### Trigger the integration ![trigger](https://github.com/user-attachments/assets/4578568a-f64a-4390-83d9-fbec751d4b14) #### Triggered, but configuration still not verified <img width="1348" alt="√ not-verified-return-to-prefilled-form" src="https://github.com/user-attachments/assets/44d0c21f-2554-40a8-9158-d1107cff2d09" /> #### Verified, short and long tenant ids: ![ezgif-75f82492180d28](https://github.com/user-attachments/assets/015f3605-81e8-463a-be74-07bab99d9724) #### Verified –> Deleted ![√ verified - delete - deleted](https://github.com/user-attachments/assets/44b8ba70-49c9-43e7-be54-8474756a5b50) #### Enable for policies of a team ![√ enable-for-team](https://github.com/user-attachments/assets/9454b0da-059d-4991-a3ff-14e74257a3a7) #### Activities <img width="886" alt="√ activities" src="https://github.com/user-attachments/assets/d21e6185-c2f2-40b2-9c69-9b92fab58766" /> #### Unavailable for self-hosted Fleet instances: ![no-access-self-hosted](https://github.com/user-attachments/assets/56213522-b721-472f-9174-c8dac0df61f3) #### Premium only ![√ premium-only](https://github.com/user-attachments/assets/97373960-6b38-458b-be37-4c3868469182) - [x] Changes file added for user-visible changes in `changes/` - [x] Added/updated automated tests - [x] A detailed QA plan exists on the associated ticket (if it isn't there, work with the product group's QA engineer to add it) - [ ] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2025-04-15 20:55:07 +00:00
if (configuration_completed) {
setPhase(Phase.Configured);
renderFlash(
"success",
"Successfully verified conditional access integration"
);
} else {
setPhase(Phase.Form);
if (
// IT admin did not complete the consent.
!setup_error ||
// IT admin clicked "Cancel" in the consent dialog.
setup_error.includes(
"A Microsoft Entra admin did not consent to the permissions requested by the conditional access integration"
)
) {
renderFlash(
"error",
"Couldn't update. Fleet didn't get permissions for Entra. Please try again and accept the permissions."
);
} else if (
setup_error.includes(
'No "Fleet conditional access" Entra ID group was found'
)
) {
renderFlash(
"error",
`Couldn't connect. The "Fleet conditional access" group doesn't exist in Entra. Please create the group and try again.`
);
} else {
// For other kind of errors we just show a generic error.
// We won't render the error as is because the error comes from the MS proxy and they may be too big or unformatted
// to display in the banner.
//
// For troubleshooting:
// - The API response contains the setup_error.
// - The Fleet server logs the error.
// - The MS proxy stores the error in its database.
renderFlash(
"error",
"Couldn't connect. Please contact your Fleet administrator."
);
}
UI: Conditional access - Microsoft Entra (#27982) _Note - currently feature flagged. Build frontend with `ALLOW_CONDITIONAL_ACCESS=true NODE_ENV=development yarn run webpack --progress --watch` to enable this feature. Also, all of this functionality depends on the new `config.license.managed_cloud` being true, so you'll need to mock that data somehow. [This branch](https://github.com/fleetdm/fleet/tree/27043-fake-data) has the appropriate fake data for testing_ ## For #27043, #27864 ### Build front end for Fleet's integration with Microsoft Entra, allowing conditional preventtion of single sign-on for hosts failing any policies on a team #### Trigger the integration ![trigger](https://github.com/user-attachments/assets/4578568a-f64a-4390-83d9-fbec751d4b14) #### Triggered, but configuration still not verified <img width="1348" alt="√ not-verified-return-to-prefilled-form" src="https://github.com/user-attachments/assets/44d0c21f-2554-40a8-9158-d1107cff2d09" /> #### Verified, short and long tenant ids: ![ezgif-75f82492180d28](https://github.com/user-attachments/assets/015f3605-81e8-463a-be74-07bab99d9724) #### Verified –> Deleted ![√ verified - delete - deleted](https://github.com/user-attachments/assets/44b8ba70-49c9-43e7-be54-8474756a5b50) #### Enable for policies of a team ![√ enable-for-team](https://github.com/user-attachments/assets/9454b0da-059d-4991-a3ff-14e74257a3a7) #### Activities <img width="886" alt="√ activities" src="https://github.com/user-attachments/assets/d21e6185-c2f2-40b2-9c69-9b92fab58766" /> #### Unavailable for self-hosted Fleet instances: ![no-access-self-hosted](https://github.com/user-attachments/assets/56213522-b721-472f-9174-c8dac0df61f3) #### Premium only ![√ premium-only](https://github.com/user-attachments/assets/97373960-6b38-458b-be37-4c3868469182) - [x] Changes file added for user-visible changes in `changes/` - [x] Added/updated automated tests - [x] A detailed QA plan exists on the associated ticket (if it isn't there, work with the product group's QA engineer to add it) - [ ] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2025-04-15 20:55:07 +00:00
}
},
onError: () => {
// distinct from successful confirmation response of `false`, this handles an API error
setPhase(Phase.ConfirmationError);
},
});
const {
microsoft_entra_tenant_id: contextConfigMsetId,
microsoft_entra_connection_configured: contextConfigMseConfigured,
} = contextConfig?.conditional_access || {};
// only checks if tenant id already present in config, not if user added it to the form
useEffect(() => {
if (contextConfigMsetId) {
if (!contextConfigMseConfigured) {
setPhase(Phase.ConfirmingConfigured);
} else {
// tenant id is present and connection is configured
setPhase(Phase.Configured);
}
}
}, [contextConfigMsetId, contextConfigMseConfigured]);
if (!isPremiumTier) {
return <PremiumFeatureMessage />;
}
// HANDLERS
const toggleDeleteConditionalAccessModal = () => {
setShowDeleteConditionalAccessModal(!showDeleteConditionalAccessModal);
};
const onSubmit = async (evt: React.FormEvent<HTMLFormElement>) => {
evt.preventDefault();
const errs = validate(formData);
if (Object.keys(errs).length > 0) {
setFormErrors(errs);
return;
}
setIsUpdating(true);
try {
const {
microsoft_authentication_url: msAuthURL,
} = await conditionalAccessAPI.triggerMicrosoftConditionalAccess(
formData[MSETID]
);
setIsUpdating(false);
setPhase(Phase.FormSubmitted);
window.open(msAuthURL);
} catch (e) {
renderFlash(
"error",
"Could not update conditional access integration settings."
);
setIsUpdating(false);
}
};
const onDeleteConditionalAccess = async () => {
setFormData({ [MSETID]: "" });
refetchConfig();
UI: Conditional access - Microsoft Entra (#27982) _Note - currently feature flagged. Build frontend with `ALLOW_CONDITIONAL_ACCESS=true NODE_ENV=development yarn run webpack --progress --watch` to enable this feature. Also, all of this functionality depends on the new `config.license.managed_cloud` being true, so you'll need to mock that data somehow. [This branch](https://github.com/fleetdm/fleet/tree/27043-fake-data) has the appropriate fake data for testing_ ## For #27043, #27864 ### Build front end for Fleet's integration with Microsoft Entra, allowing conditional preventtion of single sign-on for hosts failing any policies on a team #### Trigger the integration ![trigger](https://github.com/user-attachments/assets/4578568a-f64a-4390-83d9-fbec751d4b14) #### Triggered, but configuration still not verified <img width="1348" alt="√ not-verified-return-to-prefilled-form" src="https://github.com/user-attachments/assets/44d0c21f-2554-40a8-9158-d1107cff2d09" /> #### Verified, short and long tenant ids: ![ezgif-75f82492180d28](https://github.com/user-attachments/assets/015f3605-81e8-463a-be74-07bab99d9724) #### Verified –> Deleted ![√ verified - delete - deleted](https://github.com/user-attachments/assets/44b8ba70-49c9-43e7-be54-8474756a5b50) #### Enable for policies of a team ![√ enable-for-team](https://github.com/user-attachments/assets/9454b0da-059d-4991-a3ff-14e74257a3a7) #### Activities <img width="886" alt="√ activities" src="https://github.com/user-attachments/assets/d21e6185-c2f2-40b2-9c69-9b92fab58766" /> #### Unavailable for self-hosted Fleet instances: ![no-access-self-hosted](https://github.com/user-attachments/assets/56213522-b721-472f-9174-c8dac0df61f3) #### Premium only ![√ premium-only](https://github.com/user-attachments/assets/97373960-6b38-458b-be37-4c3868469182) - [x] Changes file added for user-visible changes in `changes/` - [x] Added/updated automated tests - [x] A detailed QA plan exists on the associated ticket (if it isn't there, work with the product group's QA engineer to add it) - [ ] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2025-04-15 20:55:07 +00:00
};
const onInputChange = ({ name, value }: IInputFieldParseTarget) => {
UI: Conditional access - Microsoft Entra (#27982) _Note - currently feature flagged. Build frontend with `ALLOW_CONDITIONAL_ACCESS=true NODE_ENV=development yarn run webpack --progress --watch` to enable this feature. Also, all of this functionality depends on the new `config.license.managed_cloud` being true, so you'll need to mock that data somehow. [This branch](https://github.com/fleetdm/fleet/tree/27043-fake-data) has the appropriate fake data for testing_ ## For #27043, #27864 ### Build front end for Fleet's integration with Microsoft Entra, allowing conditional preventtion of single sign-on for hosts failing any policies on a team #### Trigger the integration ![trigger](https://github.com/user-attachments/assets/4578568a-f64a-4390-83d9-fbec751d4b14) #### Triggered, but configuration still not verified <img width="1348" alt="√ not-verified-return-to-prefilled-form" src="https://github.com/user-attachments/assets/44d0c21f-2554-40a8-9158-d1107cff2d09" /> #### Verified, short and long tenant ids: ![ezgif-75f82492180d28](https://github.com/user-attachments/assets/015f3605-81e8-463a-be74-07bab99d9724) #### Verified –> Deleted ![√ verified - delete - deleted](https://github.com/user-attachments/assets/44b8ba70-49c9-43e7-be54-8474756a5b50) #### Enable for policies of a team ![√ enable-for-team](https://github.com/user-attachments/assets/9454b0da-059d-4991-a3ff-14e74257a3a7) #### Activities <img width="886" alt="√ activities" src="https://github.com/user-attachments/assets/d21e6185-c2f2-40b2-9c69-9b92fab58766" /> #### Unavailable for self-hosted Fleet instances: ![no-access-self-hosted](https://github.com/user-attachments/assets/56213522-b721-472f-9174-c8dac0df61f3) #### Premium only ![√ premium-only](https://github.com/user-attachments/assets/97373960-6b38-458b-be37-4c3868469182) - [x] Changes file added for user-visible changes in `changes/` - [x] Added/updated automated tests - [x] A detailed QA plan exists on the associated ticket (if it isn't there, work with the product group's QA engineer to add it) - [ ] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2025-04-15 20:55:07 +00:00
const newFormData = { ...formData, [name]: value };
setFormData(newFormData);
const newErrs = validate(newFormData);
// only set errors that are updates of existing errors
// new errors are only set onBlur or submit
const errsToSet: Record<string, string> = {};
Object.keys(formErrors).forEach((k) => {
// @ts-ignore
if (newErrs[k]) {
// @ts-ignore
errsToSet[k] = newErrs[k];
}
});
setFormErrors(errsToSet);
};
const onInputBlur = () => {
setFormErrors(validate(formData));
};
const renderContent = () => {
switch (phase) {
case Phase.Form:
return (
<form onSubmit={onSubmit} autoComplete="off">
<InputField
label="Microsoft Entra tenant ID"
helpText={
<>
You can find this in your Microsoft Entra admin center.{" "}
<CustomLink
url={`${LEARN_MORE_ABOUT_BASE_LINK}/microsoft-entra-setup`}
text="Learn more"
newTab
/>
</>
}
onChange={onInputChange}
name={MSETID}
value={formData[MSETID]}
parseTarget
onBlur={onInputBlur}
error={formErrors[MSETID]}
/>
<Button
type="submit"
disabled={!!size(formErrors)}
className="button-wrap"
isLoading={isUpdating}
>
Save
</Button>
</form>
);
case Phase.FormSubmitted:
return (
<InfoBanner>
To complete your integration, follow the instructions in the other
tab, then refresh this page to verify.
</InfoBanner>
);
case Phase.ConfirmingConfigured:
// checking integration
return <Spinner />;
case Phase.ConfirmationError:
return <DataError />;
case Phase.Configured:
return (
<InfoBanner color="grey" className={`${baseClass}__success`}>
<div className="tenant-id">
<Icon name="success" />
<b>Microsoft Entra tenant ID:</b>{" "}
<TooltipTruncatedText value={formData[MSETID]} />
</div>
<Button
variant="text-icon"
onClick={toggleDeleteConditionalAccessModal}
>
Delete
<Icon name="trash" />
</Button>
</InfoBanner>
);
default:
return <Spinner />;
}
};
return (
<div className={baseClass}>
<SectionHeader title="Conditional access" />
<p className={`${baseClass}__page-description`}>
Block hosts failing any policies from logging in with single sign-on.
Enable or disable on the{" "}
<CustomLink url={paths.MANAGE_POLICIES} text="Policies" /> page.
</p>
{renderContent()}
{showDeleteConditionalAccessModal && (
<DeleteConditionalAccessModal
onDelete={onDeleteConditionalAccess}
toggleDeleteConditionalAccessModal={
toggleDeleteConditionalAccessModal
}
/>
)}
</div>
);
};
export default ConditionalAccess;