GraphTools.psm1
using namespace System.Management.Automation #Region '.\Classes\completer_gApp_DisplayName.ps1' 0 #using namespace System.Management.Automation class completer_gApp_DisplayName : IArgumentCompleter { [System.Collections.Generic.IEnumerable[CompletionResult]] CompleteArgument( [string]$CommandName, [string]$ParameterName, [string]$WordToComplete, [Language.CommandAst]$CommandAst, [System.Collections.IDictionary] $FakeBoundParameters ) { $result = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new() if ($wordToComplete) { $wordToComplete = $wordToComplete -replace '"|''', '' arg_gApp_DisplayName -WordToComplete $WordToComplete | ForEach-Object DisplayName | Sort-Object | ForEach-Object { $result.Add([System.Management.Automation.CompletionResult]::new("'$_'", $_, ([CompletionResultType]::ParameterValue) , $_) ) } } return $result } } #EndRegion '.\Classes\completer_gApp_DisplayName.ps1' 18 #Region '.\Classes\completer_gUser_Deleted_DisplayName.ps1' 0 #using namespace System.Management.Automation class completer_gUser_Deleted_DisplayName : IArgumentCompleter { [System.Collections.Generic.IEnumerable[CompletionResult]] CompleteArgument( [string]$CommandName, [string]$ParameterName, [string]$WordToComplete, [Language.CommandAst]$CommandAst, [System.Collections.IDictionary] $FakeBoundParameters ) { $result = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new() if ($wordToComplete) { $wordToComplete = $wordToComplete -replace '"|''', '' arg_gUser_Deleted_DisplayName -WordToComplete $WordToComplete | ForEach-Object DisplayName | Sort-Object | ForEach-Object { $result.Add([System.Management.Automation.CompletionResult]::new("'$_'", $_, ([CompletionResultType]::ParameterValue) , $_) ) } } return $result } } #EndRegion '.\Classes\completer_gUser_Deleted_DisplayName.ps1' 17 #Region '.\Classes\completer_gUser_DisplayName.ps1' 0 #using namespace System.Management.Automation class completer_gUser_DisplayName : IArgumentCompleter { [System.Collections.Generic.IEnumerable[CompletionResult]] CompleteArgument( [string]$CommandName, [string]$ParameterName, [string]$WordToComplete, [Language.CommandAst]$CommandAst, [System.Collections.IDictionary] $FakeBoundParameters ) { $result = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new() if ($wordToComplete) { $wordToComplete = $wordToComplete -replace '"|''', '' arg_gUser_DisplayName -WordToComplete $WordToComplete | ForEach-Object DisplayName | Sort-Object | ForEach-Object { $result.Add([System.Management.Automation.CompletionResult]::new("'$_'", $_, ([CompletionResultType]::ParameterValue) , $_) ) } } return $result } } #EndRegion '.\Classes\completer_gUser_DisplayName.ps1' 17 #Region '.\Private\ArgumentsForCompleters\arg_gApp_DisplayName.ps1' 0 function arg_gApp_DisplayName { [CmdletBinding()] param ( [Parameter()] $WordToComplete ) $RestSplat = @{ Uri = "https://graph.microsoft.com/beta/applications?`$filter={0}&top=20&select=DisplayName" -f ( [System.Web.HttpUtility]::UrlEncode(('startswith({0}, ''{1}'')' -f 'DisplayName', $WordToComplete )) ) Headers = @{ ConsistencyLevel = 'Eventual' Authorization = "Bearer $Script:Token" } Method = 'Get' } (Invoke-RestMethod @RestSplat).value } #EndRegion '.\Private\ArgumentsForCompleters\arg_gApp_DisplayName.ps1' 22 #Region '.\Private\ArgumentsForCompleters\arg_gUser_Deleted_DisplayName.ps1' 0 function arg_gUser_Deleted_DisplayName { <# .SYNOPSIS Interactive use only. Used for autocompletion of user arguments. .PARAMETER WordToComplete Specifies the user you want to autocomplete at the command line. .NOTES This function only works with the Beta endpoint. #> [CmdletBinding()] param ( [Parameter()] $WordToComplete ) $RestSplat = @{ Uri = "https://graph.microsoft.com/beta/directory/deletedItems/microsoft.graph.user?`$filter={0}&top=50&select=DisplayName" -f ( [System.Web.HttpUtility]::UrlEncode(('startswith({0}, ''{1}'')' -f 'DisplayName', $WordToComplete )) ) Headers = @{ ConsistencyLevel = 'Eventual' Authorization = "Bearer $Script:Token" } Method = 'Get' } (Invoke-RestMethod @RestSplat).value } #EndRegion '.\Private\ArgumentsForCompleters\arg_gUser_Deleted_DisplayName.ps1' 32 #Region '.\Private\ArgumentsForCompleters\arg_gUser_DisplayName.ps1' 0 function arg_gUser_DisplayName { <# .SYNOPSIS Interactive use only. Used for autocompletion of user arguments. .PARAMETER WordToComplete Specifies the user you want to autocomplete at the command line. .NOTES This function only works with the Beta endpoint. #> [CmdletBinding()] param ( [Parameter()] $WordToComplete ) $RestSplat = @{ Uri = "https://graph.microsoft.com/beta/users?`$filter={0}&top=50&select=DisplayName" -f ( [System.Web.HttpUtility]::UrlEncode(('startswith({0}, ''{1}'')' -f 'DisplayName', $WordToComplete )) ) Headers = @{ ConsistencyLevel = 'Eventual' Authorization = "Bearer $Script:Token" } Method = 'Get' } (Invoke-RestMethod @RestSplat).value } #EndRegion '.\Private\ArgumentsForCompleters\arg_gUser_DisplayName.ps1' 32 #Region '.\Private\Connect\Connect-gGraphMI.ps1' 0 function Connect-gGraphMI { <# .DESCRIPTION Connect with Managed Identity to Graph API #> [CmdletBinding()] param () $resourceURI = 'https://graph.microsoft.com/' $tokenAuthURI = $env:IDENTITY_ENDPOINT + "?resource=$resourceURI&api-version=2019-08-01" $tokenResponse = Invoke-RestMethod -Method Get -Headers @{"X-IDENTITY-HEADER" = "$env:IDENTITY_HEADER" } -Uri $tokenAuthURI $Script:Token = $tokenResponse.access_token } #EndRegion '.\Private\Connect\Connect-gGraphMI.ps1' 16 #Region '.\Private\Filter\New-gFilterString.ps1' 0 function New-gFilterString { param ( [validatescript({ if ($_ -is [string] -and $_ -match '\*.*\*|^\*$') { throw [ParameterBindingException]::new("Wildcard cannot be '*something*' or just '*'") } else { $true } })] [parameter(position = 0, mandatory = $true)] [string] $SearchTerm, [parameter(position = 1)] [string] $SearchField, [parameter()] $ExtraFields = @(), [switch] $ToLower ) # Adapted from James O'Neil https://youtu.be/hXFbfwmdNsU: https://github.com/jhoneill/MsftGraph if ($toLower) { $SearchTerm = $SearchTerm.ToLower() } if ($Searchterm -as [mailaddress] -and (-not $SearchField)) { $SearchField = 'userPrincipalName' } #Replace ' with '' - ensure we don't turn '' into '''' ! $SearchTerm = $SearchTerm -replace "(?<!')'(?!')" , "''" #validation blocked "* and *something*" so we have no *, * at the start, in the middle, or at the end # if ($SearchField -eq 'proxyAddresses') { $filterStrings = , "{0}/any(p:endsWith(p, '{1}'))" -f $SearchField, $SearchTerm } if ($SearchTerm -notmatch '\*') { $filterStrings = , "$SearchField eq '$SearchTerm'" } elseif ($SearchTerm -match '^\*(.+)') { $filterStrings = , "endswith($SearchField,'$($Matches[1])')" } elseif ($SearchTerm -match '(.+)\*$') { $filterStrings = , "startswith($SearchField,'$($Matches[1])')" } elseif ($SearchTerm -match '^(.+)\*(.+)$') { $filterStrings = , ("(startswith($SearchField,'$($Matches[1])')" + " and endswith($SearchField,'$($Matches[2])'))" ) } if ($ToLower) { $filterStrings[0] = $filterStrings[0] -replace "$SearchField" , "toLower($SearchField)" } foreach ($f in $ExtraFields) { $filterStrings += $filterStrings[0] -replace "$SearchField", $f } $filterStrings -join ' or ' } #EndRegion '.\Private\Filter\New-gFilterString.ps1' 43 #Region '.\Private\Rest\Invoke-gRestMethod.ps1' 0 function Invoke-gRestMethod { <# .SYNOPSIS Invokes a REST method with various options. This is a private function, only used interally by other functions. .DESCRIPTION This function allows invoking a REST method with customizable parameters such as URI, HTTP method, request body, and eventual consistency. .PARAMETER Uri The URI of the REST API endpoint to invoke. .PARAMETER Method The HTTP method to use for the request. Valid values are GET, POST, DELETE, and PATCH. (Default: GET) .PARAMETER Body The request body to include in the REST request. .PARAMETER Eventual Specifies whether to use eventual consistency for the request. If specified, the 'ConsistencyLevel' header will be set to 'Eventual'. .EXAMPLE Invoke-gRestMethod -Uri 'https://api.example.com/resource' -Method GET Invokes a GET request to the specified URI. .NOTES This is a private function that requires a script-scoped token variable and is meant to be executed only by other functions within the module. #> param ( [Parameter()] $Uri, [Parameter()] [validateset('GET', 'POST', 'DELETE', 'PATCH')] $Method = 'GET', [Parameter()] $Body, [Parameter()] [switch] $Eventual ) $RestSplat = @{ Uri = $Uri Method = $Method Headers = @{ 'Content-Type' = 'application/json' } Verbose = $false } if ($Eventual) { $RestSplat['Headers']['ConsistencyLevel'] = 'Eventual' } if ($Body) { $RestSplat['Body'] = $Body } do { try { while ((-not $script:Token) -or ([DateTime]::UtcNow -ge $script:TokenExpirationTime )) { Connect-gGraph -ClientID $Script:ClientID -TenantID $Script:TenantID -Secret $Script:Secret } $RestSplat['Headers']['Authorization'] = "Bearer $Script:Token" # Send the response $Response = Invoke-RestMethod @RestSplat $Response # If page, and didn't catch, update Next $RestSplat['Uri'] = $Response.'@odata.nextLink' } catch { if ($_.Exception.Response.StatusCode -eq 429) { Write-Verbose ('IWR ERROR [ 429 ] SLEEPING FOR [ {0} ] SECONDS' -f $_.Exception.Response.Headers.GetValues('Retry-After')[0]) Start-Sleep -Seconds $_.Exception.Response.Headers.GetValues('Retry-After')[0] } elseif ($_.Exception.Response.StatusCode -eq 401) { Write-Verbose ('IWR ERROR [ {0} ] CONNECT THEN SLEEP FOR [ 5 ] SECONDS' -f $_.Exception.Response.StatusCode) Connect-gGraph -ClientID $Script:ClientID -TenantID $Script:TenantID -Secret $Script:Secret Start-Sleep -Seconds 5 } else { $PSCmdlet.WriteError($PSItem) Write-Verbose ('STOPPING! IWR ERROR [ {0} ] URI [ {1} ] EXCEPTION [ {2} ]' -f $_.Exception.Response.StatusCode, $RestSplat['Uri'], $_) Return } } } while ($RestSplat['Uri']) } #EndRegion '.\Private\Rest\Invoke-gRestMethod.ps1' 97 #Region '.\Private\Rest\Set-gToken.ps1' 0 function Set-gToken { [CmdletBinding()] param ( [Parameter(Mandatory)] $Token, [Parameter(Mandatory)] $TokenExpirationTime, [Parameter(Mandatory)] $ClientID, [Parameter(Mandatory)] $TenantID, [Parameter(Mandatory)] $Secret ) $Script:Token = $Token $Script:TokenExpirationTime = $TokenExpirationTime $Script:ClientID = $ClientID $Script:TenantID = $TenantID $Script:Secret = $Secret } #EndRegion '.\Private\Rest\Set-gToken.ps1' 27 #Region '.\Private\Scope\Set-gToken.ps1' 0 function Set-gToken { [CmdletBinding()] param ( [Parameter(Mandatory)] $Token, [Parameter()] $ClientID, [Parameter()] $TenantID, [Parameter()] $Secret, [Parameter()] $TokenExpirationTime ) $Script:Token = $Token $Script:ClientID = $ClientID $Script:Secret = $Secret $Script:TenantID = $TenantID $Script:TokenExpirationTime = $TokenExpirationTime } #EndRegion '.\Private\Scope\Set-gToken.ps1' 28 #Region '.\Private\User\Get-gUserAll.ps1' 0 function Get-gUserAll { [CmdletBinding()] param ( [Parameter()] $ThrottleLimit = 8, [Parameter()] [string] $Select, [Parameter()] [switch] $Beta ) $UserCount = Invoke-gRestMethod -Uri "https://graph.microsoft.com/v1.0/users/`$count" -Method 'GET' -Eventual Write-Verbose "Getting $($UserCount) users. . . " $ModuleBase = $MyInvocation.MyCommand.Module.Path '!#$%&*+-/0123456789=?ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`{|}~'.toCharArray() | ForEach-Object -ThrottleLimit $ThrottleLimit -Parallel { $Character = "$_" Import-Module $using:ModuleBase -Force $TokenSplat = @{ Token = $using:Token TokenExpirationTime = $using:TokenExpirationTime ClientID = $using:ClientID TenantId = $using:TenantID Secret = $using:Secret } Set-gToken @TokenSplat $Uri = 'https://graph.microsoft.com/{0}/users?$filter={1}' -f @( if ($using:Beta) { 'beta' } else { 'v1.0' } [System.Web.HttpUtility]::UrlEncode(('startswith({0}, ''{1}'')' -f 'mailnickname', "$Character" )) ) if ($using:Select) { $Uri = '{0}&$Select={1}' -f $Uri, $using:Select } $splat = @{ Uri = $Uri ErrorAction = 'Stop' } try { (Invoke-gRestMethod @splat).value } catch { Write-Error -ErrorRecord $_ } } } #EndRegion '.\Private\User\Get-gUserAll.ps1' 55 #Region '.\Private\User\Get-gUserDeletedAll.ps1' 0 function Get-gUserDeletedAll { [CmdletBinding()] param ( [Parameter()] $ThrottleLimit = 8, [Parameter()] [string] $Select, [Parameter()] [switch] $Beta ) $ModuleBase = $MyInvocation.MyCommand.Module.Path '!#$%&*+-/0123456789=?ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`{|}~'.toCharArray() | ForEach-Object -ThrottleLimit $ThrottleLimit -Parallel { $Character = "$_" Import-Module $using:ModuleBase -Force $TokenSplat = @{ Token = $using:Token TokenExpirationTime = $using:TokenExpirationTime ClientID = $using:ClientID TenantId = $using:TenantID Secret = $using:Secret } Set-gToken @TokenSplat if (-not $using:Beta) { $Uri = "https://graph.microsoft.com/v1.0/directory/deletedItems/microsoft.graph.user?`$filter={0}" -f ( [System.Web.HttpUtility]::UrlEncode(('startswith({0}, ''{1}'')' -f 'mailnickname', "$Character" )) ) } else { $Uri = "https://graph.microsoft.com/beta/directory/deletedItems/microsoft.graph.user?`$filter={0}" -f ( [System.Web.HttpUtility]::UrlEncode(('startswith({0}, ''{1}'')' -f 'mailnickname', "$Character" )) ) } if ($using:Select) { $Uri = '{0}&$Select={1}' -f $Uri, $using:Select } $splat = @{ Uri = $Uri Method = 'GET' ErrorAction = 'Stop' # Eventual = $true } try { (Invoke-gRestMethod @splat).value } catch { Write-Error -ErrorRecord $_ } } } #EndRegion '.\Private\User\Get-gUserDeletedAll.ps1' 63 #Region '.\Public\App\Get-gApp.ps1' 0 function Get-gApp { [CmdletBinding(DefaultParameterSetName = 'All')] param ( [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ByApp')] [ArgumentCompleter([completer_gApp_DisplayName])] [object] $App, [Parameter(Mandatory, ParameterSetName = 'ByAppID')] [guid] $AppId, [Parameter()] [string] $Select, [Parameter()] [string] $Filter ) begin { if ($PSCmdlet.ParameterSetName -eq 'All') { $splat = @{ Uri = 'https://graph.microsoft.com/v1.0/applications/' } (Invoke-gRestMethod @splat).value return } } process { if ($PSCmdlet.ParameterSetName -eq 'All') { return } foreach ($Item in $App) { $filterstring = if ($Item -match "\*+") { "?`$filter={0}" -f (New-gFilterString $Item -SearchField 'DisplayName') } elseif (-not $AppID -and ($Item -is [string] -and $Item -as [Guid])) { $Item } elseif ($PSCmdlet.ParameterSetName -eq 'ByAppId') { "?`$filter=AppId eq '{0}'" -f $Item } elseif ($Item -is [string]) { "?`$filter=DisplayName eq '{0}'" -f $Item } elseif ($Item.Id -and $Item.Id -as [guid]) { $Item.Id } elseif ($Item.DisplayName) { "?`$filter=DisplayName eq '{0}'" -f $Item.DisplayName } if ($Select) { $filterstring = '{0}&$Select={1}' -f $filterstring, $Select } if ($Filter) { $filterstring = '{0}&$filter={1}' -f $filterstring, $Filter } $splat = @{ Uri = 'https://graph.microsoft.com/v1.0/applications/{0}' -f $filterstring } Write-Host ("URI {0}" -f $splat['Uri']) if ($filterstring -like '*filter=*') { if ($filterstring -like '*endswith*') { $splat['Eventual'] = $true $splat['Uri'] = '{0}&$count=true' -f $Uri } (Invoke-gRestMethod @splat).value continue } Invoke-gRestMethod @splat } } } #EndRegion '.\Public\App\Get-gApp.ps1' 59 #Region '.\Public\Connect\Connect-gGraph.ps1' 0 function Connect-gGraph { <# .DESCRIPTION Connect with Client Credential Flow to Graph API .PARAMETER ClientID Client ID of the Azure AD App Registration .PARAMETER TenantID Tenant ID of the Azure AD App Registration .PARAMETER Secret The Secret from the Azure AD App Registration .PARAMETER ManagedIdentity If set, connects to the Graph API using Managed Identity .EXAMPLE Connect-gGraph -ClientID "yourClientID" -TenantID "yourTenantID" -Secret "yourSecret" Connects to the Graph API using the specified client credentials. .EXAMPLE Connect-gGraph -ClientID "yourClientID" -TenantID "yourTenantID" -Secret "yourSecret" -Verbose Connects to the Graph API using the specified client credentials with verbose output for interactive execution. .EXAMPLE Connect-gGraph -ManagedIdentity Connects to the Graph API using Managed Identity. #> [CmdletBinding()] param ( [Parameter(ParameterSetName = 'AppReg')] $ClientID, [Parameter(ParameterSetName = 'AppReg')] $TenantID, [Parameter(ParameterSetName = 'AppReg')] $Secret, [Parameter(ParameterSetName = 'ManagedIdentity')] [switch] $ManagedIdentity ) if ($ManagedIdentity) { Connect-gGraphMI } do { try { $Request = @{ Method = 'POST' ErrorAction = 'Stop' Body = @{ Grant_Type = 'client_credentials' Client_Id = $ClientID Client_Secret = $Secret Scope = 'https://graph.microsoft.com/.default' } Uri = 'https://login.microsoftonline.com/{0}/oauth2/v2.0/token' -f $TenantID } $Response = Invoke-RestMethod @Request $Script:ClientID = $ClientID $Script:TenantId = $TenantID $Script:Secret = $Secret } catch { if ($_.Exception -like '*transport*' -or $_.Exception -like '*invalid pointer*' ) { # Transport Error $TransportError++ $PSCmdlet.WriteError($_) Write-Verbose ('Retrying Transport Error. Retried {0} times.' -f $TransportError) if ($TransportError -ge 200) { Write-Verbose ('STOPPING! Retried {0} times. Halting this call!' -f $TransportError) break } } else { # Something unexpected went wrong Write-Verbose ('Continuing ! Something other than Transport Error occurred {0}' -f $_) continue } } } until ($Response.access_token) $Script:TokenExpirationTime = ([datetime]::UtcNow).AddSeconds($Response.'expires_in' - 120) $Script:Token = $Response.access_token } #EndRegion '.\Public\Connect\Connect-gGraph.ps1' 95 #Region '.\Public\Directory\Get-gDirectoryExtension.ps1' 0 function Get-gDirectoryExtension { <# .SYNOPSIS List extensions registered to an app .DESCRIPTION This function retrieves the list of extensions that are registered to a specific app. It uses the Microsoft Graph API and the provided app ID (or object) to get this information. .PARAMETER App Object representing the app. This can be an app object from the pipeline or an application ID. .EXAMPLE Get-gDirectoryExtension -App 13c18f60-226c-457c-ac82-c0da4550d524 .NOTES This function requires an existing connection to the Microsoft Graph API. #> [CmdletBinding(DefaultParameterSetName = 'Placeholder')] param ( [Parameter( Mandatory, ValueFromPipeline, ParameterSetName = 'pipeline' )] [ArgumentCompleter([completer_gApp_DisplayName])] [object] $App ) process { $AppList = foreach ($Item in $App) { try { Get-gApp -App $Item } catch { $PSCmdlet.WriteError($_) } } foreach ($thisApp in $AppList) { $Uri = "https://graph.microsoft.com/v1.0/applications/{0}/extensionProperties" -f $thisApp.Id $RestSplat = @{ Uri = $Uri Method = 'GET' } $ExtensionList = (Invoke-gRestMethod @RestSplat).value foreach ($Extension in $ExtensionList) { [PSCustomObject]@{ App = $thisApp.DisplayName AppId = $thisApp.Id Name = $Extension.name DataType = $Extension.dataType Id = $Extension.Id DeletedDateTime = $Extension.deletedDateTime AppDisplayName = $Extension.appDisplayName isMultiValued = $Extension.isMultiValued isSyncedFromOnPremises = $Extension.isSyncedFromOnPremises TargetObjects = @($Extension.targetObjects) -ne '' -join ', ' } } } } } #EndRegion '.\Public\Directory\Get-gDirectoryExtension.ps1' 64 #Region '.\Public\Directory\New-gDirectoryExtension.ps1' 0 function New-gDirectoryExtension { <# .SYNOPSIS This function creates a new application extension with the specified properties. .DESCRIPTION The New-gDirectoryExtension function is used to create an application extension with a given name, application ID, data type, and target object. It uses Microsoft Graph API to create the application extension. .PARAMETER Name This is the name of the application extension. This is a mandatory parameter. .PARAMETER ApplicationID This is the application ID for which the extension is to be created. This is a mandatory parameter. .PARAMETER dataType This is the type of data that the extension will store. This can be one of the following: 'String', 'Binary', 'Boolean', 'DateTime', 'Integer', 'LargeInteger'. This is a mandatory parameter. .PARAMETER TargetObjects This is the target object to which the extension applies. It can be one of the following: 'User', 'Group', 'Organization', 'Device', 'Application'. This is a mandatory parameter. .EXAMPLE New-gDirectoryExtension -Name extension_edc06b6cff794fb28be5bf7b17cf9ab1_Region -ApplicationID edc06b6c-ff79-4fb2-8be5-bf7b17cf9ab1 -dataType String -TargetObjects User This example creates an application extension with the name 'extension_edc06b6cff794fb28be5bf7b17cf9ab1_Region'. Here, 'edc06b6cff794fb28be5bf7b17cf9ab1' is the application ID 'edc06b6c-ff79-4fb2-8be5-bf7b17cf9ab1', but with the hyphens removed. The data type for this extension is 'String' and the target object is 'User'. .NOTES The function uses the Microsoft Graph API, so it requires the application to have the appropriate permissions to create an extension property in the application identified by the ApplicationID parameter. #> [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $Name, [Parameter(Mandatory)] [string] $ApplicationID, [Parameter(Mandatory)] [ValidateSet('String', 'Binary', 'Boolean', 'DateTime', 'Integer', 'LargeInteger')] $dataType, [Parameter(Mandatory)] [ValidateSet('User', 'Group', 'Organization', 'Device', 'Application')] $TargetObjects ) if (-not ($ApplicationID -as [guid])) { return } $Body = @{ name = $Name dataType = $dataType targetObjects = @( $TargetObjects ) } $RestSplat = @{ Uri = "https://graph.microsoft.com/v1.0/applications/{0}/extensionProperties" -f $ApplicationID Body = $Body | ConvertTo-Json Method = 'POST' } Invoke-gRestMethod @RestSplat } #EndRegion '.\Public\Directory\New-gDirectoryExtension.ps1' 73 #Region '.\Public\Parallel\Invoke-gParallel.ps1' 0 function Invoke-gParallel { [CmdletBinding(DefaultParameterSetName = 'FromPipeline')] param ( [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FromPipeline')] [object[]] $Object, [Parameter(Mandatory, ParameterSetName = 'FromFile')] [ValidateScript( { Test-Path $_ } )] [string] $SourceFilePath, [Parameter(Mandatory)] [string] $Endpoint, [Parameter(Mandatory)] [string] $Field, [Parameter()] [int] $ThrottleLimit = 8 ) begin { $objects = [System.Collections.Generic.List[object]]::new() } process { if ($PSCmdlet.ParameterSetName -eq 'FromPipeline') { $objects.AddRange($Object) } } end { if ($PSCmdlet.ParameterSetName -eq 'FromFile') { $objects = Import-Csv -Path $SourceFilePath } [ref]$Reference = 0 $groupSize = [math]::Ceiling($objects.Count / $ThrottleLimit) $Chunk = $objects | Group-Object -Property { [math]::Floor($Reference.Value++ / $groupSize) } $ModuleBase = $MyInvocation.MyCommand.Module.Path $Token = $Script:Token $ClientID = $Script:ClientID $Secret = $Script:Secret $TenantID = $Script:TenantID $TokenExpirationTime = $Script:TokenExpirationTime $Chunk | ForEach-Object -ThrottleLimit $ThrottleLimit -Parallel { Import-Module $using:ModuleBase -Force $toksplat = @{ Token = $using:Token ClientID = $using:ClientID Secret = $using:Secret TenantID = $using:TenantID TokenExpirationTime = $using:TokenExpirationTime } Set-gToken @toksplat foreach ($row in $_.Group) { $splat = @{ Uri = "https://graph.microsoft.com{0}" -f ($Using:Endpoint -f $row.$using:field) } if ($Using:Endpoint -like '*filter=*') { if ($Using:Endpoint -like '*endswith*') { $splat['Eventual'] = $true $splat['Uri'] = '{0}&$count=true' -f $Uri } (Invoke-gRestMethod @splat).value continue } Invoke-gRestMethod @splat } } } } #EndRegion '.\Public\Parallel\Invoke-gParallel.ps1' 85 #Region '.\Public\Role\Get-gRoleAssignment.ps1' 0 function Get-gRoleAssignment { <# .SYNOPSIS Retrieves role assignments from the Microsoft Graph API. .DESCRIPTION The Get-gRoleAssignment function retrieves role assignments from the Microsoft Graph API. Role assignments tie together a role definition with members and scopes. This applies to custom and built-in roles. You can retrieve role assignments by RoleDefinitionId, PrincipalId, or Id. .PARAMETER RoleDefinitionId Specifies the RoleDefinitionId for which to retrieve role assignments. May be combined with PrincipalId and/or DirectoryScopeId. .PARAMETER PrincipalId Specifies the PrincipalId for which to retrieve role assignments. May be combined with RoleDefinitionId and/or DirectoryScopeId. .PARAMETER DirectoryScopeId Specifies the DirectoryScopeId for which to retrieve role assignments. May be combined with RoleDefinitionId and/or PrincipalId. .PARAMETER Id Specifies the Id of the role assignment to retrieve. .EXAMPLE Get-gRoleAssignment Retrieves all role assignment .EXAMPLE Get-gRoleAssignment -Id 'lonqqS8SdEyVII7c0ZKCbOElzZegQW9Nuu3_bEgnD_0-1' Retrieves a specific role assignment by the assignments Id .EXAMPLE Get-gRoleAssignment -RoleDefinitionId 'b5a8dcf3-09d5-43a9-a639-8e29ef291470' Retrieves role assignments associated with the specified RoleDefinitionId .EXAMPLE Get-gRoleAssignment -RoleDefinitionId 'b5a8dcf3-09d5-43a9-a639-8e29ef291470' -PrincipalId '725d17ec-cc33-432c-9eb0-83187b9cbee7' Retrieves role assignments associated with the specified RoleDefinitionId and PrincipalId .EXAMPLE Get-gRoleAssignment -RoleDefinitionId 'b5a8dcf3-09d5-43a9-a639-8e29ef291470' -PrincipalId '725d17ec-cc33-432c-9eb0-83187b9cbee7' -DirectoryScopeId '/' Retrieves role assignments associated with the specified RoleDefinitionId, PrincipalId, and DirectoryScopeId .EXAMPLE Get-gRoleAssignment -DirectoryScopeId '/' Retrieves role assignments associated with the specified DirectoryScopeId. .NOTES The Microsoft Graph API for Intune requires an active Intune license for the tenant. #> [CmdletBinding(DefaultParameterSetName = 'placeholder')] param( [Parameter()] $RoleDefinitionId, [Parameter()] $PrincipalId, [Parameter()] $DirectoryScopeId, [Parameter( Mandatory, ParameterSetName = 'Id' )] $Id ) if ($Id) { $filterstring = '/{0}' -f $Id } elseif ($PSBoundParameters.Keys.Count -ge 1) { $filterstring = @() } if ($PrincipalId) { $filterstring += ("PrincipalId eq '{0}'" -f $PrincipalId) } if ($RoleDefinitionId) { $filterstring += ("RoleDefinitionId eq '{0}'" -f $RoleDefinitionId) } if ($DirectoryScopeId) { $filterstring += ("DirectoryScopeId eq '{0}'" -f $DirectoryScopeId) } if ($filterstring.count -ge 1 -and (-not $Id)) { $filterstring = '?$filter={0}' -f (@($filterstring) -join ' and ') } $RestSplat = @{ Uri = 'https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments{0}' -f $filterstring Method = 'GET' } $Response = Invoke-gRestMethod @RestSplat if (-not $Id) { return $Response.value } $Response } #EndRegion '.\Public\Role\Get-gRoleAssignment.ps1' 104 #Region '.\Public\Role\Get-gRoleDefinition.ps1' 0 function Get-gRoleDefinition { <# .SYNOPSIS Returns one or more Azure AD Role Definitions. .DESCRIPTION Retrieves role definitions and role assignments from the RBAC provider called 'directory' (Azure Active Directory). .PARAMETER Role Specifies the Role ID or DisplayName as a string or object. If using the DisplayName of the Role Definition, note that it is not unique in Azure AD and may result in multiple matches. .PARAMETER All Retrieves all Azure AD Role Definitions. .EXAMPLE Import-Csv .\rolelist.csv | Get-gRoleDefinition Retrieves role definitions for each role listed in a CSV file. .EXAMPLE Get-gRoleDefinition -Role 'Knowledge Administrator' Retrieves the role definition with the specified DisplayName. .EXAMPLE Get-gRoleDefinition -Role '62e90394-69f5-4237-9190-012177145e10' Retrieves the role definition with the specified Role ID. .EXAMPLE Get-gRoleDefinition -All Retrieves all Azure AD Role Definitions. .EXAMPLE Get-gRoleDefinition -All | Export-Csv .\RoleDefinitions.csv -NoTypeInformation Retrieves all Azure AD Role Definitions and exports them to a CSV file. #> [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline, ParameterSetName = 'pipeline' )] [object] $Role, [Parameter(ParameterSetName = 'All')] [switch] $All ) begin { if ($All) { $RestSplat = @{ Uri = "https://graph.microsoft.com/beta/roleManagement/directory/roleDefinitions" Method = 'GET' } (Invoke-gRestMethod @RestSplat).value return } } process { foreach ($Item in $Role) { if ($Item.Id -is [string] -and $Item.Id -as [Guid]) { $filterstring = '{0}?' -f $Item.Id } elseif ($Item -is [string] -and $Item -as [Guid]) { $filterstring = '{0}?' -f $Item } elseif ($Item.DisplayName -is [string]) { $filterstring = "?`$filter=DisplayName eq '{0}'" -f $Item.DisplayName } elseif ($Item -is [string]) { $filterstring = "?`$filter=DisplayName eq '{0}'" -f $Item } } if ($filterstring) { $RestSplat = @{ Uri = "https://graph.microsoft.com/beta/roleManagement/directory/roleDefinitions/{0}" -f $filterstring Method = 'GET' } $Result = Invoke-gRestMethod @RestSplat if ($filterstring -like '*filter=*') { return $Result.value } $Result } } } #EndRegion '.\Public\Role\Get-gRoleDefinition.ps1' 91 #Region '.\Public\Role\New-gRoleAssignment.ps1' 0 function New-gRoleAssignment { <# .SYNOPSIS Creates a new role assignment using the Microsoft Graph API. .DESCRIPTION This function creates a new role assignment object using the Microsoft Graph API. The role assignment is created with the specified role definition, principal (user or group), and directory scope. .PARAMETER RoleDefinitionId The ID of the role definition for the role assignment. .PARAMETER PrincipalId The ID of the principal (user or group) for the role assignment. .PARAMETER DirectoryScopeId The identifier of the directory object representing the scope of the assignment. The scope of an assignment determines the set of resources for which the principal has been granted access. Directory scopes are shared scopes stored in the directory that are understood by multiple applications. Use '/' for tenant-wide scope. .EXAMPLE Assigns the User Administrator role to a principal with the tenant scope. New-gRoleAssignment -RoleDefinitionId 'e8cef6f1-e4bd-4ea8-bc07-4b8d950f4477' -PrincipalId '72ae3f1a-c8f1-4aad-af82-51473013fa74' -DirectoryScopeId '/' .EXAMPLE Assigns the User Administrator role to a principal with administrative unit scope. $splat = @{ RoleDefinitionId = '9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3' PrincipalId = '72ae3f1a-c8f1-4aad-af82-51473013fa74' DirectoryScopeId = '/administrativeUnits/5d107bba-d8e2-4e13-b6ae-884be90e5d1a' } New-gRoleAssignment @splat .EXAMPLE Assigns a principal the Application Administrator role at the application scope. The object ID of the application registration is 661e1310-bd76-4795-89a7-8f3c8f855bfc. $splat = @{ RoleDefinitionId = '9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3' PrincipalId = '72ae3f1a-c8f1-4aad-af82-51473013fa74' DirectoryScopeId = '/661e1310-bd76-4795-89a7-8f3c8f855bfc' } New-gRoleAssignment @splat #> [CmdletBinding()] param( [Parameter( Mandatory )] $RoleDefinitionId, [Parameter( Mandatory )] $PrincipalId, [Parameter( Mandatory )] $DirectoryScopeId ) $Body = @{ '@odata.type' = '#microsoft.graph.unifiedRoleAssignment' roleDefinitionId = $RoleDefinitionId principalId = $PrincipalId directoryScopeId = $DirectoryScopeId } $RestSplat = @{ Uri = 'https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments' Method = 'POST' Body = $Body | ConvertTo-Json } Invoke-gRestMethod @RestSplat } #EndRegion '.\Public\Role\New-gRoleAssignment.ps1' 77 #Region '.\Public\User\Format-gObject.ps1' 0 function Format-gObject { [CmdletBinding()] param ( [Parameter( Mandatory, ValueFromPipeline, ParameterSetName = 'pipeline' )] [object] $Object ) process { $Hash = [ordered]@{} foreach ($row in $Object.PSObject.Properties) { if ($row.value -is [System.Management.Automation.PSCustomObject]) { foreach ($item in $row.value.PSObject.Properties) { $Hash[$item.name] = $item.value } continue } if ($row.name -match 'proxyaddresses|othermails|mobilephone|businessPhones|imAddresses') { $Hash[$row.name] = @($row.value) -ne '' -join ',' continue } if ($row.name -eq 'appRoles') { $AppRoleList = foreach ($role in $row.value) { '{0} [ Value {1} ] [ Enabled {2} ] {3}' -f $role.displayName, $role.value, $role.isEnabled, $role.id } $Hash[$row.name] = @($AppRoleList) -ne '' -join "`r`n" continue } if ($row.name -eq 'passwordCredentials') { $CredList = foreach ($cred in $row.value) { '{0} [ End {1} ] [ Hint {2} ] {3}' -f $cred.displayName, $cred.endDateTime, $cred.Hint, $cred.keyId } $Hash[$row.name] = @($CredList) -ne '' -join "`r`n" continue } $Hash[$row.name] = $row.value } [pscustomobject]$Hash } } #EndRegion '.\Public\User\Format-gObject.ps1' 43 #Region '.\Public\User\Get-gUser.ps1' 0 function Get-gUser { <# .SYNOPSIS Retrieve the properties and relationships of user objects in Azure Active Directory (AAD). .DESCRIPTION This cmdlet retrieves user objects from AAD, providing options for filtering and selecting specific properties. Users can be identified by their ID, UserPrincipalName, or DisplayName. The cmdlet supports wildcard characters in the UserPrincipalName and DisplayName, and the objects piped into the function are processed individually. .PARAMETER User Specifies the ID, UserPrincipalName, or DisplayName of the user to retrieve. This parameter supports wildcards (*) for UserPrincipalName and DisplayName. If this parameter is not provided, the cmdlet retrieves all users in the Azure AD Tenant. .PARAMETER Select Specifies a comma-separated list of properties to be returned by Microsoft Graph. .PARAMETER IncludeManager If the user has a manager listed in Azure AD, this switch includes the user's manager in the output. .PARAMETER Beta Specifies to use the beta version of the Microsoft Graph API. .PARAMETER ThrottleLimit Specifies the maximum number of parallel threads or concurrent operations allowed during parallel processing. Default value is 8. This parameter is only used when the User parameter is not provided. .EXAMPLE Import-Csv .\userlist.csv | Get-gUser -Select 'DisplayName,UserPrincipalName,Mail' .EXAMPLE Import-Csv .\userlist.csv | Get-gUser -IncludeManager -Select 'DisplayName,UserPrincipalName' .EXAMPLE Get-gUser -User '72ae3f1a-c8f1-4aad-af82-51443013fa74' .EXAMPLE Get-gUser -User 'Kevin Blumenfeld' .EXAMPLE Get-gUser -User 'Kevin*' Retrieves user information for users whose name begins with 'Kevin'. .EXAMPLE Get-gUser -User '*Blumenfeld' Retrieves user information for users whose name ends with 'Blumenfeld'. .EXAMPLE Get-gUser -User '*@company.com' Retrieves user information for users whose UserPrincipalName ends with '@company.com'. .EXAMPLE Get-gUser -User 'Kevin*' -Select 'DisplayName,UserPrincipalName' Retrieves the DisplayName and UserPrincipalName for users whose name begins with 'Kevin'. .EXAMPLE Get-gUser -User '*@company.com' -Select 'DisplayName,UserPrincipalName' Retrieves the DisplayName and UserPrincipalName for users whose UserPrincipalName ends with '@company.com'. .EXAMPLE Get-gUser -User 'Kevin*' -IncludeManager -Select 'DisplayName,UserPrincipalName' Retrieves the DisplayName, UserPrincipalName, and manager for users whose name begins with 'Kevin'. .EXAMPLE Get-gUser -User '*@company.com' -IncludeManager -Select 'DisplayName,UserPrincipalName' Retrieves the DisplayName, UserPrincipalName, and manager for users whose UserPrincipalName ends with '@company.com'. .EXAMPLE Get-gUser Retrieves all users in the Azure AD Tenant. .EXAMPLE Get-gUser -Beta Retrieves all users in the Azure AD Tenant using the beta version of Microsoft Graph API. .EXAMPLE Get-gUser -Select 'DisplayName,UserPrincipalName' Retrieves all users in the Azure AD Tenant with only the specified properties. .EXAMPLE Get-gUser -Beta -Select 'DisplayName,UserPrincipalName' Retrieves all users in the Azure AD Tenant using the beta version of Microsoft Graph API with only the specified properties. .NOTES When the -IncludeManager switch is used, a full user object is output for Manager field #> [CmdletBinding()] param ( [Parameter( Mandatory, ValueFromPipeline, ParameterSetName = 'pipeline' )] [ArgumentCompleter([completer_gUser_DisplayName])] [object] $User, [Parameter(ParameterSetName = 'pipeline' )] [string] $Select, [Parameter(ParameterSetName = 'pipeline' )] [switch] $IncludeManager, [Parameter(ParameterSetName = 'pipeline' )] [Parameter(ParameterSetName = 'All' )] [switch] $Beta, [Parameter(ParameterSetName = 'All' )] [int] $ThrottleLimit = 8 ) begin { if ($PSCmdlet.ParameterSetName -eq 'All') { $splat = @{ThrottleLimit = $ThrottleLimit } if ($Select) { $splat['Select'] = $Select } if ($Beta) { $splat['Beta'] = $true } Get-gUserAll @splat return } } process { if ($PSCmdlet.ParameterSetName -eq 'All') { return } foreach ($Item in $User) { $filterstring = if ($Item -match "\*+" -and $Item -as [mailaddress]) { "?`$filter={0}" -f [System.Web.HttpUtility]::UrlEncode((New-gFilterString $Item -SearchField 'userPrincipalName')) } elseif ($Item -match "\*+") { "?`$filter={0}" -f [System.Web.HttpUtility]::UrlEncode((New-gFilterString $Item -SearchField 'displayName')) } elseif ($Item -is [string] -and $Item -as [Guid]) { $Item } elseif ($Item -as [mailaddress]) { "?`$filter=userPrincipalName eq '{0}'" -f [System.Web.HttpUtility]::UrlEncode($Item) } elseif ($Item -is [string]) { "?`$filter=DisplayName eq '{0}'" -f [System.Web.HttpUtility]::UrlEncode($Item) } elseif ($Item.Id) { $Item.Id } elseif ($Item.UserPrincipalName -as [mailaddress]) { $Item.UserPrincipalName } elseif ($Item.DisplayName) { "?`$filter=DisplayName eq '{0}'" -f $Item.DisplayName } if (-not $filterstring) { continue } if ($Select) { $filterstring = '{0}&$Select={1}' -f $filterstring, $Select } if ($IncludeManager) { $filterstring = '{0}&$expand=manager' -f $filterstring } $Uri = 'https://graph.microsoft.com/{0}/users/{1}' -f @( if ($Beta) { 'beta' } else { 'v1.0' } $filterString ) $splat = @{ 'Uri' = $Uri } if ($filterstring -like '*filter=*') { if ($filterstring -like '*endswith*') { $splat['Eventual'] = $true $splat['Uri'] = '{0}&$count=true' -f $Uri } (Invoke-gRestMethod @splat).value continue } Invoke-gRestMethod -Method 'GET' -Uri $Uri } } } #EndRegion '.\Public\User\Get-gUser.ps1' 158 #Region '.\Public\User\Get-gUserApp.ps1' 0 function Get-gUserApp { param ( [Parameter(Mandatory)] $UserID, [Parameter()] $Select = 'resourceDisplayName,principalDisplayName,appRoleId' ) $GroupList = Get-gUserMemberOf -UserID $UserID foreach ($Group in $GroupList) { $RestSplat = @{ Uri = "https://graph.microsoft.com/v1.0/groups/{0}/appRoleAssignments/?`$select={1}" -f $Group.ID, $Select } (Invoke-gRestMethod @RestSplat).value } } #EndRegion '.\Public\User\Get-gUserApp.ps1' 20 #Region '.\Public\User\Get-gUserDeleted.ps1' 0 function Get-gUserDeleted { <# .SYNOPSIS Retrieve the properties and relationships of user objects in Azure Active Directory (AAD). .DESCRIPTION This cmdlet retrieves user objects from AAD and provides various options for filtering and selecting specific properties. Users can be identified by their ID, UserPrincipalName, or DisplayName. Additionally, a list of users can be provided in a CSV file. The cmdlet also supports parallel processing of user objects, with a default throttle limit of 8 threads. .PARAMETER User Specifies the ID, UserPrincipalName, or DisplayName of the user to retrieve. A list of users can also be provided in a CSV file. If the CSV file has headers, they must contain one of the following columns: Id, UserPrincipalName, or DisplayName. DisplayName is not unique in AAD and may result in multiple matches. Note that tab completion is supported for the DisplayName parameter. You can type a few letters and use tab multiple times to cycle through and find matching DisplayNames of users you want more details on. For example, typing 'fr' and pressing tab multiple times may show both 'Frank' and 'Fred' as options. .PARAMETER Select Specifies a comma-separated list of properties to be returned by Microsoft Graph. For example: Get-gUser -Select 'DisplayName,UserPrincipalName,Mail' .PARAMETER IncludeManager If the user has a manager listed in Azure AD, this switch includes the user's manager in the output .PARAMETER All Switch to retrieve all users in the Azure AD Tenant. .PARAMETER Beta Switch to use the beta version of Microsoft Graph API. .PARAMETER ThrottleLimit Only used with the -All switch. Specifies the maximum number of parallel threads or concurrent operations allowed during parallel processing. Default value is 8. .EXAMPLE Import-Csv .\userlist.csv | Get-gUser .EXAMPLE Import-Csv .\userlist.csv | Get-gUser -Select 'DisplayName,UserPrincipalName,Mail' .EXAMPLE Import-Csv .\userlist.csv | Get-gUser -IncludeManager -Select 'DisplayName,UserPrincipalName' .EXAMPLE Get-gUser -User '72ae3f1a-c8f1-4aad-af82-51473013fa74' .EXAMPLE Get-gUser -User 'Kevin Blumenfeld' .EXAMPLE Get-gUser -User 'Kevin Blumenfeld' -Beta Retrieves user information for 'Kevin Blumenfeld' using the beta version of Microsoft Graph API. .EXAMPLE Get-gUser -User 'Kevin Blumenfeld' -Select 'DisplayName,UserPrincipalName' .EXAMPLE Get-gUser -User 'Kevin Blumenfeld' -Select 'DisplayName,UserPrincipalName' .EXAMPLE Get-gUser -User 'Kevin Blumenfeld' -IncludeManager -Select 'DisplayName,UserPrincipalName' .EXAMPLE Get-gUser -All Retrieves all users in the Azure AD Tenant. .EXAMPLE Get-gUser -All -Beta Retrieves all users in the Azure AD Tenant using the beta version of Microsoft Graph API. .EXAMPLE Get-gUser -All -Select 'DisplayName,UserPrincipalName' Retrieves all users in the Azure AD Tenant. .EXAMPLE Get-gUser -All -Beta -Select 'DisplayName,UserPrincipalName' Retrieves all users in the Azure AD Tenant using the beta version of Microsoft Graph API. #> [CmdletBinding()] param ( [Parameter( Mandatory, ValueFromPipeline, ParameterSetName = 'pipeline' )] [ArgumentCompleter([completer_gUser_Deleted_DisplayName])] [object] $User, [Parameter(ParameterSetName = 'pipeline' )] [string] $Select, [Parameter(ParameterSetName = 'pipeline' )] [switch] $IncludeManager, [Parameter(ParameterSetName = 'pipeline')] [Parameter(ParameterSetName = 'All')] [switch] $Beta, [Parameter(ParameterSetName = 'All')] [switch] $All, [Parameter(ParameterSetName = 'All')] [int] $ThrottleLimit = 8 ) begin { if ($All) { $splat = @{ ThrottleLimit = $ThrottleLimit } if ($Select) { $splat['Select'] = $Select } Get-gUserDeletedAll @splat return } } process { foreach ($Item in $User) { if ($Item -is [string] -and $Item -as [Guid]) { $filterstring = '{0}?' -f $Item } elseif ($Item -as [mailaddress]) { $filterstring = "?`$filter=userprincipalname eq '{0}'" -f [System.Web.HttpUtility]::UrlEncode($Item) } elseif ($Item -is [string]) { $filterstring = "?`$filter=DisplayName eq '{0}'" -f $Item } else { if ($Item.Id) { $filterstring = '{0}?' -f $Item.Id } elseif ($Item.UserPrincipalName -as [mailaddress]) { $filterstring = '{0}?' -f $Item.UserPrincipalName } elseif ($Item.DisplayName) { $filterstring = "?`$filter=DisplayName eq '{0}'" -f $Item.DisplayName } } if ($filterstring) { if ($Select) { $filterstring = '{0}&$Select={1}' -f $filterstring, $Select } if ($IncludeManager) { $filterstring = '{0}&$expand=manager' -f $filterstring } if (-not $Beta) { $Uri = 'https://graph.microsoft.com/v1.0/directory/deletedItems/microsoft.graph.user/{0}' -f $filterstring } else { $Uri = 'https://graph.microsoft.com/beta/directory/deletedItems/microsoft.graph.user/{0}' -f $filterstring } if ($filterstring -like '*filter=*') { (Invoke-gRestMethod -Method 'GET' -Uri $Uri).value continue } Invoke-gRestMethod -Method 'GET' -Uri $Uri } } } } #EndRegion '.\Public\User\Get-gUserDeleted.ps1' 169 #Region '.\Public\User\Get-gUserMemberOf.ps1' 0 function Get-gUserMemberOf { [CmdletBinding()] param ( [Parameter(Mandatory)] $UserID, [Parameter()] $Select = 'DisplayName,ID' ) $RestSplat = @{ Uri = "https://graph.microsoft.com/v1.0/users/{0}/memberOf/microsoft.graph.group/?`$select={1}" -f $UserID, $Select } (Invoke-gRestMethod @RestSplat).value } #EndRegion '.\Public\User\Get-gUserMemberOf.ps1' 19 #Region '.\Public\User\Search-gUser.ps1' 0 function Search-gUser { <# .SYNOPSIS A function to search a user in the Microsoft Graph API. .DESCRIPTION This function allows you to search for a specific user in the Microsoft Graph API. The function accepts several parameters to refine your search, such as the user's name, the search field, and optional parameters to further specify your request. .PARAMETER SearchValue Specifies the value of the attribute to search for. This parameter is mandatory and accepts a string or object that defines the object. .PARAMETER SearchField Specifies the field to search. This parameter is mandatory. .PARAMETER Select Specifies which fields to return in the response. This is an optional parameter. .PARAMETER IncludeManager Includes the manager of the user in the search. This is an optional parameter. .PARAMETER Beta Specifies whether to use the beta version of the Microsoft Graph API. If not specified, the v1.0 version will be used. This is an optional parameter. .EXAMPLE Search-gUser -User 'johndoe' -SearchField 'displayName' -IncludeManager This example shows how to search for a user based on their display name and include their manager in the search. .EXAMPLE Search-gUser -User 'john*' -SearchField 'displayName' -Select 'displayName,mail' -Beta This example shows how to search for a user with wildcard based on their display name in the beta version of the Microsoft Graph API and select only their displayName and mail in the returned data. .EXAMPLE Search-gUser -User '*@domain.com' -SearchField 'userPrincipalName' -Select 'userPrincipalName,displayName,mail' -Beta This example shows how to search for a user with wildcard based on their display name in the beta version of the Microsoft Graph API and select only their displayName and mail in the returned data. #> [CmdletBinding()] param ( [Parameter( Mandatory )] [ArgumentCompleter([completer_gUser_DisplayName])] [object] $SearchValue, [Parameter( Mandatory )] [string] $SearchField, [Parameter()] [string] $Select, [Parameter()] [switch] $IncludeManager, [Parameter()] [switch] $Beta ) process { if ($PSCmdlet.ParameterSetName -eq 'All') { return } foreach ($Item in $SearchValue) { $filterstring = if ($Item -match "\*+") { "?`$filter={0}" -f (New-gFilterString $Item -SearchField $SearchField) } else { "?`$filter={0} eq '{1}'" -f $SearchField, $Item } if (-not $filterstring) { continue } if ($Select) { $filterstring = '{0}&$Select={1}' -f $filterstring, $Select } if ($IncludeManager) { $filterstring = '{0}&$expand=manager' -f $filterstring } $Uri = 'https://graph.microsoft.com/{0}/users/{1}' -f @( if ($Beta) { 'beta' } else { 'v1.0' } $filterstring ) $splat = @{ 'Uri' = $Uri } if ($filterstring -like '*filter=*') { if ($filterstring -like '*endswith*') { $splat['Eventual'] = $true $splat['Uri'] = '{0}&$count=true' -f $Uri } (Invoke-gRestMethod @splat).value continue } Invoke-gRestMethod -Method 'GET' -Uri $Uri } } } #EndRegion '.\Public\User\Search-gUser.ps1' 98 |