microsoft / microsoft/CSS-Exchange
[Work Item] Health Checker: Detect Exchange Well Known Security Groups with incorrect GroupType (non-Universal)
Nobody has claimed this yet.
- Dominant language
- PowerShell
- Stars
- 1.3k
- Forks
- 395
- Avg merge
- 14h 7m
- Merged PRs (30d)
- 5
Description
Describe the problem
Exchange Well Known Security Groups (e.g., Organization Management, Exchange Servers, Exchange Trusted Subsystem) are required to be Universal Security Groups for RBAC to function correctly. If an administrator or tool changes the group type (e.g., to Global or Domain Local), RBAC breaks and Exchange operations fail with permission errors.
Health Checker currently collects these groups via Get-ExchangeWellKnownSecurityGroups → Get-ExchangeOtherWellKnownObjects but only retrieves WellKnownName, WellKnownGuid, DistinguishedName, RawValue, and SID. GroupType is not collected or checked.
What needs to change
1. Data Collection — Add GroupType property
Get-ExchangeWellKnownSecurityGroups.ps1 currently queries LDAP for objectSid only. It should also retrieve the groupType attribute:
# Current (line 27-28):
$entry = [ADSI]("LDAP://$($wkObject.DistinguishedName)")
$wkObject | Add-Member -MemberType NoteProperty -Name SID -Value (...)
# Proposed: also collect groupType
$groupTypeValue = $entry.Properties["groupType"].Value
$wkObject | Add-Member -MemberType NoteProperty -Name GroupType -Value $groupTypeValue
The groupType attribute is a bitmask:
-2147483640= Universal Security Group (0x80000008) — expected-2147483646= Global Security Group (0x80000002) — problem-2147483644= Domain Local Security Group (0x80000004) — problem
2. Analyzer — Check GroupType and warn
In Invoke-AnalyzerExchangeInformation.ps1, after the existing membership checks (lines 315-408), add a new check that verifies all Well Known Security Groups have the correct Universal groupType:
$universalSecurityGroup = -2147483640 # 0x80000008
$wrongTypeGroups = $HealthServerObject.OrganizationInformation.WellKnownSecurityGroups |
Where-Object { $null -ne $_.GroupType -and $_.GroupType -ne $universalSecurityGroup }
if ($wrongTypeGroups.Count -gt 0) {
# Display Red warning for each group with wrong type
foreach ($group in $wrongTypeGroups) {
# Map groupType value to friendly name
# Show: "Organization Management - GroupType: Global (expected: Universal)"
}
}
3. Investigate RBAC impact
Before implementing, test the following scenarios on a lab server and document what breaks:
- Change
Organization Managementfrom Universal to Global — verify RBAC failure behavior - Change
Exchange Serversfrom Universal to Global — verify service impact - Change
Exchange Trusted Subsystemfrom Universal to Global — verify permission failures - Verify whether
TokenGroupsGlobalAndUniversalcount changes when groups are converted - Document exact error messages users see when RBAC breaks from this
4. Pester tests
- Update
GetExchangeWellKnownSecurityGroups.xmlmock data to includeGroupTypeproperty for all 19 groups - Add SE Main assertion:
"Exchange Security Groups GroupType"="Passed"(all Universal) - Add SE Scenario test with a mock where one or more groups have wrong GroupType
- Override mock with modified data where
Organization Managementhas GroupType =-2147483646(Global) - Assert Red warning with group name and expected vs actual type
- Override mock with modified data where
- Consider adding a dedicated unit test file for the GroupType validation logic
5. Related data collection
Consider whether to also collect and display:
-
membercount for key groups (helps identify empty groups) -
managedByattribute (identifies who owns the group) - Whether the group is in the expected OU/container
Current code references
- Data Collection:
Diagnostics\HealthChecker\DataCollection\OrganizationInformation\Get-ExchangeWellKnownSecurityGroups.ps1(lines 27-28 — LDAP query) - Well Known Object Mapping:
Shared\ActiveDirectoryFunctions\Get-ExchangeOtherWellKnownObjects.ps1(19 groups defined) - Analyzer:
Diagnostics\HealthChecker\Analyzer\Invoke-AnalyzerExchangeInformation.ps1(lines 315-408 — membership checks) - Mock Data:
Diagnostics\HealthChecker\Tests\DataCollection\ExchangeSE\Exchange\GetExchangeWellKnownSecurityGroups.xml(19 groups, no GroupType property)
Additional context
The 19 default Exchange Well Known Security Groups that should all be Universal:
Organization Management, Recipient Management, View-Only Organization Management, Public Folder Management, UM Management, Help Desk, Records Management, Discovery Management, Server Management, Delegated Setup, Hygiene Management, Compliance Management, Exchange Servers, Exchange Trusted Subsystem, Managed Availability Servers, Exchange Windows Permissions, ExchangeLegacyInterop, Security Reader, Security Administrator
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Diagnostics\HealthChecker\DataCollection\OrganizationInformation\Get-ExchangeWellKnownSecurityGroups.ps1 and Invoke-AnalyzerExchangeInformation.ps1, then inspect the 19-group XML mock and existing ExchangeSE Pester tests. Reproduce the listed group-type and RBAC scenarios in a lab if available. Done means GroupType is collected, incorrect types produce a named warning, and passing and failing mock scenarios are covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- powershell
- Domain
- security, testing-qa, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100