Merge pull request #546 from bwuch/bwuch-SkylineInsights
Timeout upates and bugfixes.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Configuration>
|
||||
<ViewDefinitions>
|
||||
<View>
|
||||
<Name>SkylineConnection</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>SkylineConnection</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Width>30</Width>
|
||||
<Label>Name</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>30</Width>
|
||||
<Label>APIKey</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>CSPName</Label>
|
||||
</TableColumnHeader>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Name</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>APIKey</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>CSPName</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
</ViewDefinitions>
|
||||
</Configuration>
|
||||
@@ -0,0 +1,128 @@
|
||||
<#
|
||||
Copyright 2021 VMware, Inc.
|
||||
SPDX-License-Identifier: BSD-2-Clause
|
||||
#>
|
||||
|
||||
#
|
||||
# Module manifest for module 'VMware.Skyline.InsightsApi'
|
||||
#
|
||||
# Generated by: Brian Wuchner
|
||||
#
|
||||
# Generated on: 2/21/2022
|
||||
#
|
||||
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
RootModule = 'VMware.Skyline.InsightsApi.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.0.0'
|
||||
|
||||
# Supported PSEditions
|
||||
# CompatiblePSEditions = @()
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '4dfcb1e5-69b9-405d-aecd-06119ec12649'
|
||||
|
||||
# Author of this module
|
||||
Author = 'Brian Wuchner'
|
||||
|
||||
# Company or vendor of this module
|
||||
CompanyName = 'VMware'
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = '(c) VMware. All rights reserved.'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'Community sourced PowerShell wrapper module for the Skyline Insights API.'
|
||||
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '4.0'
|
||||
|
||||
# Name of the Windows PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the Windows PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# CLRVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
# RequiredModules = @()
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = @()
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
FormatsToProcess = @('VMware.Skyline.InsightsApi.Format.ps1xml')
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
|
||||
FunctionsToExport = @('Connect-SkylineInsights','Disconnect-SkylineInsights','Invoke-SkylineInsightsApi','Get-SkylineFinding',
|
||||
'Get-SkylineAffectedObject','Format-SkylineResult','Start-SkylineInsightsApiExplorer')
|
||||
|
||||
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
|
||||
CmdletsToExport = @()
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = '*'
|
||||
|
||||
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
|
||||
AliasesToExport = @()
|
||||
|
||||
# DSC resources to export from this module
|
||||
# DscResourcesToExport = @()
|
||||
|
||||
# List of all modules packaged with this module
|
||||
# ModuleList = @()
|
||||
|
||||
# List of all files packaged with this module
|
||||
# FileList = @()
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
|
||||
PrivateData = @{
|
||||
|
||||
PSData = @{
|
||||
|
||||
# Tags applied to this module. These help with module discovery in online galleries.
|
||||
# Tags = @()
|
||||
|
||||
# A URL to the license for this module.
|
||||
# LicenseUri = ''
|
||||
|
||||
# A URL to the main website for this project.
|
||||
# ProjectUri = ''
|
||||
|
||||
# A URL to an icon representing this module.
|
||||
# IconUri = ''
|
||||
|
||||
# ReleaseNotes of this module
|
||||
# ReleaseNotes = ''
|
||||
|
||||
} # End of PSData hashtable
|
||||
|
||||
} # End of PrivateData hashtable
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
|
||||
}
|
||||
@@ -0,0 +1,425 @@
|
||||
<#
|
||||
Copyright 2021 VMware, Inc.
|
||||
SPDX-License-Identifier: BSD-2-Clause
|
||||
#>
|
||||
|
||||
Function Connect-SkylineInsights {
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: Brian Wuchner
|
||||
Date: February 21, 2022
|
||||
Blog: www.enterpriseadmins.org
|
||||
Twitter: @bwuch
|
||||
===========================================================================
|
||||
.SYNOPSIS
|
||||
Use this function to create the auth header to connect to Skyline Insights API
|
||||
.DESCRIPTION
|
||||
This function will allow you to connect to a Skyline Insights API.
|
||||
A global variable will be set with the Servername & Header value for use by other functions.
|
||||
.EXAMPLE
|
||||
PS C:\> Connect-SkylineInsights -apiKey 'my-key-from-csp'
|
||||
This will use the provided API key to create a connection to Skyline Insights.
|
||||
.EXAMPLE
|
||||
PS C:\> Connect-SkylineInsights -apiKey 'my-key-from-csp' -SaveCredentials
|
||||
This will use the PowerCLI VICredentialStore Item to save the provided API key. On next use this key will be provided automatically.
|
||||
#>
|
||||
param(
|
||||
[string]$apiKey,
|
||||
[switch]$SaveCredentials,
|
||||
[Parameter(DontShow)]$cspApi = 'console.cloud.vmware.com',
|
||||
[Parameter(DontShow)]$skylineApi = 'skyline.vmware.com'
|
||||
)
|
||||
|
||||
if ($PSEdition -eq 'Core' -And $SaveCredentials) {
|
||||
write-error 'The parameter SaveCredentials of Connect-SkylineInsights cmdlet is not supported on PowerShell Core.'
|
||||
return
|
||||
}
|
||||
|
||||
if ($PSEdition -eq 'Core' -AND !$apiKey) {
|
||||
write-error 'An API key is required.'
|
||||
return
|
||||
}
|
||||
|
||||
# Create VICredentialStore item to save the API key
|
||||
if ($apiKey -AND $SaveCredentials) {
|
||||
if ( (Get-Command Get-VICredentialStoreItem -ErrorAction:SilentlyContinue | Measure-Object).Count -gt 0 ) {
|
||||
$savedCred = Get-VICredentialStoreItem -host $skylineApi -ErrorAction:SilentlyContinue
|
||||
if ($savedCred) {
|
||||
$savedCred | Remove-VICredentialStoreItem -Confirm:$false
|
||||
}
|
||||
New-VICredentialStoreItem -Host $skylineApi -User 'api-key' -Password $apiKey
|
||||
} else {
|
||||
Write-Warning 'Use of -SaveCredentials requires the PowerCLI VICredentialStoreItem cmdlets.'
|
||||
}
|
||||
}
|
||||
|
||||
if (!$apiKey) {
|
||||
if ( (Get-Command Get-VICredentialStoreItem -ErrorAction:SilentlyContinue | Measure-Object).Count -gt 0 ) {
|
||||
$savedCred = Get-VICredentialStoreItem -host $skylineApi -ErrorAction:SilentlyContinue
|
||||
}
|
||||
if ( ($savedCred | Measure-Object).Count -eq 1) {
|
||||
$apiKey = $savedCred.Password
|
||||
} else {
|
||||
write-error 'An API key is required.'
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
$loginHeader = @{
|
||||
'Accept' = 'application/json'
|
||||
'Content-Type' = 'application/x-www-form-urlencoded'
|
||||
}
|
||||
$loginBody = @{'refresh_token' = $apiKey }
|
||||
|
||||
try {
|
||||
$webRequest = Invoke-RestMethod -Uri "https://$cspApi/csp/gateway/am/api/auth/api-tokens/authorize?grant_type=refresh_token" -method POST -Headers $loginHeader -Body $loginBody
|
||||
|
||||
$global:DefaultSkylineConnection = New-Object psobject -property @{ 'Name'=$skylineApi; 'CSPName'=$cspApi; 'ConnectionDetail'=$webRequest; APIKey = $apiKey;
|
||||
'Refresh_Token'=$webRequest.refresh_token; 'SkylineAPI'="https://$skylineApi/public/api/data"; PSTypeName='SkylineConnection' }
|
||||
|
||||
# Return the connection object
|
||||
$global:SkylineInsightsApiQueryCount = 0
|
||||
$global:SkylineInsightsApiQueryLastTime = $null
|
||||
$global:DefaultSkylineConnection
|
||||
} catch {
|
||||
Write-Error ("Failure connecting to $skylineAPI. Posted $loginBody " + $_)
|
||||
} # end try/catch block
|
||||
}
|
||||
|
||||
Function Disconnect-SkylineInsights {
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: Brian Wuchner
|
||||
Date: February 21, 2022
|
||||
Blog: www.enterpriseadmins.org
|
||||
Twitter: @bwuch
|
||||
===========================================================================
|
||||
.SYNOPSIS
|
||||
Use this function to disconnect from Skyline Insights API
|
||||
.DESCRIPTION
|
||||
This function will allow you to disconnect from a Skyline Insights API.
|
||||
The global variable will be set with the Servername & Header value for use by other functions.
|
||||
.EXAMPLE
|
||||
PS C:\> Disconnect-SkylineInsights
|
||||
This will remove a connection to Skyline Insights.
|
||||
#>
|
||||
if ($global:DefaultSkylineConnection) {
|
||||
$global:DefaultSkylineConnection = $null
|
||||
} else {
|
||||
Write-Error 'Could not find an existing connection to SkylineInsights API.'
|
||||
}
|
||||
}
|
||||
|
||||
Function Invoke-SkylineInsightsApi {
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: Brian Wuchner
|
||||
Date: February 21, 2022
|
||||
Blog: www.enterpriseadmins.org
|
||||
Twitter: @bwuch
|
||||
===========================================================================
|
||||
.SYNOPSIS
|
||||
Use this function to post a query to the Skyline Insights API.
|
||||
.DESCRIPTION
|
||||
This function will allow you to query the Skyline Insights API.
|
||||
Proper headers will be formatted and posted if a DefaultSkylineConnection is present.
|
||||
This is primarily a helper function used by other functions included in the module.
|
||||
It is exported in the module manifest to be used for any custom queries.
|
||||
.EXAMPLE
|
||||
PS C:\> Invoke-SkylineInsightsApi -queryBody '{formatted-query-string-converted-to-json}'
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$queryBody,
|
||||
[Parameter(DontShow=$true)][int]$sleepTimerMs=501
|
||||
)
|
||||
|
||||
if ( !$global:DefaultSkylineConnection ) {
|
||||
Write-Error 'You are not currently connected to any servers. Please connect first using Connect-SkylineInsights.'
|
||||
return;
|
||||
}
|
||||
|
||||
write-debug "Querybody: $queryBody"
|
||||
try {
|
||||
if ($global:SkylineInsightsApiQueryLastTime) {
|
||||
$timeSinceLastQuery = (New-TimeSpan $global:SkylineInsightsApiQueryLastTime (Get-Date)).TotalMilliseconds
|
||||
if ($timeSinceLastQuery -lt $sleepTimerMs) {
|
||||
Write-Debug "Waiting $($sleepTimerMs-$timeSinceLastQuery)ms to prevent HTTP 429 TOO_MANY_REQUESTS error"
|
||||
Start-Sleep -Milliseconds ($sleepTimerMs-$timeSinceLastQuery)
|
||||
}
|
||||
}
|
||||
$restCall = invoke-restmethod -method post -Uri $($global:DefaultSkylineConnection.SkylineAPI) -Headers @{Authorization = "Bearer $($global:DefaultSkylineConnection.ConnectionDetail.access_token)"} -body $queryBody -ContentType "application/json"
|
||||
$global:SkylineInsightsApiQueryCount++
|
||||
$global:SkylineInsightsApiQueryLastTime = Get-Date
|
||||
if ($restCall.errors) {
|
||||
Write-Error $restCall.errors.Message
|
||||
}
|
||||
return $restCall
|
||||
} catch {
|
||||
$incomingError = $_
|
||||
try {
|
||||
# are nested try/catch blocks the powershell equilivent of vbscript On Error Resume Next?
|
||||
$errorStatusAsJson = ($incomingError | ConvertFrom-Json).status
|
||||
if ($errorStatusAsJson -eq '429 TOO_MANY_REQUESTS') {
|
||||
write-error 'Encountered HTTP 429 TOO_MANY_REQUESTS error, consider increasing sleepTimerMs value.'
|
||||
start-sleep -Milliseconds (2*$sleepTimerMs)
|
||||
break
|
||||
}
|
||||
} catch {
|
||||
# this was the error from trying to cast the incoming error to Json
|
||||
}
|
||||
if (!$errorStatusAsJson) { write-error $incomingError }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Function Get-SkylineFinding {
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: Brian Wuchner
|
||||
Date: February 21, 2022
|
||||
Blog: www.enterpriseadmins.org
|
||||
Twitter: @bwuch
|
||||
===========================================================================
|
||||
.SYNOPSIS
|
||||
Use this function to query findings from the Skyline Insights API.
|
||||
.DESCRIPTION
|
||||
This function will allow you to query the Skyline Insights API for Findings.
|
||||
As described in the documentation, the maximum limit per page is 200 records. This function provides
|
||||
an optional pagesize parameter to request smaller batches, but by default assumes 200 records.
|
||||
.EXAMPLE
|
||||
PS C:\> Get-SkylineFinding
|
||||
#>
|
||||
[cmdletbinding()]
|
||||
param(
|
||||
[Parameter(ValueFromPipelineByPropertyName=$true)][string]$findingId,
|
||||
[Parameter(ValueFromPipelineByPropertyName=$true)][string[]]$products,
|
||||
[Parameter(ValueFromPipelineByPropertyName=$true)][ValidateSet('CRITICAL','MODERATE','TRIVIAL')][string]$severity,
|
||||
[Parameter(DontShow=$true)][ValidateRange(1,200)][int]$pagesize=200
|
||||
)
|
||||
|
||||
begin {
|
||||
$queryBody = @"
|
||||
{
|
||||
activeFindings(limit: $pagesize, start: 0 filter: {}) {
|
||||
findings {
|
||||
findingId
|
||||
accountId
|
||||
findingDisplayName
|
||||
severity
|
||||
products
|
||||
findingDescription
|
||||
findingImpact
|
||||
recommendations
|
||||
kbLinkURLs
|
||||
recommendationsVCF
|
||||
kbLinkURLsVCF
|
||||
categoryName
|
||||
findingTypes
|
||||
firstObserved
|
||||
totalAffectedObjectsCount
|
||||
}
|
||||
totalRecords
|
||||
timeTaken
|
||||
}
|
||||
}
|
||||
"@
|
||||
|
||||
}
|
||||
process {
|
||||
if (!$products) { $products = 'NO_PRODUCT_FILTER'}
|
||||
foreach ($thisProduct in $products) {
|
||||
if ($findingId) { $filterString = "findingId: `"$findingId`"," }
|
||||
if ($thisProduct -ne 'NO_PRODUCT_FILTER') { $filterString += "product: `"$thisProduct`"," }
|
||||
|
||||
# Try to get results the first time
|
||||
$results = @()
|
||||
$thisQueryBody = $queryBody -Replace 'filter: {}', "filter: { $filterString }"
|
||||
$thisIteration = 0
|
||||
do {
|
||||
$thisQueryBody = $thisQueryBody -Replace 'start: 0', "start: $thisIteration"
|
||||
Write-Debug $thisQueryBody
|
||||
$thisResult = Invoke-SkylineInsightsApi -queryBody (@{'query' = $thisQueryBody} | ConvertTo-Json -Compress)
|
||||
$totalRecords = $thisResult.data.activeFindings.totalRecords
|
||||
if ($severity) {
|
||||
$thisResult.data.activeFindings.Findings | Where-Object {$_.severity -eq $severity}
|
||||
} else {
|
||||
$thisResult.data.activeFindings.Findings
|
||||
}
|
||||
$results += ($thisResult.data.activeFindings.Findings)
|
||||
$thisIteration += $pageSize
|
||||
} while ($results.count -lt $totalRecords ) # end do/while loop
|
||||
|
||||
#return $results
|
||||
}
|
||||
}
|
||||
end {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Function Get-SkylineAffectedObject {
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: Brian Wuchner
|
||||
Date: February 21, 2022
|
||||
Blog: www.enterpriseadmins.org
|
||||
Twitter: @bwuch
|
||||
===========================================================================
|
||||
.SYNOPSIS
|
||||
Use this function to query affected objects from the Skyline Insights API.
|
||||
.DESCRIPTION
|
||||
This function will allow you to query the Skyline Insights API for affected objects.
|
||||
Input parameters are required for the findingId and product. Products can be provided as an object (from Get-SkylineFinding) or
|
||||
a single product can be specified by name (or delimited list).
|
||||
As described in the documentation, the maximum limit per page is 200 records. This function provides
|
||||
an optional pagesize parameter to request smaller batches, but by default assumes 200 records.
|
||||
.EXAMPLE
|
||||
PS C:\> Get-SkylineAffectedObject -findingId 'vSphere-Vmtoolsmemoryleak-KB#76163' -product 'core-vcenter01.lab.enterpriseadmins.org'
|
||||
This example uses the ByName parameter set to pass in specific findings/product and expects either a single product or a 'separator' delimited list
|
||||
.EXAMPLE
|
||||
PS C:\> Get-SkylineFinding | Select-Object -First 2 | Get-SkylineAffectedObject
|
||||
This example uses the ByObject parameter set to pass in products as an object from Get-SkylineFinding
|
||||
#>
|
||||
[cmdletbinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)][string]$findingId,
|
||||
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)][string[]]$products,
|
||||
[Parameter(DontShow=$true)][ValidateRange(1,200)][int]$pagesize=200
|
||||
)
|
||||
|
||||
begin {
|
||||
$queryBody = @"
|
||||
{
|
||||
activeFindings(
|
||||
filter: {
|
||||
findingId: "",
|
||||
product: "",
|
||||
}) {
|
||||
findings {
|
||||
totalAffectedObjectsCount
|
||||
affectedObjects(start: 0, limit: $pagesize) {
|
||||
sourceName
|
||||
objectName
|
||||
objectType
|
||||
version
|
||||
buildNumber
|
||||
solutionTags {
|
||||
type
|
||||
version
|
||||
}
|
||||
firstObserved
|
||||
}
|
||||
}
|
||||
totalRecords
|
||||
timeTaken
|
||||
}
|
||||
}
|
||||
"@
|
||||
|
||||
# Try to get results the first time
|
||||
}
|
||||
|
||||
process {
|
||||
$thisQueryBody = $queryBody -Replace 'findingId: "",', "findingId: `"$findingId`","
|
||||
foreach ( $thisProduct in $products ) {
|
||||
$thisIteration = 0
|
||||
$results = @() # reset results variable between products
|
||||
do {
|
||||
$thisQueryBody = $thisQueryBody -Replace 'product: "",', "product: `"$thisProduct`","
|
||||
$thisQueryBody = $thisQueryBody -Replace 'start: 0', "start: $thisIteration"
|
||||
Write-Debug $thisQueryBody
|
||||
$thisResult = Invoke-SkylineInsightsApi -queryBody (@{'query' = $thisQueryBody} | ConvertTo-Json -Compress)
|
||||
$totalRecords = $thisResult.data.activeFindings.Findings.totalAffectedObjectsCount
|
||||
$thisResult.data.activeFindings.Findings.affectedObjects | Select-Object @{N='findingId';E={$findingId}}, *
|
||||
$results += ($thisResult.data.activeFindings.Findings.affectedObjects) | Select-Object @{N='findingId';E={$findingId}}, *
|
||||
$thisIteration += $pagesize
|
||||
} while ($results.count -lt $totalRecords ) # end do/while loop
|
||||
} # end foreach product loop
|
||||
}
|
||||
}
|
||||
|
||||
Function Format-SkylineResult {
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: Brian Wuchner
|
||||
Date: February 21, 2022
|
||||
Blog: www.enterpriseadmins.org
|
||||
Twitter: @bwuch
|
||||
===========================================================================
|
||||
.SYNOPSIS
|
||||
Use this function to format results from the Skyline Insights API
|
||||
.DESCRIPTION
|
||||
This function will format the output from the Skyline Insights API.
|
||||
For example, Get-SkylineFinding and Get-SkylineAffectedObject will return some strings, date values as numbers, and object properties.
|
||||
This function will convert date numbers to powershell dates and objects to delimiter separated stings. This should help with exporting
|
||||
results to CSV files for example.
|
||||
.EXAMPLE
|
||||
PS C:\> Get-SkylineFinding | Format-SkylineResult | Export-Csv c:\temp\findings.csv -NoTypeInformation
|
||||
This will return Skyline Findings, format them as needed, and export results to a CSV file.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$true, ValueFromPipeline=$true)][PSCustomObject]$inputObject,
|
||||
[string]$separator = '; '
|
||||
)
|
||||
begin {
|
||||
$results = @()
|
||||
|
||||
# To format the dates, we need to add the value returned by the API to the begining of time
|
||||
$startOfTime = Get-Date '1970-01-01'
|
||||
}
|
||||
|
||||
process {
|
||||
if ( $inputObject.accountId ) {
|
||||
#This appears to be a Finding
|
||||
$results += $inputObject | Select-Object findingId, accountId, findingDisplayName, severity, @{N='product';E={[string]::join($separator, $_.products)}}, findingDescription,
|
||||
findingImpact, @{N='recommendations';E={[string]::Join($separator,$_.recommendations)}}, @{N='kbLinkURLs';E={[string]::Join($separator, $_.kbLinkURLs)}},
|
||||
@{N='recommendationsVCF';E={[string]::Join($separator,$_.recommendationsVCF)}}, @{N='kbLinkURLsVCF';E={[string]::Join($separator, $_.kbLinkURLsVCF)}},
|
||||
categoryName, @{N='findingTypes';E={[string]::Join($sep, $_.findingTypes)}}, @{N='firstObserved';E={ $startOfTime+[timespan]::FromMilliseconds($_.firstObserved) }},
|
||||
totalAffectedObjectsCount
|
||||
|
||||
} elseif ( $inputObject.objectName ) {
|
||||
#This appears to be an AffectedObject
|
||||
$results += $inputObject | Select-Object findingId, sourceName, objectName, objectType, version, buildNumber, @{N='solutionTags-Type';E={$_.solutionTags.type}},
|
||||
@{N='solutionTags-Version';E={$_.solutionTags.version}}, @{N='firstObserved';E={ $startOfTime+[timespan]::FromMilliseconds($_.firstObserved) }}
|
||||
} else {
|
||||
write-warning "Unable to determine input object type."
|
||||
} # end inputobject evaluation
|
||||
} #end process
|
||||
|
||||
end {
|
||||
return $results
|
||||
}
|
||||
}
|
||||
|
||||
Function Start-SkylineInsightsApiExplorer {
|
||||
<#
|
||||
.NOTES
|
||||
===========================================================================
|
||||
Created by: Brian Wuchner
|
||||
Date: February 21, 2022
|
||||
Blog: www.enterpriseadmins.org
|
||||
Twitter: @bwuch
|
||||
===========================================================================
|
||||
.SYNOPSIS
|
||||
Use this function to launch the Skyline Insights API in a browser.
|
||||
.DESCRIPTION
|
||||
This function will open the Skyline Insights API explorer in the default web browser and populate
|
||||
the clipboard with the necessary authorization header value to enable interactive queries.
|
||||
.EXAMPLE
|
||||
PS C:\> Start-SkylineInsightsApiExplorer
|
||||
#>
|
||||
if ( !$global:DefaultSkylineConnection ) {
|
||||
Write-Error 'You are not currently connected to any servers. Please connect first using Connect-SkylineInsights.'
|
||||
return;
|
||||
}
|
||||
"Default web browser will launch to the Skyline Insights API explorer. In the lower left select 'Request Headers' and paste the authorization/bearer token into the text box. `nNote: this script has updated your clipboard with the required auth token."
|
||||
"{`"Authorization`":`"Bearer $($global:DefaultSkylineConnection.ConnectionDetail.access_token)`"}" | Set-Clipboard
|
||||
Start-Process "https://$($global:DefaultSkylineConnection.Name)/public/api/docs"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user