Skip to content

Add MT.1177-MT.1180: LAPS, ASR, App Control, Managed Installer Intune tests#1676

Open
OfirGavish wants to merge 22 commits into
maester365:mainfrom
OfirGavish:intune-tests-addition
Open

Add MT.1177-MT.1180: LAPS, ASR, App Control, Managed Installer Intune tests#1676
OfirGavish wants to merge 22 commits into
maester365:mainfrom
OfirGavish:intune-tests-addition

Conversation

@OfirGavish
Copy link
Copy Markdown
Contributor

@OfirGavish OfirGavish commented Apr 22, 2026

This PR adds four Intune Endpoint Security tests for Microsoft Defender controls. Tests have been renumbered to MT.1177-MT.1180 to avoid collision with upstream MT.1148-MT.1151 (Defender antivirus batch).

Tests

ID Title Service
MT.1177 Ensure LAPS Configuration Policy is properly set Account Protection
MT.1178 Ensure ASR Rules are configured correctly Attack Surface Reduction
MT.1179 Ensure App Control for Business is enabled Application Control
MT.1180 Ensure Managed Installer Rules are configured correctly Application Control

Pass criteria (per @SamErde review)

  • MT.1177 LAPS - Pass requires at least one LAPS policy meeting all of: Backup Directory = Azure AD only AND Password Complexity >= _4 AND Password Length >= 14 AND a defined Post-Authentication Action (_1/_3/_5/_11).
  • MT.1178 ASR - Pass requires every rule in the Microsoft Defender ASR Standard Protection baseline (Block abuse of vulnerable signed drivers, Block credential stealing from LSASS, Block persistence through WMI event subscription) to be in Block or Audit mode across the union of all policies. Additional rules listed for visibility but do not affect the result.
  • MT.1179 App Control - Pass requires at least one policy to be enforcing (audit mode disabled) AND have either built-in controls selected or a non-empty uploaded XML payload. Audit-only policies and empty XML uploads are reported but do not pass.
  • MT.1180 Managed Installer - Pass requires at least one App Control policy in Enforce mode AND with Managed Installer enabled. Managed Installer on an audit-only App Control is reported but does not pass.

Files

  • powershell/public/maester/intune/Test-MtIntuneLAPSConfiguration.ps1
  • powershell/public/maester/intune/Test-MtIntuneASRRules.ps1
  • powershell/public/maester/intune/Test-MtIntuneAppControl.ps1
  • powershell/public/maester/intune/Test-MtIntuneManagedInstallerRules.ps1
  • tests/Maester/Intune/Test-MtIntunePlatform.Tests.ps1 (4 It blocks)
  • tests/maester-config.json (4 entries)
  • website/docs/tests/maester/MT.1177.md ... MT.1180.md
  • powershell/Maester.psd1 (4 function exports)

Validation

  • PowerShell parser: clean
  • PSScriptAnalyzer (Warning + Error): 0 issues across all 4 test files
  • Test-ModuleManifest on Maester.psd1: passes
  • maester-config.json: parses

Required Graph permissions

  • DeviceManagementConfiguration.Read.All

Notes

The remaining Maester.psd1 and tests/maester-config.json mergeable=CONFLICTING is positional only (function export ordering / config insert position) caused by upstream churn since the fork branched. Happy to rebase or take a maintainer suggestion on resolution strategy.

Ubuntu and others added 4 commits April 17, 2026 19:42
…tests

- MT.1124: Ensure LAPS policy backs up passwords to Entra ID
- MT.1125: Ensure ASR rules configured in Block/Audit mode
- MT.1126: Ensure App Control for Business is configured
- MT.1127: Ensure Managed Installer enabled in App Control

Changes:
- Move functions from functions/ to powershell/public/maester/intune/
- Add companion .md remediation files for each test
- Add FunctionsToExport entries to Maester.psd1
- Renumber from MT.1200-1203 to MT.1124-1127
- PSScriptAnalyzer clean, pester.ps1 5230/5230 passed
Move MT.1124-1127 It blocks into the shared Describe block in
Test-MtIntunePlatform.Tests.ps1, matching the upstream Maester pattern.
Remove the 4 separate .Tests.ps1 files.
@OfirGavish OfirGavish requested review from a team as code owners April 22, 2026 20:26
@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented Apr 22, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds four new Maester Intune Endpoint Security tests (MT.1148–MT.1151) that query deviceManagement/configurationPolicies and validate specific CSP-backed settings for LAPS, ASR Rules, App Control for Business, and Managed Installer, along with remediation docs and module/test wiring.

Changes:

  • Added 4 new Intune test functions plus corresponding remediation markdown docs.
  • Exported the new functions from the PowerShell module manifest.
  • Added 4 new Pester It blocks to execute the tests in the Intune platform suite.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tests/Maester/Intune/Test-MtIntunePlatform.Tests.ps1 Adds MT.1148–MT.1151 Pester entries
powershell/public/maester/intune/Test-MtIntuneLAPSConfiguration.ps1 New test for LAPS Entra ID password backup
powershell/public/maester/intune/Test-MtIntuneLAPSConfiguration.md New remediation guidance for LAPS policy
powershell/public/maester/intune/Test-MtIntuneASRRules.ps1 New test to evaluate ASR rule modes via configurationPolicies settings
powershell/public/maester/intune/Test-MtIntuneASRRules.md New remediation guidance for ASR rules
powershell/public/maester/intune/Test-MtIntuneAppControl.ps1 New test to validate presence/config of App Control for Business policies
powershell/public/maester/intune/Test-MtIntuneAppControl.md New remediation guidance for App Control for Business
powershell/public/maester/intune/Test-MtIntuneManagedInstallerRules.ps1 New test to verify Managed Installer is enabled in App Control policies
powershell/public/maester/intune/Test-MtIntuneManagedInstallerRules.md New remediation guidance for Managed Installer
powershell/Maester.psd1 Exports the 4 new functions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/Maester/Intune/Test-MtIntunePlatform.Tests.ps1 Outdated
Comment thread tests/Maester/Intune/Test-MtIntunePlatform.Tests.ps1 Outdated
Comment thread tests/Maester/Intune/Test-MtIntunePlatform.Tests.ps1 Outdated
Comment thread powershell/public/maester/intune/Test-MtIntuneAppControl.md Outdated
Comment thread powershell/public/maester/intune/Test-MtIntuneManagedInstallerRules.md Outdated
Comment thread powershell/public/maester/intune/Test-MtIntuneASRRules.md Outdated
Comment thread powershell/public/maester/intune/Test-MtIntuneASRRules.ps1 Outdated
SamErde and others added 2 commits April 23, 2026 13:23
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
- ASR test: align Because text with Block/Audit acceptance criteria

- Managed Installer test: clarify Because text to specific MI requirement

- ASR.md: document Warn as a fourth supported mode (informational only)

- ASR.ps1: do not treat Warn as an active rule for pass criteria

- AppControl.md / ManagedInstallerRules.md: fix portal link to Application control blade

- maester-config.json: add MT.1148-MT.1151 severity/title entries
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread powershell/public/maester/intune/Test-MtIntuneLAPSConfiguration.ps1 Outdated
Comment thread powershell/public/maester/intune/Test-MtIntuneASRRules.ps1 Outdated
@SamErde
Copy link
Copy Markdown
Contributor

SamErde commented Apr 25, 2026

I love the amount of detail in this PR description, @OfirGavish! What did you generate that summary with? Did you use our new agent skill or your own prompt?

@SamErde
Copy link
Copy Markdown
Contributor

SamErde commented Apr 25, 2026

Thank you for this fantastic contribution! 🙌

@OfirGavish — this is a really well-executed PR. Adding LAPS, ASR Rules, App Control for Business, and Managed Installer coverage in one shot fills a meaningful gap in Maester's Intune Endpoint Security story. The code quality is high, the companion documentation is thorough, and the remediation guidance is actionable. Great work.

I've done a detailed review below. There's one blocker to address before merging, a couple of things worth double-checking, and a few minor suggestions for polish.

Full Disclosure: AI helped me write these detailed suggestions based on our custom agent skill for creating and validating Maester tests. 😉


🔴 Blocking — Website documentation pages are missing

The four helper functions reference public docs URLs in their .LINK comment-based help:

https://maester.dev/docs/tests/MT.1148
https://maester.dev/docs/tests/MT.1149
https://maester.dev/docs/tests/MT.1150
https://maester.dev/docs/tests/MT.1151

…but the corresponding files (website/docs/tests/maester/MT.1148.md through MT.1151.md) aren't included in this PR. The companion .md files that drive the in-report descriptions are all present and excellent — it's just the public website doc pages that need to be added.

website/docs/tests/maester/MT.1123.md (the BitLocker test added recently) is a great template to follow. Each page needs YAML frontmatter and three sections: Description, How to fix, and Learn more. The content is essentially already written in the companion .md files — it mostly needs to be reorganised into the website format.

Example frontmatter for MT.1148:

---
title: MT.1148 - Ensure LAPS Configuration Policy is properly set
description: Checks Intune Endpoint Security Account Protection policies for Windows LAPS profiles that back up local administrator passwords to Microsoft Entra ID.
slug: /tests/MT.1148
sidebar_class_name: hidden
---

🟡 Important — AutoAccountMgmt may be reading from the wrong value type

In Test-MtIntuneLAPSConfiguration.ps1, the Automatic Account Management setting is read as a choiceSettingValue:

$val = $setting.settingInstance.choiceSettingValue.value
$policyDetail.AutoAccountMgmt = if ($val -like '*_true') { 'Enabled' } else { 'Disabled' }

The device_vendor_msft_laps_policies_automaticaccountmanagementenabled setting is a boolean toggle. In the Intune CSP, boolean settings are typically returned as simpleSettingValue (true/false) rather than a choiceSettingValue. If the API responds via simpleSettingValue, then choiceSettingValue will be $null, $val will be $null, and the -like '*_true' test will silently fail — causing every policy to report AutoAccountMgmt = 'Disabled' even when it's actually enabled.

This is informational in the report only (pass/fail is driven by BackupDirectory), so it won't cause incorrect test results, but it would show misleading data to users.

Suggested fix:

if ($defId -eq $autoAccountMgmtId) {
    $simpleVal = $setting.settingInstance.simpleSettingValue.value
    $choiceVal = $setting.settingInstance.choiceSettingValue.value
    $val = if ($null -ne $simpleVal) { $simpleVal } else { $choiceVal }
    $policyDetail.AutoAccountMgmt = if ($val -eq $true -or $val -like '*_true') { 'Enabled' } else { 'Disabled' }
}

If you have a live tenant with this setting configured, it would be great to verify which value type the API actually returns — if choiceSettingValue is correct, no change is needed.


🟡 Important — It block titles are missing the See link

The Maester convention for It block titles is:

"MT.XXXX: Description. See https://maester.dev/docs/tests/MT.XXXX"

All four new It blocks omit the See ... link:

# Current
It "MT.1148: Ensure LAPS Configuration Policy is properly set" -Tag "MT.1148" {

# Expected
It "MT.1148: Ensure LAPS Configuration Policy is properly set. See https://maester.dev/docs/tests/MT.1148" -Tag "MT.1148" {

I can see the older tests in the same file (MT.1053MT.1123) also don't include the link, so you're in good company with existing patterns. If the maintainers are happy to let this slide for consistency with those existing tests, that's fine — but since you're already adding the website docs pages, it's a great opportunity to also add the links here.


🟢 Suggestions (non-blocking)

Pass messages don't open with "Well done." The Maester style guide says pass result messages should begin with "Well done.". Current pass messages read like:

"At least one LAPS policy backs up passwords to **Entra ID**."

Consistent phrasing would be:

"Well done. At least one LAPS policy backs up passwords to **Entra ID**."

This is also missing from the existing Test-MtBitLockerFullDiskEncryption.ps1, so it's not a regression — but worth fixing here.


Missing Test-MtConnection Graph guard — All four functions jump straight to Get-MtLicenseInformation without first checking whether a Graph connection exists. The recommended pattern is:

if (!(Test-MtConnection Graph)) {
    Add-MtTestResultDetail -SkippedBecause NotConnectedGraph
    return $null
}

This pre-existing gap exists across all the other Intune helpers as well, so it's not something you introduced. I'll open a separate issue to track adding this consistently to the Intune module — no need to hold up this PR for it.


BackupDirectory loop is missing a break — The foreach over $backupDirectoryLabels.Keys continues iterating even after a match is found. Since _0, _1, and _2 are mutually exclusive, this is harmless, but adding a break after the if ($suffix -eq '_1') block would be more precise.


ASR Warn mode has no aggregate count in the report — The per-rule table correctly labels Warn mode rules, but the policy summary line only shows Block, Audit, and Disabled counts. Adding a $warnCount and including it in the summary line (e.g., "5 Block, 3 Audit, 2 Warn, 9 Disabled") would make the report more informative.


✅ What's excellent in this PR

  • All four FunctionsToExport entries added to Maester.psd1
  • maester-config.json severity entries for all four test IDs ✅
  • All four companion .md files — detailed, well-written, end with %TestResult%, include direct admin portal links ✅
  • Invoke-MtGraphRequest used throughout (not Invoke-MgGraphRequest or Get-Mg*) ✅
  • License check (Get-MtLicenseInformation -Product Intune) before every API call ✅
  • try/catch error handling with Add-MtTestResultDetail -SkippedBecause Error in the catch block ✅
  • [CmdletBinding()], [OutputType([bool])], full comment-based help in all four functions ✅
  • [SuppressMessageAttribute('PSUseSingularNouns')] correctly applied to ASRRules and ManagedInstallerRules
  • Null check pattern in all four It blocks ✅
  • API filter scoped by templateFamily to avoid false matches across policy types ✅
  • No hardcoded tenant-specific values or GUIDs ✅
  • ASR rule GUID-to-friendly-name mapping is comprehensive and accurate ✅
  • The App Control nested child setting traversal is correctly implemented ✅
  • The audit-only warning notes in the report output are a nice touch ✅

Once the four website docs pages are added, this is ready to go. Thanks again for putting this together — these are exactly the kinds of Endpoint Security checks that Maester needs more of! 🚀

@OfirGavish
Copy link
Copy Markdown
Contributor Author

Thank you Sam, I used my own personal prompt, working with GHCP on VSCode with Opus 4.6 mostly

@OfirGavish OfirGavish requested a review from a team as a code owner April 25, 2026 20:24
- Add website docs pages MT.1148-MT.1151 (blocking item)

- Add Test-MtConnection Graph guard to all 4 functions

- Fix LAPS AutoAccountMgmt to handle both simpleSettingValue and choiceSettingValue

- Add 'See https://maester.dev/docs/tests/MT.XXXX' links to all 4 It block titles

- Prefix pass result messages with 'Well done.' per Maester style guide

- Add break after BackupDirectory suffix match in LAPS test

- Track and display Warn rule count in ASR policy summary
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread powershell/public/maester/intune/Test-MtIntuneLAPSConfiguration.ps1 Outdated
- LAPS: surface PostAuthDelay in the per-policy results table (was parsed but unused)

- ASR: update comment-based help to list all four supported modes (Block/Audit/Warn/Disabled), matching the implementation and the .md doc
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread powershell/public/maester/intune/Test-MtIntuneASRRules.ps1 Outdated
The condition matches policies with no Block rules and >=1 Audit rule (which may also include Warn/Disabled rules), so the wording 'Audit mode only' was misleading. Reworded to accurately describe what the condition checks.
@SamErde
Copy link
Copy Markdown
Contributor

SamErde commented May 11, 2026

Thanks so much for putting this together — these Intune checks fill an important gap, and the PR is already in good shape structurally. I reviewed it with the Maester test checklist and the maester-test-expert guidance: the split-file pattern, function exports, test IDs, config metadata, companion docs, website docs, Graph connection checks, Intune license checks, Invoke-MtGraphRequest usage, and Pester null-check patterns are all largely aligned. Local validation also passed.

I do think a few logic issues should be tightened before this is production-ready, mainly to avoid false passes/false failures in tenant assessments:

  1. MT.1150 may not recognize uploaded XML App Control policies

    In Test-MtIntuneAppControl.ps1, the build option check appears to look for *_upload_policy_selected. Intune App Control for Business uses an uploaded XML policy path, so this may need to recognize the XML upload value as well. Otherwise, a tenant with a valid uploaded App Control/WDAC XML policy could be reported as failing.

    Potential solution: update the build-options matching to include the uploaded XML option, and ideally add a small mocked unit case that proves both built-in controls and uploaded XML policies pass.

  2. MT.1150 currently passes audit-only App Control policies

    The test title says App Control for Business is enabled, but the helper returns success even when all matching policies are in audit mode. Audit mode is useful for rollout, but it does not enforce application control, so this can overstate the tenant's protection level.

    Potential solution: either require at least one configured policy to be in enforce mode for the current title/pass criteria, or rename/reword the test and docs to clearly state that audit-mode policies satisfy the check. If audit mode remains a pass, consider lowering severity or marking the result as needing follow-up when no enforcing policy exists.

  3. MT.1148 only enforces LAPS backup location, not the full “properly set” configuration

    Test-MtIntuneLAPSConfiguration.ps1 parses password complexity, password length, post-auth actions, delay, and automatic account management, but the pass/fail decision only checks whether backup is set to Entra ID. That means a weak LAPS policy could pass even though the title/docs imply a broader configuration assessment.

    Potential solution: either tighten the pass criteria to require the documented minimums, such as Entra ID backup plus acceptable password complexity/length and post-auth behavior, or narrow the test title/docs to say it only verifies Entra ID backup for Windows LAPS.

  4. MT.1149 may be too permissive for “ASR Rules are configured correctly”

    Test-MtIntuneASRRules.ps1 passes if any single ASR rule is in Block or Audit mode. A tenant with one audited rule and all other ASR rules disabled would pass, which seems weaker than the current title and remediation guidance suggest.

    Potential solution: define a minimum expected ASR baseline, for example a required set/count of rules in Block or Audit mode, or reframe the test as “at least one ASR rule is configured” if that is the intended control.

  5. MT.1151 does not account for audit-only App Control policies

    Test-MtIntuneManagedInstallerRules.ps1 reports App Control audit/enforce state, but the pass/fail result only checks whether Managed Installer is enabled. If the associated App Control policy is audit-only, the check can pass even though the production enforcement value is limited.

    Potential solution: require Managed Installer on at least one enforcing App Control policy, or clearly document that the check only validates Managed Installer configuration regardless of enforcement state and surface audit-only policies as an investigate/warning outcome.

One more practical blocker: GitHub currently reports the PR as conflicting, so it will also need a rebase or merge update before it can be merged.

Again, thank you for the contribution — the scaffolding and documentation are very close. Once the pass criteria match the stated security outcomes and the conflict is resolved, this should be much easier to approve confidently.

Copy link
Copy Markdown
Contributor

@SamErde SamErde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comment and suggestions. Thanks again! 🙂

Upstream merill commit 7ebade5 (Added test meta data, May 2 2026)
claimed MT.1148-MT.1151 for Microsoft Defender antivirus tests:

  MT.1148 Archive Scanning should be enabled
  MT.1149 Behavior Monitoring should be enabled
  MT.1150 Cloud Protection should be enabled
  MT.1151 Email Scanning should be enabled

Renumber this PR's Intune Endpoint Security tests to the next
available contiguous range MT.1177-MT.1180 to resolve the add/add
conflicts on website/docs/tests/maester/MT.115X.md and the title
collisions in tests/maester-config.json.

  MT.1148 -> MT.1177 LAPS Configuration Policy
  MT.1149 -> MT.1178 ASR Rules
  MT.1150 -> MT.1179 App Control for Business
  MT.1151 -> MT.1180 Managed Installer
MT.1177 LAPS: pass now requires Entra backup AND complexity >= _4 AND length >= 14 AND a defined post-auth action (per-policy boolean tracking, Compliant column added).

MT.1178 ASR: pivot to Microsoft Defender ASR Standard Protection baseline. Pass now requires every baseline rule (Block abuse of exploited vulnerable signed drivers, Block credential stealing from LSASS, Block persistence through WMI event subscription) to be in Block or Audit mode across the union of all policies. Additional rules still listed for visibility.

MT.1179 App Control: detect uploaded XML payload (simpleSettingValue under upload_policy_selected). Pass now requires at least one policy to be enforcing (audit mode disabled) AND have either built-in controls or a non-empty XML upload. Audit-only policies and empty XML uploads are reported but no longer pass.

MT.1180 Managed Installer: pass now requires at least one App Control policy to be in Enforce mode AND have Managed Installer enabled. Managed Installer on an audit-only policy is reported but no longer passes, since the underlying App Control is not blocking.

Website docs (MT.1177-1180.md) updated to document the new pass criteria.
@OfirGavish OfirGavish changed the title Add MT.1148-MT.1151: LAPS, ASR, App Control, Managed Installer Intune tests Add MT.1177-MT.1180: LAPS, ASR, App Control, Managed Installer Intune tests May 12, 2026
@OfirGavish
Copy link
Copy Markdown
Contributor Author

Hi @SamErde - thanks again for the detailed review. Pushing the following in 3a19a95d (on top of the afb3b56f renumber commit):

Renumber: MT.1148-MT.1151 -> MT.1177-MT.1180

Upstream 7ebade57 (Defender antivirus batch) claimed MT.1148-1151, so I renumbered the four tests, It blocks, maester-config.json IDs, and website/docs/tests/maester/MT.117x.md files to clear the collision.

Logic gaps from your second-round review

  1. MT.1177 LAPS - "title says properly set but only checks BackupDirectory"
    Pass criteria tightened: at least one LAPS policy must meet all of:

    • Backup Directory = Azure AD only (_1)
    • Password Complexity >= _4 (large + small + numbers + special) - or _8 (improved)
    • Password Length >= 14
    • Post-Authentication Action defined (_1/_3/_5/_11 - reset / reset+logoff / reset+reboot / disabled-with-rotation)
      Per-policy boolean tracking + a Compliant column added to the result table.
  2. MT.1178 ASR - "passes if any single rule is Block/Audit"
    Pivoted to the published Microsoft Defender ASR Standard Protection baseline - the minimum recommended set for initial deployment:

    • Block abuse of exploited vulnerable signed drivers
    • Block credential stealing from LSASS
    • Block persistence through WMI event subscription
      Pass requires every baseline rule to be in Block or Audit across the union of all ASR policies. Additional rules are still listed for visibility but do not affect the result. Baseline rules in Audit-only mode trigger an info note recommending Block transition.
  3. MT.1179 App Control - "missing XML upload value detection"
    Added matcher for the device_vendor_msft_policy_config_applicationcontrolv2_policy simpleSettingValue (the actual XML payload nested under upload_policy_selected). New Policy XML column in the result table shows Present (N chars) / Empty / N/A. Upload-mode policies with empty payloads no longer count as configured.

  4. MT.1179 App Control - "passes audit-only policies"
    Pass criteria tightened: at least one policy must be enforcing (audit mode disabled) AND have either built-in controls selected OR a non-empty XML upload. Audit-only policies and empty-XML uploads are still reported but no longer satisfy the test.

  5. MT.1180 Managed Installer - "passes when underlying App Control is audit-only"
    Pass criteria tightened: at least one App Control policy must be in Enforce mode AND have Managed Installer enabled. Managed-Installer-on-audit-only is now reported as "underlying App Control is in Audit mode, so deployed apps are not actively trusted" and does not pass.

Validation

  • PowerShell parser: clean on all 4 test files
  • PSScriptAnalyzer (Warning + Error): 0 issues
  • Test-ModuleManifest on Maester.psd1: passes
  • maester-config.json: parses

Note on remaining mergeable=CONFLICTING

The renumbering cleared the file-rename collision on the website docs. The remaining conflict is positional in Maester.psd1 (function export ordering) and tests/maester-config.json (insert position) due to broader upstream churn since the fork branched. Happy to rebase or follow whatever resolution approach you prefer.

@SamErde
Copy link
Copy Markdown
Contributor

SamErde commented May 12, 2026

@copilot resolve the merge conflicts in this pull request

Resolves conflicts in powershell/Maester.psd1 and tests/maester-config.json by taking upstream's version and re-inserting the four MT.1177-MT.1180 entries (LAPS, ASR, App Control, Managed Installer).

Validation:
- PowerShell parser: clean on all 4 test files
- PSScriptAnalyzer (Warning + Error): 0 issues
- Test-ModuleManifest: passes (now reports v2.0.0 from upstream)
- maester-config.json: parses
@OfirGavish
Copy link
Copy Markdown
Contributor Author

Follow-up: I went ahead and rebased / merged upstream/main into the PR branch (commit be449a6a). The only real conflicts were the two positional ones in powershell/Maester.psd1 (function exports) and tests/maester-config.json (test entries); both resolved by taking upstream's version and re-inserting the four MT.1177-MT.1180 entries alphabetically / sequentially.

GitHub now reports the PR as MERGEABLE. Validation re-run after the merge:

  • PowerShell parser: clean on all 4 test files
  • PSScriptAnalyzer (Warning + Error): 0 issues
  • Test-ModuleManifest: passes (now resolves against upstream's v2.0.0 manifest)
  • maester-config.json: parses

Ready for another look whenever you have time.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 10 comments.

Comment thread powershell/public/maester/intune/Test-MtIntuneLAPSConfiguration.md Outdated
Comment thread powershell/public/maester/intune/Test-MtIntuneASRRules.md Outdated
Comment thread powershell/public/maester/intune/Test-MtIntuneAppControl.md Outdated
Comment thread powershell/public/maester/intune/Test-MtIntuneManagedInstallerRules.md Outdated
Comment thread website/docs/tests/maester/MT.1177.md
Comment thread website/docs/tests/maester/MT.1178.md
Comment thread website/docs/tests/maester/MT.1179.md
Comment thread website/docs/tests/maester/MT.1180.md
Comment thread powershell/public/maester/intune/Test-MtIntuneASRRules.ps1 Outdated
Comment thread powershell/public/maester/intune/Test-MtIntuneManagedInstallerRules.ps1 Outdated
Code fixes:
- Test-MtIntuneASRRules.ps1: remove duplicate .EXAMPLE block.
- Test-MtIntuneManagedInstallerRules.ps1: gate pass on active App Control
  (built-in controls OR non-empty uploaded XML). An enforce-mode upload
  policy with empty XML + MI enabled no longer falsely passes. Mirrors
  the active-control gate used by MT.1179. Report empty-XML MI policies
  alongside audit-mode MI policies in failure output. Expand result
  table with Build Options + Policy XML columns. Update .DESCRIPTION
  and .EXAMPLE accordingly.

Companion docs (powershell/public/maester/intune/*.md):
- LAPS: pass now requires Entra backup AND complexity >= _4 AND
  length >= 14 AND a defined post-auth action.
- ASRRules: pass now requires every Standard Protection baseline
  rule (drivers, LSASS, WMI persistence) in Block or Audit across
  the union of all ASR policies. Links to MS Defender baseline.
- AppControl: pass now requires Enforce mode AND active control
  (built-in or non-empty uploaded XML).
- ManagedInstallerRules: pass now requires Enforce mode AND MI
  enabled AND active control.

Website docs:
- Regenerated MT.1177.md, MT.1178.md, MT.1179.md, MT.1180.md via
  website/scripts/generate-test-docs.mjs so they reflect the
  authoritative companion .md content (no longer hand-authored).
@OfirGavish
Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review! I've pushed 1a1ffd7e addressing all 10 inline comments:

Code (2)

  • Test-MtIntuneASRRules.ps1: removed the duplicate .EXAMPLE block.
  • Test-MtIntuneManagedInstallerRules.ps1: added an active-control gate so an enforce-mode upload policy with an empty XML payload + MI enabled no longer falsely passes. Pass now requires MIEnabled AND Enforcing AND HasActiveControl (built-in controls OR non-empty uploaded XML) — mirrors the active-control gate already used by MT.1179. The failure branch now reports $emptyXmlMI alongside $auditMI, and the result table gained Build Options + Policy XML columns.

Companion .md docs (4) — rewrote the pass-criteria sections so they match the tightened logic:

  • LAPS: pass requires Entra backup AND complexity ≥ _4 AND length ≥ 14 AND a defined post-auth action.
  • ASR Rules: pass requires every Standard Protection baseline rule (vulnerable signed drivers, LSASS credential theft, WMI persistence) in Block or Audit across the union of all ASR policies, with a link to the MS Defender deployment guide.
  • App Control: pass requires Enforce mode AND active control.
  • Managed Installer: pass requires Enforce mode AND MI enabled AND active control.

Website docs (4)MT.1177.mdMT.1180.md are no longer hand-authored; regenerated via website/scripts/generate-test-docs.mjs so they pick up the corrected companion content automatically. (The 377 other "stale" files reported by --check are pre-existing upstream drift unrelated to this PR, so I left them alone.)

Validation: parser clean, PSScriptAnalyzer clean for all four .ps1 files, Test-ModuleManifest OK, tests/maester-config.json parses, and generate-test-docs.mjs --check reports no drift for MT.1177–1180.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 8 comments.

Comment thread powershell/public/maester/intune/Test-MtIntuneLAPSConfiguration.ps1
Comment thread powershell/public/maester/intune/Test-MtIntuneLAPSConfiguration.md Outdated
Comment thread tests/maester-config.json
Comment thread website/docs/tests/maester/MT.1177.md Outdated
Comment thread website/docs/tests/maester/MT.1178.md Outdated
Comment thread website/docs/tests/maester/MT.1179.md Outdated
Comment thread website/docs/tests/maester/MT.1180.md Outdated
Comment thread powershell/public/maester/intune/Test-MtIntuneManagedInstallerRules.md Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.

Comment thread website/docs/tests/maester/MT.1177.md Outdated
Comment thread website/docs/tests/maester/MT.1178.md Outdated
Comment thread website/docs/tests/maester/MT.1179.md Outdated
Comment thread website/docs/tests/maester/MT.1180.md Outdated
Comment thread powershell/public/maester/intune/Test-MtIntuneLAPSConfiguration.md
Issue 1 — Duplicated remediation/related-links sections in MT.1177-1180
- Root cause: the website doc generator's dedup check
  (renderTestPage in website/scripts/generate-test-docs.mjs)
  compares the raw companion .md (CRLF on Windows) against the
  extracted Remediation/Related Links sections (which extract()
  normalizes to LF by splitting on /\r?\n/ and joining with \n).
  Whenever the companion .md is checked out with CRLF endings,
  String.prototype.includes returns false and the generator emits
  both copies (inside Overview AND as separate ## sections).
- Fix: normalize line endings of the four Intune companion .md
  files to LF on disk so the dedup check succeeds regardless of
  platform. Regenerated MT.1177-1180.md no longer have duplicated
  ## Remediation / ## Related Links blocks.

Issue 2 — LAPS `_11` label inconsistency
- Companion .md previously labelled `_11` as "disabled-with-rotation"
  while Test-MtIntuneLAPSConfiguration.ps1:156 reports it as
  "Reset password + logoff + terminate processes". Aligned the .md
  wording (and the other suffix labels) to the function's output.

Also: merge upstream/main to clear the BEHIND status.
@OfirGavish
Copy link
Copy Markdown
Contributor Author

Thanks for the second pass! Pushed c57e0b83 addressing all 5 comments and merged upstream/main (a70a9c1c) to clear the BEHIND state.

1. Duplicated Remediation / Related Links in MT.1177–1180

You were right that the generated pages had both #### Remediation action / #### Related links inside Overview and ## Remediation / ## Related Links later in the page, unlike MT.1123.

Root cause is in the dedup logic in website/scripts/generate-test-docs.mjs (renderTestPage):

if (test.remediation && !test.markdown.includes(test.remediation)) { ... }
if (test.relatedLinks && !test.markdown.includes(test.relatedLinks)) { ... }

test.markdown is the companion .md content as read from disk (CRLF on Windows checkouts thanks to core.autocrlf=true), while test.remediation / test.relatedLinks are produced by extractSection, which splits on /\r?\n/ and joins with \n — i.e. always LF. So includes() returns false whenever the companion .md is checked out with CRLF, and the generator emits both copies. (MT.1123 is fine because the checked-in version was generated on a LF host and never regenerated on Windows; if you regenerate it on a Windows checkout you'll see the same duplication.)

Fix in this PR: normalize the four Intune companion .md files (LAPS / ASR / AppControl / ManagedInstaller) to LF on disk so the dedup check succeeds on any platform. Regenerated MT.1177–1180 no longer have the duplicated ## Remediation / ## Related Links blocks. Confirmed via node website/scripts/generate-test-docs.mjs --check — no drift reported for our four pages.

A proper fix to the generator itself (e.g. normalizing line endings before the includes() check) probably belongs in a separate upstream PR since it would affect every other suite that may share this pattern. Happy to open one if you'd like.

2. LAPS _11 label

You're right — the docs said "disabled-with-rotation" while Test-MtIntuneLAPSConfiguration.ps1:156 reports _11 as "Reset password + logoff + terminate processes". Aligned the wording (and made _1/_3/_5 labels match the function's output too) in Test-MtIntuneLAPSConfiguration.md.

Validation: parser clean, PSSA clean, Test-ModuleManifest OK, maester-config.json parses, generator --check reports no drift for MT.1177–1180 or the four companion .md files.

@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented May 27, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

OfirGavish and others added 3 commits May 28, 2026 00:38
Three remaining items from the Copilot review:

1. **LAPS PasswordComplexity wording** (Test-MtIntuneLAPSConfiguration.md / MT.1177):
   The pass-criteria paragraph said "complexity >= `_4`" which is technically
   ambiguous because the Intune Settings Catalog only exposes `_1`..`_4` plus
   the newer `_8` ("improved 4-class") choice — there is no `_5`..`_7`. The
   implementation already accepts exactly `_4` or `_8` (which together cover
   every value that satisfies the 4-character-class requirement). Tightened
   the docs wording to "complexity is `_4` or `_8`" and added a one-line
   note explaining why those are the only two valid choices, so the docs
   match the code exactly.

2. **Managed Installer remediation steps** (Test-MtIntuneManagedInstallerRules.md / MT.1180):
   The remediation list only said "enable Trust apps from managed installer".
   The test (after the previous tightening) also requires the policy to be in
   Enforce mode (Audit only = Disabled) AND to have an active control
   (Built-in controls selected OR a non-empty uploaded XML payload). Updated
   the remediation steps to call out both requirements explicitly so users
   following the steps actually end up with a passing configuration.

3. **Stale test indexes** (`website/docs/tests/readme.md`,
   `website/docs/tests/maester/readme.md`, `website/docs/tests/tags/readme.md`):
   The generated indexes did not include MT.1177-1180. Regenerated via
   `npm --prefix website run generate-test-docs`. The three index pages now
   list the four new tests and the Maester count is bumped from 144 to 148.

Notes:
- Only files actually relevant to this PR are included. Other generated
  pages in `website/docs/tests/` show up as "stale" on Windows due to the
  pre-existing CRLF/LF dedup bug in `generate-test-docs.mjs` that I called
  out in the previous reply; those are intentionally left alone and a
  separate upstream fix to the generator would clear them globally.

Validation:
- PSSA Warning,Error: clean on all four Intune test scripts.
- PowerShell parser: clean.
- Test-ModuleManifest: OK (v2.0.0, 396 exported functions).
- `tests/maester-config.json`: parses OK.
- `generate-test-docs.mjs --check`: no drift reported for MT.1177-1180 or
  the three regenerated index pages.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants