- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 06-21-2022 12:40 PM
My organization was interested in automating some of our Microsoft AD tasks -- creating users, adding them to groups, disabling users, etc -- however we were not interested in upgrading to Integration Hub Professional for the Microsoft AD V2 spoke. Fortunately, there is an open-source project for Powershell called Polaris (not be confused with the SN UI formerly named Polaris) which exposes a Powershell instance as a web service. This allows SN to call a RESTful web service which runs Powershell scripts for tasks like creating and disabling users. REST is available in Integration Hub Starter.
This article will outline the steps to create a Powershell web service with two end points and to call one of those end points from a Flow Designer Action.
Setup Polaris
The first step is to install the Polaris module PS> Install-Module Polaris
in Powershell and make sure it's working. Here is the Getting Started Guide
Next, build a Powershell/Polaris script to do the operations you require in AD. Below is an example script with two endpoints (Polaris calls these routes) -- one GET endpoint which serves as a test and another POST endpoint to disable a user account.
############################################
# Example Powershell / Polaris script with two end points
# 1) /whoami - A GET endpoint for testing
# 2) /disable-user - A POST endpoint for disabling an AD user account
#
############################################
Import-Module Polaris
# Stop any Polaris instances that are already running
Stop-Polaris
############################################
# Helper functions
#
############################################
# This function provides a standard output for all routes
function global:CreateResponse ($code,$message) {
$jsonOutput= @"
{
"code":$code,
"message":"$message"
}
"@
return $jsonOutput
}
############################################
# Polaris Middleware: These are run before each route
#
############################################
#Authentication middleware. All routes should check $global:Auth to make sure user is authenticated
New-PolarisRouteMiddleware -Force -Name "BasicAuthValidation" -Scriptblock {
#Basic auth username and password hardcoded below.
if ($Request.User.Identity.Name -ne "username" -or $Request.User.Identity.Password -ne "password") {
$global:Auth = $false
$Response.StatusCode = 401
$Response.Send("Unauthorized")
}
else {
$global:Auth = $true
}
}
#middleware for converting json in request body to hash table
New-PolarisRouteMiddleware -Force -Name "ConvertJsontoHash" -Scriptblock {
if ($Request.BodyString) {
$global:hash = $Request.BodyString | ConvertFrom-Json -AsHashTable
}
}
############################################
# Polaris Routes
#
############################################
# A route testing. This route does not require authentication.
New-PolarisRoute -Method GET -Path "test" -Force -Scriptblock {
$Response.Send('Im alive')
}
#disables a user
New-PolarisPostRoute -Force -Path "disable-user" -Scriptblock {
#if the user is not authenticated, return
if (!$global:Auth) {
return
}
#get the hash table (middleware converted to hash from json)
$hash = $global:hash
#get the UPN out of the hash table. This is how we search for the user
$upn = $hash.Item('upn')
try {
#find the user with the UPN
$user = Get-ADUser -Filter "UserPrincipalName -eq '$upn'"
#disable the account
$result = Disable-ADAccount -Identity $user -PassThru
$message = "User disabled successfully"
$resp = global:CreateResponse 1 $message
$Response.Send($resp)
}
catch {
$resp = global:CreateResponse 0 $_
$Response.Send($resp)
}
}
############################################
# Start Polaris
#
############################################
Start-Polaris -Port 8085 -Auth Basic -Https
Run the script in a Powershell console. You should see the below output if Polaris is listening
Port : 8085
RouteMiddleWare : {BasicAuthValidation, ConvertJsontoHash}
ScriptblockRoutes : {[/whoami, System.Collections.Generic.Dictionary`2[System.String,System.Management.Automation.ScriptBlock]], [/disable-user,
System.Collections.Generic.Dictionary`2[System.String,System.Management.Automation.ScriptBlock]]}
GetLogsString : PolarisLogs
ClassDefinitions :
ContextHandler : System.AsyncCallback
Though the output above indicates that Polaris is running, it actually won't yet respond to requests because we specified -Https in the Start-Polaris command at the end of the script. The Polaris webserver, HTTPListener, needs a certificate to use SSL. The below script creates a self-signed certificate and binds it to HTTPListener
# Create self signed cert and bind to HTTPListener
# Based on https://jeremymcgee.com/powershell/polaris/https/2018/10/29/Polaris-HTTPS.html
# Create the cert, default expiration is 1 year if NotAfter is not specified
# Polaris is called from the MID server. If Polaris and the MID server are on the same server, the -DnsName will be "localhost". If they are on different servers, use the hostname of the server running Polaris
$Cert = New-SelfSignedCertificate -DnsName "localhost" -CertStoreLocation "cert:\LocalMachine\My" -NotAfter "2040-01-01"
#Bind cert to HTTPListener
$AppID = "{" + $(New-Guid) + "}"
$Port = '8085' #This is the port we specify for Polaris
Invoke-Expression -Command "netsh http add sslcert ipport=0.0.0.0:$($Port) certhash=$($Cert.Thumbprint) appid='$($AppID)' certstorename=MY"
#Manually add this cert to Trusted Root Certificate Authorities to certificate errors (certlm.msc in Windows).
After running the above, close the Powershell session that ran the Polaris script (if you ran it in Windows Powershell ISE, you have to close the whole Powershell ISE application). Closing the application that ran the Polaris script is necessary to unbind it from the HTTPListener. Open a new Powershell session and run the Polaris session script again. You should see this output
Port : 8085
RouteMiddleWare : {BasicAuthValidation, ConvertJsontoHash}
ScriptblockRoutes : {[/whoami, System.Collections.Generic.Dictionary`2[System.String,System.Management.Automation.ScriptBlock]], [/disable-user,
System.Collections.Generic.Dictionary`2[System.String,System.Management.Automation.ScriptBlock]]}
GetLogsString : PolarisLogs
ClassDefinitions :
ContextHandler : System.AsyncCallback
Now Polaris should be able to respond. You can test it in a browser by going to https://localhost:8085/test. You will be prompted for the basic auth username and password you specified in the script (username/password above). If everything is working you should see the below (note that I added the self-signed certificate to the cert store on my local computer which is why the browser did not complain about it. The certificate first has to exported to a file.)
Because the certificate for the ssl encryption is self-signed, the SN MID server will throw an error when trying to connect to the web service (much like the browser does if the cert is not in the cert store of the local machine). This can be fixed by adding the self-signed certificate to the MID server's cert store.
Create the Connection and Credential in ServiceNow
Create a Basic Auth credential with the username and password specified in the Polaris script above. Note that I created a new scoped app for these records.
Create a record in Connection and Credential Aliases. Then create a Connection from the related list like the below. The credential will be the record you created in the previous step. Note that I have the Polaris instance running on the same instance as the MID server, thus my Connection URL is localhost.
Create an Action in Flow Designer
This Action in Flow Designer will use the /disable-user route (endpoint) on the Polaris service. This endpoint requires one parameter, the UPN of the AD user to be disabled. Note that the user account under which the Polaris service is running has to have the rights in AD to disable accounts for this to work.
The third step, Map output, is optional.
You can then test with flow designer, specifying the UPN of the user to be disabled. If all goes well, message_polaris output will be "User disabled successfully". If it is not successful, ensure that the MID server can communicate with the Polaris service on port 8085 using https. The self signed certificate may need to be added to the Trusted Root Authorities on the MID server. From the MID server, you can use Postman to test the Polaris endpoints.
One downside of this set up of Polaris is that it requires a logged in user session to run. Running Polaris as a Windows service would remediate this defect, however converting it is not simple. It's on my todo list.
- 1,599 Views