AnsweredAssumed Answered

PowerShell to Samanage API User accounts (Full Script)

Question asked by Bernard Welmers on Mar 16, 2018

Well I spent the last week working on a PowerShell script to upload and update all my user accounts. I wanted to share this for anyone else that is looking to keep their Samanage account up to date with their AD information.

Note I did this for AD not AzureAD. 

2nd Note This uses PowerShell 5.0 and the JSON API from Samanage

 

Changes that are needed to use this script:

1. You must get a Token for an administrator account (replace text MYTOKEN)

2. You may need to add your AD Credentials to the script to connect to AD, I do this outside of the script (You #also need the RSAT tools on your computer).

 

here are some small excerpts from the file to help other people create their own scripts

PowerShell the API and JSON - Lessons learned/examples 

 

 

I hope this helps other people with their Samange accounts.

 

So here is the script. I will also attach it as a file.

<##############################
.SYNOPSIS
Update all the users in Samanage

.DESCRIPTION
This powershell scrip connects to the Symanage API and makes sure that all the AD users have been added to Samanage. Then it goes through all the users and checks to see if the information is up to date in Samanage

 

.NOTES
This was created using Symanage API 2.1 using JSON
You MUST add an administator token fom Samanage on third line of headers to access Symange


You can run this function as update-Samanage.ps1 -verbose to get a LOT of debugging information.

at the bottom of the scrip there is a line that you need to uncomment if you want the script to start removing users.

Created 3/15/2018
##############################>
[CmdletBinding()]
param()

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Accept", 'application/vnd.samanage.v2.1+json')
$headers.Add("X-Samanage-Authorization", 'Bearer MYTOKEN')

#This pulls all the users from Samanage as JSON and converts that JSON output into a PowerShell Object that can be manipulated like normal.
Function Get-SamanageUsers
{
$SamangeUserList = @()
$count = 1
do{
$Result=@()
$result = Invoke-RestMethod -Uri https://api.samanage.com/users.json?page=$count -Method Get -Headers $headers -ContentType 'application/json'
$SamangeUserList += $result
$count+=1
}while ($result.count -gt 0)
$SamangeUserList
}

##############################
#.SYNOPSIS
# Take the Ad user info and generate an object that can be uploaded to Samanage
#
#.DESCRIPTION
# This script takes all the AD user info and parses it into a format that the Samanage API is able to understand.
# This script only pushes the fields that are not null or equal to information already in Samanage to be updated
#
#.PARAMETER UserFromAD
# User account information from AD
#
#.PARAMETER UserFromSamanage
# user record from Samanage
##
#.NOTES
# Created 3/15/2018
##############################
Function Parse-UserUpload{
Param (
[Parameter(ValueFromPipeline)]$UserFromAD,
$UserFromSamanage
)
#define the veriable every time to make sure it is empty
$UploadUser = @{user=@{}}

if($UserFromAD.EmailAddress -ne $null ){
if ($UserFromSamanage.email -ne $UserFromAD.EmailAddress)
{
$UploadUser.user['email'] = $UserFromAD.EmailAddress.tostring()
}
}

if ($UserFromSamanage.disabled -eq !$UserFromAD.enabled){
#if both are the same don't do anything
}elseif (($UserFromSamanage.disabled -eq $False) -and ($UserFromAD.enabled -eq $False)){
#If AD is disabled but samanage is Enabled then set Samanage to disabled
$UploadUser.user['disabled']= $True
}else{
#If AD is enabled but Samanage is Disabled then set samanage to enabled
$UploadUser.user['disabled']= $false
}
if($UserFromAD.DisplayName -ne $null ){
if ($UserFromAD.DisplayName -ne $UserFromSamanage.name){
$UploadUser.user['name'] = $UserFromAD.DisplayName
}
}

if($UserFromAD.phone -ne $null ){
if ($UserFromAD.phone -ne $UserFromSamanage.phone){
$UploadUser.user['phone'] = $UserFromAD.phone
}
}
if($UserFromAD.MobilePhone -ne $null ){
if ($UserFromAD.MobilePhone -ne $UserFromSamanage.mobile_phone){
$UploadUser.user['mobile_phone'] = $UserFromAD.MobilePhone
}
}
if($UserFromAD.title -ne $null ){
if ($UserFromAD.title -ne $UserFromSamanage.title){
$UploadUser.user['title'] = $UserFromAD.title
}
}
#Only add user's manager on edit not on create (as the manager has to exist before it can be assigned)
if(($UserFromAD.Manager -ne $null) -and ($UserFromSamanage.id -ne $null) ){
$tempManager = (get-aduser $UserFromAD.manager).userprincipalname
if ($tempManager -ne $UserFromSamanage.reports_to.email){
$UploadUser.user['reports_to'] = @{}
$UploadUser.user.reports_to['email'] = $tempManager
}
}

if($UserFromAD.Department -ne $null ){
if ($UserFromAD.department -ne $UserFromSamanage.department.name){
$UploadUser.user['department'] = @{}
$UploadUser.user.department['name'] = "$($UserFromAD.Department)"
}
}
if($UserFromAD.Office -ne $null ){
if ($UserFromAD.Office -ne $UserFromSamanage.site.name){
$UploadUser.user['site'] = @{}
$UploadUser.user.site['name'] = $UserFromAD.Office
}
}

if (!($UserFromSamanage.role.name)) {
$UploadUser.user['role'] = @{}
$UploadUser.user.role['name'] = "requester"
}

#return the item that was just created for updating or adding to Samanage
$UploadUser
}

# goes though the process of actually adding the user to Samange
Function Add-SamanageUser{
param ($UsertoUpload)
write-verbose "Adding user to Samanage $(convertto-json $UsertoUpload)"
Try{
$Output = Invoke-RestMethod -Headers $headers -ContentType 'application/json' -Method POST -uri https://api.samanage.com/users.json -Body (convertto-json $UsertoUpload)
}catch{
Write-Output "$($UsertoUpload.user.name) had an issue when adding to Samanage"
Write-output "User JSON file $(Convertto-json $UsertoUpload)"
#Get-ADUser -Filter "EmailAddress -eq '$($UsertoUpload.user.email)'" -Properties EmailAddress,DisplayName,Title,Department,Office,OfficePhone,MobilePhone,Fax,Manager,UserPrincipalName,Enabled
}
}

#Remove the user from Samanage
Function Remove-SamanageUser{
param($RemoveEmail)
write-verbose "Removing user from Samanage $RemoveEmail"
$RemoveUser = Invoke-RestMethod -uri https://api.samanage.com/users.json?email=$RemoveEmail -Method get -Headers $headers -ContentType 'application/json'
$Output = Invoke-RestMethod -uri https://api.samanage.com/users/$($RemoveUser.id).json -Method delete -Headers $headers -ContentType 'application/json'
#write-verbose $Output
}

#update the user in Samanage
Function Update-samanageuser{
param ($UserToUpdate,$UserID)
write-verbose "Updating user in Samanage $($userid)"
write-verbose "Updating user in Samanage $(convertto-json $UserToUpdate)"
try{
$Output = Invoke-webrequest -Headers $headers -ContentType 'application/json' -Method PUT -uri "https://api.samanage.com/users/$($UserID).json" -Body (convertto-json $UserToUpdate)
#write-verbose $Output
}catch
{Write-Verbose "There was an error updating this user"}
}
################################
#base part of the script
################################

Write-Progress -"Activity Add new user to Samange" -Status "Getting current Samange user list" -PercentComplete 3 -Id 1
#update list of Samanage users
$SamanageUsers = Get-SamanageUsers

#I have all my service accounts/non user accounts tagged with the department or "Service Account" you can change this to what ever value you want to exclude from your import
Write-Progress -"Activity Add new user to Samange" -Status "Getting current AD user list" -PercentComplete 6 -Id 1
$AD_Users = Get-ADUser  -Filter 'Department -ne "Service Account"' -Properties EmailAddress,DisplayName,Title,Department,Office,OfficePhone,MobilePhone,Fax,Manager,UserPrincipalName,Enabled

#add check all AD users to see who should be added to Samanage
Write-Progress -"Activity Add new user to Samange" -Status "Comparing user lists and adding new users" -PercentComplete 9 -Id 1
$UserNumber = 0
$TotalUsers = $AD_Users.count

foreach ($AD_User in $AD_Users){
$UserNumber += 1
$PercentComplete = $UserNumber / $totalusers * 100.
Write-Progress -"Activity Adding users in Samange" -Status "Comparing user lists and adding new users" -PercentComplete $PercentComplete -id 2 -ParentId 1

Write-Verbose "checking $($ad_user.DisplayName) to see if it is in Samanage already"
if ($SamanageUsers.Email -contains $AD_User.UserPrincipalName){
#Skip if already in Samanage
Write-Verbose "user is already in Samanage"
}
else{
#add the new users to Samanage
Write-Verbose "user is not in Samange - add them now"
#if the parse-UserUpload returns a "blank" user then skip the upload
Add-SamanageUser -UsertoUpload (Parse-UserUpload -UserFromAD $AD_User)
}
Write-Verbose "
"#adds some space between records
}
Write-Progress -"Activity Adding users in Samange" -Status "Comparing user lists and adding new users" -PercentComplete $PercentComplete -id 2 -ParentId 1 -Completed

#check to see if any accounts need to be updated
Write-Progress -"Activity updating users in Samange" -Status "Getting current Samange user list" -PercentComplete 50 -Id 1
$SamanageUsers = Get-SamanageUsers
Write-Progress -"Activity updating users in Samange" -Status "Comparing current Samange users to AD record" -PercentComplete 75 -Id 1
$UserNumber = 0
$TotalUsers = $SamanageUsers.count

foreach ($User in $SamanageUsers)
{
$UserNumber += 1
$PercentComplete = $UserNumber / $totalusers * 100
Write-Progress -"Activity updating users in Samange" -Status "Comparing current Samange users to AD record" -PercentComplete $PercentComplete -id 3 -ParentId 1

Write-Verbose "checking if $($user.name) has updated information in AD"
#get user from AD, if user does not exist remove the user record

Try{
$AD_User = Get-ADUser -Filter "EmailAddress -like '$($user.Email)'" -Properties EmailAddress,DisplayName,Title,Department,Office,OfficePhone,MobilePhone,Fax,Manager,UserPrincipalName,Enabled
#get the manager
Write-Verbose "found user in AD $($ad_user.DisplayName) so going to update them"
#if the parse-UserUpload returns a "blank" user then skip the upload

$temp = Parse-UserUpload -UserFromSamanage $user -UserFromAD $AD_User
#Create a string to test if the update is "blank" (must be against the left side NO INDENTING)
$test = @"
"{\r\n \"user\": {\r\n\r\n }\r\n}"
"@
if ((convertto-json $temp) -ne (convertfrom-json $test)){
Write-Verbose "updating the user"
$upoutput = Update-samanageuser -UserToUpdate $temp -UserID $user.id
}else{
Write-Verbose "User has no updates"
}

}catch{
Write-Verbose "Did not find user in AD $($ad_user.DisplayName) so going to remove them"
#account does not exist in AD so remove the Samanage account
Write-Verbose "update output $upoutput"
#check to see if the user has a department listed. If so the user is LIKELY from AD. Therefore don't delete the user.
Write-Verbose "check if upoutput is null $($upoutput -eq $null)"
Write-Verbose "check if department is not null $($User.department -ne $null)"

if (($User.department) -and ($upoutput -eq $null)) {
Write-Verbose "going to remove $($user.name)"

#uncomment this line to allow the script to delete users
#Remove-SamanageUser -RemoveEmail $user.Email
}
}
Write-Verbose "
"#adds some space between records

}
Write-Progress -"Activity updating users in Samange" -Status "Comparing current Samange users to AD record" -PercentComplete $PercentComplete -id 3 -ParentId 1 -Completed
Write-Progress -"Activity updating users in Samange" -Status "all done" -PercentComplete 100 -Id 1 -Completed

Attachments

Outcomes