Introduction
Squared Up’s Web-API tile allows it to integrate information from any web-service that returns JSON data.
With Polaris, a free and open source framework it is possible to build web-services just in PowerShell.
This example explains the steps to create web-service in Polaris which returns locked out user information and how to integrate them nicely in Squared Up.

Requirement
- A windows server that will host your Polaris web-service
- On that server PowerShell version 5.1
- Active Directory Users & Computer and its module installed ( part of the RSAT )
- Administrative permissions on to install Polaris (Install-Module -Name Polaris)
- Create an empty directory adsvc insight of C:\Program Files\WindowsPowerShell\Modules\Polaris
- Open the Windows firewall to allow incoming connection to the port you specify, here 8082.
- Limit this port to only accept request from your Squared Up server.
- NSSM – the Non-Sucking Service Manage to run your web-service script as a service.
https://nssm.cc/
Realization
The solution consists of two PowerShell scripts. The first one exports locked user information into a JSON file. It needs to be scheduled via Task Scheduler to provide up-to-date information for the dashboard. It would be also possible to extract locked user information on each dashboard load, but that would be very slow.
Export Script
Create a directory C:\ScheduledTasks and copy the following lines into text file. Name it Export-ADLockedAndExpiredUsers.ps1. Place the following content into it:
Import-module ActiveDirectory
$jsonFilePath = 'C:\ScheduledTasks\SquaredUpExports\ADLockedAndExpiredUsers.json'
# storing raw active directory information in ArrayList
$rawLockedUersList = New-Object -TypeName System.Collections.ArrayList
Search-ADAccount -LockedOut | Select-Object -Property Name,SamAccountName,Enabled,PasswordNeverExpires,LockedOut,`
LastLogonDate,PasswordExpired,DistinguishedName | ForEach-Object {
if ($_.Enabled) {
$null = $rawLockedUersList.Add($_)
}
}
# helper function to get account lock out time
Function Get-ADUserLockedOutTime {
param(
[Parameter(Mandatory=$true)]
[string]$userID
)
$time = Get-ADUser -Identity $_.SamAccountName -Properties AccountLockoutTime `
| Select-Object @{Name = 'AccountLockoutTime'; Expression = {$_.AccountLockoutTime | Get-Date -Format "yyyy-MM-dd HH:mm"}}
$rtnValue = $time | Select-Object -ExpandProperty AccountLockoutTime
$rtnValue
} #End Function Get-ADUserLockedOutTime
# main function that sorts and formats the output to fit better in the dashboard
Function Get-ADUsersRecentLocked {
param(
[Parameter(Mandatory=$true)]
[System.Collections.ArrayList]$userList
)
$tmpList = New-Object -TypeName System.Collections.ArrayList
$tmpList = $userList | Sort-Object -Property LastLogonDate -Descending
$tmpList = $tmpList | Select-Object -Property Name,`
@{Name = 'UserId' ; Expression = { $_.SamAccountName }}, `
@{Name = 'OrgaUnit' ; Expression = { ($_.DistinguishedName -replace('(?i),DC=\w{1,}|CN=|\\','')) -replace(',OU=',' / ')} }, `
Enabled,PasswordExpired,PasswordNeverExpires, `
@{Name = 'LastLogonDate'; Expression = { $_.LastLogonDate | Get-Date -Format "yyyy-MM-dd HH:mm" }}, `
@{Name = 'AccountLockoutTime'; Expression = { (Get-ADUserLockedOutTime -userID $_.SamAccountName) }}
$tmpList = $tmpList | Sort-Object -Property AccountLockoutTime -Descending
# adding a flag character for improved visualization (alternating)
$rtnList = New-Object -TypeName System.Collections.ArrayList
$itmNumber = $tmpList.Count
for ($counter = 0; $counter -lt $itmNumber; $counter ++) {
$flack = ''
if ($counter % 2) {
$flack = ''
} else {
$flack = '--'
}
$userProps = @{
UserId = $($flack + $tmpList[$counter].UserId)
OrgaUnit = $($flack + $tmpList[$counter].OrgaUnit)
Enabled = $($flack + $tmpList[$counter].Enabled)
PasswordExpired = $($flack + $tmpList[$counter].PasswordExpired)
PasswordNeverExpires = $($flack + $tmpList[$counter].PasswordNeverExpires)
LastLogonDate = $($flack + $tmpList[$counter].LastLogonDate)
AccountLockoutTime = $($flack + $tmpList[$counter].AccountLockoutTime)
}
$userObject = New-Object -TypeName psobject -Property $userProps
$null = $rtnList.Add($userObject)
Write-Host $userObject
} #end for ()
$rtnList
} #End Function Get-ADUsersRecentLocked
if (Test-Path -Path $jsonFilePath) {
Remove-Item -Path $jsonFilePath -Force
}
# exporting result to a JSON file and storing it on $jsonFilePath
Get-ADUsersRecentLocked -userList $rawLockedUersList | ConvertTo-Json | Out-File $jsonFilePath -Encoding utf8
Publish Script
Create a directory C:\WebSrv and create an empty text file in it. Rename the file Publish-ADData.ps1. Place the following content into it. This directory contains your web-service.
Import-Module -Name Polaris
$polarisPath = 'C:\Program Files\WindowsPowerShell\Modules\Polaris'
# runs every time the code runs and ensure valid JSON output
$middleWare = @"
`$PolarisPath = '$polarisPath\adsvc'
if (-not (Test-path `$PolarisPath)) {
[void](New-Item `$PolarisPath -ItemType Directory)
}
if (`$Request.BodyString -ne `$null) {
`$Request.Body = `$Request.BodyString | ConvertFrom-Json
}
`$Request | Add-Member -Name PolarisPath -Value `$PolarisPath -MemberType Noteproperty
"@
New-PolarisRouteMiddleware -Name JsonBodyParser -ScriptBlock ([scriptblock]::Create($middleWare)) -Force
# the Get route is launched every time the web-service is called
New-PolarisGetRoute -Path "/adsvc" -ScriptBlock {
$rawLockedUersList = New-Object -TypeName System.Collections.ArrayList
$rawData = Get-Content -Path 'C:\ScheduledTasks\SquaredUpExports\ADLockedAndExpiredUsers.json'
$jsonData = $rawData | ConvertFrom-Json
if ($jsonData.Count -ne 0) {
$jsonData | ForEach-Object {
$null = $rawLockedUersList.Add($_)
}
}
$reportTime = Get-item -Path C:\ScheduledTasks\SquaredUpExports\ADLockedAndExpiredUsers.json `
| Select-Object -ExpandProperty LastWriteTime | Get-Date -Format "yyyy-MM-dd HH:mm"
$maxNoOfUsers = $null
$maxNoOfUsers = $request.Query['maxNoOfUsers']
$getReportTime = 'no'
$getReportTime = $request.Query['getReportTime']
$getLockedUserCount = 'no'
$getLockedUserCount = $request.Query['getLockedUserCount']
#if getLockedUserCoutn is yes then return number of locked users
if ($getLockedUserCount -eq 'yes') {
$noProps = @{ 'number' = $rawLockedUersList.Count }
$noObj = New-Object psobject -Property $noProps
$response.Send(($noObj | ConvertTo-Json))
}
#if maxNumber is a number than return locked user information
if ($maxNoOfUsers -match '\d') {
$rawLockedUersList = $rawLockedUersList | Select-Object -First $maxNoOfUsers
$response.Send(($rawLockedUersList | ConvertTo-Json))
}
#if getReportTime is yes then the time of export will be returned
if ($getReportTime -eq 'yes') {
$tmProps = @{
'Time' = $reportTime
'DisplayName' = [System.TimezoneInfo]::Local | Select-Object -ExpandProperty DisplayName
}
$tmObj = New-Object psobject -Property $tmProps
$response.Send(($tmObj | ConvertTo-Json))
}
} -Force
Start-Polaris -Port 8082
#Keep Polaris running
while($true) {
Start-Sleep -Milliseconds 10
}
Configure your web-service to run as a service
Download NSSM and store the nssm.exe in C:\WebSrv . Run the following PowerShell line to convert Publish-ADData.ps1 into a service. – Use ISE or VSCode.
function Install-Service {
Param(
[string]$nssmPath = '.',
[string]$Name,
[string]$Description,
[string]$Executable,
[string]$Arguments
)
$nssm = Join-Path -Path $nssmPath -ChildPath 'nssm.exe'
& $nssm install $name $executable $arguments
$null = & $nssm set $name Description $description
Start-Service $name
}
Install-Service -Name WWW-Polaris-ADUserLockData -Description 'PowerShell HTTP API Service - Serves ADUserLockedInfo via REST' -Executable powershell.exe -Arguments '-ExecutionPolicy Bypass -Command C:\WebSrv\Publish-ADData.ps1'
The result can be found in the Windows Services:

Testing
From your Squared Up server, start a web browser and query the web-service.



Dashboard Building
Add a provider
In Squared Up, switch to System and add a new WEB API provider. The URL is the one of your Polaris web-service.

Add the Dashboard
Create a new dashboard and name it Locked User Info for example. Add a Web-API tile to show the locked user count information.
1- Locked User Counter





2 – Locked Users Details








3 – Report time

Summery
This walk through shows how to integrate own data via Polaris as REST web-service.
Hope it is useful to one of you.
Feedback is appreciated