Collectors/Applications.ps1
|
@{ Name = 'Applications' FileName = 'applications' ApiVersion = 'v1.0' RequiredScopes = @('Application.Read.All') Description = 'App registrations (credential expiry, requested high-privilege Graph application permissions, owners) and service principals.' Collect = { $applications = @(Invoke-TLGraphRequest -Uri '/v1.0/applications?$expand=owners($select=id,displayName,userPrincipalName)' -All) $servicePrincipals = @(Invoke-TLGraphRequest -Uri '/v1.0/servicePrincipals?$select=id,appId,displayName,accountEnabled,servicePrincipalType&$top=999' -All) # Well-known high-privilege Microsoft Graph application role ids $graphResourceAppId = '00000003-0000-0000-c000-000000000000' $riskyGraphAppRoles = @{ '19dbc75e-c2e2-444c-a770-ec69d8559fc7' = 'Directory.ReadWrite.All' '1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9' = 'Application.ReadWrite.All' '9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8' = 'RoleManagement.ReadWrite.Directory' '06b708a9-e830-4db3-a914-8e69da51d44f' = 'AppRoleAssignment.ReadWrite.All' '741f803b-c850-494e-b5df-cde7c675a1ca' = 'User.ReadWrite.All' 'e2a3a72e-5f79-4c64-b1b1-878b674786c9' = 'Mail.ReadWrite' 'b633e1c5-b582-4048-a93e-9f11b44c7e96' = 'Mail.Send' '75359482-378d-4052-8f01-80520e7db3cd' = 'Files.ReadWrite.All' '62a82d76-70ea-41e2-9197-370581804d09' = 'Group.ReadWrite.All' } $utcNow = [DateTime]::UtcNow foreach ($application in $applications) { $total = 0; $expired = 0; $expiringSoon = 0; $passwordCount = 0 $soonest = $null foreach ($credential in (@($application.passwordCredentials) + @($application.keyCredentials))) { if ($null -eq $credential) { continue } $total++ $endsAt = $null if ($credential.PSObject.Properties['endDateTime'] -and $credential.endDateTime) { $endsAt = ([DateTime]$credential.endDateTime).ToUniversalTime() } if ($null -eq $endsAt) { continue } if ($null -eq $soonest -or $endsAt -lt $soonest) { $soonest = $endsAt } if ($endsAt -lt $utcNow) { $expired++ } elseif ($endsAt -lt $utcNow.AddDays(30)) { $expiringSoon++ } } $passwordCount = @($application.passwordCredentials).Count Add-Member -InputObject $application -NotePropertyName '_tlCredentialStatus' -NotePropertyValue ([pscustomobject]@{ total = $total passwordCredentials = $passwordCount expired = $expired expiringWithin30Days = $expiringSoon soonestEndUtc = $(if ($soonest) { $soonest.ToString('o') } else { $null }) }) -Force $risky = @() foreach ($resource in @($application.requiredResourceAccess)) { if ($null -eq $resource -or [string]$resource.resourceAppId -ne $graphResourceAppId) { continue } foreach ($access in @($resource.resourceAccess)) { if ([string]$access.type -eq 'Role' -and $riskyGraphAppRoles.ContainsKey([string]$access.id)) { $risky += $riskyGraphAppRoles[[string]$access.id] } } } Add-Member -InputObject $application -NotePropertyName '_tlRiskyPermissions' -NotePropertyValue @($risky | Sort-Object -Unique) -Force Add-Member -InputObject $application -NotePropertyName '_tlOwnerCount' -NotePropertyValue (@($application.owners).Count) -Force } @{ applications = $applications servicePrincipals = $servicePrincipals } } } |