Private/Initialize-EntraService.ps1
|
function Initialize-EntraService { <# .SYNOPSIS Initializes the Entra ID service by pre-loading all required resources. .DESCRIPTION Loads Entra ID (Azure AD) resources from Microsoft Graph API and caches them in $script:EntraService for use by check scripts. This follows the singleton service pattern to avoid redundant API calls. Resources loaded: - Users and their MFA registration status - Directory roles and role members - Security defaults policy - Authorization policy settings - Conditional access policies - Named locations - Group settings .EXAMPLE Initialize-EntraService $script:EntraService.Users # Access cached users #> [CmdletBinding()] [OutputType([void])] param() $ErrorActionPreference = 'Stop' $graphApiBase = $script:Config.azure.endpoints.graphApi # Initialize service hashtable $script:EntraService = @{ Users = $null UserMFAStatus = $null DirectoryRoles = $null DirectoryRoleMembers = @{} SecurityDefaults = $null AuthorizationPolicy = $null ConditionalAccessPolicies = $null NamedLocations = $null GroupSettings = $null } # Load paginated resources Write-Verbose "Loading users..." $usersUri = "$graphApiBase/users?`$select=id,displayName,userPrincipalName,accountEnabled,userType" $script:EntraService.Users = @(Get-AllGraphPage -Uri $usersUri -ResourceName "Users") Write-Verbose "Loading user MFA status..." $mfaUri = "$graphApiBase/reports/authenticationMethods/userRegistrationDetails" $script:EntraService.UserMFAStatus = @(Get-AllGraphPage -Uri $mfaUri -ResourceName "UserMFAStatus") # Define non-paginated API endpoints to load - data-driven pattern $apiEndpoints = @{ DirectoryRoles = 'directoryRoles' SecurityDefaults = 'policies/identitySecurityDefaultsEnforcementPolicy' AuthorizationPolicy = 'policies/authorizationPolicy' ConditionalAccessPolicies = 'identity/conditionalAccess/policies' NamedLocations = 'identity/conditionalAccess/namedLocations' GroupSettings = 'groupSettings' } foreach ($endpoint in $apiEndpoints.GetEnumerator()) { $params = @{ Uri = "$graphApiBase/$($endpoint.Value)" ResourceName = $endpoint.Key } $script:EntraService[$endpoint.Key] = Invoke-AzureApi @params } # Load members for each directory role if ($script:EntraService.DirectoryRoles) { foreach ($role in $script:EntraService.DirectoryRoles) { $params = @{ Uri = "$graphApiBase/directoryRoles/$($role.id)/members" ResourceName = "DirectoryRole Members ($($role.displayName))" } $script:EntraService.DirectoryRoleMembers[$role.id] = Invoke-AzureApi @params } } # Log summary $counts = @{ Users = if ($script:EntraService.Users) { $script:EntraService.Users.Count } else { 0 } Roles = if ($script:EntraService.DirectoryRoles) { $script:EntraService.DirectoryRoles.Count } else { 0 } Policies = if ($script:EntraService.ConditionalAccessPolicies) { $script:EntraService.ConditionalAccessPolicies.Count } else { 0 } } Write-Verbose "Entra service initialized: $($counts.Users) users, $($counts.Roles) roles, $($counts.Policies) conditional access policies" } |