@@ -7,7 +7,10 @@ function Test-CIPPAccess {
77
88 # Get function help
99 $FunctionName = ' Invoke-{0}' -f $Request.Params.CIPPEndpoint
10- $Help = Get-Help $FunctionName
10+
11+ try {
12+ $Help = Get-Help $FunctionName - ErrorAction Stop
13+ } catch {}
1114
1215 # Check help for role
1316 $APIRole = $Help.Role
@@ -21,7 +24,27 @@ function Test-CIPPAccess {
2124 $CIPPRoot = (Get-Item $CIPPCoreModuleRoot ).Parent.Parent
2225 $BaseRoles = Get-Content - Path $CIPPRoot \Config\cipp- roles.json | ConvertFrom-Json
2326
27+ if ($APIRole -eq ' Public' ) {
28+ return $true
29+ }
30+
31+ # Get default roles from config
32+ $CIPPCoreModuleRoot = Get-Module - Name CIPPCore | Select-Object - ExpandProperty ModuleBase
33+ $CIPPRoot = (Get-Item $CIPPCoreModuleRoot ).Parent.Parent
34+ $BaseRoles = Get-Content - Path $CIPPRoot \Config\cipp- roles.json | ConvertFrom-Json
35+ $DefaultRoles = @ (' superadmin' , ' admin' , ' editor' , ' readonly' , ' anonymous' , ' authenticated' )
36+
37+ if ($APIRole -eq ' Public' ) {
38+ return $true
39+ }
40+
41+ # Get default roles from config
42+ $CIPPCoreModuleRoot = Get-Module - Name CIPPCore | Select-Object - ExpandProperty ModuleBase
43+ $CIPPRoot = (Get-Item $CIPPCoreModuleRoot ).Parent.Parent
44+ $BaseRoles = Get-Content - Path $CIPPRoot \Config\cipp- roles.json | ConvertFrom-Json
45+
2446 if ($Request.Headers .' x-ms-client-principal-idp' -eq ' aad' -and $Request.Headers .' x-ms-client-principal-name' -match ' ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$' ) {
47+ $Type = ' APIClient'
2548 # Direct API Access
2649 $ForwardedFor = $Request.Headers .' x-forwarded-for' -split ' ,' | Select-Object - First 1
2750 $IPRegex = ' ^(?<IP>(?:\d{1,3}(?:\.\d{1,3}){3}|\[[0-9a-fA-F:]+\]|[0-9a-fA-F:]+))(?::\d+)?$'
@@ -44,7 +67,20 @@ function Test-CIPPAccess {
4467
4568 if ($IPMatched ) {
4669 if ($Client.Role ) {
47- $CustomRoles = @ ($Client.Role )
70+ $CustomRoles = $Client.Role | ForEach-Object {
71+ if ($DefaultRoles -notcontains $_ ) {
72+ $_
73+ }
74+ }
75+ $BaseRole = $null
76+ foreach ($Role in $BaseRoles.PSObject.Properties ) {
77+ foreach ($ClientRole in $Client.Role ) {
78+ if ($Role.Name -eq $ClientRole ) {
79+ $BaseRole = $Role
80+ break
81+ }
82+ }
83+ }
4884 } else {
4985 $CustomRoles = @ (' cipp-api' )
5086 }
@@ -56,73 +92,163 @@ function Test-CIPPAccess {
5692 Write-Information " API Access: AppId=$ ( $Request.Headers .' x-ms-client-principal-name' ) , IP=$IPAddress "
5793 }
5894 } else {
59- $DefaultRoles = @ ( ' admin ' , ' editor ' , ' readonly ' , ' anonymous ' , ' authenticated ' )
95+ $Type = ' User '
6096 $User = [System.Text.Encoding ]::UTF8.GetString([System.Convert ]::FromBase64String($Request.Headers .' x-ms-client-principal' )) | ConvertFrom-Json
6197
62- if (! $TenantList.IsPresent -and $APIRole -match ' SuperAdmin' -and $User.userRoles -notcontains ' superadmin' ) {
63- throw ' Access to this CIPP API endpoint is not allowed, the user does not have the required permission'
98+ # Check for roles granted via group membership
99+ if (($User.userRoles | Measure-Object ).Count -eq 2 -and $User.userRoles -contains ' authenticated' -and $User.userRoles -contains ' anonymous' ) {
100+ $User = Test-CIPPAccessUserRole - User $User
101+ }
102+
103+ # Write-Information ($User | ConvertTo-Json -Depth 5)
104+ # Return user permissions
105+ if ($Request.Params.CIPPEndpoint -eq ' me' ) {
106+ Push-OutputBinding - Name Response - Value ([HttpResponseContext ]@ {
107+ StatusCode = [HttpStatusCode ]::OK
108+ Body = (@ { ' clientPrincipal' = $User } | ConvertTo-Json - Depth 5 )
109+ })
110+ return
64111 }
65112
66113 if ($User.userRoles -contains ' admin' -or $User.userRoles -contains ' superadmin' ) {
67114 if ($TenantList.IsPresent ) {
68115 return @ (' AllTenants' )
69116 }
70- return $true
71117 }
72118
73119 $CustomRoles = $User.userRoles | ForEach-Object {
74120 if ($DefaultRoles -notcontains $_ ) {
75121 $_
76122 }
77123 }
124+
125+ $BaseRole = $null
126+ foreach ($Role in $BaseRoles.PSObject.Properties ) {
127+ foreach ($UserRole in $User.userRoles ) {
128+ if ($Role.Name -eq $UserRole ) {
129+ $BaseRole = $Role
130+ break
131+ }
132+ }
133+ }
78134 }
79- if (($CustomRoles | Measure-Object ).Count -gt 0 ) {
80- $Tenants = Get-Tenants - IncludeErrors
81- $PermissionsFound = $false
82- $PermissionSet = foreach ($CustomRole in $CustomRoles ) {
83- try {
84- Get-CIPPRolePermissions - Role $CustomRole
85- $PermissionsFound = $true
86- } catch {
87- Write-Information $_.Exception.Message
88- continue
135+
136+ # Check base role permissions before continuing to custom roles
137+ if ($null -ne $BaseRole ) {
138+ Write-Information " Base Role: $ ( $BaseRole.Name ) "
139+ $BaseRoleAllowed = $false
140+ foreach ($Include in $BaseRole.Value.include ) {
141+ if ($APIRole -like $Include ) {
142+ $BaseRoleAllowed = $true
143+ break
89144 }
90145 }
91- if ($PermissionsFound ) {
92- if ($TenantList.IsPresent ) {
93- $LimitedTenantList = foreach ($Permission in $PermissionSet ) {
94- if ((($Permission.AllowedTenants | Measure-Object ).Count -eq 0 -or $Permission.AllowedTenants -contains ' AllTenants' ) -and (($Permission.BlockedTenants | Measure-Object ).Count -eq 0 )) {
95- @ (' AllTenants' )
96- } else {
97- if ($Permission.AllowedTenants -contains ' AllTenants' ) {
98- $Permission.AllowedTenants = $Tenants.customerId
146+ foreach ($Exclude in $BaseRole.Value.exclude ) {
147+ if ($APIRole -like $Exclude ) {
148+ $BaseRoleAllowed = $false
149+ break
150+ }
151+ }
152+ if (! $BaseRoleAllowed ) {
153+ throw " Access to this CIPP API endpoint is not allowed, the '$ ( $BaseRole.Name ) ' base role does not have the required permission: $APIRole "
154+ }
155+ }
156+
157+ # Check custom role permissions for limitations on api calls or tenants
158+ if ($null -eq $BaseRole.Name -and $Type -eq ' User' -and ($CustomRoles | Measure-Object ).Count -eq 0 ) {
159+ Write-Information $BaseRole.Name
160+ throw ' Access to this CIPP API endpoint is not allowed, the user does not have the required permission'
161+ } elseif (($CustomRoles | Measure-Object ).Count -gt 0 ) {
162+ if (@ (' admin' , ' superadmin' ) -contains $BaseRole.Name ) {
163+ return $true
164+ } else {
165+ $Tenants = Get-Tenants - IncludeErrors
166+ $PermissionsFound = $false
167+ $PermissionSet = foreach ($CustomRole in $CustomRoles ) {
168+ try {
169+ Get-CIPPRolePermissions - Role $CustomRole
170+ $PermissionsFound = $true
171+ } catch {
172+ Write-Information $_.Exception.Message
173+ continue
174+ }
175+ }
176+ if ($PermissionsFound ) {
177+ if ($TenantList.IsPresent ) {
178+ $LimitedTenantList = foreach ($Permission in $PermissionSet ) {
179+ if ((($Permission.AllowedTenants | Measure-Object ).Count -eq 0 -or $Permission.AllowedTenants -contains ' AllTenants' ) -and (($Permission.BlockedTenants | Measure-Object ).Count -eq 0 )) {
180+ @ (' AllTenants' )
181+ } else {
182+ if ($Permission.AllowedTenants -contains ' AllTenants' ) {
183+ $Permission.AllowedTenants = $Tenants.customerId
184+ }
185+ $Permission.AllowedTenants | Where-Object { $Permission.BlockedTenants -notcontains $_ }
99186 }
100- $Permission.AllowedTenants | Where-Object { $Permission.BlockedTenants -notcontains $_ }
101187 }
188+ return $LimitedTenantList
102189 }
103- return $LimitedTenantList
104- }
105- foreach ($Role in $PermissionSet ) {
106- # Loop through each custom role permission and check API / Tenant access
190+
107191 $TenantAllowed = $false
108192 $APIAllowed = $false
193+ foreach ($Role in $PermissionSet ) {
194+ foreach ($Perm in $Role.Permissions ) {
195+ if ($Perm -match $APIRole ) {
196+ $APIAllowed = $true
197+ break
198+ }
199+ }
109200
110- foreach ($Perm in $Role.Permissions ) {
111- if ($Perm -match $APIRole ) {
112- $APIAllowed = $true
113- break
201+ if ($APIAllowed ) {
202+ $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter ?? $Request.Body.tenantFilter.value ?? $Request.Query.tenantId ?? $Request.Body.tenantId ?? $Request.Body.tenantId.value ?? $env: TenantID
203+ # Check tenant level access
204+ if (($Role.BlockedTenants | Measure-Object ).Count -eq 0 -and $Role.AllowedTenants -contains ' AllTenants' ) {
205+ $TenantAllowed = $true
206+ } elseif ($TenantFilter -eq ' AllTenants' ) {
207+ $TenantAllowed = $false
208+ } else {
209+ $Tenant = ($Tenants | Where-Object { $TenantFilter -eq $_.customerId -or $TenantFilter -eq $_.defaultDomainName }).customerId
210+ if ($Role.AllowedTenants -contains ' AllTenants' ) {
211+ $AllowedTenants = $Tenants.customerId
212+ } else {
213+ $AllowedTenants = $Role.AllowedTenants
214+ }
215+ if ($Tenant ) {
216+ $TenantAllowed = $AllowedTenants -contains $Tenant -and $Role.BlockedTenants -notcontains $Tenant
217+ if (! $TenantAllowed ) { continue }
218+ break
219+ } else {
220+ $TenantAllowed = $true
221+ break
222+ }
223+ }
114224 }
115225 }
116226
227+ if (! $APIAllowed ) {
228+ throw " Access to this CIPP API endpoint is not allowed, you do not have the required permission: $APIRole "
229+ }
230+ if (! $TenantAllowed -and $Help.Functionality -notmatch ' AnyTenant' ) {
231+ throw ' Access to this tenant is not allowed'
232+ } else {
233+ return $true
234+ }
235+ } else {
236+ # No permissions found for any roles
237+ if ($TenantList.IsPresent ) {
238+ return @ (' AllTenants' )
239+ }
240+ return $true
117241 if ($APIAllowed ) {
118242 $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter ?? $Request.Query.tenantId ?? $Request.Body.tenantId ?? $env: TenantID
119243 # Check tenant level access
120244 if (($Role.BlockedTenants | Measure-Object ).Count -eq 0 -and $Role.AllowedTenants -contains ' AllTenants' ) {
121245 $TenantAllowed = $true
122246 } elseif ($TenantFilter -eq ' AllTenants' ) {
247+
123248 $TenantAllowed = $false
124249 } else {
125250 $Tenant = ($Tenants | Where-Object { $TenantFilter -eq $_.customerId -or $TenantFilter -eq $_.defaultDomainName }).customerId
251+
126252 if ($Role.AllowedTenants -contains ' AllTenants' ) {
127253 $AllowedTenants = $Tenants.customerId
128254 } else {
@@ -140,14 +266,19 @@ function Test-CIPPAccess {
140266 }
141267 }
142268
143- if (! $APIAllowed ) {
144- throw " Access to this CIPP API endpoint is not allowed, you do not have the required permission: $APIRole "
145- }
146269 if (! $TenantAllowed -and $Help.Functionality -notmatch ' AnyTenant' ) {
147- Write-Information " Tenant not allowed: $TenantFilter "
148- throw ' Access to this tenant is not allowed'
149- } else {
150- return $true
270+
271+ if (! $APIAllowed ) {
272+ throw " Access to this CIPP API endpoint is not allowed, you do not have the required permission: $APIRole "
273+ }
274+ if (! $TenantAllowed -and $Help.Functionality -notmatch ' AnyTenant' ) {
275+ Write-Information " Tenant not allowed: $TenantFilter "
276+
277+ throw ' Access to this tenant is not allowed'
278+ } else {
279+ return $true
280+ }
281+
151282 }
152283 } else {
153284 # No permissions found for any roles
@@ -156,7 +287,10 @@ function Test-CIPPAccess {
156287 }
157288 return $true
158289 }
159- } else {
160- return $true
161290 }
291+
292+ if ($TenantList.IsPresent ) {
293+ return @ (' AllTenants' )
294+ }
295+ return $true
162296}
0 commit comments