Skip to content

Commit 829afc9

Browse files
committed
Improve Teams federation domains parsing and validation
Refactor parsing and comparison logic for Teams federation AllowedDomains/BlockedDomains. Handle PSObject and deserialized types, detect AllowAllKnownDomains, extract AllowedDomain/Domain properties, and normalize blocked domains up-front. Add DomainControl-specific validation for allow/block modes and normalize values for reporting. Remove a noisy Update info log and tidy comparison initialization to avoid false mismatches.
1 parent d0d2595 commit 829afc9

1 file changed

Lines changed: 84 additions & 56 deletions

File tree

Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1

Lines changed: 84 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -90,69 +90,86 @@ function Invoke-CIPPStandardTeamsFederationConfiguration {
9090
}
9191
}
9292

93-
# Parse current allowed domains and compare with expected configuration
93+
# Parse current state based on DomainControl mode
9494
$CurrentAllowedDomains = $CurrentState.AllowedDomains
95-
$AllowedDomainsMatches = $false
95+
$CurrentBlockedDomains = $CurrentState.BlockedDomains
9696
$IsCurrentAllowAllKnownDomains = $false
97+
$AllowedDomainsMatches = $false
98+
$BlockedDomainsMatches = $false
9799

98-
if (!$CurrentAllowedDomains) {
99-
# Current state has no allowed domains set
100-
$CurrentAllowedDomains = @()
101-
$AllowedDomainsMatches = (!$AllowedDomains -and $AllowedDomainsAsAList.Count -eq 0)
102-
} elseif ($CurrentAllowedDomains.GetType().Name -eq 'PSObject') {
103-
# Current state is a PSObject - check if it has AllowAllKnownDomains, AllowedDomain, or Domain property
104-
$properties = Get-Member -InputObject $CurrentAllowedDomains -MemberType Properties, NoteProperty
105-
106-
if ($null -ne $CurrentAllowedDomains.AllowAllKnownDomains -or (Get-Member -InputObject $CurrentAllowedDomains -Name 'AllowAllKnownDomains')) {
107-
# PSObject with AllowAllKnownDomains property = Allow all known domains
108-
$IsCurrentAllowAllKnownDomains = $true
109-
$CurrentAllowedDomains = 'AllowAllKnownDomains'
110-
Write-Information 'Detected AllowAllKnownDomains configuration (via property)'
111-
$AllowedDomainsMatches = ($null -ne $AllowedDomains) -and (!$AllowedDomainsAsAList -or $AllowedDomainsAsAList.Count -eq 0)
112-
} elseif ($null -ne $CurrentAllowedDomains.AllowedDomain -or (Get-Member -InputObject $CurrentAllowedDomains -Name 'AllowedDomain')) {
113-
# PSObject with AllowedDomain property = Specific domain list (array of objects with Domain property)
114-
$CurrentAllowedDomains = @($CurrentAllowedDomains.AllowedDomain | ForEach-Object { $_.Domain }) | Sort-Object
115-
$DomainList = ($CurrentAllowedDomains | Sort-Object) ?? @()
116-
Write-Information "Detected AllowedDomain list: $($CurrentAllowedDomains -join ', ')"
117-
# Compare with expected domain list
118-
if ($AllowedDomainsAsAList -and $AllowedDomainsAsAList.Count -gt 0) {
119-
$AllowedDomainsMatches = -not (Compare-Object -ReferenceObject $AllowedDomainsAsAList -DifferenceObject $DomainList)
100+
# Check if current allowed domains is AllowAllKnownDomains, and parse specific domains if not
101+
if ($CurrentAllowedDomains) {
102+
if ($CurrentAllowedDomains.GetType().Name -eq 'PSObject') {
103+
$properties = Get-Member -InputObject $CurrentAllowedDomains -MemberType Properties, NoteProperty
104+
if (($null -ne $CurrentAllowedDomains.AllowAllKnownDomains) -or
105+
(Get-Member -InputObject $CurrentAllowedDomains -Name 'AllowAllKnownDomains') -or
106+
(!$properties -or $properties.Count -eq 0)) {
107+
$IsCurrentAllowAllKnownDomains = $true
108+
Write-Information "Current AllowedDomains is AllowAllKnownDomains"
120109
} else {
121-
$AllowedDomainsMatches = $false
110+
# Parse specific allowed domains list
111+
if ($null -ne $CurrentAllowedDomains.AllowedDomain -or (Get-Member -InputObject $CurrentAllowedDomains -Name 'AllowedDomain')) {
112+
$CurrentAllowedDomains = @($CurrentAllowedDomains.AllowedDomain | ForEach-Object { $_.Domain }) | Sort-Object
113+
Write-Information "Current AllowedDomains (extracted): $($CurrentAllowedDomains -join ', ')"
114+
} elseif ($null -ne $CurrentAllowedDomains.Domain -or (Get-Member -InputObject $CurrentAllowedDomains -Name 'Domain')) {
115+
$CurrentAllowedDomains = @($CurrentAllowedDomains.Domain) | Sort-Object
116+
Write-Information "Current AllowedDomains (via Domain property): $($CurrentAllowedDomains -join ', ')"
117+
} else {
118+
$CurrentAllowedDomains = @()
119+
}
122120
}
123-
} elseif ($null -ne $CurrentAllowedDomains.Domain -or (Get-Member -InputObject $CurrentAllowedDomains -Name 'Domain')) {
124-
# PSObject with Domain property = Specific domain list (direct array)
125-
$CurrentAllowedDomains = $CurrentAllowedDomains.Domain | Sort-Object
126-
$DomainList = ($CurrentAllowedDomains | Sort-Object) ?? @()
127-
# Compare with expected domain list
128-
if ($AllowedDomainsAsAList -and $AllowedDomainsAsAList.Count -gt 0) {
129-
$AllowedDomainsMatches = -not (Compare-Object -ReferenceObject $AllowedDomainsAsAList -DifferenceObject $DomainList)
121+
} elseif ($CurrentAllowedDomains.GetType().Name -eq 'Deserialized.Microsoft.Rtc.Management.WritableConfig.Settings.Edge.AllowAllKnownDomains') {
122+
$IsCurrentAllowAllKnownDomains = $true
123+
Write-Information "Current AllowedDomains is AllowAllKnownDomains (Deserialized type)"
124+
}
125+
} else {
126+
$CurrentAllowedDomains = @()
127+
}
128+
129+
# Parse blocked domains upfront (always extract Domain property if present)
130+
if ($CurrentBlockedDomains -is [System.Collections.IEnumerable] -and $CurrentBlockedDomains -isnot [string]) {
131+
$blockedDomainsArray = @($CurrentBlockedDomains)
132+
if ($blockedDomainsArray.Count -gt 0) {
133+
$firstElement = $blockedDomainsArray[0]
134+
$hasDomainProperty = ($null -ne $firstElement.Domain) -or (Get-Member -InputObject $firstElement -Name 'Domain' -MemberType Properties, NoteProperty)
135+
136+
if ($hasDomainProperty) {
137+
$CurrentBlockedDomains = @($blockedDomainsArray | ForEach-Object { $_.Domain }) | Sort-Object
138+
Write-Information "Current BlockedDomains (extracted): $($CurrentBlockedDomains -join ', ')"
130139
} else {
131-
$AllowedDomainsMatches = $false
140+
$CurrentBlockedDomains = @($blockedDomainsArray) | Sort-Object
141+
Write-Information "Current BlockedDomains (plain strings): $($CurrentBlockedDomains -join ', ')"
132142
}
133-
} elseif (!$properties -or $properties.Count -eq 0) {
134-
# Empty PSObject with no properties = AllowAllKnownDomains (this is how Teams API returns it)
135-
$IsCurrentAllowAllKnownDomains = $true
136-
$CurrentAllowedDomains = 'AllowAllKnownDomains'
137-
Write-Information 'Detected AllowAllKnownDomains configuration (empty PSObject)'
138-
$AllowedDomainsMatches = ($null -ne $AllowedDomains) -and (!$AllowedDomainsAsAList -or $AllowedDomainsAsAList.Count -eq 0)
139143
} else {
140-
# Unknown PSObject structure
141-
Write-Information "Unknown PSObject structure with properties: $($properties.Name -join ', ')"
142-
$CurrentAllowedDomains = @()
143-
$AllowedDomainsMatches = $false
144-
}
145-
} elseif ($CurrentAllowedDomains.GetType().Name -eq 'Deserialized.Microsoft.Rtc.Management.WritableConfig.Settings.Edge.AllowAllKnownDomains') {
146-
# Current state is set to AllowAllKnownDomains
147-
$IsCurrentAllowAllKnownDomains = $true
148-
# Match if expected is also AllowAllKnownDomains (not a specific list)
149-
$AllowedDomainsMatches = ($null -ne $AllowedDomains) -and (!$AllowedDomainsAsAList -or $AllowedDomainsAsAList.Count -eq 0)
144+
$CurrentBlockedDomains = @()
145+
}
146+
} else {
147+
$CurrentBlockedDomains = @()
148+
}
149+
150+
# Mode-specific validation
151+
switch ($DomainControl) {
152+
'AllowAllExternal' {
153+
$AllowedDomainsMatches = $IsCurrentAllowAllKnownDomains
154+
$BlockedDomainsMatches = (!$CurrentBlockedDomains -or @($CurrentBlockedDomains).Count -eq 0)
155+
}
156+
'BlockAllExternal' {
157+
# When blocking all, federation must be disabled
158+
$AllowedDomainsMatches = $true
159+
$BlockedDomainsMatches = $true
160+
}
161+
'AllowSpecificExternal' {
162+
$AllowedDomainsMatches = -not (Compare-Object -ReferenceObject $AllowedDomainsAsAList -DifferenceObject $CurrentAllowedDomains)
163+
$BlockedDomainsMatches = (!$CurrentBlockedDomains -or @($CurrentBlockedDomains).Count -eq 0)
164+
}
165+
'BlockSpecificExternal' {
166+
# Allowed should be AllowAllKnownDomains, blocked domains already parsed above
167+
$AllowedDomainsMatches = $IsCurrentAllowAllKnownDomains
168+
$BlockedDomainsMatches = -not (Compare-Object -ReferenceObject $BlockedDomains -DifferenceObject $CurrentBlockedDomains)
169+
}
150170
}
151171

152-
# Normalize blocked domains for comparison
153-
$CurrentBlockedDomains = $CurrentState.BlockedDomains ?? @()
154172
$ExpectedBlockedDomains = $BlockedDomains ?? @()
155-
$BlockedDomainsMatches = -not (Compare-Object -ReferenceObject $ExpectedBlockedDomains -DifferenceObject $CurrentBlockedDomains)
156173

157174
$StateIsCorrect = ($CurrentState.AllowTeamsConsumer -eq $Settings.AllowTeamsConsumer) -and
158175
($CurrentState.AllowFederatedUsers -eq $AllowFederatedUsers) -and
@@ -178,8 +195,6 @@ function Invoke-CIPPStandardTeamsFederationConfiguration {
178195

179196
try {
180197
New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTenantFederationConfiguration' -CmdParams $cmdParams
181-
Write-Information "Updated Teams Federation Configuration for tenant $Tenant with parameters: $($cmdParams | ConvertTo-Json -Compress -Depth 5)"
182-
183198
Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Federation Configuration Policy' -sev Info
184199
} catch {
185200
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
@@ -217,17 +232,30 @@ function Invoke-CIPPStandardTeamsFederationConfiguration {
217232
@()
218233
}
219234

235+
# Normalize blocked domains for reporting
236+
$CurrentBlockedDomainsForReport = if ($null -ne $CurrentBlockedDomains -and @($CurrentBlockedDomains).Count -gt 0) {
237+
@($CurrentBlockedDomains)
238+
} else {
239+
@()
240+
}
241+
242+
$ExpectedBlockedDomainsForReport = if ($null -ne $ExpectedBlockedDomains -and @($ExpectedBlockedDomains).Count -gt 0) {
243+
@($ExpectedBlockedDomains)
244+
} else {
245+
@()
246+
}
247+
220248
$CurrentValue = @{
221249
AllowTeamsConsumer = $CurrentState.AllowTeamsConsumer
222250
AllowFederatedUsers = $CurrentState.AllowFederatedUsers
223251
AllowedDomains = $CurrentAllowedDomainsForReport
224-
BlockedDomains = $CurrentBlockedDomains
252+
BlockedDomains = $CurrentBlockedDomainsForReport
225253
}
226254
$ExpectedValue = @{
227255
AllowTeamsConsumer = $Settings.AllowTeamsConsumer
228256
AllowFederatedUsers = $AllowFederatedUsers
229257
AllowedDomains = $ExpectedAllowedDomainsForReport
230-
BlockedDomains = $ExpectedBlockedDomains
258+
BlockedDomains = $ExpectedBlockedDomainsForReport
231259
}
232260
Set-CIPPStandardsCompareField -FieldName 'standards.TeamsFederationConfiguration' -CurrentValue $CurrentValue -ExpectedValue $ExpectedValue -Tenant $Tenant
233261
}

0 commit comments

Comments
 (0)