Functions/Get-RSCObjectSnapshots.ps1
################################################ # Creating the Get-RSCObjectSnapshots function ################################################ Function Get-RSCObjectSnapshots { <# .SYNOPSIS A Rubrik Security Cloud (RSC) Reporting Module Function that returns an array of snapshots for the ObjectID specified with a configurable max number of snapshots. .DESCRIPTION Makes the required GraphQL API calls to RSC via Invoke-RestMethod to get the data as described, then creates a usable array of the returned information, removing the need for the PowerShell user to understand GraphQL in order to interact with RSC. .LINK GraphQL schema reference: https://rubrikinc.github.io/rubrik-api-documentation/schema/reference .PARAMETER ObjectID A valid ObjectID in RSC, use Get-RSCObjects to obtain. .PARAMETER MaxSnapshots Uses 30 by default unless specified otherwise with this param. .OUTPUTS Returns an array of all the available information on the GraphQL endpoint in a uniform and usable format. .EXAMPLE Get-RSCObjectSnapshots -ObectID "32ffrferf-erferf-erferfe" -MaxSnapshots 50 This example returns the last 50 snapshots for the ObjectID specified. .NOTES Author: Joshua Stenhouse Date: 05/11/2023 #> ################################################ # Paramater Config ################################################ [CmdletBinding(DefaultParameterSetName = "List")] Param( [Parameter( ParameterSetName = "ObjectID", Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [String]$ObjectID,$MaxSnapshots,[switch]$Detailed ) # Example: $ObjectSnapshots= Get-RSCObjectSnapshots -ObjectID "$ObjectID" ################################################ # Importing Module & Running Required Functions ################################################ # Importing the module is it needs other modules Import-Module RSCReporting # Checking connectivity, exiting function with error if not connected Test-RSCConnection # Setting $MaxSnapshots to default if null IF($MaxSnapshots -eq $null){$MaxSnapshots = 30} ################################################ # Running Main Function ################################################ # Note: for "sortOrder" = use ASC for oldest snapshots first, DESC for newest snapshots first $RSCGraphQL = @{"operationName" = "SnapshotOfASnappableConnection"; "variables" = @{ "workloadId" = "$ObjectID" "sortOrder" = "DESC" "first" = $MaxSnapshots }; "query" = "query SnapshotOfASnappableConnection(`$workloadId: String!, `$first: Int, `$sortOrder: SortOrder) { snapshotOfASnappableConnection(workloadId: `$workloadId, first: `$first, sortOrder: `$sortOrder) { nodes { ... on CdmSnapshot { id date expiryHint expirationDate } ... on PolarisSnapshot { id date expirationDate __typename } } } }" } # Override if extended IF($Detailed) { $RSCGraphQL = @{"operationName" = "SnapshotOfASnappableConnection"; "variables" = @{ "workloadId" = "$ObjectID" "sortOrder" = "DESC" "first" = $MaxSnapshots }; "query" = "query SnapshotOfASnappableConnection(`$workloadId: String!, `$first: Int, `$sortOrder: SortOrder) { snapshotOfASnappableConnection(workloadId: `$workloadId, first: `$first, sortOrder: `$sortOrder) { nodes { ... on CdmSnapshot { id date expiryHint snapshotRetentionInfo { localInfo { expirationTime isExpirationDateCalculated isExpirationInformationUnavailable isSnapshotPresent locationId name snapshotFrequency } archivalInfos { expirationTime isExpirationDateCalculated isExpirationInformationUnavailable isSnapshotPresent locationId name snapshotFrequency } replicationInfos { expirationTime isExpirationDateCalculated isExpirationInformationUnavailable isSnapshotPresent snapshotFrequency name locationId } } localLocations { isActive id } expirationDate archivalLocations { id isActive name } replicationLocations { id isActive name } __typename } ... on PolarisSnapshot { id date expirationDate __typename } } } }" } } ################################################ # API Call To RSC GraphQL URI ################################################ # Querying API Try { $ObjectSnapshotsResponse = Invoke-RestMethod -Method POST -Uri $RSCGraphqlURL -Headers $RSCSessionHeader -Body $($RSCGraphQL | ConvertTo-JSON -Depth 10) $ObjectSnapshotsToProcess = $ObjectSnapshotsResponse.data.snapshotOfASnappableConnection.nodes } Catch { $ErrorMessage = $_.ErrorDetails; "ERROR: $ErrorMessage" } # Creating array $ObjectSnapshots = [System.Collections.ArrayList]@() # Processing snapshots ForEach ($ObjectSnapshot in $ObjectSnapshotsToProcess) { # Getting snapshot data $SnapshotDateUNIX = $ObjectSnapshot.date $SnapshotID = $ObjectSnapshot.id # Converting $SnapshotDateUTC = Convert-RSCUNIXTime $SnapshotDateUNIX # Calculating hours since each snapshot $UTCDateTime = [System.DateTime]::UtcNow IF($SnapshotDateUTC -ne $null) { $SnapshotDateTimespan = New-TimeSpan -Start $SnapshotDateUTC -End $UTCDateTime $SnapshotHoursSince = $SnapshotDateTimespan | Select-Object -ExpandProperty TotalHours $SnapshotHoursSince = [Math]::Round($SnapshotHoursSince,1) $SnapshotDaysSince = $SnapshotDateTimespan | Select-Object -ExpandProperty TotalDays $SnapshotDaysSince = [Math]::Round($SnapshotDaysSince,1) } ELSE { $SnapshotHoursSince = $null $SnapshotDaysSince = $null } # Adding $Object = New-Object PSObject $Object | Add-Member -MemberType NoteProperty -Name "RSCInstance" -Value $RSCInstance $Object | Add-Member -MemberType NoteProperty -Name "DateUTC" -Value $SnapshotDateUTC $Object | Add-Member -MemberType NoteProperty -Name "HoursSince" -Value $SnapshotHoursSince $Object | Add-Member -MemberType NoteProperty -Name "SnapshotDaysSince" -Value $SnapshotDaysSince $Object | Add-Member -MemberType NoteProperty -Name "SnapshotID" -Value $SnapshotID $Object | Add-Member -MemberType NoteProperty -Name "ObjectID" -Value $ObjectID # Detailed section IF($Detailed) { # Getting detailed info $ArchivalInfo = $ObjectSnapshot.snapshotRetentionInfo.archivalInfos $ReplicationInfo = $ObjectSnapshot.snapshotRetentionInfo.replicationInfos $LocalInfo = $ObjectSnapshot.snapshotRetentionInfo.localInfo # Archival info $ArchiveName = $ArchivalInfo.Name $ArchiveExpiration = $ArchivalInfo.expirationTime IF($ArchiveExpiration -ne $null){$ArchiveExpirationUTC = Convert-RSCUNIXTime $ArchiveExpiration}ELSE{$ArchiveExpirationUTC = $null} # Replication info $ReplicaName = $ReplicationInfo.Name $ReplicaExpiration = $ReplicationInfo.expirationTime IF($ReplicaExpiration -ne $null){$ReplicaExpirationUTC = Convert-RSCUNIXTime $ReplicaExpiration}ELSE{$ReplicaExpirationUTC = $null} # Local info $IsLocal = $LocalInfo.isSnapshotPresent $RubrikCluster = $LocalInfo.name $LocalExpiration = $LocalInfo.expirationTime IF($LocalExpiration -ne $null){$LocalExpirationUTC = Convert-RSCUNIXTime $LocalExpiration}ELSE{$LocalExpirationUTC = $null} # Setting opposite if null IF($IsLocal -eq $null){$IsLocal = $False} # Adding additional fields $Object | Add-Member -MemberType NoteProperty -Name "OnSourceCluster" -Value $IsLocal $Object | Add-Member -MemberType NoteProperty -Name "RubrikCluster" -Value $RubrikCluster $Object | Add-Member -MemberType NoteProperty -Name "LocalExpirationUTC" -Value $LocalExpirationUTC $Object | Add-Member -MemberType NoteProperty -Name "Replica" -Value $ReplicaName $Object | Add-Member -MemberType NoteProperty -Name "ReplicaExpirationUTC" -Value $ReplicaExpirationUTC $Object | Add-Member -MemberType NoteProperty -Name "Archive" -Value $ArchiveName $Object | Add-Member -MemberType NoteProperty -Name "ArchiveExpirationUTC" -Value $ArchiveExpirationUTC } # Adding to the array $ObjectSnapshots.Add($Object) | Out-Null } # Returning Result Return $ObjectSnapshots } |