OGraph.psm1
############################################################################################### # Module Variables ############################################################################################### $ModuleVariableNames = ('OGraphConfiguration','GraphVersion') $ModuleVariableNames.ForEach( { Set-Variable -Scope Script -Name $_ -Value $null }) $Script:GraphVersion = 'v1.0' ############################################################################################### # Module Removal ############################################################################################### #Clean up objects that will exist in the Global Scope due to no fault of our own . . . like PSSessions $OnRemoveScript = { # perform cleanup Write-Verbose -Message 'Removing Module Items from Global Scope' } $ExecutionContext.SessionState.Module.OnRemove += $OnRemoveScript <# .SYNOPSIS Add Group Member .DESCRIPTION Add a group member using its object id or user principal name. If using the later, a lookup is performed with get-oguser to get the Object ID for the user. Permissions: https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0&tabs=http .PARAMETER GroupId Parameter description .PARAMETER UserPrincipalName Parameter description .PARAMETER MemberId Parameter description .EXAMPLE Add-OGGroupMember -GroupObjectId 3175b598-0fa0-4002-aebf-bfbf759c94a7 -UserObjectId 3fbabd10-7bbc-410d-ba6c-0ba60e863c30 .NOTES General notes #> Function Add-OGGroupMember { [CmdletBinding(DefaultParameterSetName = 'MID')] param ( [Parameter(Mandatory, ParameterSetName = 'MID')] [Parameter(Mandatory, ParameterSetName = 'UPN')] $GroupId, [Parameter(Mandatory, ParameterSetName = 'UPN')] $UserPrincipalName, [Parameter(Mandatory, ParameterSetName = 'MID')] $MemberId ) switch ($PSCmdlet.ParameterSetName) { 'UPN' { $MemberId = Get-OGUser -UserPrincipalName $UserPrincipalName $MemberId = $MemberId.Id } } $URI = "/$GraphVersion/groups/$GroupID/members/`$ref" $Body = [PSCustomObject]@{ '@odata.id' = "https://graph.microsoft.com/$GraphVersion/directoryObjects/$MemberId" } $account_params = @{ Uri = $URI Body = $Body | ConvertTo-Json Method = 'POST' } Invoke-MgGraphRequest @Account_params } <# .SYNOPSIS Get API Token from Azure AD app using Access Secret or Certificate Thumprint, then authenticate to graph with the token. Or authenticate using user credentials. .DESCRIPTION This function allows easy Authentication to Azure AD application authentication tokens or User Credentials. To get a Azure AD application token, provide the tenant ID, Application ID, and either an access secret or certificate thumbprint. The token with automatically authenticate the session after a valid token is acquired or online credentials are entered. If you have an existing token, paste it into accesstoken. .PARAMETER ApplicationID Identifier for the Application Registration to use for connection to the Microsoft Tenant .PARAMETER TenantId Identifier for the Microsoft Tenant .PARAMETER ClientSecret Client Secret for the Application Registration to be used for client authentication for connection to the Microsoft Tenant .PARAMETER CertificateThumbprint Certificat thumbprint of the certificate to be used for client authentiaction for connection to the Microsoft Tenant .PARAMETER UseDeviceAuthentication Use device code flow .PARAMETER Scope Specify the Microsoft Graph scope(s) to include in the connection context. User must have appropriate permissions and/or be able to consent to the permissions. .PARAMETER AccessToken Specify the pre-obtained access code to use for the connection to the Microsoft Tenant .EXAMPLE Authenticate to graph with application access secret: Connect-OGGraph -ApplicationID f3857fc2-d4a5-1427-8f4c-2bdcd0cd9a2d -TenantID 27f1409e-4f28-4115-8ef5-71058ab01821 -AccessSecret Rb4324~JBiAJclWeG1W239CPgKHlChi9l0423jjdg~ .NOTES General notes #> Function Connect-OGGraph { [CmdletBinding(DefaultParameterSetName = 'Interactive')] param ( [Parameter(Mandatory,Parametersetname = 'Secret')] [Parameter(Mandatory,Parametersetname = 'Cert')] $ApplicationID , [Parameter(Mandatory,Parametersetname = 'Secret')] [Parameter(Mandatory,Parametersetname = 'Cert')] $TenantId , [Parameter(Mandatory,Parametersetname = 'Secret')] $ClientSecret , [Parameter(Mandatory,Parametersetname = 'Cert')] $CertificateThumbprint , [Parameter(Parametersetname = 'Interactive')] [Parameter(Parametersetname = 'DeviceAuth')] [string[]]$Scope , [Parameter(Mandatory,Parametersetname = 'Token')] $AccessToken , [Parameter(Mandatory,Parametersetname = 'DeviceAuth')] [switch]$UseDeviceAuthentication ) switch ($PSCmdlet.ParameterSetName) { 'Secret' { $Body = @{ Grant_Type = 'client_credentials' Scope = 'https://graph.microsoft.com/.default' client_Id = $ApplicationID Client_Secret = $ClientSecret } $ConnectGraph = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" -Method POST -Body $Body $script:GraphAPIKey = $ConnectGraph.access_token Connect-MgGraph -AccessToken $GraphAPIKey } 'Cert' { $splat = @{ ClientID = $ApplicationID TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint } Connect-MgGraph @splat } 'Interactive' { switch ($scope.count -ge 1) { $true { Connect-MgGraph -UseDeviceAuthentication -Scopes $Scope } $false { Connect-MgGraph } } } 'DeviceAuth' { switch ($scope.count -ge 1) { $true { Connect-MgGraph -UseDeviceAuthentication -Scopes $Scope } $false { Connect-MgGraph -UseDeviceAuthentication } } } 'Token' { Connect-MgGraph -AccessToken $AccessToken } } } <# .SYNOPSIS Get the current version of the Graph API that OGraph is using .DESCRIPTION Get the current version of the Graph API that OGraph is using .EXAMPLE Get-OGGraphVersion #> Function Get-OGGraphVersion { $Script:GraphVersion } <# .SYNOPSIS List Calendars for a user or specify a users calendar with the calendars guid. .DESCRIPTION List Calendars for a user or specify a users calendar with the calendars guid. Permissions: https://learn.microsoft.com/en-us/graph/api/user-list-calendars?view=graph-rest-1.0&tabs=http .PARAMETER UserPrincipalName Parameter description .PARAMETER Id Parameter description .EXAMPLE Get-OGCalendar -UserPrincipalName jdoe@contoso.com .NOTES General notes #> Function Get-OGCalendar { [CmdletBinding()] param ( [Parameter(Mandatory)]$UserPrincipalName, [Parameter(Mandatory = $false)]$Id ) if (-not [string]::IsNullOrWhiteSpace($id)) { $URI = "/$GraphVersion/users/$UserPrincipalName/calendars/$id" Get-OGNextPage -uri $URI } else { $URI = "/$GraphVersion/users/$UserPrincipalName/calendars" Get-OGNextPage -uri $URI } } <# .SYNOPSIS Get group from Azure AD .DESCRIPTION Get group using an Object ID, by searching for a displayname, or getting all groups. Permissions: https://learn.microsoft.com/en-us/graph/api/group-list?view=graph-rest-1.0&tabs=http .PARAMETER GroupId GroupID (guid) for the group .PARAMETER SearchDisplayName Get the Group(s) by DisplayName search .PARAMETER All Get all Groups from the Microsoft Tenant .PARAMETER UnifiedAll Get all Unified Groups from the Microsoft Tenant .PARAMETER Property Include the specified group property(ies) in the output .EXAMPLE Get a group by Object ID Get-OGGroup -GroupId 3175b598-0fa0-4002-aebf-bfbf759c94a7 .NOTES General notes #> Function Get-OGGroup { [CmdletBinding(DefaultParameterSetName = 'OID')] param ( [Parameter(ParameterSetName = 'OID')] $GroupId , [Parameter(ParameterSetName = 'Search')] $SearchDisplayName , [Parameter(ParameterSetName = 'All')] [Switch]$All , [Parameter(ParameterSetName = 'UnifiedAll')] [Switch]$UnifiedAll , [Parameter()] [string[]]$Property ) $IncludeAttributes =[System.Collections.Generic.List[string]]@('classification', 'createdByAppId', 'createdDateTime', 'deletedDateTime', 'description', 'displayName', 'expirationDateTime', 'groupTypes', 'id', 'infoCatalogs', 'isAssignableToRole', 'isManagementRestricted', 'mail', 'mailEnabled', 'mailNickname', 'membershipRule', 'membershipRuleProcessingState', 'onPremisesDomainName', 'onPremisesLastSyncDateTime', 'onPremisesNetBiosName', 'onPremisesProvisioningErrors', 'onPremisesSamAccountName', 'onPremisesSecurityIdentifier', 'onPremisesSyncEnabled', 'organizationId', 'preferredDataLocation', 'preferredLanguage', 'proxyAddresses', 'renewedDateTime', 'resourceBehaviorOptions', 'resourceProvisioningOptions', 'securityEnabled', 'securityIdentifier', 'theme', 'visibility', 'writebackConfiguration') $IncludeAttributeString = $($($includeAttributes; $Property) | Sort-Object -unique) -join ',' switch ($PSCmdlet.ParameterSetName) { 'OID' { $URI = "/$GraphVersion/groups/$($GroupId)?`$select=$($IncludeAttributeString)" get-ognextpage -uri $uri } 'Search' { $URI = '/' + $GraphVersion + '/groups?$search="displayName:' + $SearchDisplayName + '"&$select=' + $IncludeAttributeString Get-OGNextPage -uri $URI -Filter } 'All' { $URI = "/$GraphVersion/groups?`$select=$($IncludeAttributeString)" Get-OGNextPage -Uri $URI } 'UnifiedAll' { $URI = "/$GraphVersion/groups?`$filter=groupTypes/any(c:c+eq+'Unified')&`$select=$($IncludeAttributeString)" Get-OGNextPage -Uri $URI -Filter } } } <# .SYNOPSIS Get group drive from Microsoft Graph .DESCRIPTION Get group drive using Group Object ID Permissions: https://learn.microsoft.com/en-us/graph/api/group-list?view=graph-rest-1.0&tabs=http .PARAMETER GroupId GroupID (guid) for the group .EXAMPLE Get a group drive by Object ID Get-OGGroupDrive -GroupId 3175b598-0fa0-4002-aebf-bfbf759c94a7 GroupID : 3175b598-0fa0-4002-aebf-bfbf759c94a7 DriveName : Documents DriveURL : https://contoso.sharepoint.com/teams/contosoteam/Shared%20Documents DriveID : b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd driveType : documentLibrary SiteURL : https://contoso.sharepoint.com/teams/contosoteam createdDateTime : 10/24/2022 05:12:09 AM lastModifiedDateTime : 11/21/2022 02:37:01 PM quotaTotal : 1073741824000 quotaUsed : 1479181 quotaRemaining : 1479181 quotaDeleted : 0 quotaState : normal #> Function Get-OGGroupDrive { [CmdletBinding()] param ( [Parameter()] [guid]$GroupId ) $URI = "/$GraphVersion/groups/$($GroupId)/drive/" $Result = get-ognextpage -uri $uri $Result | Select-Object -Property @{n='GroupID'; e={$GroupId}}, @{n='DriveName'; e={$_.name}}, @{n='DriveURL'; e={$_.webUrl}}, @{n='DriveID'; e={$_.id}}, 'driveType', @{n='SiteURL'; e={$_.webUrl.substring(0, $_.weburl.LastIndexOf('/'))}}, 'createdDateTime', 'lastModifiedDateTime', @{n='quotaTotal'; e={$_.quota.total}}, @{n='quotaUsed'; e={$_.quota.used}}, @{n='quotaRemaining'; e={$_.quota.used}}, @{n='quotaDeleted'; e={$_.quota.Deleted}}, @{n='quotaState'; e={$_.quota.state}} } <# .SYNOPSIS Get the license skus applied by a group .DESCRIPTION Gets the license skus applied by a group and any disabled service plans of those skus Permissions: https://learn.microsoft.com/en-us/graph/api/group-list?view=graph-rest-1.0&tabs=http .EXAMPLE Get-OGGroupLicense -GroupId f6557fc2-d4a5-4266-8f4c-2bdcd0cd9a2d .NOTES General notes #> Function Get-OGGroupLicense { [CmdletBinding()] param ( # GroupID (guid) for the Group [Parameter(Mandatory)]$GroupId , # Specify if you want to include the SKU Display Name (Friendly Name) in the output object [parameter()] [switch]$IncludeDisplayName <# , [parameter()] [ValidateLength(1,1)] [string]$ServicePlanDelimiter = ';' #> , # Specify if you want to pass through the GroupID to the output object as an attribute [parameter()] [switch]$PassthruGroupID ) $ReadableHash = @{} switch ($IncludeDisplayName) { $true { $skusReadable = Get-OGReadableSku foreach ($sR in $skusReadable) { $ReadableHash[$sR.GUID] = $sR.Product_Display_Name $ReadableHash[$sR.Service_Plan_Id] = $sR.Service_Plans_Included_Friendly_Names } } } $URI = "/$GraphVersion/groups/$GroupId/assignedLicenses" $rawSku = @(Get-OGNextPage -uri $Uri) if ($PassthruGroupID) { $rawSku = @($rawSku | Select-Object -Property @{n='GroupID';e={$GroupID}},*) } foreach ($s in $rawSku) { $s | Select-Object -Property *, @{n='skuDisplayName';e = {$ReadableHash[$s.skuid]}} #@{n='servicePlanNames';e= {$s.ServicePlans.foreach({$_.ServicePlanName}) -join $ServicePlanDelimiter}}, #@{n='servicePlanDisplayNames'; e= {$s.ServicePlans.foreach({$ReadableHash[$_.ServicePlanID]}).where({$null -ne $_}) -join $ServicePlanDelimiter}} } } <# .SYNOPSIS Report all Enabled and Disabled skus and service plans applied by a group .DESCRIPTION Report all Enabled and Disabled skus and service plans applied by a group Permissions: https://learn.microsoft.com/en-us/graph/api/group-list?view=graph-rest-1.0&tabs=http .PARAMETER GroupId GroupID (guid) for the group for which to report licensing details. .PARAMETER All Includes all groups that have a license assignment. .PARAMETER IncludeDisplayName Includes "human readable" Display Names for skus and service plans. .EXAMPLE Get-OGGroupLicenseReport -GroupId f6557fc2-d4a5-4266-8f4c-2bdcd0cd9a2d .NOTES General notes #> Function Get-OGGroupLicenseReport { [CmdletBinding(DefaultParameterSetName = 'Single')] param ( [Parameter(Mandatory, ParameterSetName = 'Single')] $GroupId, [Parameter(Mandatory, ParameterSetName = 'All')] [switch]$All, [Parameter()] [switch]$IncludeDisplayName ) switch ($PSCmdlet.ParameterSetName) { 'All' { $groups = @(Get-OGGroup -All -Property assignedLicenses).where({$_.assignedLicenses.count -ge 1}) $getOGGLRParams = @{IncludeDisplayName = $IncludeDisplayName} $groups.foreach({ Get-OGGroupLicenseReport -GroupId $_.id @getOGGLRParams}) } 'Single' { $ReadableHash = @{} switch ($IncludeDisplayName) { $true { $skusReadable = Get-OGReadableSku foreach ($sR in $skusReadable) { $ReadableHash[$sR.GUID] = $sR.Product_Display_Name $ReadableHash[$sR.Service_Plan_Id] = $sR.Service_Plans_Included_Friendly_Names } } } $skus = Get-OGSku $group = Get-OGGroup -GroupId $groupid $skuHash = @{} #hashtable to be populated with key SkuID and value SKU detail object $spHash = @{} #hashtable to be populated with key service plan ID and value service plan detail object $spPerSku = @{} #hasthable to be populated with key SkuID and value ServicePlanIDs collection foreach ($s in $skus) { $sku = [PSCustomObject]@{ type = 'Sku' skuDisplayName = $ReadableHash[$s.skuid] skuName = $s.skuPartNumber prepaidUnitsEnabled = $s.prepaidUnitsEnabled consumedUnits = $s.consumedUnits nonConsumedUnits = $s.nonConsumedUnits skuAppliesTo = $s.appliesTo skuId = $s.skuId servicePlanName = $null servicePlanId = $null servicePlanProvisioningStatus = $null servicePlanAppliesTo = $null } $skuHash[$sku.skuId] = $Sku $splans = @($s.servicePlans) foreach ($sp in $splans) { $servicePlan = [PSCustomObject]@{ type = 'ServicePlan' skuDisplayName = $ReadableHash[$s.skuid] skuName = $s.skuPartNumber #skuPrepaidUnits = $s.prepaidUnits skuPrepaidUnitsEnabled = $s.prepaidUnits.Enabled skuConsumedUnits = $s.consumedUnits skuNonConsumedUnits = $sku.nonConsumedUnits skuAppliesTo = $s.appliesTo skuId = $s.skuId servicePlanDisplayName = $ReadableHash[$sp.servicePlanId] servicePlanName = $sp.servicePlanName servicePlanId = $sp.servicePlanId servicePlanProvisioningStatus = $sp.provisioningStatus servicePlanAppliesTo = $sp.appliesTo } $spHash[$servicePlan.servicePlanId + '_' + $sku.skuID] = $servicePlan } $spPerSku[$s.skuid] = $splans.servicePlanId } $groupLicense = Get-OGGroupLicense -GroupId $GroupId $outputProperties = @( @{Name = 'groupId'; Expression = { $group.id } } @{Name = 'groupDisplayName'; Expression = { $group.DisplayName } } @{Name = 'type'; Expression = { 'ServicePlanPerSku' } } 'skuDisplayName' 'skuName' 'skuId' 'skuPrepaidUnitsEnabled' 'skuConsumedUnits' 'skuNonConsumedUnits' 'skuAppliesTo' 'servicePlanDisplayName' 'servicePlanName' 'servicePlanId' 'servicePlanProvisioningStatus' 'servicePlanAppliesTo' @{Name = 'servicePlanIsEnabled'; Expression = { $_.serviceplanid -notin $groupLicense.disabledPlans } } ) @($grouplicense.skuid).foreach({ $gskuid = $_ $gsp = @($spPerSku[$gskuid]) $gsp.foreach({ $spHash[$_ + '_' + $gskuid] }) }) | Select-Object -ExcludeProperty type -Property $outputProperties } } } <# .SYNOPSIS Get calendar events for a group .DESCRIPTION Get calendar events for a group or provide a filter queary to filter the results. NOTE: Delegated Permission Only Permissions: https://learn.microsoft.com/en-us/graph/api/group-get-event?view=graph-rest-1.0&tabs=http .PARAMETER GroupId GroupID (guid) for the group .PARAMETER Filter Parameter description .EXAMPLE Get all calendar events for a group Get-OGGroupEvent -GroupId 3fbabd10-7bbc-410d-ba6c-0ba60e863c30 .NOTES General notes #> Function Get-OGGroupEvent { param ( [Parameter(Mandatory = $True)]$GroupId, [Parameter(Mandatory = $False)]$Filter ) if ($filter) { $URI = "/$GraphVersion/groups/$GroupId/events?`$filter=$filter" Get-OGNextPage -URI $URI } else { $URI = "/$GraphVersion/groups/$GroupId/events" Get-OGNextPage -URI $URI } } <# .SYNOPSIS Get Members of a Group in Azure AD .DESCRIPTION Get Members of a Group in Azure AD Permissions: https://learn.microsoft.com/en-us/graph/api/group-list?view=graph-rest-1.0&tabs=http .PARAMETER GroupId GroupID (guid) for the group .EXAMPLE Get-OGGroupMember -GroupId 3175b598-0fa0-4002-aebf-bfbf759c94a7 .NOTES General notes #> Function Get-OGGroupMember { [CmdletBinding()] param ( [Parameter(Mandatory)]$GroupId ) $URI = "/$GraphVersion/groups/$GroupId/members" Get-OGNextPage -uri $URI } <# .SYNOPSIS Get specified or all Sharepoint Online Sites in a tenant .DESCRIPTION Get specified or all Sharepoint Online Sites in a tenant Permissions: https://learn.microsoft.com/en-us/graph/api/site-get?view=graph-rest-1.0&tabs=http .PARAMETER SiteId SharePoint Site Identifier .PARAMETER SiteURL SharePoint Site URL .PARAMETER All Get all SharePoint Sites for the connected tenant .PARAMETER IncludePersonalSites Include OneDrive for Business Sites in the results .EXAMPLE Get-OGSite -SiteId f232e745-0801-4705-beb6-4d9880fc92b4 .NOTES General notes #> Function Get-OGSite { [CmdletBinding(DefaultParameterSetName = 'SID')] Param( [Parameter(Mandatory, ParameterSetName = 'SID')]$SiteId, [Parameter(Mandatory, ParameterSetName = 'URL')]$SiteURL, [Parameter(Mandatory, ParameterSetName = 'All')][Switch]$All, [Parameter(Mandatory = $False, ParameterSetName = 'All')][Switch]$IncludePersonalSites ) switch ($PSCmdlet.ParameterSetName) { 'SID' { $account_params = @{ Uri = "/$GraphVersion/sites/$SiteId" Method = 'GET' OutputType = 'PSObject' ContentType = 'application/json' } Invoke-MgGraphRequest @Account_params } 'URL' { $SiteURI = [uri]::new($SiteURL) $account_params = @{ Uri = "/$GraphVersion/sites/$($SiteURI.Host):/$($SiteURI.LocalPath)" Method = 'GET' OutputType = 'PSObject' ContentType = 'application/json' } Invoke-MgGraphRequest @Account_params } 'All' { $URI = "/$GraphVersion/sites/?$search=*" $allResults = Get-OGNextPage -uri $URI switch ($IncludePersonalSites) { True { $allResults } False { $allResults | Where-Object WebUrl -NotLike '*/personal/*' } } } } } <# .SYNOPSIS Get the lists in a Sharepoint Online Site .DESCRIPTION Get the lists in a Sharepoint Online Site Permissions: https://learn.microsoft.com/en-us/graph/api/site-get?view=graph-rest-1.0&tabs=http .PARAMETER SiteId SharePoitn Site Identifier .EXAMPLE Get-OGSiteList -SiteId b767d342-3712-492a-94dc-504304cb8412 .NOTES General notes #> Function Get-OGSiteList { [CmdletBinding()] param ( [Parameter(Mandatory)]$SiteId ) $URI = "/$GraphVersion/sites/$SiteId/lists" Get-OGNextPage -uri $URI } <# .SYNOPSIS Get columns contained in an SPO site list .DESCRIPTION Get columns contained in an SPO site list Permissions: https://learn.microsoft.com/en-us/graph/api/site-get?view=graph-rest-1.0&tabs=http .PARAMETER SiteId SharePoint Site Identifier .PARAMETER ListId SharePoint List Identifier .EXAMPLE Get-OGSiteListColumn -SiteId b767d342-3712-492a-94dc-504304cb8412 -ListId c1e7d5b3-ed9e-409e-a956-9d77df7c1ec3 .NOTES General notes #> Function Get-OGSiteListColumn { [CmdletBinding()] param ( [Parameter(Mandatory)]$SiteId , [Parameter(Mandatory)]$ListId ) $URI = "/$GraphVersion/sites/$SiteId/lists/$ListId/Columns" Get-OGNextPage -uri $URI } <# .SYNOPSIS Get items in a SPO List .DESCRIPTION Get items in a SPO List Permissions: https://learn.microsoft.com/en-us/graph/api/site-get?view=graph-rest-1.0&tabs=http .PARAMETER SiteId SharePoint Site Identifier .PARAMETER ListId SharePoint List Identifier .PARAMETER ItemId SharePoint List Item Identifier .EXAMPLE Get-OGSiteListItem -SiteId a3299706-eac5-46a1-b5eb-5709bea18e89 -ListId 79aafc35-e805-491c-bf19-f0b6c28b6be0 .NOTES General notes #> Function Get-OGSiteListItem { [CmdletBinding()] param ( [Parameter(Mandatory)]$SiteId, [Parameter(Mandatory)]$ListId, [Parameter(Mandatory = $false)]$ItemId ) if ($ItemId) { $URI = "/$GraphVersion/sites/$SiteId/lists/$ListId/items?expand=fields" $response = Get-OGNextPage -uri $URI | Where-Object id -EQ $ItemId $response.fields } else { $URI = "/$GraphVersion/sites/$SiteId/lists/$ListId/items?expand=fields" $response = Get-OGNextPage -uri $URI $response.fields } } <# .SYNOPSIS Get an items version history .DESCRIPTION Get an items version history by specifying the site ID, list ID, and item ID Permissions: https://learn.microsoft.com/en-us/graph/api/listitem-list-versions?view=graph-rest-1.0&tabs=http .PARAMETER SiteId Parameter description .PARAMETER ListId Parameter description .PARAMETER ItemId Parameter description .EXAMPLE Get-OGSiteListItemVersion -SiteId a3299706-eac5-46a1-b5eb-5709bea18e89 -ListId 79aafc35-e805-491c-bf19-f0b6c28b6be0 .NOTES General notes #> Function Get-OGSiteListItemVersion { [CmdletBinding()] param ( [Parameter(Mandatory)]$SiteId, [Parameter(Mandatory)]$ListId, [Parameter(Mandatory)]$ItemId ) $URI = "/$GraphVersion/sites/$SiteId/lists/$ListId/items/$ItemId/versions" $response = Get-OGNextPage -uri $URI $response.fields } <# .SYNOPSIS REcursive Helper function for simplifying graph api requests including next page functionality .DESCRIPTION Recursive Helper function for simplifying graph api requests including next page functionality. .PARAMETER URI Parameter description .PARAMETER Filter Parameter description .EXAMPLE Get-OGNextpage -URI "/v1.0/users" .NOTES General notes #> Function Get-OGNextPage { [CmdletBinding()] param ( [Parameter(Mandatory = $True)][string]$URI, [Parameter(Mandatory = $False)][Switch]$Filter ) $account_params = @{ URI = $URI Method = 'GET' OutputType = 'PSObject' ContentType = 'application/json' } switch ($filter) { $true { $account_params.add('Headers', @{}) $account_params.Headers.add('ConsistencyLevel', 'eventual') } } $Result = Invoke-MgGraphRequest @Account_params switch ($null -ne $Result.value) { $true { $Result.value } $False { $Result | Select-Object -ExcludeProperty '@odata.*' } } if ($result.'@odata.nextlink') { Get-OGNextPage -Uri $result.'@odata.nextlink' } } <# .SYNOPSIS Provide human readable description to M365 Service Plans by downloading the csv in the Microsoft Docs reference. .DESCRIPTION Provide human readable description to M365 Service Plans by downloading the csv in the Microsoft Docs reference. If the CSV fails to download a local copy will be used for the output. If the download is successful, the local copy will be updated. .PARAMETER StoreCSV Stores the readable sku csv from Microsoft in the Module folder. .EXAMPLE Get-OGReadableSku .NOTES #> function Get-OGReadableSku { [CmdletBinding()] param ( [switch]$StoreCSV ) $PreDownloadedCSV = Join-Path -Path $PSScriptRoot -ChildPath 'OGReadableSku.csv' switch (Test-Path -Path $PreDownloadedCSV -Type Leaf) { $True { switch ($StoreCSV) { $true { # add a refresh option here (rework flow or create separate function for storing) } $False { Import-Csv $PreDownloadedCSV } } } $False { try { $temp = Get-PSDrive -Name 'Temp' $TempPath = Join-Path -Path $temp.Root -ChildPath 'OGReadableSku.csv' $url = 'https://download.microsoft.com/download/e/3/e/e3e9faf2-f28b-490a-9ada-c6089a1fc5b0/Product%20names%20and%20service%20plan%20identifiers%20for%20licensing.csv' Invoke-WebRequest -Uri $url -OutFile $TempPath switch ($StoreCSV) { $True { Move-Item -Path $TempPath -Destination $PreDownloadedCSV -Force -Confirm:$false } $False { Import-Csv $TempPath } } } catch { Out-Null } } } } <# .SYNOPSIS Get Skus available in the connected Microsoft tenant .DESCRIPTION Gets Skus available in the connected Microsoft Tenant and allows the inclusion of "human readable" DisplayNames. .PARAMETER IncludeDisplayName Includes "human readable" display names in the output for both skus and serviceplans. .PARAMETER ServicePlanDelimiter Specify the delimiter for the ServicePlanNames and ServicePlanDisplayNames. Defaults to ";". .EXAMPLE Get-OGSku .NOTES Permissions Required: https://learn.microsoft.com/en-us/graph/api/subscribedsku-list?view=graph-rest-1.0&tabs=http #> Function Get-OGSku { [CmdletBinding()] [OutputType([System.Array],[System.String])] param( [switch]$IncludeDisplayName , [parameter()] [ValidateLength(1,1)] [string]$ServicePlanDelimiter = ';' ) $Uri = "/$GraphVersion/subscribedSkus" $ReadableHash = @{} $rawSku = get-ognextpage -uri $Uri switch ($IncludeDisplayName) { $true { $skusReadable = Get-OGReadableSku foreach ($sR in $skusReadable) { $ReadableHash[$sR.GUID] = $sR.Product_Display_Name $ReadableHash[$sR.Service_Plan_Id] = $sR.Service_Plans_Included_Friendly_Names } } } foreach ($s in $rawSku) { [PSCustomObject]@{ 'AccountName' = $s.AccountName 'AccountID' = $s.AccountID 'AppliesTo' = $s.AppliesTo 'CapabilityStatus' = $s.CapabilityStatus 'id' = $s.id 'skuid' = $s.skuid 'skupartnumber'= $s.skupartnumber 'prepaidUnitsEnabled'= $s.prepaidUnits.enabled 'consumedUnits' = $s.consumedUnits 'nonConsumedUnits'= $s.prepaidUnits.Enabled - $s.consumedUnits 'skuDisplayName' = $ReadableHash[$s.skuid] 'servicePlanIDs' = $s.ServicePlans.foreach({$_.ServicePlanID}) -join $ServicePlanDelimiter 'servicePlanNames' = $s.ServicePlans.foreach({$_.ServicePlanName}) -join $ServicePlanDelimiter 'servicePlanDisplayNames' = $s.ServicePlans.foreach({$ReadableHash[$_.ServicePlanID]}).where({$null -ne $_}) -join $ServicePlanDelimiter 'SubscriptionIDs' = $s.SubscriptionIDs 'ServicePlans' = $s.ServicePlans 'PrepaidUnits' = $s.PrepaidUnits } } } <# .SYNOPSIS Get users from Azure AD .DESCRIPTION Get users from Azure AD Permissions: https://learn.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=http .PARAMETER UserPrincipalName Get Users by userprincipalname .PARAMETER SearchDisplayName Search for users by displayname .PARAMETER All Get all users in tenant .PARAMETER Property Select additional properties of a user .EXAMPLE Get-OGUser -UserPrincipalName test@testaccount.onmicrosoft.com .NOTES General notes #> Function Get-OGUser { [CmdletBinding(DefaultParameterSetName = 'UPN')] param ( [Parameter(ParameterSetName = 'UPN', Mandatory)]$UserPrincipalName, [Parameter(ParameterSetName = 'Search')]$SearchDisplayName, [Parameter(ParameterSetName = 'All')] [Switch]$All, [Parameter()] [string[]]$Property ) $includeAttributes = 'businessPhones', 'displayName', 'givenName', 'id', 'jobTitle', 'mail', 'mobilePhone', 'officeLocation', 'preferredLanguage', 'surname', 'userPrincipalName' $IncludeAttributeString = $($($includeAttributes; $Property) | Sort-Object -unique) -join ',' switch ($PSCmdlet.ParameterSetName) { 'UPN' { $URI = "/$GraphVersion/users/$($userprincipalname)?`$select=$($IncludeAttributeString)" Get-OGNextPage -Uri $URI } 'Search' { $IncludeAttributeString = $includeAttributes -split ',' $URI = "/$GraphVersion/users?`$search=`"displayName:$SearchDisplayName`"" Get-OGNextPage -uri $URI -filter | select-object $IncludeAttributeString } 'All' { $URI = "/$GraphVersion/users?`$select=$($IncludeAttributeString)" Get-OGNextPage -Uri $URI } } } <# .SYNOPSIS Get user OneDrive Meta information .DESCRIPTION Get user OneDrive Meta information Permissions: https://learn.microsoft.com/en-us/graph/api/drive-get?view=graph-rest-1.0&tabs=http .EXAMPLE Get-OGUserDrive -userprincipalname test.user@domain.com .NOTES General notes #> Function Get-OGUserDrive { [CmdletBinding()] param ( #Specify the UserPrincipalName OR ID for the user [Parameter(Mandatory)] $UserPrincipalName , # Specify whether to pass through the UserPrincipalName to the output object at an attribute of the output [parameter()] [alias('PassthruUPN')] [switch]$PassthruUserPrincipalName ) $URI = "/$GraphVersion/users/$userprincipalname/drive" try {$rawDrive = Get-OGNextPage -uri $URI -ErrorAction Stop} catch { Write-Warning -Message $_.tostring() } if ($PassthruUserPrincipalName) { $rawDrive = $rawDrive | Select-Object -Property @{n='UserPrincipalName';e={$UserPrincipalName}},* } $rawDrive } <# .SYNOPSIS Get calendar events for a user .DESCRIPTION Get calendar events for a user or provide a filter queary to filter the results. Permissions: https://learn.microsoft.com/en-us/graph/api/user-list-events?view=graph-rest-1.0&tabs=http .PARAMETER UserPrincipalName Parameter description .PARAMETER Filter Parameter description .EXAMPLE Get all calendar events for a group Get-OGUserEvent -GroupId 3fbabd10-7bbc-410d-ba6c-0ba60e863c30 .NOTES General notes #> Function Get-OGUserEvent { param ( [Parameter(Mandatory = $True)]$UserPrincipalName, [Parameter(Mandatory = $False)]$Filter ) if ($filter) { $URI = "/$GraphVersion/users/$userprincipalname/events?`$filter=$filter" Get-OGNextPage -URI $URI -Filter } else { $URI = "/$GraphVersion/users/$userprincipalname/events" Get-OGNextPage -URI $URI } } <# .SYNOPSIS Get users from Entra ID with there signInActivity .DESCRIPTION Get users from Entra ID with there signInActivity .PARAMETER UserPrincipalName Get users by the UserPrincipalName .PARAMETER UserID Get users by the entra user id .PARAMETER All Get last login for all users NOTE: The signInActivity call made by Graph only accepts Entra Id. The parameter will be less performant than UserId because users the UPN to get the user Id. .PARAMETER Property Select additional properties of a user .EXAMPLE Get-OGUserLastLogin -UserId d7e0Qb89-6ef6-4a6b-433f-193558b630ff .NOTES The signInActivity property only works with Graph version Beta. The function automatically changes the graph version to beta but does not change it globally. #> Function Get-OGUserLastLogin { [CmdletBinding(DefaultParameterSetName = 'UserId')] param ( [Parameter(ParameterSetName = 'UserID' )] [string]$UserID , [Parameter(ParameterSetName = 'UPN')] [string]$UserPrincipalName , [Parameter(ParameterSetName = 'All')] [switch]$All , [Parameter()] [string[]]$Property ) $includeAttributes = 'signInActivity', 'businessPhones', 'displayName', 'givenName', 'id', 'jobTitle', 'mail', 'mobilePhone', 'officeLocation', 'preferredLanguage', 'surname', 'UserID' $IncludeAttributeString = $($($includeAttributes; $Property) | Sort-Object -unique) -join ',' $GraphVersion = 'Beta' switch ($PSCmdlet.ParameterSetName) { 'UserID' { $URI = "/$GraphVersion/users/$($UserID)?`$select=$($IncludeAttributeString)" Get-OGNextPage -URI $URI -Filter } 'UPN' { try { $UserID = $(Get-OGUser -UserPrincipalName $UserPrincipalName -ErrorAction Stop).id } catch { Throw($_) } $URI = "/$GraphVersion/users/$($UserID)?`$select=$($IncludeAttributeString)" Get-OGNextPage -URI $URI -Filter } 'All' { $URI = "/$GraphVersion/users?`$select=$($IncludeAttributeString)" Get-OGNextPage -URI $URI } } } <# .SYNOPSIS Get Azure AD skus for individual user .DESCRIPTION Get Azure AD skus for individual user Permissions: https://learn.microsoft.com/en-us/graph/api/user-list-licensedetails?view=graph-rest-1.0&tabs=http .EXAMPLE Get-OGUserSku -UserPrincipalName jdoe@contoso.com .NOTES General notes #> Function Get-OGUserSku { [CmdletBinding()] param ( #Specify the UserPrincipalName for the user [Parameter(Mandatory)] $UserPrincipalName , # Specify whether to include the SKU and ServicePlan Display Names (Friendly Names) in the output object(s) [parameter()] [switch]$IncludeDisplayName , # Specify the delimeter to use betwen Service Plan items in the output object [parameter()] [ValidateLength(1,1)] [string]$ServicePlanDelimiter = ';' , # Specify whether to pass through the UserPrincipalName to the output object at an attribute of the output [parameter()] [alias('PassthruUPN')] [switch]$PassthruUserPrincipalName ) $ReadableHash = @{} switch ($IncludeDisplayName) { $true { $skusReadable = Get-OGReadableSku foreach ($sR in $skusReadable) { $ReadableHash[$sR.GUID] = $sR.Product_Display_Name $ReadableHash[$sR.Service_Plan_Id] = $sR.Service_Plans_Included_Friendly_Names } } } $Uri = "$GraphVersion/Users/$($UserPrincipalName)/licenseDetails" $rawSku = Get-OGNextPage -uri $Uri if ($PassthruUserPrincipalName) { $rawSku = $rawSku | Select-Object -Property @{n='UserPrincipalName';e={$UserPrincipalName}},* } foreach ($s in $rawSku) { $s | Select-Object -Property *, @{n='skuDisplayName';e = {$ReadableHash[$s.skuid]}}, @{n='servicePlanNames';e= {$s.ServicePlans.foreach({$_.ServicePlanName}) -join $ServicePlanDelimiter}}, @{n='servicePlanDisplayNames'; e= {$s.ServicePlans.foreach({$ReadableHash[$_.ServicePlanID]}).where({$null -ne $_}) -join $ServicePlanDelimiter}} } } <# .SYNOPSIS Add new item to a SharePoint list .DESCRIPTION Create a SharePoint Online list item by providing the SharePoint site ID, the List ID, and the values of the fields to be added in a hash table. Permissions: https://learn.microsoft.com/en-us/graph/api/listitem-create?view=graph-rest-1.0&tabs=http .PARAMETER SiteId SharePoint Site Identifier .PARAMETER ListId SharePoint List Identifier .PARAMETER Fields Hashtable of item fields and values to include in the new SharePoint List Item .EXAMPLE $fields = @{ field_1 = "Sample String" } New-OGSiteListItem -SiteId 26776db6-ffd1-4e58-a6bf-851d6302733a -ListId 26f11389-ffd1-4e24-a7h1-85af93422733a -Fields $fields .NOTES General notes #> function New-OGSiteListItem { [CmdletBinding(SupportsShouldProcess)] Param( [Parameter(Mandatory)] [String]$SiteId , [Parameter(Mandatory)] [String]$ListId , [Parameter(Mandatory)] [hashtable]$Fields ) $URI = "/$GraphVersion/sites/$SiteId/lists/$ListId/items" $body = @{fields = $Fields } $account_params = @{ URI = $URI body = $body | ConvertTo-Json -Depth 5 Method = 'POST' ContentType = 'application/json' } if ($PSCmdlet.ShouldProcess($ItemID,'POST')) { Invoke-MgGraphRequest @Account_params } } <# .SYNOPSIS Remove member from Azure AD group membership .DESCRIPTION Remove member from Azure AD group membership Permissions: https://learn.microsoft.com/en-us/graph/api/group-delete-members?view=graph-rest-1.0&tabs=http .PARAMETER GroupId Parameter description .PARAMETER UserPrincipalName Parameter description .PARAMETER MemberId Parameter description .EXAMPLE Remove-OGGroupMember -ObjectId a3299706-eac5-46a1-b5eb-5709bea18e89 -MemberId b767d342-3712-492a-94dc-504304cb8412 .NOTES General notes #> Function Remove-OGGroupMember { [CmdletBinding(DefaultParameterSetName = 'MID', SupportsShouldProcess)] param ( [Parameter(Mandatory, ParameterSetName = 'MID')] [Parameter(Mandatory, ParameterSetName = 'UPN')] $GroupId, [Parameter(Mandatory, ParameterSetName = 'UPN')] $UserPrincipalName, [Parameter(Mandatory, ParameterSetName = 'MID')] $MemberId ) switch ($PSCmdlet.ParameterSetName) { 'UPN' { $MemberId = Get-OGUser -UserPrincipalName $UserPrincipalName $MemberId = $MemberId.Id } } $URI = "/$GraphVersion/groups/$GroupId/members/$MemberId/`$ref" $account_params = @{ Uri = $URI Method = 'DELETE' } if ($PSCmdlet.ShouldProcess($GroupID, "remove member $($UserPrincipalName)$($MemberId)")) { Invoke-MgGraphRequest @Account_params } } <# .SYNOPSIS Delete an item in a SharePoint Online list .DESCRIPTION Delete a SharePoint Online list item by providing the SharePoint site ID, the List ID, and the ID of the item to be deleted. Permissions: https://learn.microsoft.com/en-us/graph/api/listitem-delete?view=graph-rest-1.0&tabs=http .EXAMPLE Remove-OGSiteListItem -SiteId 26776db6-ffd1-4e58-a6bf-851d6302733a -ListId 26f11389-ffd1-4e24-a7h1-85af93422733a -ItemId 1234 #> function Remove-OGSiteListItem { [CmdletBinding(SupportsShouldProcess)] Param( #SharePoint Site Identifier [Parameter(Mandatory)] $SiteId , #SharePoint List Identifier [Parameter(Mandatory)] $ListId , #SharePoint List Item Identifier [Parameter(Mandatory)] $ItemId ) $URI = "/$GraphVersion/sites/$SiteId/lists/$ListId/items/$ItemId" $account_params = @{ URI = $URI Method = 'DELETE' ContentType = 'application/json' } if ($PSCmdlet.ShouldProcess($ItemID,'DELETE')) { Invoke-MgGraphRequest @Account_params } } <# .SYNOPSIS Set basic fields for a user object or disable an account .DESCRIPTION Updated UPN, disable a user, Set firstname, lastname, or displayname Permissions: https://learn.microsoft.com/en-us/graph/api/user-update?view=graph-rest-1.0&tabs=http .PARAMETER UserPrincipalName Parameter description .PARAMETER NewUserPrincipalName Parameter description .PARAMETER accountEnabled Parameter description .PARAMETER FirstName Parameter description .PARAMETER LastName Parameter description .PARAMETER DisplayName Parameter description .EXAMPLE Set-OGUser -UserPrincipalName jdoe@contoso.com -accountEnabled $false .NOTES General notes #> Function Set-OGUser { [CmdletBinding(SupportsShouldProcess)] Param( [Parameter(Mandatory)]$UserPrincipalName, [Parameter(Mandatory = $false)][String]$NewUserPrincipalName, [Parameter(Mandatory = $false)][String]$accountEnabled, [Parameter(Mandatory = $false)][String]$FirstName, [Parameter(Mandatory = $false)][String]$LastName, [Parameter(Mandatory = $false)][String]$DisplayName ) $User = Get-OGUser -UserPrincipalName $UserPrincipalName $bodyparams = @{} switch ($PSBoundParameters.Keys) { 'NewUserPrincipalName' { $bodyparams.add('userPrincipalName', $NewUserPrincipalName) } 'accountEnabled' { $bodyparams.add('accountEnabled', $accountEnabled) } 'FirstName' { $bodyparams.add('givenName', $FirstName) } 'LastName' { $bodyparams.add('surname', $LastName) } 'DisplayName' { $bodyparams.add('displayName', $DisplayName) } } $Body = [PSCustomObject]@{} $body | Add-Member $bodyparams $account_params = @{ Uri = "/$GraphVersion/users/$($User.Id)" body = $body | ConvertTo-Json -Depth 5 Method = 'PATCH' ContentType = 'application/json' } if ($PSCmdlet.ShouldProcess($UserPrincipalName, "set $($bodyparams.keys)")) { Invoke-MgGraphRequest @Account_params | Out-Null } } <# .SYNOPSIS Switch between graph api versions beta and v1.0 .DESCRIPTION Switch between graph api versions beta and v1.0 .PARAMETER Beta Parameter description .PARAMETER v1 Parameter description .EXAMPLE Set-OGGraphVersion -Beta .NOTES General notes #> Function Set-OGGraphVersion { [CmdletBinding(DefaultParameterSetName = 'v1', SupportsShouldProcess)] param ( [Parameter(Mandatory = $false, ParameterSetName = 'Beta')][switch]$Beta, [Parameter(Mandatory = $false, ParameterSetName = 'v1')][switch]$v1 ) if ($PSCmdlet.ShouldProcess("Graph Version", "set Graph API version to $($PSCmdlet.ParameterSetName)")) { switch ($PSCmdlet.ParameterSetName) { 'Beta' { $Script:GraphVersion = 'beta' } 'v1' { $Script:GraphVersion = 'v1.0' } } } } <# .SYNOPSIS Update an item in a SharePoint Online list .DESCRIPTION Update a SharePoint Online list item by providing the SharePoint site ID, the List ID, and the ID of the item to be updated. Next, provide the fields to be updated in a hash table Permissions: https://learn.microsoft.com/en-us/graph/api/listitem-update?view=graph-rest-1.0&tabs=http .EXAMPLE $fields = @{ field_1 = "Sample String" } Update-OGSiteListItem -SiteId 26776db6-ffd1-4e58-a6bf-851d6302733a -ListId 26f11389-ffd1-4e24-a7h1-85af93422733a -ItemId 1234 -Fields $fields #> function Update-OGSiteListItem { [CmdletBinding(SupportsShouldProcess)] Param( #SharePoint Site Identifier [Parameter(Mandatory)] [String]$SiteId , #SharePoint List Identifier [Parameter(Mandatory)] [String]$ListId , #SharePoint List Item Identifier [Parameter(Mandatory)] $ItemId , #Hashtable of item fields and values to update in the item [Parameter(Mandatory)] [hashtable]$Fields ) $URI = "/$GraphVersion/sites/$SiteId/lists/$ListId/items/$ItemId/fields" $account_params = @{ URI = $URI body = $Fields | ConvertTo-Json -Depth 5 Method = 'PATCH' ContentType = 'application/json' } if ($PSCmdlet.ShouldProcess($ItemID,'PATCH')) { Invoke-MgGraphRequest @Account_params } } ############################################################################################### # Import User's Configuration ############################################################################################### #Import-OGConfiguration ############################################################################################### # Setup Tab Completion ############################################################################################### # Tab Completions for IM Definition Names <# $ImDefinitionsScriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) $MyParams = @{ } if ($null -ne $fakeBoundParameter.InstallManager) { $MyParams.InstallManager = $fakeBoundParameter.InstallManager } if ($null -ne $wordToComplete) { $MyParams.Name = $wordToComplete + '*' } $MyNames = Get-IMDefinition @MyParams | Select-Object -expandProperty Name foreach ($n in $MyNames) { [System.Management.Automation.CompletionResult]::new($n, $n, 'ParameterValue', $n) } } Register-ArgumentCompleter -CommandName @( 'Get-IMDefinition' 'Set-IMDefinition' 'Remove-IMDefinition' 'Update-IMInstall' ) -ParameterName 'Name' -ScriptBlock $ImDefinitionsScriptBlock #> |