From 51a82e82684e9d6638eb8f029566d13fafc338da Mon Sep 17 00:00:00 2001
From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com>
Date: Sun, 18 Jan 2026 14:59:30 +0100
Subject: [PATCH 01/17] updated text guidiance
---
src/components/CippWizard/CippSAMDeploy.jsx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/components/CippWizard/CippSAMDeploy.jsx b/src/components/CippWizard/CippSAMDeploy.jsx
index 2cb619fef7aa..d38d0f66ddf2 100644
--- a/src/components/CippWizard/CippSAMDeploy.jsx
+++ b/src/components/CippWizard/CippSAMDeploy.jsx
@@ -92,7 +92,10 @@ export const CippSAMDeploy = (props) => {
here
-
(Temporary) Global Administrator permissions for the CIPP Service Account
+
+ An account with at minimum: Application Administrator
+ User Administrator
+
Multi-factor authentication enabled for the CIPP Service Account, with no trusted
locations or other exclusions.
From f3e3b47b9e864ff0f9e30858d71b6b60bcf36043 Mon Sep 17 00:00:00 2001
From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com>
Date: Sun, 18 Jan 2026 16:52:38 +0100
Subject: [PATCH 02/17] Updated drift management
---
src/pages/tenant/manage/drift.js | 409 +++++++++++++++++++++++++++++--
1 file changed, 387 insertions(+), 22 deletions(-)
diff --git a/src/pages/tenant/manage/drift.js b/src/pages/tenant/manage/drift.js
index 5e3d3756352d..4dea1b493dab 100644
--- a/src/pages/tenant/manage/drift.js
+++ b/src/pages/tenant/manage/drift.js
@@ -205,8 +205,10 @@ const ManageDriftPage = () => {
ComplianceStatus: detail.ComplianceStatus,
StandardValue: detail.StandardValue,
ReportingDisabled: detail.ReportingDisabled,
- expectedValue: "Compliant with template",
- receivedValue: detail.StandardValue,
+ ExpectedValue: detail.ExpectedValue,
+ CurrentValue: detail.CurrentValue,
+ expectedValue: detail.ExpectedValue || "Compliant with template",
+ receivedValue: detail.CurrentValue || detail.StandardValue,
};
})
.filter((item) => item !== null); // Filter out null items where templates weren't found
@@ -376,6 +378,45 @@ const ManageDriftPage = () => {
}
};
+ // Helper function to format differences for display
+ const formatDifferences = (differences) => {
+ if (!differences || typeof differences !== 'object') return null;
+
+ const formatted = [];
+ Object.entries(differences).forEach(([key, value]) => {
+ formatted.push({
+ property: key,
+ expected: value.expected !== undefined ? JSON.stringify(value.expected, null, 2) : 'Not set',
+ current: value.current !== undefined ? JSON.stringify(value.current, null, 2) : 'Not set',
+ });
+ });
+
+ return formatted;
+ };
+
+ // Helper function to format matching properties for compliant items
+ const formatCompliantProperties = (value) => {
+ if (!value) return null;
+
+ try {
+ const obj = typeof value === "string" ? JSON.parse(value) : value;
+
+ if (typeof obj !== 'object' || obj === null) return null;
+
+ const formatted = [];
+ Object.entries(obj).forEach(([key, val]) => {
+ formatted.push({
+ property: key,
+ value: val !== undefined ? JSON.stringify(val, null, 2) : 'Not set',
+ });
+ });
+
+ return formatted.length > 0 ? formatted : null;
+ } catch (e) {
+ return null;
+ }
+ };
+
// Helper function to format policy objects for display
const formatPolicyValue = (value) => {
if (!value) return "N/A";
@@ -466,10 +507,15 @@ const ManageDriftPage = () => {
let displayExpectedValue = deviation.ExpectedValue || deviation.expectedValue;
let displayReceivedValue = deviation.CurrentValue || deviation.receivedValue;
- // If we have JSON differences, show only the differences
+ // If we have JSON differences, format them for display
+ let formattedDifferences = null;
+ let formattedCompliantProps = null;
+
if (jsonDifferences && !isLicenseSkipped && !isActuallyCompliant) {
- displayExpectedValue = JSON.stringify(jsonDifferences, null, 2);
- displayReceivedValue = "See differences in Expected column";
+ formattedDifferences = formatDifferences(jsonDifferences);
+ } else if ((isActuallyCompliant || actualStatus === "aligned") && displayExpectedValue) {
+ // For compliant items, format the properties to show them matching
+ formattedCompliantProps = formatCompliantProperties(displayExpectedValue);
}
return {
@@ -512,10 +558,285 @@ const ManageDriftPage = () => {
)}
- {(displayExpectedValue && displayExpectedValue !== "Compliant with template") ||
- displayReceivedValue ? (
-
- {displayExpectedValue && displayExpectedValue !== "Compliant with template" && (
+ {formattedDifferences && formattedDifferences.length > 0 ? (
+
+
+ Property Differences
+
+ {formattedDifferences.map((diff, idx) => (
+
+
+ {diff.property}
+
+
+
+
+ Expected
+
+
+
+
+
+
+ {diff.expected}
+
+
+
+
+
+ Current
+
+
+
+
+
+
+ {diff.current}
+
+
+
+
+
+ ))}
+
+ ) : formattedCompliantProps && formattedCompliantProps.length > 0 ? (
+
+
+ Compliant Properties
+
+ {formattedCompliantProps.map((prop, idx) => (
+
+
+ {prop.property}
+
+
+
+
+ Expected
+
+
+
+
+
+
+ {prop.value}
+
+
+
+
+
+ Current
+
+
+
+
+
+
+ {prop.value}
+
+
+
+
+
+ ))}
+
+ ) : displayExpectedValue || displayReceivedValue ? (
+
+ {displayExpectedValue && (
{
color: "text.secondary",
textTransform: "uppercase",
letterSpacing: 0.5,
+ display: "block",
+ mb: 0.5,
}}
>
- {jsonDifferences ? "Differences" : "Expected"}
+ Expected
+ {(isActuallyCompliant || actualStatus === "aligned") && (
+
+
+
+ )}
{
fontSize: "0.8125rem",
whiteSpace: "pre-wrap",
wordBreak: "break-word",
+ color: isActuallyCompliant || actualStatus === "aligned" ? "success.dark" : "text.primary",
}}
>
- {displayExpectedValue}
+ {displayExpectedValue === "Compliant with template"
+ ? displayReceivedValue || "Compliant"
+ : displayExpectedValue}
)}
- {displayReceivedValue && !jsonDifferences && (
+ {displayReceivedValue && (
{
color: "text.secondary",
textTransform: "uppercase",
letterSpacing: 0.5,
+ display: "block",
+ mb: 0.5,
}}
>
Current
+ {(isActuallyCompliant || actualStatus === "aligned") && (
+
+
+
+ )}
{
fontSize: "0.8125rem",
whiteSpace: "pre-wrap",
wordBreak: "break-word",
+ color: isActuallyCompliant || actualStatus === "aligned" ? "success.dark" : "text.primary",
}}
>
{displayReceivedValue}
From 2c5ab0d167c57631a095b93e79e57e2c5844f158 Mon Sep 17 00:00:00 2001
From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com>
Date: Sun, 18 Jan 2026 16:52:46 +0100
Subject: [PATCH 03/17] Update compliant drift monitoring
---
src/pages/tenant/manage/drift.js | 123 +++++++++++++++++++------------
1 file changed, 77 insertions(+), 46 deletions(-)
diff --git a/src/pages/tenant/manage/drift.js b/src/pages/tenant/manage/drift.js
index 4dea1b493dab..0b3c226bc693 100644
--- a/src/pages/tenant/manage/drift.js
+++ b/src/pages/tenant/manage/drift.js
@@ -130,7 +130,7 @@ const ManageDriftPage = () => {
}
if (item.customerSpecificDeviations && Array.isArray(item.customerSpecificDeviations)) {
acc.customerSpecificDeviationsList.push(
- ...item.customerSpecificDeviations.filter((dev) => dev !== null)
+ ...item.customerSpecificDeviations.filter((dev) => dev !== null),
);
}
if (item.deniedDeviations && Array.isArray(item.deniedDeviations)) {
@@ -143,7 +143,7 @@ const ManageDriftPage = () => {
Array.isArray(item.driftSettings.ComparisonDetails)
) {
const compliantStandards = item.driftSettings.ComparisonDetails.filter(
- (detail) => detail.Compliant === true
+ (detail) => detail.Compliant === true,
)
.map((detail) => {
// Strip "standards." prefix if present
@@ -238,7 +238,7 @@ const ManageDriftPage = () => {
deniedDeviationsList: [],
alignedStandards: [],
latestDataCollection: null,
- }
+ },
);
// Transform currentDeviations into deviation items for display
@@ -380,14 +380,15 @@ const ManageDriftPage = () => {
// Helper function to format differences for display
const formatDifferences = (differences) => {
- if (!differences || typeof differences !== 'object') return null;
+ if (!differences || typeof differences !== "object") return null;
const formatted = [];
Object.entries(differences).forEach(([key, value]) => {
formatted.push({
property: key,
- expected: value.expected !== undefined ? JSON.stringify(value.expected, null, 2) : 'Not set',
- current: value.current !== undefined ? JSON.stringify(value.current, null, 2) : 'Not set',
+ expected:
+ value.expected !== undefined ? JSON.stringify(value.expected, null, 2) : "Not set",
+ current: value.current !== undefined ? JSON.stringify(value.current, null, 2) : "Not set",
});
});
@@ -400,14 +401,14 @@ const ManageDriftPage = () => {
try {
const obj = typeof value === "string" ? JSON.parse(value) : value;
-
- if (typeof obj !== 'object' || obj === null) return null;
+
+ if (typeof obj !== "object" || obj === null) return null;
const formatted = [];
Object.entries(obj).forEach(([key, val]) => {
formatted.push({
property: key,
- value: val !== undefined ? JSON.stringify(val, null, 2) : 'Not set',
+ value: val !== undefined ? JSON.stringify(val, null, 2) : "Not set",
});
});
@@ -495,13 +496,13 @@ const ManageDriftPage = () => {
const actualStatus = isActuallyCompliant
? "aligned"
: isLicenseSkipped
- ? "skipped"
- : statusOverride || deviation.Status || deviation.state;
+ ? "skipped"
+ : statusOverride || deviation.Status || deviation.state;
const actualStatusText = isActuallyCompliant
? "Compliant"
: isLicenseSkipped
- ? "Skipped - No License Available"
- : getDeviationStatusText(actualStatus);
+ ? "Skipped - No License Available"
+ : getDeviationStatusText(actualStatus);
// For skipped items, show different expected/received values
let displayExpectedValue = deviation.ExpectedValue || deviation.expectedValue;
@@ -510,7 +511,7 @@ const ManageDriftPage = () => {
// If we have JSON differences, format them for display
let formattedDifferences = null;
let formattedCompliantProps = null;
-
+
if (jsonDifferences && !isLicenseSkipped && !isActuallyCompliant) {
formattedDifferences = formatDifferences(jsonDifferences);
} else if ((isActuallyCompliant || actualStatus === "aligned") && displayExpectedValue) {
@@ -583,7 +584,9 @@ const ManageDriftPage = () => {
>
{diff.property}
-
+
{
>
{prop.property}
-
+
{
@@ -886,11 +901,14 @@ const ManageDriftPage = () => {
fontSize: "0.8125rem",
whiteSpace: "pre-wrap",
wordBreak: "break-word",
- color: isActuallyCompliant || actualStatus === "aligned" ? "success.dark" : "text.primary",
+ color:
+ isActuallyCompliant || actualStatus === "aligned"
+ ? "success.dark"
+ : "text.primary",
}}
>
- {displayExpectedValue === "Compliant with template"
- ? displayReceivedValue || "Compliant"
+ {displayExpectedValue === "Compliant with template"
+ ? displayReceivedValue || "Compliant"
: displayExpectedValue}
@@ -915,10 +933,20 @@ const ManageDriftPage = () => {
@@ -947,7 +975,10 @@ const ManageDriftPage = () => {
fontSize: "0.8125rem",
whiteSpace: "pre-wrap",
wordBreak: "break-word",
- color: isActuallyCompliant || actualStatus === "aligned" ? "success.dark" : "text.primary",
+ color:
+ isActuallyCompliant || actualStatus === "aligned"
+ ? "success.dark"
+ : "text.primary",
}}
>
{displayReceivedValue}
@@ -1011,15 +1042,15 @@ const ManageDriftPage = () => {
const deviationItems = createDeviationItems(processedDriftData.currentDeviations);
const acceptedDeviationItems = createDeviationItems(
processedDriftData.acceptedDeviations,
- "accepted"
+ "accepted",
);
const customerSpecificDeviationItems = createDeviationItems(
processedDriftData.customerSpecificDeviationsList,
- "customerspecific"
+ "customerspecific",
);
const deniedDeviationItems = createDeviationItems(
processedDriftData.deniedDeviationsList,
- "denied"
+ "denied",
);
const alignedStandardItems = createDeviationItems(processedDriftData.alignedStandards, "aligned");
@@ -1027,7 +1058,7 @@ const ManageDriftPage = () => {
const licenseSkippedItems = deviationItems.filter((item) => item.isLicenseSkipped);
const compliantFromDeviations = deviationItems.filter((item) => item.isActuallyCompliant);
const actualDeviationItems = deviationItems.filter(
- (item) => !item.isLicenseSkipped && !item.isActuallyCompliant
+ (item) => !item.isLicenseSkipped && !item.isActuallyCompliant,
);
// Combine compliant items from both sources
@@ -1249,7 +1280,7 @@ const ManageDriftPage = () => {
// Find current tenant data
const currentTenantData = currentTenantInfo.data?.find(
- (tenant) => tenant.defaultDomainName === tenantFilter
+ (tenant) => tenant.defaultDomainName === tenantFilter,
);
// Actions for the ActionsMenu
@@ -1412,7 +1443,7 @@ const ManageDriftPage = () => {
(item) =>
item.text?.toLowerCase().includes(searchQuery.toLowerCase()) ||
item.subtext?.toLowerCase().includes(searchQuery.toLowerCase()) ||
- item.standardName?.toLowerCase().includes(searchQuery.toLowerCase())
+ item.standardName?.toLowerCase().includes(searchQuery.toLowerCase()),
);
}
@@ -1650,10 +1681,10 @@ const ManageDriftPage = () => {
combinedScore === 100
? "success"
: combinedScore >= 80
- ? "warning"
- : combinedScore >= 30
- ? "warning"
- : "error"
+ ? "warning"
+ : combinedScore >= 30
+ ? "warning"
+ : "error"
}
variant="outlined"
/>
@@ -1685,7 +1716,7 @@ const ManageDriftPage = () => {
query: query,
},
undefined,
- { shallow: true }
+ { shallow: true },
);
}}
placeholder="Select a drift template..."
@@ -1729,8 +1760,8 @@ const ManageDriftPage = () => {
sortBy === "name"
? "Name"
: sortBy === "status"
- ? "Status"
- : "Category",
+ ? "Status"
+ : "Category",
value: sortBy,
}
: null
@@ -1791,7 +1822,7 @@ const ManageDriftPage = () => {
(deviation.standardName?.includes("ConditionalAccessTemplate") ||
deviation.standardName?.includes("IntuneTemplate")) &&
deviation.expectedValue ===
- "This policy only exists in the tenant, not in the template."
+ "This policy only exists in the tenant, not in the template.",
) && (