Private/Get-AACM365AssessmentQuery.ps1
|
function Get-AACM365AssessmentQuery { <# .SYNOPSIS The Microsoft Graph calls of Invoke-AACM365Assessment: each one's URI, the section it belongs to and the permission it needs. .DESCRIPTION -Section picks Entra, Microsoft365 and Intune (all by default). Returns an ordered hashtable: name -> @{ Uri; Section; Data (what it reads, for the Permissions table); Permission (the least Microsoft Graph permission, delegated or application); Note }, and for a few: Fallback the URI to read instead when Uri is refused (Users: without the last sign-in, which needs Entra ID P1) Lookup Users: not listed but looked up - the principals of the role assignments, the users Conditional Access excludes, and break-glass-like names - {0} a $filter DependsOn read in a second round, Uri's {0} filled from that query's id (GraphAppRoleGrants: Microsoft Graph's service principal) MaxItems read no more than this many (LegacySignIns: Uri is a template - {0} the start date, {1} a protocol - read once per legacy protocol) Everything is read-only and v1.0, except Intune's endpoint security profiles (configurationPolicies, intents and templates), which exist only in the beta API. #> [CmdletBinding()] [OutputType([System.Collections.Specialized.OrderedDictionary])] param( [ValidateSet('Entra', 'Microsoft365', 'Intune')] [string[]] $Section = @('Entra', 'Microsoft365', 'Intune') ) $v1 = 'https://graph.microsoft.com/v1.0' $beta = 'https://graph.microsoft.com/beta' $all = [ordered]@{ # --- Entra ID --------------------------------------------------------------------------------------------- Organization = @{ Section = 'Entra'; Data = 'Tenant details'; Permission = 'Organization.Read.All'; Uri = "$v1/organization?`$select=id,displayName,verifiedDomains,createdDateTime,tenantType,onPremisesSyncEnabled,onPremisesLastSyncDateTime,technicalNotificationMails,securityComplianceNotificationMails,countryLetterCode,preferredDataLocation" } Licenses = @{ Section = 'Entra'; Data = 'Licences (subscribed SKUs)'; Permission = 'Organization.Read.All'; Uri = "$v1/subscribedSkus" } SecurityDefaults = @{ Section = 'Entra'; Data = 'Security defaults'; Permission = 'Policy.Read.All'; Uri = "$v1/policies/identitySecurityDefaultsEnforcementPolicy" } AuthorizationPolicy = @{ Section = 'Entra'; Data = 'User and guest settings (authorization policy)'; Permission = 'Policy.Read.All'; Uri = "$v1/policies/authorizationPolicy" } AuthenticationMethods = @{ Section = 'Entra'; Data = 'Authentication methods policy'; Permission = 'Policy.Read.All'; Uri = "$v1/policies/authenticationMethodsPolicy" } CrossTenantAccess = @{ Section = 'Entra'; Data = 'Cross-tenant access defaults'; Permission = 'Policy.Read.All'; Uri = "$v1/policies/crossTenantAccessPolicy/default" } ConditionalAccess = @{ Section = 'Entra'; Data = 'Conditional Access policies'; Permission = 'Policy.Read.All'; Uri = "$v1/identity/conditionalAccess/policies" } NamedLocations = @{ Section = 'Entra'; Data = 'Named locations'; Permission = 'Policy.Read.All'; Uri = "$v1/identity/conditionalAccess/namedLocations" } RoleDefinitions = @{ Section = 'Entra'; Data = 'Directory role definitions'; Permission = 'RoleManagement.Read.Directory'; Uri = "$v1/roleManagement/directory/roleDefinitions?`$select=id,displayName,isBuiltIn,isPrivileged,templateId" } RoleAssignments = @{ Section = 'Entra'; Data = 'Active admin role assignments'; Permission = 'RoleManagement.Read.Directory'; Uri = "$v1/roleManagement/directory/roleAssignments?`$expand=principal" } RoleEligibility = @{ Section = 'Entra'; Data = 'Eligible admin role assignments (PIM)'; Permission = 'RoleManagement.Read.Directory'; Note = 'Needs Entra ID P2 (Privileged Identity Management).'; Uri = "$v1/roleManagement/directory/roleEligibilityScheduleInstances" } Registration = @{ Section = 'Entra'; Data = 'MFA registration of every user'; Permission = 'AuditLog.Read.All'; Note = 'Needs Entra ID P1 or P2.'; Uri = "$v1/reports/authenticationMethods/userRegistrationDetails" } IdentityProviders = @{ Section = 'Entra'; Data = 'External identity providers'; Permission = 'IdentityProvider.Read.All'; Uri = "$v1/identity/identityProviders" } # Not every user: the admins, the accounts Conditional Access excludes # and break-glass-like names - looked up by ID ({0}: a $filter). Users = @{ Section = 'Entra'; Data = 'Admins'' and excluded accounts'' last sign-in'; Permission = 'User.Read.All'; Note = 'The last sign-in needs AuditLog.Read.All and Entra ID P1; without them they are read without it.'; Uri = "$v1/users?`$filter={0}&`$select=id,displayName,userPrincipalName,accountEnabled,userType,onPremisesSyncEnabled,createdDateTime,signInActivity&`$top=999"; Fallback = "$v1/users?`$filter={0}&`$select=id,displayName,userPrincipalName,accountEnabled,userType,onPremisesSyncEnabled,createdDateTime&`$top=999"; DependsOn = 'RoleAssignments'; Lookup = $true } AdminConsentPolicy = @{ Section = 'Entra'; Data = 'Admin consent workflow'; Permission = 'Policy.Read.All'; Uri = "$v1/policies/adminConsentRequestPolicy" } LegacySignIns = @{ Section = 'Entra'; Data = 'Sign-ins with legacy authentication protocols'; Permission = 'AuditLog.Read.All'; Note = 'Needs Entra ID P1; one query per protocol, up to 200 sign-ins each.'; Uri = "$v1/auditLogs/signIns?`$filter=createdDateTime ge {0} and clientAppUsed eq '{1}'&`$top=200"; MaxItems = 200 } Applications = @{ Section = 'Entra'; Data = 'App registrations: credentials and redirect URIs'; Permission = 'Application.Read.All'; Uri = "$v1/applications?`$select=id,appId,displayName,passwordCredentials,keyCredentials,web,spa,publicClient,signInAudience,createdDateTime,publisherDomain&`$top=999" } ServicePrincipals = @{ Section = 'Entra'; Data = 'Enterprise applications: credentials and publishers'; Permission = 'Application.Read.All'; Uri = "$v1/servicePrincipals?`$select=id,appId,displayName,servicePrincipalType,accountEnabled,appOwnerOrganizationId,passwordCredentials,keyCredentials,verifiedPublisher,publisherName&`$top=999" } GraphServicePrincipal = @{ Section = 'Entra'; Data = 'Microsoft Graph''s permissions (app roles)'; Permission = 'Application.Read.All'; Uri = "$v1/servicePrincipals(appId='00000003-0000-0000-c000-000000000000')?`$select=id,appId,appRoles,oauth2PermissionScopes" } GraphAppRoleGrants = @{ Section = 'Entra'; Data = 'Application permissions granted on Microsoft Graph'; Permission = 'Application.Read.All'; Uri = "$v1/servicePrincipals/{0}/appRoleAssignedTo?`$top=999"; DependsOn = 'GraphServicePrincipal' } DelegatedGrants = @{ Section = 'Entra'; Data = 'Delegated permission grants (consents)'; Permission = 'DelegatedPermissionGrant.Read.All'; Uri = "$v1/oauth2PermissionGrants?`$top=999" } DirectorySync = @{ Section = 'Entra'; Data = 'Directory sync settings (Entra Connect)'; Permission = 'OnPremDirectorySynchronization.Read.All'; Uri = "$v1/directory/onPremisesSynchronization" } PimPolicies = @{ Section = 'Entra'; Data = 'PIM role settings (activation rules)'; Permission = 'RoleManagementPolicy.Read.Directory'; Note = 'Needs Entra ID P2.'; Uri = "$v1/policies/roleManagementPolicyAssignments?`$filter=scopeId eq '/' and scopeType eq 'DirectoryRole'&`$expand=policy(`$expand=rules)" } AccessReviews = @{ Section = 'Entra'; Data = 'Access reviews'; Permission = 'AccessReview.Read.All'; Note = 'Needs Entra ID P2 or Entra ID Governance.'; Uri = "$v1/identityGovernance/accessReviews/definitions?`$top=100" } # The groups Conditional Access excludes and the groups holding roles ({0}: a $filter), then their members. Groups = @{ Section = 'Entra'; Data = 'Groups excluded from Conditional Access or holding admin roles'; Permission = 'GroupMember.Read.All'; Uri = "$v1/groups?`$filter={0}&`$select=id,displayName,isAssignableToRole,groupTypes,membershipRule,securityEnabled"; DependsOn = 'ConditionalAccess'; Lookup = $true } GroupMembers = @{ Section = 'Entra'; Data = 'Members of those groups (nested included)'; Permission = 'GroupMember.Read.All'; Uri = "$v1/groups/{0}/transitiveMembers?`$select=id,displayName,userPrincipalName,userType,accountEnabled&`$top=999"; DependsOn = 'Groups'; MaxItems = 1000 } RiskyUsers = @{ Section = 'Entra'; Data = 'Risky users (Identity Protection)'; Permission = 'IdentityRiskyUser.Read.All'; Note = 'Needs Entra ID P2 for the full list.'; Uri = "$v1/identityProtection/riskyUsers?`$top=500"; MaxItems = 2000 } RiskDetections = @{ Section = 'Entra'; Data = 'Risk detections (Identity Protection)'; Permission = 'IdentityRiskEvent.Read.All'; Note = 'Needs Entra ID P2 for the full detail.'; Uri = "$v1/identityProtection/riskDetections?`$filter=detectedDateTime ge {since}&`$top=500"; MaxItems = 1000 } # --- Microsoft 365 ------------------------------------------------------------------------------------------ Domains = @{ Section = 'Microsoft365'; Data = 'Domains'; Permission = 'Domain.Read.All'; Uri = "$v1/domains" } SecureScore = @{ Section = 'Microsoft365'; Data = 'Microsoft Secure Score'; Permission = 'SecurityEvents.Read.All'; Uri = "$v1/security/secureScores?`$top=1"; MaxItems = 1 } SecureScoreProfiles = @{ Section = 'Microsoft365'; Data = 'Secure Score control profiles'; Permission = 'SecurityEvents.Read.All'; Uri = "$v1/security/secureScoreControlProfiles" } SharePoint = @{ Section = 'Microsoft365'; Data = 'SharePoint and OneDrive sharing settings'; Permission = 'SharePointTenantSettings.Read.All'; Uri = "$v1/admin/sharepoint/settings" } DirectoryAudits = @{ Section = 'Microsoft365'; Data = 'Entra audit log (latest event)'; Permission = 'AuditLog.Read.All'; Uri = "$v1/auditLogs/directoryAudits?`$top=1"; MaxItems = 1 } Incidents = @{ Section = 'Microsoft365'; Data = 'Microsoft Defender XDR incidents'; Permission = 'SecurityIncident.Read.All'; Uri = "$v1/security/incidents?`$top=50&`$orderby=lastUpdateDateTime desc"; MaxItems = 200 } UsageReport = @{ Section = 'Microsoft365'; Data = 'Microsoft 365 activity per user, last 30 days (beta)'; Permission = 'Reports.Read.All'; Note = 'User names are hidden when the tenant conceals them in reports (Microsoft 365 admin center > Reports).'; Uri = "$beta/reports/getOffice365ActiveUserDetail(period='D30')?`$format=application/json" } # --- Intune -------------------------------------------------------------------------------------------------- DeviceManagement = @{ Section = 'Intune'; Data = 'Intune tenant settings'; Permission = 'DeviceManagementConfiguration.Read.All'; Uri = "$v1/deviceManagement?`$select=settings" } EnrollmentRestrictions = @{ Section = 'Intune'; Data = 'Enrollment restrictions'; Permission = 'DeviceManagementServiceConfig.Read.All'; Uri = "$v1/deviceManagement/deviceEnrollmentConfigurations" } ComplianceSummary = @{ Section = 'Intune'; Data = 'Device compliance summary'; Permission = 'DeviceManagementConfiguration.Read.All'; Uri = "$v1/deviceManagement/deviceCompliancePolicyDeviceStateSummary" } CompliancePolicies = @{ Section = 'Intune'; Data = 'Compliance policies'; Permission = 'DeviceManagementConfiguration.Read.All'; Uri = "$v1/deviceManagement/deviceCompliancePolicies?`$expand=assignments" } ConfigurationPolicies = @{ Section = 'Intune'; Data = 'Endpoint security and settings catalog policies (beta)'; Permission = 'DeviceManagementConfiguration.Read.All'; Uri = "$beta/deviceManagement/configurationPolicies?`$select=id,name,platforms,technologies,templateReference,lastModifiedDateTime,isAssigned" } Intents = @{ Section = 'Intune'; Data = 'Endpoint security profiles from templates (beta)'; Permission = 'DeviceManagementConfiguration.Read.All'; Uri = "$beta/deviceManagement/intents?`$select=id,displayName,templateId,isAssigned,lastModifiedDateTime" } Templates = @{ Section = 'Intune'; Data = 'Endpoint security templates (beta)'; Permission = 'DeviceManagementConfiguration.Read.All'; Uri = "$beta/deviceManagement/templates?`$select=id,displayName,templateType,templateSubtype" } ManagedDevices = @{ Section = 'Intune'; Data = 'Intune managed devices'; Permission = 'DeviceManagementManagedDevices.Read.All'; Uri = "$v1/deviceManagement/managedDevices?`$select=id,deviceName,operatingSystem,osVersion,complianceState,managementAgent,managedDeviceOwnerType,lastSyncDateTime,enrolledDateTime,userPrincipalName,isEncrypted,jailBroken,model,manufacturer,azureADDeviceId,deviceEnrollmentType&`$top=999" } AppProtectionIos = @{ Section = 'Intune'; Data = 'App protection policies: iOS/iPadOS'; Permission = 'DeviceManagementApps.Read.All'; Uri = "$v1/deviceAppManagement/iosManagedAppProtections?`$expand=assignments" } AppProtectionAndroid = @{ Section = 'Intune'; Data = 'App protection policies: Android'; Permission = 'DeviceManagementApps.Read.All'; Uri = "$v1/deviceAppManagement/androidManagedAppProtections?`$expand=assignments" } EntraDevices = @{ Section = 'Intune'; Data = 'Entra ID devices (managed or not)'; Permission = 'Device.Read.All'; Uri = "$v1/devices?`$select=id,deviceId,displayName,operatingSystem,operatingSystemVersion,isManaged,isCompliant,trustType,approximateLastSignInDateTime,accountEnabled,registrationDateTime&`$top=999" } } $picked = [ordered]@{} foreach ($key in $all.Keys) { if ($Section -contains $all[$key].Section) { $picked[$key] = $all[$key] } } $picked } |