Functions/Public/MSAzure.ps1
|
# Microsoft Azure and Graph API functions Function Get-MSAzureUser { <# .SYNOPSIS Return a list of users from Azure AD. .DESCRIPTION Return a list of users from Azure AD. .PARAMETER Properties A comma-delimited list of properties to return in the results Format as per https://docs.microsoft.com/en-us/graph/query-parameters?view=graph-rest-1.0#select-parameter Available properties can be found at https://docs.microsoft.com/en-us/graph/api/resources/user?view=graph-rest-1.0#properties .PARAMETER Filter Add filter parameters as per https://docs.microsoft.com/en-us/graph/query-parameters?context=graph%2Fapi%2F1.0&view=graph-rest-1.0#filter-parameter Available properties can be found at https://docs.microsoft.com/en-us/graph/api/resources/user?view=graph-rest-1.0#properties .PARAMETER UPN Return user details for the given UserPrincipalName .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER HideProgressBar Don't show the progress bar. Cleans up logs when running on Docker. .PARAMETER AuthToken The authorization token used for this request. Normally obtained via Get-MSGraphAccessToken .PARAMETER TotalCount Only return a total count of objects .PARAMETER ResultSize The number of results to return. Defaults to 1000. .EXAMPLE Get-MSAzureUser Returns all MS Azure user accounts .EXAMPLE Get-MSAzureUser -Properties 'id,userPrincipalName' -AuthToken $AuthToken Returns a list of Azure users' ID and userPrincipalNames using a previously-obtained authtoken .EXAMPLE Get-MSAzureUser -Filter "startswith(displayName,'Meeting Room')" Returns a list of Azure users whose display names start with 'Meeting Room' .NOTES Version 1.3 #> Param ( [Parameter(Mandatory=$False)] [string]$Properties, [Parameter(Mandatory=$False)] [string]$Filter, [Parameter(Mandatory=$False)] [string]$UPN, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(Mandatory=$False)] [switch]$TotalCount, [Parameter(Mandatory=$False)] [switch]$HideProgressBar, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$AuthToken, [Parameter(Mandatory=$False)] [ValidateRange(1,500000)] [int]$ResultSize = 500000, [Parameter(Mandatory=$False)] [ValidateRange(1,99999)] [int]$ProgressUpdateFreq = 1 ) Process { $Body = @{'$count' = 'true'} Try { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } If (!$AuthToken) { $AuthToken = Get-NectarMSTeamsConfig -TenantName $TenantName | Get-MSGraphAccessToken } } Catch { Write-Error "Could not obtain authorization token. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } If ($AuthToken) { Try { $Headers = @{ Authorization = "Bearer $AuthToken" ConsistencyLevel = 'eventual' } If ($Properties) { $Body.Add('$select',$Properties) } If ($Filter) { $Body.Add('$filter',$Filter) } # If UPN is entered, just look for that user and exit. If ($UPN) { $URI = "https://graph.microsoft.com/v1.0/users/$UPN" Write-Verbose $URI $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers Return $JSON } If ($TotalCount) { $URI = 'https://graph.microsoft.com/v1.0/users/$count' $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $UserCount = New-Object PsObject $UserCount | Add-Member -NotePropertyName 'UserCount' -NotePropertyValue $JSON If ($TenantName) { $UserCount | Add-Member -NotePropertyName 'TenantName' -NotePropertyValue $TenantName } Clear-Variable -Name AuthToken Return $UserCount } Else { $URI = "https://graph.microsoft.com/v1.0/users" $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $TotalUsers = $JSON.'@odata.count' $JSON.value $PageSize = $JSON.value.count $Message = "Getting $TotalUsers Azure AD users for tenant $TenantName." If ($HideProgressBar) { Write-Host $Message } $UserCount = 0 $Stopwatch = [System.Diagnostics.Stopwatch]::StartNew() While (($JSON.'@odata.nextLink') -And ($PageSize -lt $ResultSize)) { $NextURI = $JSON.'@odata.nextLink' $JSON = Invoke-RestMethod -Method GET -URI $NextURI -Headers $Headers $JSON.value $PageSize += $JSON.value.count If ($Stopwatch.Elapsed.TotalSeconds -ge $ProgressUpdateFreq) { $Percentage = ($PageSize / $TotalUsers) * 100 If ($HideProgressBar) { $Percentage = [math]::Round($Percentage,1) Write-Host "Retrieving $Percentage`% of $($TotalUsers) users on tenant $TenantName..." } Else { Write-Progress -Activity $Message -PercentComplete $Percentage -Status 'Retrieving...' } $Stopwatch.Reset() $Stopwatch.Start() } } } Clear-Variable -Name AuthToken } Catch { Write-Error "Could not get user data. $($_.Exception.Message)" Clear-Variable -Name AuthToken } } } } Function Get-MSAzureUserGroupMembership { <# .SYNOPSIS Return the groups that a user is a member of from Azure AD. .DESCRIPTION Return the groups that a user is a member of from Azure AD. .PARAMETER ID The Azure AD GUID of the user .PARAMETER Transitive Show groups where the user is a member of a group that is a member of another group .PARAMETER Properties A comma-delimited list of properties to return in the results Format as per https://docs.microsoft.com/en-us/graph/query-parameters?view=graph-rest-1.0#select-parameter Available properties can be found at https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties .PARAMETER Filter Add filter parameters as per https://docs.microsoft.com/en-us/graph/query-parameters?context=graph%2Fapi%2F1.0&view=graph-rest-1.0#filter-parameter Available properties can be found at https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER AuthToken The authorization token used for this request. Normally obtained via Get-MSGraphAccessToken .PARAMETER TotalCount Only return a total count of objects .PARAMETER ResultSize The number of results to return. Defaults to 10000. .EXAMPLE Get-MSAzureUserGroupMembership -ID abcdefab-1234-1234-1234-abcdabcdabcd Returns the groups that the selected user is a member of .EXAMPLE Get-MSAzureUser -Properties 'id,userPrincipalName' -AuthToken $AuthToken Returns a list of Azure users' ID and userPrincipalNames using a previously-obtained authtoken .NOTES Version 1.0 #> Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)] [string]$ID, [Parameter(Mandatory=$False)] [switch]$Transitive, [string]$Properties, [Parameter(Mandatory=$False)] [string]$Filter, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(Mandatory=$False)] [switch]$TotalCount, [Parameter(Mandatory=$False)] [switch]$HideProgressBar, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$AuthToken, [Parameter(Mandatory=$False)] [ValidateRange(1,500000)] [int]$ResultSize = 10000, [Parameter(Mandatory=$False)] [ValidateRange(1,99999)] [int]$ProgressUpdateFreq = 1 ) Begin { If ($Transitive) { $MemberOfScope = 'transitiveMemberOf' } Else { $MemberOfScope = 'MemberOf' } } Process { $Body = @{} $Params = @{} Try { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } If (!$AuthToken) { $AuthToken = Get-NectarMSTeamsConfig -TenantName $TenantName | Get-MSGraphAccessToken } } Catch { Write-Error "Could not obtain authorization token. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } If ($AuthToken) { Try { $Headers = @{ Authorization = "Bearer $AuthToken" } If ($Properties) { $Body.Add('$select',$Properties) $Params.Add('Properties',$Properties) } If ($Filter) { $Body.Add('$filter',$Filter) $Params.Add('Filter',$Filter) } If ($TotalCount) { $Body.Add('ConsistencyLevel','eventual') $URI = "https://graph.microsoft.com/v1.0/users/$ID/$MemberOfScope/`$count" Write-Verbose $URI $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $GroupCount = New-Object PsObject $GroupCount | Add-Member -NotePropertyName 'UserCount' -NotePropertyValue $JSON If ($TenantName) { $GroupCount | Add-Member -NotePropertyName 'TenantName' -NotePropertyValue $TenantName } Clear-Variable -Name AuthToken Return $GroupCount } Else { $URI = "https://graph.microsoft.com/v1.0/users/$ID/$MemberOfScope" Write-Verbose $URI $Params = @{} If ($AuthToken) { $Params.Add('AuthToken',$AuthToken) } If ($TenantName) { $Params.Add('Tenant',$TenantName) } $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $JSON.value $PageSize = $JSON.value.count While (($JSON.'@odata.nextLink') -And ($PageSize -lt $ResultSize)) { $NextURI = $JSON.'@odata.nextLink' $JSON = Invoke-RestMethod -Method GET -URI $NextURI -Headers $Headers $JSON.value $PageSize += $JSON.value.count } } Clear-Variable -Name AuthToken } Catch { Write-Error "Could not get group membership data. $($_.Exception.Message)" Clear-Variable -Name AuthToken } } } } Function Get-MSAzureGroup { <# .SYNOPSIS Return a list of groups from Azure AD. .DESCRIPTION Return a list of groups from Azure AD. .PARAMETER Properties A comma-delimited list of properties to return in the results Format as per https://docs.microsoft.com/en-us/graph/query-parameters?view=graph-rest-1.0#select-parameter Available properties can be found at https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties .PARAMETER Filter Add filter parameters as per https://docs.microsoft.com/en-us/graph/query-parameters?context=graph%2Fapi%2F1.0&view=graph-rest-1.0#filter-parameter Available properties can be found at https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER HideProgressBar Don't show the progress bar. Cleans up logs when running on Docker. .PARAMETER AuthToken The authorization token used for this request. Normally obtained via Get-MSGraphAccessToken .PARAMETER TotalCount Only return a total count of objects .PARAMETER ResultSize The number of results to return. Defaults to 1000. .EXAMPLE Get-MSAzureGroup Returns all MS Azure groups .EXAMPLE Get-MSAzureGroup -Filter "startsWith(displayName,'Global-')" Returns all MS Azure groups whose display names start with Global- .EXAMPLE Get-MSAzureGroup -Properties 'id,DisplayName' -AuthToken $AuthToken Returns a list of Azure group ID and display names using a previously-obtained authtoken .NOTES Version 1.0 #> Param ( [Parameter(Mandatory=$False)] [string]$Properties, [Parameter(Mandatory=$False)] [string]$Filter, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(Mandatory=$False)] [switch]$TotalCount, [Parameter(Mandatory=$False)] [switch]$HideProgressBar, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$AuthToken, [Parameter(Mandatory=$False)] [ValidateRange(1,500000)] [int]$ResultSize, [Parameter(Mandatory=$False)] [ValidateRange(1,99999)] [int]$ProgressUpdateFreq = 1 ) Process { $Body = @{} $Params = @{} Try { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } If (!$AuthToken) { $AuthToken = Get-NectarMSTeamsConfig -TenantName $TenantName | Get-MSGraphAccessToken } } Catch { Write-Error "Could not obtain authorization token. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } If ($AuthToken) { Try { $Headers = @{ Authorization = "Bearer $AuthToken" } If ($Properties) { $Body.Add('$select',$Properties) $Params.Add('Properties',$Properties) } If ($Filter) { $Body.Add('$filter',$Filter) $Params.Add('Filter',$Filter) } If ($TotalCount) { $Body.Add('ConsistencyLevel','eventual') $URI = 'https://graph.microsoft.com/v1.0/groups/$count' $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $GroupCount = New-Object PsObject $GroupCount | Add-Member -NotePropertyName 'GroupCount' -NotePropertyValue $JSON If ($TenantName) { $GroupCount | Add-Member -NotePropertyName 'TenantName' -NotePropertyValue $TenantName } Clear-Variable -Name AuthToken Return $GroupCount } Else { $URI = "https://graph.microsoft.com/v1.0/groups" Write-Verbose $URI $Params = @{} If ($AuthToken) { $Params.Add('AuthToken',$AuthToken) } If ($TenantName) { $Params.Add('Tenant',$TenantName) } $TotalGroups = Get-MSAzureGroup @Params -TotalCount $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $JSON.value $PageSize = $JSON.value.count $Message = "Getting Azure AD groups for tenant $TenantName." If ($HideProgressBar) { Write-Host $Message } $GroupCount = 0 $Stopwatch = [System.Diagnostics.Stopwatch]::StartNew() While (($JSON.'@odata.nextLink') -And ($PageSize -lt $ResultSize)) { $NextURI = $JSON.'@odata.nextLink' $JSON = Invoke-RestMethod -Method GET -URI $NextURI -Headers $Headers $JSON.value $PageSize += $JSON.value.count If ($Stopwatch.Elapsed.TotalSeconds -ge $ProgressUpdateFreq) { $Percentage = ($PageSize / $TotalGroups.GroupCount) * 100 If ($HideProgressBar) { $Percentage = [math]::Round($Percentage,1) Write-Host "Retrieving $Percentage`% of $($TotalGroups.GroupCount) users on tenant $TenantName..." } Else { Write-Progress -Activity $Message -PercentComplete $Percentage -Status 'Retrieving...' } $Stopwatch.Reset() $Stopwatch.Start() } } } Clear-Variable -Name AuthToken } Catch { Write-Error "Could not get group data. $($_.Exception.Message)" Clear-Variable -Name AuthToken } } } } Function Get-MSAzureGroupMembers { <# .SYNOPSIS Return a list of group members from Azure AD. .DESCRIPTION Return a list of group members from Azure AD. .PARAMETER ID The GUID of the group to return membership info .PARAMETER Transitive Show members where the members are members of a group that is a member of another group .PARAMETER Properties A comma-delimited list of properties to return in the results Format as per https://docs.microsoft.com/en-us/graph/query-parameters?view=graph-rest-1.0#select-parameter Available properties can be found at https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties .PARAMETER Filter Add filter parameters as per https://docs.microsoft.com/en-us/graph/query-parameters?context=graph%2Fapi%2F1.0&view=graph-rest-1.0#filter-parameter Available properties can be found at https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER AuthToken The authorization token used for this request. Normally obtained via Get-MSGraphAccessToken .PARAMETER ResultSize The number of results to return. Defaults to 10000. .EXAMPLE Get-MSAzureGroup -Filter "startsWith(displayName,'Global-Sales')" | Get-MSAzureGroupMembers -TotalOnly Returns all MS Azure groups whose display names start with Global-Sales .NOTES Version 1.0 #> Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$ID, [Parameter(Mandatory=$False)] [switch]$Transitive, [Parameter(Mandatory=$False)] [string]$Properties, [Parameter(Mandatory=$False)] [string]$Filter, [Parameter(Mandatory=$False)] [switch]$TotalCount, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$AuthToken, [Parameter(Mandatory=$False)] [ValidateRange(1,500000)] [int]$ResultSize = 10000 ) Begin { If ($Transitive) { $MemberScope = 'transitiveMembers' } Else { $MemberScope = 'members' } Try { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } If (!$AuthToken) { $AuthToken = Get-NectarMSTeamsConfig -TenantName $TenantName | Get-MSGraphAccessToken } } Catch { Write-Error "Could not obtain authorization token. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } Process { $Body = @{} $Params = @{} If ($AuthToken) { Try { $Headers = @{ Authorization = "Bearer $AuthToken" } If ($Properties) { $Body.Add('$select',$Properties) $Params.Add('Properties',$Properties) } If ($Filter) { $Body.Add('$filter',$Filter) $Params.Add('Filter',$Filter) } If ($TotalCount) { $Body.Add('ConsistencyLevel','eventual') $URI = "https://graph.microsoft.com/v1.0/groups/$ID/$MemberScope/`$count" $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $MemberCount = New-Object PsObject $MemberCount | Add-Member -NotePropertyName 'MemberCount' -NotePropertyValue $JSON If ($TenantName) { $MemberCount | Add-Member -NotePropertyName 'TenantName' -NotePropertyValue $TenantName } Clear-Variable -Name AuthToken Return $MemberCount } Else { $URI = "https://graph.microsoft.com/v1.0/groups/$ID/$MemberScope" $Params = @{} If ($AuthToken) { $Params.Add('AuthToken',$AuthToken) } If ($TenantName) { $Params.Add('Tenant',$TenantName) } $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Headers -Body $Body $JSON.value $PageSize = $JSON.value.count While (($JSON.'@odata.nextLink') -And ($PageSize -lt $ResultSize)) { $NextURI = $JSON.'@odata.nextLink' $JSON = Invoke-RestMethod -Method GET -URI $NextURI -Headers $Headers $JSON.value $PageSize += $JSON.value.count } } Clear-Variable -Name AuthToken } Catch { Write-Error "Could not get group member data. $($_.Exception.Message)" Clear-Variable -Name AuthToken } } } } |