Created
August 10, 2021 10:50
-
-
Save jfrmilner/77c62167ee008940cdebd9ddb1bd3de1 to your computer and use it in GitHub Desktop.
PowerShell wrapper for the Veeam Backup for Microsoft Office 365 API - Export OneDrive Content Report
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
PowerShell wrapper for the Veeam Backup for Microsoft Office 365 API - Export OneDrive Content Report | |
Veeam Backup for Microsoft Office 365 API - REST API Reference | |
https://helpcenter.veeam.com/docs/vbo365/rest/overview.html?ver=50 | |
API Version = 5.0 | |
.NOTES | |
Author: John Milner / jfrmilner | |
Date: 2021-08-06 | |
Legal: This script is provided "AS IS" with no warranties or guarantees, and confers no rights. You may use, modify, reproduce, and distribute this script file in any way provided that you agree to give the original author credit. | |
V1 - Initial Release | |
#> | |
break | |
# Ignore self signed certificate or request failS | |
add-type @" | |
using System.Net; | |
using System.Security.Cryptography.X509Certificates; | |
public class TrustAllCertsPolicy : ICertificatePolicy { | |
public bool CheckValidationResult( | |
ServicePoint srvPoint, X509Certificate certificate, | |
WebRequest request, int certificateProblem) { | |
return true; | |
} | |
} | |
"@ | |
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy | |
$veeamAPI = "https://$($env:COMPUTERNAME):4443" | |
$cred = Get-Credential | |
function Connect-VeeamAPI { | |
[CmdletBinding()] | |
param ( | |
[string] $AppUri, | |
[pscredential] $Cred | |
) | |
begin { | |
$header = @{ | |
"Content-Type" = "application/x-www-form-urlencoded" | |
"accept" = "application/json" | |
} | |
$body = @{ | |
"grant_type" = "password" | |
"username" = $cred.UserName | |
"password" = $cred.GetNetworkCredential().password | |
"refresh_token" = " " | |
"rememberMe" = " " | |
} | |
$requestURI = $veeamAPI + $appUri | |
$tokenRequest = Invoke-RestMethod -Uri $requestURI -Headers $header -Body $body -Method Post -Verbose | |
Write-Output $tokenRequest.access_token | |
} | |
} | |
$token = Connect-VeeamAPI -AppUri "/v5/token" -Cred $cred | |
$token | |
function Get-VeeamAPI { | |
[CmdletBinding()] | |
param ( | |
[string] $AppUri, | |
[string] $Token | |
) | |
begin { | |
$header = @{ | |
"accept" = "application/json" | |
"Authorization" = "Bearer $Token" | |
} | |
$requestURI = $veeamAPI + $AppUri | |
Invoke-RestMethod -Method GET -Uri $requestUri -Headers $header | |
} | |
} | |
#organizationId | |
$organizationId = "" | |
#https://helpcenter.veeam.com/docs/vbo365/rest/post_organizations_id_action.html?ver=50 | |
$header = @{ | |
"accept" = "application/json" | |
"Authorization" = "Bearer $Token" | |
} | |
$explore = @{ "explore" = @{ | |
"datetime" = $(Get-Date -UFormat '%Y.%m.%d') | |
"type" = "veod" | |
"showAllVersions" = $true | |
"showDeleted" = $true | |
} | |
} | |
$exploreJSON = $explore | ConvertTo-Json | |
$session = Invoke-RestMethod -Method Post -Uri "$($veeamAPI)/v5/Organizations/$($organizationId)/action" -Headers $header -Body $exploreJSON -ContentType "application/json" | |
$restoreSessionId = $session.id | |
#https://helpcenter.veeam.com/docs/vbo365/rest/get_onedrives.html?ver=50 | |
#Get All User OneDrive(s) | |
#GET /v5/RestoreSessions/{restoreSessionId}/Organization/OneDrive | |
$appURI = "/v5/RestoreSessions/$($restoreSessionId)/Organization/OneDrives?offset=0&limit=9999" | |
$allODs = Get-VeeamAPI -AppUri $appURI -Token $token | |
#Set-ODPath - Helper Function for Logical Path Rebuild | |
function Set-ODPath { | |
param ( | |
$find, | |
$set | |
) | |
begin { | |
}#begin | |
process { | |
try { | |
$folders = $allFolders | Where-Object { $_._links.parent.href -eq $find } | |
$folders | ForEach-Object { $_.ParentPath = $set } | |
$folders | ForEach-Object { $_.Path = $($set + $_.Name + "/") } | |
$folders | |
} | |
catch [system.exception] { | |
Write-Host '$_ is' $_ | |
Write-Host '$Error[0].GetType().FullName is' $Error[0].GetType().FullName | |
Write-Host '$Error[0].Exception is' $Error[0].Exception | |
Write-Host '$Error[0].Exception.GetType().FullName is' $Error[0].Exception.GetType().FullName | |
Write-Host '$Error[0].Exception.Message is' $Error[0].Exception.Message | |
} | |
finally { | |
#"end of script" | |
} | |
}#process | |
end { | |
}#end | |
} | |
foreach ($od in $allODs) { | |
$oneDriveId = $od.id | |
Write-Host "Processing $($od.name)" -ForegroundColor DarkGreen | |
#All Folder List | |
#https://<hostname>:4443/v5/RestoreSessions/{restoreSessionId}/Organization/OneDrives/{oneDriveId}/Folders[?parentId=<value>] | |
$appURI = "/v5/RestoreSessions/$($restoreSessionId)/Organization/OneDrives/$($oneDriveId)/Folders?offset=0&limit=9999" | |
#All Folders | |
$allFolders = Get-VeeamAPI -AppUri $appURI -Token $token | Select-Object -ExpandProperty results | |
Write-Host "Folder(s): $($allFolders.count)" -ForegroundColor DarkGreen | |
$allFolders | Add-Member -MemberType NoteProperty -Name "Path" -Value "" | |
$allFolders | Add-Member -MemberType NoteProperty -Name "ParentPath" -Value "" | |
# #Debug - Reset | |
# $allFolders | % { $_.Path = $null } | |
# $allFolders | % { $_.ParentPath = $null } | |
#Set Root Folders | |
$foldersNext = $allFolders | Where-Object { $null -eq $_._links.parent.href } | ForEach-Object { $_.Path = "/$($_.name)/"; $_.ParentPath = "/" ; $_ } | |
#Starting with Root Folders, branch out and logicly rebuilt folder hierarchy | |
while ($foldersNext) { | |
$foldersNext = foreach ($folder in $foldersNext) { | |
Set-ODPath -find $folder._links.self.href -set $($folder.ParentPath + $folder.name + "/") | |
} | |
} | |
#Debug - Report | |
#$allFolders | ? { $_.Path } | Sort-Object -Property Path | Select-Object -Property Path, ParentPath, Name, creationTime | ft -AutoSize | |
#Folder Hast Table | |
$folderHashtable = [Ordered]@{} | |
$allFolders | ForEach-Object { $folderHashtable.Add($_.id, $_) } | |
#All Files - aka alldocuments | |
#Pagination 10,000 Max. Zero indexed. Process 9000 per page (9001 on first page) | |
$i = 0 | |
$allFiles = do { | |
$page = Get-VeeamAPI -AppUri "/v5/restoresessions/$($restoreSessionId)/organization/onedrives/$($oneDriveId)/documents?offset=$($i)&limit=9000" -Token $token | |
$page.results | |
$i = $i + 9000 | |
Write-Host "Files Page $($i/9000)" -ForegroundColor DarkGreen | |
} while ($page.results) | |
Write-Host "File(s): $($allFiles.count)" | |
$scriptPropertyFilePath = { | |
if ($null -eq $this._links.parent.href) { | |
#Root | |
"/" | |
} | |
else { | |
$folderHashtable[$this._links.parent.href -replace '.*/folders/'].Path | |
} | |
} | |
$allFiles | Add-Member -Name folder -MemberType ScriptProperty -Value $scriptPropertyFilePath | |
#Debug - Report | |
#$allFiles | Select-Object -Property Folder, Name | Sort-Object -Property Folder, Name | ConvertTo-Csv -NoTypeInformation | clip | |
Write-Host "Out File C:\Support\OneDrive_Content_Reports\$($od.name + "-" + $od.id).csv" -ForegroundColor Green | |
$allFiles | Sort-Object -Property folder, name | Select-Object -Property folder, name, sizeBytes, version, id, creationTime, modificationTime, createdBy, modifiedBy | Export-Csv -NoTypeInformation -Path "C:\Support\OneDrive_Content_Reports\$($od.name + "-" + $od.id).csv" | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment