public/Invoke-VPASMetricsProviders.ps1
<#
.Synopsis RUN VARIOUS PROVIDER METRICS FROM CYBERARK CREATED BY: Vadim Melamed, EMAIL: vmelamed5@gmail.com .DESCRIPTION USE THIS FUNCTION TO GENERATE VARIOUS PROVIDER RELATED METRICS FROM CYBERARK .PARAMETER token HashTable of data containing various pieces of login information (PVWA, LoginToken, HeaderType, etc). If -token is not passed, function will use last known hashtable generated by New-VPASToken .PARAMETER TargetMetric Specify which report will be run Possible values: ApplicationIDsOnSafes, AccountsPulledViaApplicationID .PARAMETER MetricFormat Specify the report output format NONE will return the generated hashtable of data that can be assigned to a variable Possible values: JSON, HTML, ALL, NONE .PARAMETER OutputDirectory Specify where the location for report output to be saved .PARAMETER HTMLChart Specify the HTML report type Possible values: BarGraph, LineGraph, PieChart, ALL .PARAMETER HideRawData Removes the RawData visual from the exported output Helpful when exporting to a PDF or document to remove extra not needed information .EXAMPLE $GenerateReport = Invoke-VPASMetricsProviders -TargetMetric AccountsPulledViaApplicationID -OutputDirectory "C:\temp\VPASMetrics" -MetricFormat ALL -HTMLChart ALL .OUTPUTS HashTable object if successful $false if failed #> function Invoke-VPASMetricsProviders{ [OutputType([bool])] [CmdletBinding()] Param( [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,HelpMessage="Enter TargetMetric to be generated (ApplicationIDsOnSafes, AccountsPulledViaApplicationID)",Position=0)] [ValidateSet('ApplicationIDsOnSafes','AccountsPulledViaApplicationID')] [String]$TargetMetric, [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,HelpMessage="Enter ReportOutput type (JSON, HTML, ALL, NONE)",Position=1)] [ValidateSet('JSON','HTML','ALL','NONE')] [String]$MetricFormat, [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,Position=2)] [String]$OutputDirectory, [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,Position=3)] [ValidateSet('BarGraph','LineGraph','PieChart','ALL')] [String]$HTMLChart, [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,Position=4)] [switch]$HideRawData, [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true,Position=5)] [hashtable]$token ) Begin{ $tokenval,$sessionval,$PVWA,$Header,$ISPSS,$IdentityURL,$EnableTextRecorder,$AuditTimeStamp,$NoSSL,$VaultVersion,$HideWarnings,$AuthenticatedAs,$SubDomain = Get-VPASSession -token $token $CommandName = $MyInvocation.MyCommand.Name $log = Write-VPASTextRecorder -inputval $CommandName -token $token -LogType COMMAND } Process{ Write-Verbose "SUCCESSFULLY PARSED PVWA VALUE" Write-Verbose "SUCCESSFULLY PARSED TOKEN VALUE" Write-Verbose "SUCCESSFULLY PARSED TARGET METRIC VALUE: $TargetMetric" Write-Verbose "SUCCESSFULLY PARSED METRIC OUTPUT VALUE: $MetricFormat" try{ if($MetricFormat -ne "NONE"){ if([String]::IsNullOrEmpty($OutputDirectory)){ $curUser = $env:UserName $OutputDirectory = "C:\Users\$curUser\AppData\Local\VPASModuleOutputs\Metrics" Write-Verbose "NO OUTPUT DIRECTORY SUPPLIED, USING DEFAULT LOCATION: $OutputDirectory" if(Test-Path -Path $OutputDirectory){ #DO NOTHING } else{ write-verbose "$OutputDirectory DOES NOT EXIST, CREATING DIRECTORY" $MakeDirectory = New-Item -Path $OutputDirectory -Type Directory } } else{ if(Test-Path -Path $OutputDirectory){ #DO NOTHING } else{ $curUser = $env:UserName $OutputDirectory = "C:\Users\$curUser\AppData\Local\VPASModuleOutputs\Metrics" write-verbose "$OutputDirectory DOES NOT EXIST, USING DEFAULT LOCATION: $OutputDirectory" if(Test-Path -Path $OutputDirectory){ #DO NOTHING } else{ $MakeDirectory = New-Item -Path $OutputDirectory -Type Directory } } } } if([String]::IsNullOrEmpty($HTMLChart)){ $HTMLChart = "BarGraph" } if($TargetMetric -eq "ApplicationIDsOnSafes"){ $tagout = "safes" #INITIALIZE HASH $OutputHash = @{} $AllAppIDs = Get-VPASAllApplications if(!$AllAppIDs){ Write-Verbose "FAILED TO PULL ALL APPLICATION IDS" Write-VPASOutput -str "FAILED TO PULL ALL APPLICATION IDS" -type E Write-VPASOutput -str $_ -type E return $false } else{ $AllAppIDsArr = @() foreach($appID in $AllAppIDs){ $targetAppID = $appID.AppID $OutputHash += @{ $targetAppID = @{ Safes = @() RawData = @() counter = 0 } } $AllAppIDsArr += $targetAppID } } $AllEPVGroups = Get-VPASAllEPVGroups -IncludeMembers if(!$AllEPVGroups){ Write-Verbose "FAILED TO PULL ALL EPV GROUPS" Write-VPASOutput -str "FAILED TO PULL ALL EPV GROUPS" -type E Write-VPASOutput -str $_ -type E return $false } else{ $EPVGroupMatrix = @{} foreach($group in $AllEPVGroups.value){ $GroupName = $group.groupName $GroupMembers = $group.members foreach($mem in $GroupMembers.username){ if($AllAppIDsArr.Contains($mem)){ if($EPVGroupMatrix.$GroupName){ $EPVGroupMatrix.$GroupName.Members += $mem } else{ $EPVGroupMatrix += @{ $GroupName = @{ Members = @($mem) } } } } } } } $AllSafes = Get-VPASAllSafes if(!$AllSafes){ Write-Verbose "FAILED TO PULL ALL SAFES" Write-VPASOutput -str "FAILED TO PULL ALL SAFES" -type E Write-VPASOutput -str $_ -type E return $false } else{ foreach($safe in $AllSafes.value){ $targetSafeName = $safe.safeName $AllSafeMembers = Get-VPASSafeMembers -safe $targetSafeName -IncludePredefinedMembers if($AllSafeMembers){ foreach($mem in $AllSafeMembers.value){ $targetMember = $mem.memberName if($AllAppIDsArr.Contains($targetMember)){ $OutputHash.$targetMember.counter += 1 $OutputHash.$targetMember.Safes += $targetSafeName $OutputHash.$targetMember.RawData += $safe } elseif($EPVGroupMatrix.$targetMember){ $CheckArr = $EPVGroupMatrix.$targetMember.Members foreach($ArrCheck in $CheckArr){ $OutputHash.$ArrCheck.counter += 1 $OutputHash.$ArrCheck.Safes += $targetSafeName $OutputHash.$ArrCheck.RawData += $safe } } } } } } if($MetricFormat -eq "JSON" -or $MetricFormat -eq "ALL"){ $outputfile = "$OutputDirectory/ApplicationIDsOnSafes.json" $OutputDataJSON = $OutputHash | ConvertTo-Json -Depth 100 Write-Output $OutputDataJSON | Set-Content $outputfile } if($MetricFormat -eq "NONE"){ $htmlData += @{ datahash = $OutputHash } } if($MetricFormat -eq "HTML" -or $MetricFormat -eq "ALL"){ $outputfile = "$OutputDirectory/ApplicationIDsOnSafes.html" $titlesplit = "ApplicationIDs on Safes" $metricTag = "Provider Metrics" $recommendation1 = "An ApplicationID is a critical component of CyberArk's Application Access Manager (AAM), enabling secure and controlled access to sensitive credentials without hardcoding them into applications or scripts" $recommendation2 = "By using AAM, organizations can avoid hardcoding credentials in application code, configuration files, or scripts, which significantly reduces the risk of credential exposure, and decreases the amount of dependencies needed to update if the credential changes" $recommendation3 = "AAM allows the creation of detailed policies that control which applications can access specific credentials, ensuring that only authorized applications have access based on predefined criteria" $OutputDataJSON = $OutputHash | ConvertTo-Json -Depth 100 $curTime = get-date -Format "MM/dd/yyyy HH:mm:ss" if($HTMLChart -eq "ALL"){ $tablestr = "Bar Graph, Line Graph, Pie Chart" } else{ $tablestr = $HTMLChart } $metricexplanation = "This metric tracks the number of safes that contain individual ApplicationIDs as safe members. This metric will count a safe twice if multiple ApplicationIDs are found as safe members" $tempstr = "" $tempstr2 = "" $tempstr3 = "" $tempstr4 = "" $AllKeys = $OutputHash.Keys $GetMinMax = @() foreach($key in $AllKeys){ $curCount = $OutputHash.$key.counter $GetMinMax += $curCount $textColor = '#{0:X6}' -f (Get-Random -Maximum 0x1000000) $tempstr += "`"$key`"," $tempstr2 += "$curCount," $tempstr3 += "`"green`"," $tempstr4 += "`"$textColor`"," } if($GetMinMax.count -ne 0){ $GetMinMax = $GetMinMax | Sort-Object $mintick = 0 $maxtick = $GetMinMax[$GetMinMax.Count - 1] } else{ $mintick = 0 $maxtick = 0 } if(![String]::IsNullOrEmpty($tempstr)){ $tempstr = $tempstr.Substring(0,$tempstr.Length-1) } if(![String]::IsNullOrEmpty($tempstr2)){ $tempstr2 = $tempstr2.Substring(0,$tempstr2.Length-1) } if(![String]::IsNullOrEmpty($tempstr3)){ $tempstr3 = $tempstr3.Substring(0,$tempstr3.Length-1) } if(![String]::IsNullOrEmpty($tempstr4)){ $tempstr4 = $tempstr4.Substring(0,$tempstr4.Length-1) } $htmlData += @{ Recommendation1 = $recommendation1 Recommendation2 = $recommendation2 Recommendation3 = $recommendation3 titlesplit = $titlesplit outputfile = $outputfile metricTag = $metricTag OutputDataJSON = $OutputDataJSON curTime = $curTime tablestr = $tablestr metricexplanation = $metricexplanation HTMLChart = $HTMLChart tempstr = $tempstr tempstr2 = $tempstr2 tempstr3 = $tempstr3 tempstr4 = $tempstr4 datahash = $OutputHash maxtick = $maxtick mintick = $mintick } } } if($TargetMetric -eq "AccountsPulledViaApplicationID"){ $tagout = "accounts" #INITIALIZE HASH $OutputHash = @{} $AllAppIDs = Get-VPASAllApplications if(!$AllAppIDs){ Write-Verbose "FAILED TO PULL ALL APPLICATION IDS" Write-VPASOutput -str "FAILED TO PULL ALL APPLICATION IDS" -type E Write-VPASOutput -str $_ -type E return $false } else{ $AllAppIDsArr = @() foreach($appID in $AllAppIDs){ $targetAppID = $appID.AppID $OutputHash += @{ $targetAppID = @{ Accounts = @() RawData = @() counter = 0 } } $AllAppIDsArr += $targetAppID } } $AllEPVGroups = Get-VPASAllEPVGroups -IncludeMembers if(!$AllEPVGroups){ Write-Verbose "FAILED TO PULL ALL EPV GROUPS" Write-VPASOutput -str "FAILED TO PULL ALL EPV GROUPS" -type E Write-VPASOutput -str $_ -type E return $false } else{ $EPVGroupMatrix = @{} foreach($group in $AllEPVGroups.value){ $GroupName = $group.groupName $GroupMembers = $group.members foreach($mem in $GroupMembers.username){ if($AllAppIDsArr.Contains($mem)){ if($EPVGroupMatrix.$GroupName){ $EPVGroupMatrix.$GroupName.Members += $mem } else{ $EPVGroupMatrix += @{ $GroupName = @{ Members = @($mem) } } } } } } } $AllSafes = Get-VPASAllSafes if(!$AllSafes){ Write-Verbose "FAILED TO PULL ALL SAFES" Write-VPASOutput -str "FAILED TO PULL ALL SAFES" -type E Write-VPASOutput -str $_ -type E return $false } else{ foreach($safe in $AllSafes.value){ $targetSafeName = $safe.safeName $AllSafeMembers = Get-VPASSafeMembers -safe $targetSafeName -IncludePredefinedMembers if($AllSafeMembers){ foreach($mem in $AllSafeMembers.value){ $targetMember = $mem.memberName if($AllAppIDsArr.Contains($targetMember)){ #GET ALL ACCOUNTS HERE $AllAccts = Get-VPASAccountDetails -safe $targetSafeName -ExactMatch foreach($recacct in $AllAccts.value){ $AcctID = $recacct.id $OutputHash.$targetMember.counter += 1 $OutputHash.$targetMember.Accounts += $AcctID $OutputHash.$targetMember.RawData += $recacct } } elseif($EPVGroupMatrix.$targetMember){ $CheckArr = $EPVGroupMatrix.$targetMember.Members foreach($ArrCheck in $CheckArr){ #GET ALL ACCOUNTS HERE $AllAccts = Get-VPASAccountDetails -safe $targetSafeName -ExactMatch foreach($recacct in $AllAccts.value){ $AcctID = $recacct.id $OutputHash.$targetMember.counter += 1 $OutputHash.$targetMember.Accounts += $AcctID $OutputHash.$targetMember.RawData += $recacct } } } } } } } if($MetricFormat -eq "JSON" -or $MetricFormat -eq "ALL"){ $outputfile = "$OutputDirectory/AccountsPulledViaApplicationID.json" $OutputDataJSON = $OutputHash | ConvertTo-Json -Depth 100 Write-Output $OutputDataJSON | Set-Content $outputfile } if($MetricFormat -eq "NONE"){ $htmlData += @{ datahash = $OutputHash } } if($MetricFormat -eq "HTML" -or $MetricFormat -eq "ALL"){ $outputfile = "$OutputDirectory/AccountsPulledViaApplicationID.html" $titlesplit = "Accounts Pulled via ApplicationIDs" $metricTag = "Provider Metrics" $recommendation1 = "An ApplicationID is a critical component of CyberArk's Application Access Manager (AAM), enabling secure and controlled access to sensitive credentials without hardcoding them into applications or scripts" $recommendation2 = "By using AAM, organizations can avoid hardcoding credentials in application code, configuration files, or scripts, which significantly reduces the risk of credential exposure, and decreases the amount of dependencies needed to update if the credential changes" $recommendation3 = "AAM allows the creation of detailed policies that control which applications can access specific credentials, ensuring that only authorized applications have access based on predefined criteria" $OutputDataJSON = $OutputHash | ConvertTo-Json -Depth 100 $curTime = get-date -Format "MM/dd/yyyy HH:mm:ss" if($HTMLChart -eq "ALL"){ $tablestr = "Bar Graph, Line Graph, Pie Chart" } else{ $tablestr = $HTMLChart } $metricexplanation = "This metric tracks the number of accounts that can be pulled via specific ApplicationIDs. This metric will count an account twice if multiple ApplicationIDs are found as safe members" $tempstr = "" $tempstr2 = "" $tempstr3 = "" $tempstr4 = "" $AllKeys = $OutputHash.Keys $GetMinMax = @() foreach($key in $AllKeys){ $curCount = $OutputHash.$key.counter $GetMinMax += $curCount $textColor = '#{0:X6}' -f (Get-Random -Maximum 0x1000000) $tempstr += "`"$key`"," $tempstr2 += "$curCount," $tempstr3 += "`"green`"," $tempstr4 += "`"$textColor`"," } if($GetMinMax.count -ne 0){ $GetMinMax = $GetMinMax | Sort-Object $mintick = 0 $maxtick = $GetMinMax[$GetMinMax.Count - 1] } else{ $mintick = 0 $maxtick = 0 } if(![String]::IsNullOrEmpty($tempstr)){ $tempstr = $tempstr.Substring(0,$tempstr.Length-1) } if(![String]::IsNullOrEmpty($tempstr2)){ $tempstr2 = $tempstr2.Substring(0,$tempstr2.Length-1) } if(![String]::IsNullOrEmpty($tempstr3)){ $tempstr3 = $tempstr3.Substring(0,$tempstr3.Length-1) } if(![String]::IsNullOrEmpty($tempstr4)){ $tempstr4 = $tempstr4.Substring(0,$tempstr4.Length-1) } $htmlData += @{ Recommendation1 = $recommendation1 Recommendation2 = $recommendation2 Recommendation3 = $recommendation3 titlesplit = $titlesplit outputfile = $outputfile metricTag = $metricTag OutputDataJSON = $OutputDataJSON curTime = $curTime tablestr = $tablestr metricexplanation = $metricexplanation HTMLChart = $HTMLChart tempstr = $tempstr tempstr2 = $tempstr2 tempstr3 = $tempstr3 tempstr4 = $tempstr4 datahash = $OutputHash maxtick = $maxtick mintick = $mintick } } } $datahash = $htmlData.datahash if($MetricFormat -eq "HTML" -or $MetricFormat -eq "ALL"){ #OUTPUT DATA IN A PRETTY HTML write-output " <!DOCTYPE html> <html> <head> <title>$TargetMetric</title> <style> body { font-family: Arial, sans-serif; background-color: #c0c0c0; margin: 0; padding: 20px; } .metrics-container3 { background-color: #333; border-radius: 16px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); padding: 20px; margin: 0; color: white; font-size: 24px; font-weight: bold; Text-align: center; } .metrics-container2 { background-color: #333; border-radius: 16px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); padding: 20px; margin: 0; color: white; } .metrics-container { background-color: #fff; border-radius: 16px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); padding: 20px; margin: 0; } .metric { margin-bottom: 10px; } .metric-label { font-weight: bold; } </style> </head> <script src=`"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js`"></script> <body> <div style=`"max-width: 1200px; width: 100%; margin: 0 auto;`"> <div style=`"width: 95%; margin-right: 1%; margin-left: 1%`" class=`"metrics-container3`"> $titlesplit <small><small>(Powered By Vpas)</small></small> </div> <br> <div style=`"display: flex; width: 99%;`"> <div style=`"width:48%; margin-left: 1%; margin-right: 1%;`" class=`"metrics-container`"> <div class=`"metric`"> <span class=`"metric-label`">Generated By:</span> $AuthenticatedAs </div> <div class=`"metric`"> <span class=`"metric-label`">Generated Date:</span> $curTime </div> <div class=`"metric`"> <span class=`"metric-label`">Metric Category:</span> $metricTag </div> <div class=`"metric`"> <span class=`"metric-label`">Output Table(s):</span> $tablestr </div> </div> <div style=`"width:48%; margin-left: 1%; margin-right: 1;%`" class=`"metrics-container`"> <div class=`"metric`"> <span class=`"metric-label`">Metric Type:</span><small> $titlesplit</small> </div> <div class=`"metric`"> <span class=`"metric-label`">Explanation:</span> <small>$metricexplanation</small> </div> </div> </div> <br> " | Set-content $outputfile if($HTMLChart -eq "BarGraph" -or $HTMLChart -eq "ALL"){ write-output "<div style=`"max-width:95%; margin-right: 1%; margin-left: 1%`"class=`"metrics-container`"><canvas height=`"500%`" id=`"myChartBAR`" style=`"width:100%;`"></canvas></div>`n<br><br>`n" | Add-Content $outputfile } if($HTMLChart -eq "LineGraph" -or $HTMLChart -eq "ALL"){ write-output "<div style=`"max-width:95%; margin-right: 1%; margin-left: 1%`"class=`"metrics-container`"><canvas height=`"500%`" id=`"myChartLINE`" style=`"width:100%;`"></canvas></div>`n<br><br>`n"| Add-Content $outputfile } if($HTMLChart -eq "PieChart" -or $HTMLChart -eq "ALL"){ write-output "<div style=`"max-width:95%; margin-right: 1%; margin-left: 1%`"class=`"metrics-container`"><canvas height=`"500%`" id=`"myChartPIE`" style=`"width:100%;`"></canvas></div>`n<br><br>`n"| Add-Content $outputfile } Write-Output " <div style=`"display: flex;`"> <div style=`"width:33%; margin-right: 1%; margin-left: 1%`" class=`"metrics-container`"> <div class=`"metric`"> <span class=`"metric-label`">Totals:</span> </div> " | Add-Content $outputfile if($TargetMetric -eq "AccountsOnboardedXDays"){ $countkeys = $datahash.Keys.Count $i = 1 while($i -le $countkeys){ $Max = $datahash."Set$i".Max $Min = $datahash."Set$i".Min $curCount = $datahash."Set$i".Count Write-Output " <div class=`"metric`"> <span class=`"metric-label`"><small> Set$i) $Max-$Min`:</small></span><small> $curCount $tagout</small> </div> " | Add-Content $outputfile $i += 1 } } else{ foreach($key in $datahash.Keys){ $curCount = $datahash."$key".counter Write-Output " <div class=`"metric`"> <span class=`"metric-label`"><small> $key`:</small></span><small> $curCount $tagout</small> </div> " | Add-Content $outputfile } } Write-Output " </div> <div style=`"max-width:58%; width: 68%; margin-right: 1%; margin-left: 1%`" class=`"metrics-container`"> <div class=`"metric`"> <span class=`"metric-label`">Recommendations:</span> </div> <div class=`"metric`"> <span class=`"metric-label`"><small> 1)</small></span> <small>$recommendation1</small> </div> <div class=`"metric`"> <span class=`"metric-label`"><small> 2)</small></span> <small>$recommendation2</small> </div> <div class=`"metric`"> <span class=`"metric-label`"><small> 3)</small></span> <small>$recommendation3</small> </div> </div> </div> <br> " | Add-Content $outputfile if(!$HideRawData){ Write-Output " <div style=`"max-width:95%; width: 95%; margin-right: 1%; margin-left: 1%`" class=`"metrics-container`"> <div class=`"metric`"> <span class=`"metric-label`">Raw Data:</span> <div><button onclick=`"copyText()`">Copy JSON</button></div> <br> <div style=`"max-width:95%; width: 95%; margin-right: 1%; margin-left: 1%`" class=`"metrics-container2`"> <span id=`"CopyText`" ><small>$OutputDataJSON</small></span> </div> </div> </div> " | Add-Content $outputfile } Write-Output " </div> <script> " | Add-Content $outputfile if($HTMLChart -eq "BarGraph" -or $HTMLChart -eq "ALL"){ write-output "const xValuesBAR = [$tempstr];" | Add-Content $outputfile write-output "const yValuesBAR = [$tempstr2];" | Add-Content $outputfile write-output "const barColorsBAR = [$tempstr3];" | Add-Content $outputfile } if($HTMLChart -eq "LineGraph" -or $HTMLChart -eq "ALL"){ write-output "const xValuesLINE = [$tempstr];" | Add-Content $outputfile write-output "const yValuesLINE = [$tempstr2];" | Add-Content $outputfile } if($HTMLChart -eq "PieChart" -or $HTMLChart -eq "ALL"){ write-output "const xValuesPIE = [$tempstr];" | Add-Content $outputfile write-output "const yValuesPIE = [$tempstr2];" | Add-Content $outputfile write-output "const barColorsPIE = [$tempstr4];" | Add-Content $outputfile } if($HTMLChart -eq "BarGraph" -or $HTMLChart -eq "ALL"){ #BAR Write-Output " new Chart(`"myChartBAR`", { type: `"bar`", data: { labels: xValuesBAR, datasets: [{ backgroundColor: barColorsBAR, data: yValuesBAR }] }, options: { scales: { yAxes: [{ ticks: { beginAtZero: true } }] }, legend: {display: false}, title: { display: true, text: `"$titlesplit`" } } }); " | Add-Content $outputfile } if($HTMLChart -eq "LineGraph" -or $HTMLChart -eq "ALL"){ #LINE Write-Output " new Chart(`"myChartLINE`", { type: `"line`", data: { labels: xValuesLINE, datasets: [{ label: `"$titlesplit`", fill: false, lineTension: 0, backgroundColor: `"rgba(0,0,255,1.0)`", borderColor: `"rgba(0,0,255,0.1)`", data: yValuesLINE }] }, options: { legend: {display: true}, scales: { yAxes: [{ticks: {min: $mintick, max:$maxtick}}], } } }); " | Add-Content $outputfile } if($HTMLChart -eq "PieChart" -or $HTMLChart -eq "ALL"){ #PIE write-output " new Chart(`"myChartPIE`", { type: `"pie`", data: { labels: xValuesPIE, datasets: [{ backgroundColor: barColorsPIE, data: yValuesPIE }] }, options: { title: { display: true, text: `"$titlesplit`" } } }); function copyText() { var copyText = document.getElementById(`"CopyText`"); var textArea = document.createElement(`"textarea`"); textArea.value = copyText.textContent; document.body.appendChild(textArea); textArea.select(); document.execCommand(`"Copy`"); textArea.remove(); alert(`"JSON copied to clipboard`"); } " | Add-Content $outputfile } write-output "</script>`n</body>`n</html>" | Add-Content $outputfile } return $datahash }catch{ Write-Verbose "UNABLE TO RUN REPORT...RETURNING FALSE" Write-VPASOutput -str "UNABLE TO RUN REPORT...RETURNING FALSE" -type E Write-VPASOutput -str $_ -type E return $false } } End{ $log = Write-VPASTextRecorder -inputval $CommandName -token $token -LogType DIVIDER } } |