Skip to content

Commit 67df3ba

Browse files
authored
Merge pull request #1077 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents 45e2cff + 15cc4b4 commit 67df3ba

7 files changed

Lines changed: 110 additions & 62 deletions

File tree

Modules/CIPPCore/Public/Authentication/Get-CIPPRolePermissions.ps1

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,25 @@ function Get-CIPPRolePermissions {
1717
$Filter = "RowKey eq '$RoleName'"
1818
$Role = Get-CIPPAzDataTableEntity @Table -Filter $Filter
1919
if ($Role) {
20-
$Permissions = $Role.Permissions | ConvertFrom-Json
20+
$Permissions = ($Role.Permissions | ConvertFrom-Json).PSObject.Properties.Value
21+
# Stored permissions can reference endpoints removed or renamed in later CIPP
22+
# versions; drop those so stale entries don't inflate the role's permission set
23+
# (e.g. failing the Test-CippApiClientRoleGrant subset check). Skip filtering if
24+
# the valid-permission universe can't be resolved, rather than emptying the role.
25+
try {
26+
$ValidPermissions = Get-CippHttpPermissions
27+
if (@($ValidPermissions).Count -gt 0) {
28+
$Permissions = @($Permissions | Where-Object { $ValidPermissions -contains $_ })
29+
}
30+
} catch {
31+
Write-Warning "Unable to resolve valid permissions to filter role '$RoleName': $($_.Exception.Message)"
32+
}
2133
$AllowedTenants = if ($Role.AllowedTenants) { $Role.AllowedTenants | ConvertFrom-Json } else { @() }
2234
$BlockedTenants = if ($Role.BlockedTenants) { $Role.BlockedTenants | ConvertFrom-Json } else { @() }
2335
$BlockedEndpoints = if ($Role.BlockedEndpoints) { $Role.BlockedEndpoints | ConvertFrom-Json } else { @() }
2436
[PSCustomObject]@{
2537
Role = $Role.RowKey
26-
Permissions = $Permissions.PSObject.Properties.Value
38+
Permissions = @($Permissions)
2739
AllowedTenants = @($AllowedTenants)
2840
BlockedTenants = @($BlockedTenants)
2941
BlockedEndpoints = @($BlockedEndpoints)

Modules/CIPPCore/Public/Authentication/Get-CippAllowedPermissions.ps1

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,10 @@ function Get-CippAllowedPermissions {
2222
)
2323

2424
# Get all available permissions and base roles configuration
25-
26-
$Version = if ($env:CIPPNG -eq 'true') {
27-
$env:APP_VERSION
28-
} else {
29-
(Get-Content -Path (Join-Path $env:CIPPRootPath 'version_latest.txt')).Trim()
30-
}
3125
$BaseRoles = Get-Content -Path (Join-Path $env:CIPPRootPath 'Config\cipp-roles.json') | ConvertFrom-Json
3226
$DefaultRoles = @('superadmin', 'admin', 'editor', 'readonly', 'anonymous', 'authenticated')
3327

34-
$AllPermissionCacheTable = Get-CIPPTable -tablename 'cachehttppermissions'
35-
$AllPermissionsRow = Get-CIPPAzDataTableEntity @AllPermissionCacheTable -Filter "PartitionKey eq 'HttpFunctions' and RowKey eq 'HttpFunctions' and Version eq '$($Version)'"
36-
37-
if (-not $AllPermissionsRow.Permissions) {
38-
$AllPermissions = Get-CIPPHttpFunctions -ByRole | Select-Object -ExpandProperty Permission
39-
$Entity = @{
40-
PartitionKey = 'HttpFunctions'
41-
RowKey = 'HttpFunctions'
42-
Version = [string]$Version
43-
Permissions = [string]($AllPermissions | ConvertTo-Json -Compress)
44-
}
45-
Add-CIPPAzDataTableEntity @AllPermissionCacheTable -Entity $Entity -Force
46-
} else {
47-
$AllPermissions = $AllPermissionsRow.Permissions | ConvertFrom-Json
48-
}
28+
$AllPermissions = Get-CippHttpPermissions
4929

5030
$AllowedPermissions = [System.Collections.Generic.List[string]]::new()
5131

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
function Get-CippHttpPermissions {
2+
<#
3+
.SYNOPSIS
4+
Returns the set of API permissions that exist on the current HTTP functions.
5+
6+
.DESCRIPTION
7+
Resolves the full permission universe for the running CIPP version from the
8+
cachehttppermissions table, computing and caching it via Get-CIPPHttpFunctions
9+
on a cache miss. Results are memoized in-process per version so hot paths
10+
(Test-CIPPAccess, Get-CippAllowedPermissions) avoid repeated table reads.
11+
12+
.OUTPUTS
13+
[string[]] of valid permission names, e.g. 'Exchange.Mailbox.ReadWrite'.
14+
15+
.FUNCTIONALITY
16+
Internal
17+
#>
18+
[CmdletBinding()]
19+
param()
20+
21+
$Version = if ($env:CIPPNG -eq 'true') {
22+
$env:APP_VERSION
23+
} else {
24+
(Get-Content -Path (Join-Path $env:CIPPRootPath 'version_latest.txt')).Trim()
25+
}
26+
27+
if ($script:CippHttpPermissions -and $script:CippHttpPermissionsVersion -eq $Version) {
28+
return $script:CippHttpPermissions
29+
}
30+
31+
$AllPermissionCacheTable = Get-CIPPTable -tablename 'cachehttppermissions'
32+
$AllPermissionsRow = Get-CIPPAzDataTableEntity @AllPermissionCacheTable -Filter "PartitionKey eq 'HttpFunctions' and RowKey eq 'HttpFunctions' and Version eq '$($Version)'"
33+
34+
if (-not $AllPermissionsRow.Permissions) {
35+
$AllPermissions = Get-CIPPHttpFunctions -ByRole | Select-Object -ExpandProperty Permission
36+
$Entity = @{
37+
PartitionKey = 'HttpFunctions'
38+
RowKey = 'HttpFunctions'
39+
Version = [string]$Version
40+
Permissions = [string]($AllPermissions | ConvertTo-Json -Compress)
41+
}
42+
Add-CIPPAzDataTableEntity @AllPermissionCacheTable -Entity $Entity -Force
43+
} else {
44+
$AllPermissions = $AllPermissionsRow.Permissions | ConvertFrom-Json
45+
}
46+
47+
$script:CippHttpPermissions = @($AllPermissions)
48+
$script:CippHttpPermissionsVersion = $Version
49+
return $script:CippHttpPermissions
50+
}

Modules/CIPPCore/Public/Compare-CIPPIntuneObject.ps1

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ function Compare-CIPPIntuneObject {
450450
}
451451
$values.Add($displayValue)
452452
}
453-
$childValue = $values -join ', '
453+
$childValue = ($values | Sort-Object) -join ', '
454454

455455
$results.Add([PSCustomObject]@{
456456
Key = "GroupChild-$($child.settingDefinitionId)"
@@ -466,7 +466,7 @@ function Compare-CIPPIntuneObject {
466466
foreach ($simpleValue in $child.simpleSettingCollectionValue) {
467467
$values.Add($simpleValue.value)
468468
}
469-
$childValue = $values -join ', '
469+
$childValue = ($values | Sort-Object) -join ', '
470470

471471
$results.Add([PSCustomObject]@{
472472
Key = "GroupChild-$($child.settingDefinitionId)"
@@ -767,7 +767,9 @@ function Compare-CIPPIntuneObject {
767767
$key
768768
}
769769

770-
if ($refRawValue -ne $diffRawValue -or $null -eq $refRawValue -or $null -eq $diffRawValue) {
770+
# Flag when values differ or the setting exists on only one side; a setting present on both sides with equal (even null) values is compliant
771+
$presenceMismatch = ($null -eq $refItem) -xor ($null -eq $diffItem)
772+
if ($refRawValue -ne $diffRawValue -or $presenceMismatch) {
771773
$result.Add([PSCustomObject]@{
772774
Property = $label
773775
ExpectedValue = $refValue

Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,7 @@ function Invoke-CIPPStandardAntiPhishPolicy {
312312
}
313313

314314
if ($Settings.report -eq $true) {
315-
$FieldValue = $StateIsCorrect ? $true : $CurrentState
316-
Set-CIPPStandardsCompareField -FieldName 'standards.AntiPhishPolicy' -FieldValue $FieldValue -TenantFilter $Tenant
315+
Set-CIPPStandardsCompareField -FieldName 'standards.AntiPhishPolicy' -CurrentValue $CurrentValue -ExpectedValue $ExpectedValue -TenantFilter $Tenant
317316
Add-CIPPBPAField -FieldName 'AntiPhishPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant
318317
}
319318

Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardBranding.ps1

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,22 @@ function Invoke-CIPPStandardBranding {
5454
$Localizations = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/organization/$($TenantId.customerId)/branding/localizations" -tenantID $Tenant -AsApp $true
5555
# Get layoutTemplateType value using null-coalescing operator
5656
$layoutTemplateType = $Settings.layoutTemplateType.value ?? $Settings.layoutTemplateType
57+
58+
$SetSignInPageText = -not [string]::IsNullOrEmpty($Settings.signInPageText)
59+
$SetUsernameHintText = -not [string]::IsNullOrEmpty($Settings.usernameHintText)
60+
61+
$BrandingBody = [ordered]@{
62+
loginPageTextVisibilitySettings = [pscustomobject]@{
63+
hideAccountResetCredentials = $Settings.hideAccountResetCredentials
64+
}
65+
loginPageLayoutConfiguration = [pscustomobject]@{
66+
layoutTemplateType = $layoutTemplateType
67+
isHeaderShown = $Settings.isHeaderShown
68+
isFooterShown = $Settings.isFooterShown
69+
}
70+
}
71+
if ($SetSignInPageText) { $BrandingBody['signInPageText'] = $Settings.signInPageText }
72+
if ($SetUsernameHintText) { $BrandingBody['usernameHintText'] = $Settings.usernameHintText }
5773
# If default localization (id "0") exists, use that to get the currentState. Otherwise we have to create it first.
5874
if ($Localizations | Where-Object { $_.id -eq '0' }) {
5975
try {
@@ -71,18 +87,7 @@ function Invoke-CIPPStandardBranding {
7187
AsApp = $true
7288
Type = 'POST'
7389
ContentType = 'application/json; charset=utf-8'
74-
Body = [pscustomobject]@{
75-
signInPageText = $Settings.signInPageText
76-
usernameHintText = $Settings.usernameHintText
77-
loginPageTextVisibilitySettings = [pscustomobject]@{
78-
hideAccountResetCredentials = $Settings.hideAccountResetCredentials
79-
}
80-
loginPageLayoutConfiguration = [pscustomobject]@{
81-
layoutTemplateType = $layoutTemplateType
82-
isHeaderShown = $Settings.isHeaderShown
83-
isFooterShown = $Settings.isFooterShown
84-
}
85-
} | ConvertTo-Json -Compress
90+
Body = [pscustomobject]$BrandingBody | ConvertTo-Json -Compress
8691
}
8792
$CurrentState = New-GraphPostRequest @GraphRequest
8893
} catch {
@@ -92,22 +97,18 @@ function Invoke-CIPPStandardBranding {
9297
}
9398
}
9499

95-
$StateIsCorrect = ($CurrentState.signInPageText -eq $Settings.signInPageText) -and
96-
($CurrentState.usernameHintText -eq $Settings.usernameHintText) -and
97-
($CurrentState.loginPageTextVisibilitySettings.hideAccountResetCredentials -eq $Settings.hideAccountResetCredentials) -and
100+
$StateIsCorrect = ($CurrentState.loginPageTextVisibilitySettings.hideAccountResetCredentials -eq $Settings.hideAccountResetCredentials) -and
98101
($CurrentState.loginPageLayoutConfiguration.layoutTemplateType -eq $layoutTemplateType) -and
99102
($CurrentState.loginPageLayoutConfiguration.isHeaderShown -eq $Settings.isHeaderShown) -and
100-
($CurrentState.loginPageLayoutConfiguration.isFooterShown -eq $Settings.isFooterShown)
103+
($CurrentState.loginPageLayoutConfiguration.isFooterShown -eq $Settings.isFooterShown) -and
104+
(-not $SetSignInPageText -or ($CurrentState.signInPageText -eq $Settings.signInPageText)) -and
105+
(-not $SetUsernameHintText -or ($CurrentState.usernameHintText -eq $Settings.usernameHintText))
101106

102-
$CurrentValue = [PSCustomObject]@{
103-
signInPageText = $CurrentState.signInPageText
104-
usernameHintText = $CurrentState.usernameHintText
107+
$CurrentValue = [ordered]@{
105108
loginPageTextVisibilitySettings = $CurrentState.loginPageTextVisibilitySettings | Select-Object -Property hideAccountResetCredentials
106109
loginPageLayoutConfiguration = $CurrentState.loginPageLayoutConfiguration | Select-Object -Property layoutTemplateType, isHeaderShown, isFooterShown
107110
}
108-
$ExpectedValue = [PSCustomObject]@{
109-
signInPageText = $Settings.signInPageText
110-
usernameHintText = $Settings.usernameHintText
111+
$ExpectedValue = [ordered]@{
111112
loginPageTextVisibilitySettings = [pscustomobject]@{
112113
hideAccountResetCredentials = $Settings.hideAccountResetCredentials
113114
}
@@ -117,6 +118,16 @@ function Invoke-CIPPStandardBranding {
117118
isFooterShown = $Settings.isFooterShown
118119
}
119120
}
121+
if ($SetSignInPageText) {
122+
$CurrentValue['signInPageText'] = $CurrentState.signInPageText
123+
$ExpectedValue['signInPageText'] = $Settings.signInPageText
124+
}
125+
if ($SetUsernameHintText) {
126+
$CurrentValue['usernameHintText'] = $CurrentState.usernameHintText
127+
$ExpectedValue['usernameHintText'] = $Settings.usernameHintText
128+
}
129+
$CurrentValue = [pscustomobject]$CurrentValue
130+
$ExpectedValue = [pscustomobject]$ExpectedValue
120131

121132
if ($Settings.remediate -eq $true) {
122133
if ($StateIsCorrect -eq $true) {
@@ -129,18 +140,7 @@ function Invoke-CIPPStandardBranding {
129140
AsApp = $true
130141
Type = 'PATCH'
131142
ContentType = 'application/json; charset=utf-8'
132-
Body = [pscustomobject]@{
133-
signInPageText = $Settings.signInPageText
134-
usernameHintText = $Settings.usernameHintText
135-
loginPageTextVisibilitySettings = [pscustomobject]@{
136-
hideAccountResetCredentials = $Settings.hideAccountResetCredentials
137-
}
138-
loginPageLayoutConfiguration = [pscustomobject]@{
139-
layoutTemplateType = $layoutTemplateType
140-
isHeaderShown = $Settings.isHeaderShown
141-
isFooterShown = $Settings.isFooterShown
142-
}
143-
} | ConvertTo-Json -Compress
143+
Body = [pscustomobject]$BrandingBody | ConvertTo-Json -Compress
144144
}
145145
$null = New-GraphPostRequest @GraphRequest
146146
Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully updated branding.' -Sev Info

Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ function Invoke-CIPPStandardIntuneTemplate {
121121
$JSONTemplate = $RawJSON | ConvertFrom-Json
122122
$Compare = Compare-CIPPIntuneObject -ReferenceObject $JSONTemplate -DifferenceObject $JSONExistingPolicy -compareType $TemplateType -ErrorAction SilentlyContinue
123123
} catch {
124+
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to compare Intune Template $displayname against the existing policy: $($_.Exception.Message)" -sev 'Error'
125+
$Compare = [pscustomobject]@{
126+
MatchFailed = $true
127+
Difference = "Comparison failed: $($_.Exception.Message)"
128+
}
124129
}
125130
Write-Information "[IntuneTemplate][$Tenant] Compare '$displayname': $([int]($sw.Elapsed - $lap).TotalMilliseconds)ms"
126131
$lap = $sw.Elapsed

0 commit comments

Comments
 (0)