@@ -7,7 +7,10 @@ function Test-CIPPAccess {
7
7
8
8
# Get function help
9
9
$FunctionName = ' Invoke-{0}' -f $Request.Params.CIPPEndpoint
10
- $Help = Get-Help $FunctionName
10
+
11
+ try {
12
+ $Help = Get-Help $FunctionName - ErrorAction Stop
13
+ } catch {}
11
14
12
15
# Check help for role
13
16
$APIRole = $Help.Role
@@ -21,7 +24,27 @@ function Test-CIPPAccess {
21
24
$CIPPRoot = (Get-Item $CIPPCoreModuleRoot ).Parent.Parent
22
25
$BaseRoles = Get-Content - Path $CIPPRoot \Config\cipp- roles.json | ConvertFrom-Json
23
26
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
+
24
46
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'
25
48
# Direct API Access
26
49
$ForwardedFor = $Request.Headers .' x-forwarded-for' -split ' ,' | Select-Object - First 1
27
50
$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 {
44
67
45
68
if ($IPMatched ) {
46
69
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
+ }
48
84
} else {
49
85
$CustomRoles = @ (' cipp-api' )
50
86
}
@@ -56,73 +92,163 @@ function Test-CIPPAccess {
56
92
Write-Information " API Access: AppId=$ ( $Request.Headers .' x-ms-client-principal-name' ) , IP=$IPAddress "
57
93
}
58
94
} else {
59
- $DefaultRoles = @ ( ' admin ' , ' editor ' , ' readonly ' , ' anonymous ' , ' authenticated ' )
95
+ $Type = ' User '
60
96
$User = [System.Text.Encoding ]::UTF8.GetString([System.Convert ]::FromBase64String($Request.Headers .' x-ms-client-principal' )) | ConvertFrom-Json
61
97
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
64
111
}
65
112
66
113
if ($User.userRoles -contains ' admin' -or $User.userRoles -contains ' superadmin' ) {
67
114
if ($TenantList.IsPresent ) {
68
115
return @ (' AllTenants' )
69
116
}
70
- return $true
71
117
}
72
118
73
119
$CustomRoles = $User.userRoles | ForEach-Object {
74
120
if ($DefaultRoles -notcontains $_ ) {
75
121
$_
76
122
}
77
123
}
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
+ }
78
134
}
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
89
144
}
90
145
}
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 $_ }
99
186
}
100
- $Permission.AllowedTenants | Where-Object { $Permission.BlockedTenants -notcontains $_ }
101
187
}
188
+ return $LimitedTenantList
102
189
}
103
- return $LimitedTenantList
104
- }
105
- foreach ($Role in $PermissionSet ) {
106
- # Loop through each custom role permission and check API / Tenant access
190
+
107
191
$TenantAllowed = $false
108
192
$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
+ }
109
200
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
+ }
114
224
}
115
225
}
116
226
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
117
241
if ($APIAllowed ) {
118
242
$TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter ?? $Request.Query.tenantId ?? $Request.Body.tenantId ?? $env: TenantID
119
243
# Check tenant level access
120
244
if (($Role.BlockedTenants | Measure-Object ).Count -eq 0 -and $Role.AllowedTenants -contains ' AllTenants' ) {
121
245
$TenantAllowed = $true
122
246
} elseif ($TenantFilter -eq ' AllTenants' ) {
247
+
123
248
$TenantAllowed = $false
124
249
} else {
125
250
$Tenant = ($Tenants | Where-Object { $TenantFilter -eq $_.customerId -or $TenantFilter -eq $_.defaultDomainName }).customerId
251
+
126
252
if ($Role.AllowedTenants -contains ' AllTenants' ) {
127
253
$AllowedTenants = $Tenants.customerId
128
254
} else {
@@ -140,14 +266,19 @@ function Test-CIPPAccess {
140
266
}
141
267
}
142
268
143
- if (! $APIAllowed ) {
144
- throw " Access to this CIPP API endpoint is not allowed, you do not have the required permission: $APIRole "
145
- }
146
269
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
+
151
282
}
152
283
} else {
153
284
# No permissions found for any roles
@@ -156,7 +287,10 @@ function Test-CIPPAccess {
156
287
}
157
288
return $true
158
289
}
159
- } else {
160
- return $true
161
290
}
291
+
292
+ if ($TenantList.IsPresent ) {
293
+ return @ (' AllTenants' )
294
+ }
295
+ return $true
162
296
}
0 commit comments