MyPSFunctions.SPO.ps1
<#
=========================================================================== Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.196 Created on: 10/26/2023 7:18 PM Created by: John@MyPSFunctions.com Organization: MyPSFunctions Filename: MyPSFunctions.SPO.psm1 ------------------------------------------------------------------------- Module Name: MyPSFunctions.SPO =========================================================================== #> Function Generate-OnedriveUsageReport { [CmdletBinding()] param () # Get a list of OneDrive for Business sites in the tenant sorted by the biggest consumer of quota Write-Log -Level Warning -Message "Finding OneDrive sites..." [array]$ODFBSites = Get-SPOSite -IncludePersonalSite $True -Limit All -Filter "Url -like '-my.sharepoint.com/personal/'" | Select Owner, Title, URL, StorageQuota, StorageUsageCurrent | Sort StorageUsageCurrent -Descending If (!($ODFBSites)) { Write-Log -Level Error -Message "No OneDrive sites found (surprisingly...)"; break } # Calculate total used $TotalODFBGBUsed = [Math]::Round(($ODFBSites.StorageUsageCurrent | Measure-Object -Sum).Sum /1024, 2) # Create list to store report data $Report = [System.Collections.Generic.List[Object]]::new() # Store information for each OneDrive site ForEach ($Site in $ODFBSites) { $ReportLine = [PSCustomObject]@{ Owner = $Site.Title Email = $Site.Owner URL = $Site.URL QuotaGB = [Math]::Round($Site.StorageQuota/1024, 2) UsedGB = [Math]::Round($Site.StorageUsageCurrent/1024, 4) PercentUsed = [Math]::Round(($Site.StorageUsageCurrent/$Site.StorageQuota * 100), 4) } $Report.Add($ReportLine) } Write-Log -Level Warning -Message "Current OneDrive for Business storage consumption is $TotalODFBGBUsed GB" $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFilexlsx = ".\Report_CurrentUser_Onedrive_Usage_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFilexlsx -TableName "OnedriveUsage" -Title "OnedriveUsage" -TitleBold -WorksheetName "OnedriveUsage" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFilexlsx" } Function Add-SharepointCollaborationSiteAdminPermission { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$SiteURL, [Parameter(Mandatory = $true, Position = 2)] [string]$AdminUPN ) Set-SPOUser -site $SiteURL -LoginName $AdminUPN -IsSiteCollectionAdmin $True Write-Log -Level Error -message "Updated permission" } Function Add-SharepointCollaborationSiteAdminPermissionToGroup { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$SiteURL, [Parameter(Mandatory = $true, Position = 2)] [string]$GroupEmailAddress ) $AADGroup = Get-AzureADGroup -SearchString $GroupEmailAddress $AADGroupID = $AADGroup.Objectid $LoginName = "C:0t.c|tenant|" + $AADGroupID Set-SPOUser -site $SiteURL -LoginName $LoginName -IsSiteCollectionAdmin $True Write-Log -Level Error -message "Updated permission" } Function Add-SharepointCollectionSiteURLAdminusingCSV { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$CSVFile ) $CollabSites = Import-Csv $CSVFile #Initiate the Hash Table [Int]$i = 1 $Table = $Null $Table = @() $Count = ($CollabSites | Measure).count #Loop through each Site Collection ForEach ($Site in $CollabSites) { $SiteURL = $Null $SiteURL = $Site.SiteUrl $Title = $Null $Title = $Site.Title Write-Log -Level Warning -message "The script is analyzing $Title - $SiteURL….. --- $i/$Count" #Get the Site colection $SiteCollectionData = Get-SPOSite $SiteURL #sharepoint online powershell get all site collection admins $SiteAdmins = Get-SPOUser -Site $SiteCollectionData -Limit ALL | Where { $_.IsSiteAdmin -eq $True } $FoundSiteAdmins = $Null $FoundSiteAdmins = @() foreach ($Admin in $SiteAdmins) { $FoundSiteAdmins += $Admin.DisplayName + "-:-" + $Admin.LoginName } $FoundAdmins = $FoundSiteAdmins -join "_" Write-Log -Level Warning -message "Found admin $FoundAdmins" $FoundKMSAdmins = $FoundSiteAdmins | where { $_ -like "*KMS-Admin*" } $FoundKMSSiteAdmins = $FoundKMSAdmins -join "-" $FoundKMSAdminCount = ($FoundKMSAdmins | Measure).count If ($FoundKMSAdminCount -ge 1) { Write-Log -Level INFO -message "Found admins are/is : $FoundKMSSiteAdmins for $Title" $KMSAdmins = "Yes" # Add KMS Group as Admin Try { Set-SPOUser -site $SiteURL -LoginName "C:0t.c|tenant|9804662d-449e-4215-8725-1537c236d680" -IsSiteCollectionAdmin $True $Added = "Yes" } Catch { $ErrorMessage = $Error[0].Exception.Message $Added = "No, Failed with Error: $ErrorMessage" } } Else { Write-Log -Level Error -message "Did NOT Found admins for $Title" $Added = "No" $KMSAdmins = "No" } $Table += New-object PSobject -Property ([Ordered] @{ Title = $Title; SiteURL = $SiteURL; FoundAdmins = $FoundAdmins; Found_KMSAdmins = $KMSAdmins; Added = $Added; }) $i++ } $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFilexlsx = ".\Report_SharepointCollectionAdmins_Sites_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFilexlsx -TableName "SharepointCollection" -Title "SharepointCollection" -TitleBold -WorksheetName "SharepointCollection" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFilexlsx" } Function Add-SharepointCollectionSiteAdminusingCSV { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$CSVFile ) $CollabSites = Import-Csv $CSVFile #Initiate the Hash Table [Int]$i = 1 $Table = $Null $Table = @() $Count = ($CollabSites | Measure).count #Loop through each Site Collection ForEach ($Site in $CollabSites) { $SiteURL = $Null $SiteURL = $Site.SiteUrl $Title = $Null $Title = $Site.Title $FoundAdmins = $Null $FoundAdmins = $Site.FoundAdmins Write-Log -Level Warning -message "The script is analyzing $Title - $SiteURL….. --- $i/$Count" Write-Log -Level Warning -message "Found admins: $FoundAdmins" $FoundKMSAdmins = $FoundAdmins | where { $_ -like "*KMS-Admin*" } $FoundKMSAdminCount = ($FoundKMSAdmins | Measure).count If ($FoundKMSAdminCount -ge 1) { Write-Log -Level warning -message "Found admins are/is : $FoundAdmins for $Title" $KMSAdmins = "Yes" # Add KMS Group as Admin Try { Set-SPOUser -site $SiteURL -LoginName "C:0t.c|tenant|9804662d-449e-4215-8725-1537c236d680" -IsSiteCollectionAdmin $True Write-Log -Level Error -message "Update permission" $Added = "Yes" sleep 10 } Catch { $ErrorMessage = $Error[0].Exception.Message $Added = "No, Failed with Error: $ErrorMessage" } } Else { Write-Log -Level Error -message "Did NOT Found admins for $Title" $Added = "No" $KMSAdmins = "No" } $Table += New-object PSobject -Property ([Ordered] @{ Title = $Title; SiteURL = $SiteURL; FoundAdmins = $FoundAdmins; Found_KMSAdmins = $KMSAdmins; Added = $Added; }) $i++ } $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $ReportFilexlsx = ".\Report_SharepointCollectionAdmins_Sites_" + $DateFull + ".xlsx" $Table | Export-Excel $ReportFilexlsx -TableName "SharepointCollectionAdminSites" -Title "SharepointCollectionAdminSites" -TitleBold -WorksheetName "SharepointCollectionAdminSites" -TableStyle Medium9 -AutoSize -AutoFilter Write-log INFO -Message "Generate the following Report: $ReportFilexlsx" } Function Get-PnPOffice365GroupOwners { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$Identity ) $Microsoft365GroupID = (Get-PnPMicrosoft365Group -Identity $Identity).id.GUID Get-PnPMicrosoft365GroupOwner -Identity $Microsoft365GroupID } Function Get-UnifiedLogs_SharepointSite_30Days { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$SharepointSiteURL ) $StartDate = (Get-Date).AddDays(-90) $EndDate = Get-Date $Logs = Search-UnifiedAuditLog -StartDate $StartDate -EndDate $EndDate -ObjectIDs $SharepointSiteURL $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" $SharepointSiteURLName = $SharepointSiteURL.Substring(30) $SharepointSiteURLName = $SharepointSiteURLName -replace '/', "_" $SPO_UnifiedLogs_CSVFile = ".\SharepointSite_90Days_UnifiedLogs_" + $SharepointSiteURLName + "_" + $DateFull + ".xlsx" $Logs | Export-Excel $SPO_UnifiedLogs_CSVFile -TableName "SharepointSite90DaysLogs" -Title "SharepointSite90DaysLogs" -TitleBold -WorksheetName "SharepointSite90DaysLogs" -TableStyle Medium9 -AutoSize -AutoFilter $Logs | ft UserIds, Operations, RecordType, CreationDate Write-Host "The Sharepoint Site unified logs for last 30 days was exported to:" -NoNewline; Write-Host "$SPO_UnifiedLogs_CSVFile" -ForegroundColor Green } Function Reset-OnedriveQuotaToDefault { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$UPN ) Try { $SPOSite = Get-SPOSite -IncludePersonalSite $true -Limit all -Filter "Owner -eq $UPN" | where { $_.Url -like "*-my.sharepoint.com/personal/*" } | select -First 1 Write-Log -Level warning -Message "The Onedrive current configuration:" $SPOSite | fl Owner, StorageUsageCurrent, StorageQuota, StorageQuotaType $OneDriveURL = $SPOSite.Url Set-SPOSite -Identity $OneDriveURL -StorageQuotaReset Sleep 5 $SPOSite2 = Get-SPOSite -Identity $OneDriveURL -Detailed Write-Log -Level warning -Message "The Onedrive quota as been resetted" $SPOSite2 | fl Owner, StorageUsageCurrent, StorageQuota, StorageQuotaType } Catch { $ErrorMessage = $Error[0].Exception.Message $CMDLet = $Error[0].InvocationInfo.Line $FailedItem = $Error[0].Exception.ItemName Write-Log -Level Error -Message "Failed to Reset the Onedrive quota" Write-Log -Level Error -Message "Failed to run the following CMDLet: $CMDLet" Write-Log -Level Error -Message "Failed with Error:$ErrorMessage" } } Function Generate-OneDriveStorageUsageReport { [CmdletBinding()] param ( [Parameter(Mandatory = $False, Position = 1)] [string]$CSVName ) $ODFBSites = Get-SPOSite -IncludePersonalSite $True -Limit All -Filter "Url -like '-my.sharepoint.com/personal/'" | Select Owner, Title, URL, StorageQuota, StorageUsageCurrent | Sort StorageUsageCurrent -Desc $TotalODFBGBUsed = [Math]::Round(($ODFBSites.StorageUsageCurrent | Measure-Object -Sum).Sum /1024, 2) $Report = @() ForEach ($Site in $ODFBSites) { $Owner = $Null $Owner = $Site.Title $URL = $Null $URL = $Site.URL Write-Host "Generating Data for Site : Owner:" -NoNewline; Write-Host "$Owner" -ForegroundColor Yellow -NoNewline; Write-Host " - URL:" -NoNewline; Write-Host "$URL" -ForegroundColor Green $ReportLine = [PSCustomObject][Ordered]@{ Owner = $Site.Title Email = $Site.Owner URL = $Site.URL QuotaGB = [Math]::Round($Site.StorageQuota/1024, 2) UsedGB = [Math]::Round($Site.StorageUsageCurrent/1024, 4) } $Report += $ReportLine } $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss" If ($CSVName) { $CSVOuputFile = $CSVName } Else { $CSVOuputFile = "OneDriveStorageUsageReport_" + $DateFull + ".csv" } $Report | Export-CSV $CSVOuputFile -NoTypeInformation -Encoding UTF8 $File = Get-Item $CSVOuputFile $FileLocation = $File.VersionInfo.FileName Write-Host "Current OneDrive for Business storage consumption:" -NoNewline; Write-Host "$TotalODFBGBUsed GB" -ForegroundColor red -NoNewline; Write-Host " - Report location is: " -NoNewline; Write-Host "$FileLocation" -ForegroundColor Yellow } Function Update-OnedriveQuota { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$UPN, [Parameter(Mandatory = $true, Position = 2)] [int]$QuotaGB ) # Source https://docs.microsoft.com/en-us/onedrive/change-user-storage # Check Sharepoint Online Connection Read-Host 'Are you Connected to Sharepoint Online (Powershell Module)? - <CTRL+C> to Cancel or <Enter> to continue' #Find Onedrive URL #$SPOSite = Get-SPOSite -IncludePersonalSite $true -Limit all -Filter { "Url -like '-my.sharepoint.com/personal/'" -and "Owner -eq $UPN" } | select -First 1 $SPOSites = $Null $SPOSites = @() $SPOSites = Get-SPOSite -IncludePersonalSite $true -Limit all -Filter "Owner -eq $UPN" | where { $_.Url -like "*-my.sharepoint.com/personal/*" } foreach ($SPOSite in $SPOSites) { $OneDriveURL = $SPOSite.Url $OneDriveCurrentQuotaMB = $SPOSite.StorageQuota $OneDriveCurrentQuotaGB = $OneDriveCurrentQuotaMB / 1024 Write-Host "$UPN Onedrive Url is : $OneDriveURL - The current Quota is $OneDriveCurrentQuotaGB GB" -ForegroundColor Yellow # Convert Quota in MB [Int]$QuotaMB = 1024 * $QuotaGB Set-SPOSite -Identity $OneDriveURL -StorageQuota $QuotaMB #Set-PnPTenantSite -Url $OneDriveURL -StorageMaximumLevel $QuotaMB Write-Host "$UPN new Quota is $QuotaGB" -ForegroundColor Green } } Function Update-OnedriveAnonymousLinkExpiration { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$UPN, [Parameter(Mandatory = $true, Position = 2)] [int32]$ExpirationInDays ) #Find User Onedrive link $SPOSite = Get-SPOSite -IncludePersonalSite $true -Limit all -Filter "Owner -eq $UPN" | where { $_.Url -like "*-my.sharepoint.com/personal/*" } | select -First 1 $OneDriveURL = $SPOSite.Url $SPOSiteCurrent = Get-SPOSite -Identity $OneDriveURL $CurrentAnonymousLinkExpirationInDays = $Null $CurrentAnonymousLinkExpirationInDays = $SPOSiteCurrent.AnonymousLinkExpirationInDays $CurrentOverrideTenantAnonymousLinkExpirationPolicy = $Null $CurrentOverrideTenantAnonymousLinkExpirationPolicy = $SPOSiteCurrent.OverrideTenantAnonymousLinkExpirationPolicy Write-Host "The script find for $UPN the following Onedrive URL:" -NoNewline; Write-Host $OneDriveURL -ForegroundColor Yellow Write-Host " -- Current OverrideTenantAnonymousLinkExpirationPolicy =" -NoNewline; Write-Host $CurrentOverrideTenantAnonymousLinkExpirationPolicy -ForegroundColor Red Write-Host " -- Current AnonymousLinkExpirationInDays = " -NoNewline; Write-Host $CurrentAnonymousLinkExpirationInDays -ForegroundColor Red #Update OneDrive AnymousLinkExpiration Set-SPOSite -Identity $OneDriveURL -AnonymousLinkExpirationInDays $ExpirationInDays -OverrideTenantAnonymousLinkExpirationPolicy $True $SPOSiteNew = Get-SPOSite -Identity $OneDriveURL $NewAnonymousLinkExpirationInDays = $Null $NewAnonymousLinkExpirationInDays = $SPOSiteNew.AnonymousLinkExpirationInDays $NewOverrideTenantAnonymousLinkExpirationPolicy = $Null $NewOverrideTenantAnonymousLinkExpirationPolicy = $SPOSiteNew.OverrideTenantAnonymousLinkExpirationPolicy Write-Host "The script update for user with $UPN and the following Onedrive URL:" -NoNewline; Write-Host $OneDriveURL -ForegroundColor Yellow Write-Host " -- New OverrideTenantAnonymousLinkExpirationPolicy =" -NoNewline; Write-Host $NewOverrideTenantAnonymousLinkExpirationPolicy -ForegroundColor Green Write-Host " -- New AnonymousLinkExpirationInDays =" -NoNewline; Write-Host $NewAnonymousLinkExpirationInDays -ForegroundColor Green } Function Search-DeletedOnedriveInfo { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$UPN ) $LocalPart = $UPN.Substring(0, $UPN.LastIndexOf("@")) $Filter = '*' + $LocalPart + '*' $SPODeletedSites = $Null $SPODeletedSites = @() $Table = $Null $Table = @() $SPODeletedSites = Get-SPODeletedSite -IncludeOnlyPersonalSite -limit All | where { $_.Url -like $Filter } foreach ($SPODeletedSite in $SPODeletedSites) { $URL = $Null $URL = $SPODeletedSite.url $DeletedSite = $Null $StorageUsageCurrent = $Null $SPOSite = $Null $DeletedSite = Get-SPODeletedSite -Identity $URL Try { $SPOSite = Get-SPOSite $URL -Detailed $StorageUsageCurrent = $SPOSite.StorageUsageCurrent } Catch { $StorageUsageCurrent = "Not Found" } $Table += New-object PSobject -Property ([Ordered] @{ Url = $DeletedSite.Url; StorageUsageCurrent = $StorageUsageCurrent; DeletionTime = $DeletedSite.DeletionTime; DaysRemaining = $DeletedSite.DaysRemaining; }) } $Table | ft } Function Find-OneDriveUserURL { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [String]$UPN ) $LocalPart = $UPN.Substring(0, $UPN.LastIndexOf("@")) $Filter = '*' + $LocalPart + '*' $SPOSites = Get-SPOSite -IncludePersonalSite:$true -limit All | where { $_.Url -like $Filter } $SPOSites | ft Owner, URL -AutoSize } Function Find-PnPOnedriveUserURL { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1)] [string]$UPN ) Get-PnPUserProfileProperty -Account $UPN | select personalUrl } |