246 lines
10 KiB
PowerShell
246 lines
10 KiB
PowerShell
|
## Generates a Disk Report for all the devices in a specific group.
|
||
|
|
||
|
#Enter the percentage threshold for disks to be flagged.
|
||
|
$threshold = 94 #Integer
|
||
|
|
||
|
# Variables From Ninja
|
||
|
$ClientID = "" #String
|
||
|
$ClientSecret = "" #String
|
||
|
$GroupID = 0 #Integer
|
||
|
|
||
|
# Variables to be used for mailing
|
||
|
$MgTenantID = ""
|
||
|
$MgUserID = ""
|
||
|
$MgClientID = ""
|
||
|
$MgValue = ""
|
||
|
$ToAddress = ""
|
||
|
$Subject = ""
|
||
|
|
||
|
#Gets the API token and creates the headers for subsequent calls
|
||
|
$body = @{
|
||
|
grant_type = "client_credentials"
|
||
|
client_id = "$ClientID"
|
||
|
client_secret = "$ClientSecret"
|
||
|
redirect_uri = "https://localhost"
|
||
|
scope = "monitoring"
|
||
|
}
|
||
|
|
||
|
Write-Host "Connect Ninja API"
|
||
|
$API_AuthHeaders = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
|
||
|
$API_AuthHeaders.Add("accept", 'application/json')
|
||
|
$API_AuthHeaders.Add("Content-Type", 'application/x-www-form-urlencoded')
|
||
|
|
||
|
$auth_token = Invoke-RestMethod -Uri https://eu.ninjarmm.com/oauth/token -Method POST -Headers $API_AuthHeaders -Body $body
|
||
|
$access_token = $auth_token | Select-Object -ExpandProperty 'access_token' -EA 0
|
||
|
|
||
|
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
|
||
|
$headers.Add("Accept", "application/json")
|
||
|
$headers.Add("Authorization", "Bearer $access_token")
|
||
|
Write-Host "Connected Ninja API"
|
||
|
|
||
|
## Main
|
||
|
|
||
|
Write-Host "Import Microsoft.Graph Modules"
|
||
|
Install-Module -Name Microsoft.Graph.Authentication -Force
|
||
|
Install-Module -Name Microsoft.Graph.Mail -Force
|
||
|
Install-Module -Name Microsoft.Graph.Users.Actions -Force
|
||
|
Write-Host "Imported Microsoft.Graph Modules"
|
||
|
|
||
|
# Calls Ninja's API and assigns all the device IDs of the devices in the "Disk Report" Group to an array
|
||
|
Write-Host "Get Device Group"
|
||
|
$deviceIDs = @()
|
||
|
$deviceIDs = Invoke-RestMethod "https://eu.ninjarmm.com/api/v2/group/$GroupID/device-ids" -Method 'GET' -Headers $headers
|
||
|
Write-Host "Got Device Group"
|
||
|
|
||
|
# Starts a thread jobs to go through every Device ID and put the output into an Array
|
||
|
Write-Host "Get Disk Report"
|
||
|
$fullDiskReport = ($deviceIDs | ForEach-Object -Parallel {
|
||
|
# Pass through Varibles to thread
|
||
|
$ID = $_
|
||
|
$headers = $using:headers
|
||
|
$threshold = $using:threshold
|
||
|
# Calls API to get details for the device and assign to variables
|
||
|
$device = Invoke-RestMethod "https://eu.ninjarmm.com/api/v2/device/$ID" -Method 'GET' -Headers $headers
|
||
|
$hostname = $device.systemName
|
||
|
$volumes = $device.volumes
|
||
|
$orgID = $device.organizationId
|
||
|
$locID = $device.locationId
|
||
|
Write-Host "Get Device Disk Report For: $hostname"
|
||
|
|
||
|
# Calls API to get the Organization the Device Belongs to and assigns to a variable
|
||
|
$organization = Invoke-RestMethod -Uri "https://eu.ninjarmm.com/api/v2/organization/$orgID" -Method GET -Headers $headers
|
||
|
$orgName = $organization.name
|
||
|
|
||
|
# Calls API to get the All Locations in the Organization, find the Location the Device is in and assign it to a variable
|
||
|
$locations = Invoke-RestMethod -Uri "https://eu.ninjarmm.com/api/v2/organization/$orgID/locations" -Method GET -Headers $headers
|
||
|
ForEach ($location in $locations){if ($location.id -eq $locID){$locName = $location.name}}
|
||
|
|
||
|
# Starts a loop to go through every Volume in the device, Only looking at Local Disks and putting the output into an Array
|
||
|
$DeviceDiskReport = ForEach ($volume in $volumes){
|
||
|
if ($volume.deviceType -eq "Local Disk"){
|
||
|
# Assigns values to variables and formats them
|
||
|
$name = $volume.name
|
||
|
$capacity = [math]::Round(($volume.capacity / 1GB),2)
|
||
|
$free = [math]::Round(($volume.freeSpace / 1GB),2)
|
||
|
# Try/Catch to stop error when capacity is less than 0.5GB
|
||
|
Try{$PercUsed = [math]::Round((($volume.capacity - $volume.freeSpace) / $volume.capacity)*100,2)}
|
||
|
Catch{$PercUsed = "Error"}
|
||
|
|
||
|
# Crates a flag to show whether a volume will need to be investigated
|
||
|
if (($PercUsed -eq 100) -or ($PercUsed -eq "Error")){$needsIv = $false}
|
||
|
elseif ($PercUsed -gt $threshold){$needsIv = $true}
|
||
|
else {$needsIv = $false}
|
||
|
|
||
|
# Formats Data to Copy Pasta into Halo Ticket
|
||
|
if ($needsIv -eq $true){$ticket = ($hostname + " Disk Space on " + $name + " Drive at " + $PercUsed + "% " + $free + "/" + $capacity + "GB")}
|
||
|
else {$ticket = "N/A"}
|
||
|
|
||
|
# Creates Object of DiskReport Class and assigns properties
|
||
|
$DiskReport = [PSCustomObject]@{
|
||
|
DiskLetter = $name
|
||
|
DiskCapacity = $capacity
|
||
|
DiskFreeSpace = $free
|
||
|
DiskPercentageUsed = $PercUsed
|
||
|
NeedsInvestigation = $needsIv
|
||
|
TicketCopyPasta = $ticket
|
||
|
}
|
||
|
$DiskReport
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# Creates Object of DeviceReport Class and assigns properties
|
||
|
$DeviceReport = [PSCustomObject]@{
|
||
|
OrganizationName = $orgName
|
||
|
LocationName = $locName
|
||
|
HostName = $hostname
|
||
|
DeviceDiskReport = $DeviceDiskReport
|
||
|
DiskLetter = $null
|
||
|
DiskCapacity = $null
|
||
|
DiskFreeSpace = $null
|
||
|
DiskPercentageUsed = $null
|
||
|
NeedsInvestigation = $null
|
||
|
TicketCopyPasta = $null
|
||
|
}
|
||
|
$DeviceReport
|
||
|
Write-Host "Got Device Disk Report For: $hostname"
|
||
|
} -AsJob | Wait-Job | Receive-Job)
|
||
|
Write-Host "Got Disk Report"
|
||
|
|
||
|
# Sorts Array into Alphabetical order
|
||
|
Write-Host "Sort Disk Report"
|
||
|
$fullDiskReport = $fullDiskReport | Sort-Object -Property OrganizationName, LocationName, Hostname
|
||
|
|
||
|
$filteredDiskReport = ForEach ($DeviceReport3 in $fullDiskReport){
|
||
|
$NeedsInvestigation = $false
|
||
|
ForEach ($DiskReport2 in $DeviceReport3.DeviceDiskReport){if ($DiskReport2.NeedsInvestigation -eq $true){$NeedsInvestigation = $true}}
|
||
|
if ($NeedsInvestigation -eq $true){$DeviceReport3}
|
||
|
}
|
||
|
Write-Host "Sorted Disk Report"
|
||
|
|
||
|
# Bit of logic to format the child objects correctly with the parent object, but I don't remember why or how it works, I just know it works
|
||
|
# Just joking I do, but its hard to explain, So: For each Object in the report it will output the Device Data then, For each disk within the device, get the disk data and add it to an array, sort the array then output it
|
||
|
Write-Host "Filter Disk Report"
|
||
|
$fullDiskReport1 = ForEach ($DeviceReport1 in $fullDiskReport){
|
||
|
$DeviceReport1
|
||
|
$DeviceReport2 = ForEach ($DiskReport1 in $DeviceReport1.DeviceDiskReport){$DiskReport1}
|
||
|
# Sorts the disks in alphabetical order
|
||
|
$DeviceReport2 = $DeviceReport2 | Sort-Object -Property DiskLetter
|
||
|
$DeviceReport2
|
||
|
}
|
||
|
|
||
|
$filteredDiskReport1 = ForEach ($DeviceReport4 in $filteredDiskReport){
|
||
|
$DeviceReport4
|
||
|
$DeviceReport5 = ForEach ($DiskReport3 in $DeviceReport4.DeviceDiskReport){$DiskReport3}
|
||
|
# Sorts the disks in alphabetical order
|
||
|
$DeviceReport5 = $DeviceReport5 | Sort-Object -Property DiskLetter
|
||
|
$DeviceReport5
|
||
|
}
|
||
|
|
||
|
$doubleFilteredDiskReport = ForEach ($DeviceReport6 in $filteredDiskReport){
|
||
|
$DeviceReport6
|
||
|
$DeviceReport7 = ForEach ($DiskReport4 in $DeviceReport6.DeviceDiskReport){If ($DiskReport4.NeedsInvestigation -eq $true){$DiskReport4}}
|
||
|
# Sorts the disks in alphabetical order
|
||
|
$DeviceReport7 = $DeviceReport7 | Sort-Object -Property DiskLetter
|
||
|
$DeviceReport7
|
||
|
}
|
||
|
Write-Host "Filtered Disk Report"
|
||
|
|
||
|
# Outputs to html file in current directory
|
||
|
Write-Host "Create Disk Report Files"
|
||
|
$fullDiskReport1 | ConvertTo-Html -Property OrganizationName, LocationName, Hostname, DiskLetter, DiskFreeSpace, DiskCapacity, DiskPercentageUsed, NeedsInvestigation, TicketCopyPasta | Out-File "./fullDiskReport.html"
|
||
|
|
||
|
$filteredDiskReport1 | ConvertTo-Html -Property OrganizationName, LocationName, Hostname, DiskLetter, DiskFreeSpace, DiskCapacity, DiskPercentageUsed, NeedsInvestigation, TicketCopyPasta | Out-File "./filteredDiskReport.html"
|
||
|
|
||
|
$doubleFilteredDiskReport | ConvertTo-Html -Property OrganizationName, LocationName, Hostname, DiskLetter, DiskFreeSpace, DiskCapacity, DiskPercentageUsed, NeedsInvestigation, TicketCopyPasta | Out-File "./doubleFilteredDiskReport.html"
|
||
|
Write-Host "Created Disk Report Files"
|
||
|
|
||
|
#$fullDiskReport2 = "./fullDiskReport.html"
|
||
|
#$filteredDiskReport2 = "./filteredDiskReport.html"
|
||
|
#$doubleFilteredDiskReport1 = "./doubleFilteredDiskReport.html"
|
||
|
|
||
|
# Created variables to be used for mailing
|
||
|
Write-Host "Send Disk Report email"
|
||
|
Write-Host "Connect MgGraph"
|
||
|
$MgValue = ConvertTo-SecureString -String $MgValue -AsPlainText -Force
|
||
|
$Secret = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $MgClientID, $MgValue
|
||
|
Connect-MgGraph -TenantId $MgTenantID -ClientSecretCredential $Secret
|
||
|
Write-Host "Connected MgGraph"
|
||
|
|
||
|
|
||
|
$attachmentpath1 = "./fullDiskReport.html"
|
||
|
$attachmentmessage1 = [Convert]::ToBase64String([IO.File]::ReadAllBytes($attachmentpath1))
|
||
|
$attachmentname1 = (Get-Item -Path $attachmentpath1).Name
|
||
|
|
||
|
$attachmentpath2 = "./filteredDiskReport.html"
|
||
|
$attachmentmessage2 = [Convert]::ToBase64String([IO.File]::ReadAllBytes($attachmentpath2))
|
||
|
$attachmentname2 = (Get-Item -Path $attachmentpath2).Name
|
||
|
|
||
|
$attachmentpath3 = "./doubleFilteredDiskReport.html"
|
||
|
$attachmentmessage3 = [Convert]::ToBase64String([IO.File]::ReadAllBytes($attachmentpath3))
|
||
|
$attachmentname3 = (Get-Item -Path $attachmentpath3).Name
|
||
|
|
||
|
$params = @{
|
||
|
Message = @{
|
||
|
Subject = $Subject
|
||
|
Body = @{
|
||
|
ContentType = "Text"
|
||
|
Content = "Find attached Disk Reports"
|
||
|
}
|
||
|
ToRecipients = @(
|
||
|
@{
|
||
|
EmailAddress = @{
|
||
|
Address = $ToAddress
|
||
|
}
|
||
|
}
|
||
|
)
|
||
|
Attachments = @(
|
||
|
@{
|
||
|
"@odata.type" = "#microsoft.graph.fileAttachment"
|
||
|
Name = $attachmentname1
|
||
|
ContentType = "text/html"
|
||
|
ContentBytes = $attachmentmessage1
|
||
|
}
|
||
|
@{
|
||
|
"@odata.type" = "#microsoft.graph.fileAttachment"
|
||
|
Name = $attachmentname2
|
||
|
ContentType = "text/html"
|
||
|
ContentBytes = $attachmentmessage2
|
||
|
}
|
||
|
@{
|
||
|
"@odata.type" = "#microsoft.graph.fileAttachment"
|
||
|
Name = $attachmentname3
|
||
|
ContentType = "text/html"
|
||
|
ContentBytes = $attachmentmessage3
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
SaveToSentItems = "false"
|
||
|
}
|
||
|
|
||
|
Send-MgUserMail -UserId $MgUserID -BodyParameter $params
|
||
|
Write-Host "Sent Disk Report email"
|
||
|
|
||
|
Write-Host "Disconnect MgGraph"
|
||
|
Disconnect-MgGraph
|
||
|
Write-Host "Disconnected MgGraph"
|