Skip to content

Commit

Permalink
first version gdap check
Browse files Browse the repository at this point in the history
  • Loading branch information
KelvinTegelaar committed Nov 3, 2023
1 parent d1a733d commit 146f3ac
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 90 deletions.
116 changes: 26 additions & 90 deletions ExecAccessChecks/run.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,20 @@ if ($Request.query.Permissions -eq 'true') {
Href = 'https://docs.cipp.app/setup/installation/cleartokencache'
}
) | Out-Null
} else {
}
else {
$Messages.Add('Your refresh token matches key vault.') | Out-Null
}
} catch {
}
catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Key vault exception: $($_) " -Sev 'Error'
}
}

try {
$AccessTokenDetails = Read-JwtAccessDetails -Token $GraphToken.access_token -erroraction SilentlyContinue
} catch {
}
catch {
$AccessTokenDetails = [PSCustomObject]@{
Name = ''
AuthMethods = @()
Expand All @@ -71,10 +74,12 @@ if ($Request.query.Permissions -eq 'true') {
if ($AccessTokenDetails.Name -eq '') {
$Messages.Add('Your refresh token is invalid, check for line breaks or missing characters.') | Out-Null
$Success = $false
} else {
}
else {
if ($AccessTokenDetails.AuthMethods -contains 'mfa') {
$Messages.Add('Your access token contains the MFA claim.') | Out-Null
} else {
}
else {
$Messages.Add('Your access token does not contain the MFA claim, Refresh your SAM tokens.') | Out-Null
$Success = $false
$Links.Add([PSCustomObject]@{
Expand All @@ -96,7 +101,8 @@ if ($Request.query.Permissions -eq 'true') {
Href = 'https://docs.cipp.app/setup/installation/permissions'
}
) | Out-Null
} else {
}
else {
$Messages.Add('Your Secure Application Model has all required permissions') | Out-Null
}
$CIPPGroupCount = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/`$count?`$filter=startsWith(displayName,'M365 GDAP')" -NoAuthCheck $true -ComplexFilter
Expand Down Expand Up @@ -135,10 +141,12 @@ if ($Request.query.Permissions -eq 'true') {
}
if (($MissingGroups | Measure-Object).Count -eq 0) {
$Messages.Add('The SAM user has all the required groups')
} else {
}
else {
$Success = $false
}
} catch {
}
catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Permissions check failed: $($_) " -Sev 'Error'
$Messages.Add("We could not connect to the API to retrieve the permissions. There might be a problem with the secure application model configuration. The returned error is: $(Get-NormalizedError -message $_)") | Out-Null
$Success = $false
Expand Down Expand Up @@ -177,93 +185,21 @@ if ($Request.query.Tenants -eq 'true') {
$TenantIds = foreach ($Tenant in $Tenants) {
($TenantList | Where-Object { $_.defaultDomainName -eq $Tenant }).customerId
}
$MyRoles = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/managedTenants/myRoles?`$filter=tenantId in ('$($TenantIds -join "','")')"
try {
$MyRoles = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/managedTenants/myRoles?`$filter=tenantId in ('$($TenantIds -join "','")')"
}
catch {
$MyRoles = $null
}
$results = foreach ($tenant in $Tenants) {
$AddedText = ''
try {
$TenantId = ($TenantList | Where-Object { $_.defaultDomainName -eq $tenant }).customerId
$Assignments = ($MyRoles | Where-Object { $_.tenantId -eq $TenantId }).assignments
$SAMUserRoles = ($Assignments | Where-Object { $_.assignmentType -eq 'granularDelegatedAdminPrivileges' }).roles

$BulkRequests = $ExpectedRoles | ForEach-Object { @(
@{
id = "roleManagement_$($_.id)"
method = 'GET'
url = "roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq '$($_.id)'&`$expand=principal"
}
)
}
$GDAPRolesGraph = New-GraphBulkRequest -tenantid $tenant -Requests $BulkRequests
$GDAPRoles = [System.Collections.Generic.List[object]]::new()
$MissingRoles = [System.Collections.Generic.List[object]]::new()
foreach ($RoleId in $ExpectedRoles) {
$GraphRole = $GDAPRolesGraph.body.value | Where-Object -Property roleDefinitionId -EQ $RoleId.Id
$Role = $GraphRole.principal | Where-Object -Property organizationId -EQ $ENV:tenantid
$SAMRole = $SAMUserRoles | Where-Object -Property templateId -EQ $RoleId.Id
if (!$Role) {
$MissingRoles.Add(
[PSCustomObject]@{
Name = $RoleId.Name
Type = 'Tenant'
}
)
$AddedText = 'but missing GDAP roles'
} else {
$GDAPRoles.Add([PSCustomObject]$RoleId)
}
if (!$SAMRole) {
$MissingRoles.Add(
[PSCustomObject]@{
Name = $RoleId.Name
Type = 'SAM User'
}
)
$AddedText = 'but missing GDAP roles'
}
}
if (!($MissingRoles | Measure-Object).Count -gt 0) {
$MissingRoles = $true
}
@{
TenantName = "$($Tenant)"
Status = "Successfully connected $($AddedText)"
GDAPRoles = $GDAPRoles
MissingRoles = $MissingRoles
SAMUserRoles = $SAMUserRoles
}
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message 'Tenant access check executed successfully' -Sev 'Info'

} catch {
@{
TenantName = "$($tenant)"
Status = "Failed to connect: $(Get-NormalizedError -message $_.Exception.Message)"
GDAP = ''
}
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Tenant access check failed: $(Get-NormalizedError -message $_) " -Sev 'Error'

}

try {
$GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig' -ErrorAction Stop
@{
TenantName = "$($Tenant)"
Status = 'Successfully connected to Exchange'
}

} catch {
$ReportedError = ($_.ErrorDetails | ConvertFrom-Json -ErrorAction SilentlyContinue)
$Message = if ($ReportedError.error.details.message) { $ReportedError.error.details.message } else { $ReportedError.error.innererror.internalException.message }
if ($null -eq $Message) { $Message = $($_.Exception.Message) }
@{
TenantName = "$($Tenant)"
Status = "Failed to connect to Exchange: $(Get-NormalizedError -message $Message)"
}
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Tenant access check for Exchange failed: $(Get-NormalizedError -message $Message) " -Sev 'Error'
}
Test-CIPPTenantAccess -TenantFilter $Tenant -Myroles $Myroles -ExpectedRoles $ExpectedRoles
}
if (!$Tenants) { $results = 'Could not load the tenants list from cache. Please run permissions check first, or visit the tenants page.' }
}

if ($Request.query.GDAP -eq 'true') {
$Results = Test-CIPPGDAPConnection
}
$body = [pscustomobject]@{'Results' = $Results }

# Associate values to output bindings by calling 'Push-OutputBinding'.
Expand Down
82 changes: 82 additions & 0 deletions Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
function Test-CIPPTenantAccess {
[CmdletBinding()]
param (
$TenantFilter,
$APIName = "Access Check",
$ExecutingUser
)

$GDAPissues = [System.Collections.ArrayList]@()
try {
#Get graph request to list all relationships.
$Relationships = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships?`$filter=status eq 'active'" -tenantid $ENV:TenantID -NoAuthCheck $true
#Group relationships by tenant. The tenant information is in $relationships.customer.TenantId.
$RelationshipsByTenant = $Relationships | Group-Object -Property { $_.customer.TenantId }
foreach ($Tenant in $RelationshipsByTenant) {
if ($Tenant.Group.displayName.count -le 1 -and $Tenant.Group.displayName -like 'MLT_*') {
$GDAPissues.add([PSCustomObject]@{
Type = "Error"
Issue = "This tenant only has a MLT(Microsoft Led Transition) relationship. This is a read-only relationship. You must migrate this tenant to GDAP."
Tenant = $Tenant.Group.customer.displayName
Relationship = $Tenant.Group.displayName
}) | Out-Null
}
foreach ($Group in $Tenant.Group) {
if ("62e90394-69f5-4237-9190-012177145e10" -in $Group.accessDetails) {
$GDAPissues.add([PSCustomObject]@{
Type = "Warning"
Issue = "The relationship for $($Tenant.Group.customer.displayName) has global administrator access. This relationship is not available for auto-extend."
Tenant = $Tenant.Group.customer.displayName
Relationship = $group.displayName
}) | Out-Null
}
}

}
$CIPPGroupCount = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/`$count?`$filter=startsWith(displayName,'M365 GDAP')" -NoAuthCheck $true -ComplexFilter
$SAMUserMemberships = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/me/memberOf?$select=id,displayName,isAssignableToRole' -NoAuthCheck $true
$ExpectedGroups = @(
'AdminAgents',
'M365 GDAP Application Administrator',
'M365 GDAP User Administrator',
'M365 GDAP Intune Administrator',
'M365 GDAP Exchange Administrator',
'M365 GDAP Security Administrator',
'M365 GDAP Cloud App Security Administrator',
'M365 GDAP Cloud Device Administrator',
'M365 GDAP Teams Administrator',
'M365 GDAP Sharepoint Administrator',
'M365 GDAP Authentication Policy Administrator',
'M365 GDAP Privileged Role Administrator',
'M365 GDAP Privileged Authentication Administrator'
)
$RoleAssignableGroups = $SAMUserMemberships | Where-Object { $_.isAssignableToRole }
$NestedGroups = foreach ($Group in $RoleAssignableGroups) {
New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/$($Group.id)/memberOf?`$select=id,displayName" -NoAuthCheck $true
}
foreach ($Group in $ExpectedGroups) {
$GroupFound = $false
foreach ($Membership in ($SAMUserMemberships + $NestedGroups)) {
if ($Membership.displayName -match $Group -and (($CIPPGroupCount -gt 0 -and $Group -match 'M365 GDAP') -or $Group -notmatch 'M365 GDAP')) {
$GroupFound = $true
}
}
if (-not $GroupFound) {
$GDAPissues.add([PSCustomObject]@{
Type = "Warning"
Issue = "$($Group) cannot be found in your tenant. If you have migrated outside of CIPP this is to be expected. Please perform an access check to make sure you have the correct set of permissions."
Tenant = "*Partner Tenant"
Relationship = "None"
}) | Out-Null
}
}

}
catch {
Write-LogMessage -user $ExecutingUser -API $APINAME -message "Failed to run GDAP check for $($TenantFilter): $($_.Exception.Message)" -Sev "Error"
}

return [PSCustomObject]@{
GDAPIssues = @($GDAPissues)
}
}

0 comments on commit 146f3ac

Please sign in to comment.