Skip to content

Instantly share code, notes, and snippets.

@darrenjrobinson
Last active November 17, 2018 22:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darrenjrobinson/7cae9544d7a5b39dbd90 to your computer and use it in GitHub Desktop.
Save darrenjrobinson/7cae9544d7a5b39dbd90 to your computer and use it in GitHub Desktop.
Microsoft Identity Manager Terminal Services PowerShell Management Agent Schema Script. Supporting blog post is located here https://blog.darrenjrobinson.com/managing-ad-terminal-services-configuration-with-fim-mim-using-the-granfeldt-powershell-management-agent/
param (
$Username,
$Password
)
BEGIN
{
$DebugFilePath = "C:\PROGRA~1\MICROS~4\2010\SYNCHR~1\EXTENS~2\TermServ\ts\DebugTermServicesMA.txt"
if(!(Test-Path $DebugFilePath))
{
$DebugFile = New-Item -Path $DebugFilePath -ItemType File
}
else
{
$DebugFile = Get-Item -Path $DebugFilePath
}
"Starting Export : " + (Get-Date) | Out-File $DebugFile -Append
}
PROCESS
{
#Initialize Parameters
$Identifier = $_.Identifier
$objectGuid = $_.DN
Write-Output "UserDN: $objectGuid" | Out-File $DebugFile -Append
$ErrorName = "success"
$ErrorDetail = $null
$error.clear()
$errorstatus = "success"
$date = Get-Date -Format "yyyy-MM-dd"
$_ | out-file $DebugFile -Append
$curUser = New-Object System.DirectoryServices.DirectoryEntry "LDAP://<GUID=$objectGuid>", $Username, $Password
[ADSI]$user = "LDAP://<GUID=$objectGuid>"
$account = $curUser.sAMAccountName.Value
# Look at the user to see if the user already has a terminal services config
$curTSProfilePath = $null
if ($User.terminalServicesProfilePath) {$curTSProfilePath = $User.terminalServicesProfilePath}
$curTSAllowLogon = $null
if ($User.allowlogon) {$curTSAllowLogon = $User.allowlogon}
$curTSHomeDirectory = $null
if ($User.terminalServicesHomeDirectory) { $curTSHomeDirectory = $User.terminalServicesHomeDirectory}
$curTSHomeDrive = $null
if ($User.terminalServicesHomeDrive) {$curTSHomeDrive = $User.terminalServicesHomeDrive}
### --- FUNCTIONS --- ###
#NOTE! Function calls from the script will generate output to the pipeline unless catched by parameter.
#This output will be seen as errors when running the MA
#Call functions using $catch = FunctionName param1 param2
#Function for adding AccessRule to folder
#$A = Account in the format "AccountName"
#$F = Folder
#$P = Permission to assign. Modify, Read or FullControl typically
#Inheritence is added by default.
function AddAccessRule($F, $A, $P)
{
Try{
$errorstatus = "success"
$acl = Get-Acl $F
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($A,$P,"ContainerInherit,ObjectInherit","None","Allow")
$acl.AddAccessRule($rule)
# Assign the permissions one level up as when we did the create of the home directory we also created the hdrive subdirectory.
Set-Acl -Path $F.Parent.FullName -AclObject $acl -errorvariable $err
if ( $err ) {throw $err}
}
Catch [exception]
{
"Error in AddAccessRule" | Out-File $DebugFile -Append
Write-Output "Error detail: $err" | Out-File $DebugFile -Append
$ErrorName = "Script Error"
$errordetail = $error[0].exception
}
}
#Function for setting terminal servies homeDirectory, profile directory, allowLogon and terminal services homeDrive attributes on user in AD
#ProfDir = Full profileDirectory path in the format \\server\share\username
#Dir = Full homeDirectory path in the format \\server\share\username
#Drive = The drive letter to use, W:
function UpdateUser( $TSHome, $TSProfile, $TSLogon, $TSDrive)
{
If($TSHome -and $TSProfile -and $TSLogon -and $TSDrive)
{
# We're only provisioning so will only do initial values as per Declarative Rule Flows.
$user.psbase.InvokeSet("terminalServicesHomeDirectory",$TSHome)
$user.psbase.InvokeSet("terminalServicesProfilePath", $TSProfile)
$user.psbase.InvokeSet("allowlogon",$TSLogon)
$user.psbase.InvokeSet("terminalServicesHomeDrive",$TSDrive)
$User.SetInfo()
}
}
### --- End of FUNCTIONS --- ###
### --- MAIN SCRIPT --- ###
#Loop through changes and update parameters
foreach ($can in $_.ChangedAttributeNames)
{
foreach ($ValueChange in $_.AttributeChanges[$can].ValueChanges)
{
if ( $can -eq 'TSProfilePath' ){$TSProfilePath = $ValueChange.Value}
if ( $can -eq 'TSHomeDir' ){$TSHomeDirectory = $ValueChange.Value}
if ( $can -eq 'TSHomeDrive' ){$TSHomeDrive = $ValueChange.Value}
if ( $can -eq 'TSAllowLogon' ){$TSAllowLogon = $ValueChange.Value}
}
}
#Verify changetype.
if ($_.ObjectModificationType -eq 'Add')
{
# adds are caught by importing new objects from Active Directory (see import script)
# and joining these to existing user objects on the metaverse
throw "Add modification are not supported"
}
if ($_.ObjectModificationType -eq 'Delete')
{
# deletes are caught by importing deleted objects (isDeleted) from Active
# Directory (see import script). This way we clear up the CS
throw "Delete modification are not supported"
}
#Supported ChangeType is Replace
if ($_.ObjectModificationType -match 'Replace')
{
# No current TS Profile Attrs -> Get new TSHomeDir, TSHomeDrive, TSProfile : NewHomeDir
if (!$curTSHomeDirectory)
{
if ( $TSHomeDirectory -and $TSProfilePath -and $TSHomeDrive -and $TSAllowLogon)
{
#NewTSHomeDir
#Check if TS folder already Exists
$exists1 = Test-Path $TSHomeDirectory
$exists2 = Test-Path $TSProfilePath
if(!$exists1)
{
# Create NEW TSHomeFolder
$folder1 = New-Item $TSHomeDirectory -Type Directory
$catch = AddAccessRule $folder1 $account "Modify"
# Update the AD User Object with the config attributes
$catch = UpdateUser $TSHomeDirectory $TSProfilePath $TSAllowLogon $TSHomeDrive
}
if (!$exists2)
{
# Create NEW TS Profile Dir
$folder2 = New-Item $TSProfilePath -Type Directory
$catch = AddAccessRule $folder2 $account "Modify"
# Update the AD User Object with the config attributes
$catch = UpdateUser $TSHomeDirectory $TSProfilePath $TSAllowLogon $TSHomeDrive
}
if ($exists1 -OR $exists2)
{
#Folders already exists!
#Likely a missmatch in AD and Folder data. Update user and folder
$folder1 = Get-Item $TSHomeDirectory
$catch = AddAccessRule $folder1 $account "Modify"
$folder2 = Get-Item $TSProfilePath
$catch = AddAccessRule $folder2 $account "Modify"
$catch = UpdateUser $TSHomeDirectory $TSProfilePath $TSAllowLogon $TSHomeDrive
}
}
}
else
{
# in case the AD Attr's didn't update for any reason
if ( $TSHomeDirectory -and $TSProfilePath -and $TSHomeDrive -and $TSAllowLogon)
{
$catch = UpdateUser $TSHomeDirectory $TSProfilePath $TSAllowLogon $TSHomeDrive
}
else
{
if ($_.TSHomeDirectory) {$TSHomeDirectory = $_.TSHomeDirectory}else{$TSHomeDirectory = $null}
if ($_.TSProfilePath){$TSProfilePath = $_.TSProfilePath}else{$TSProfilePath=$null}
if ( $_.TSAllowLogon){$TSAllowLogon = $_.TSAllowLogon}else{$TSAllowLogon = $null}
if ( $_.TSHomeDrive ){$TSHomeDrive = $_.TSHomeDrive }else{ $TSHomeDrive =$null}
$catch = UpdateUser $TSHomeDirectory $TSProfilePath $TSAllowLogon $TSHomeDrive
}
}
}
#Return the result to the MA
$obj = @{}
$obj.Add("[Identifier]",$Identifier)
$obj.Add("[ErrorName]",$ErrorName)
if($ErrorDetail){$obj.Add("[ErrorDetail]",$ErrorDetail)}
$obj
}
END
{#Writing close tag in debugfile
"Ending Export : " + (Get-Date) | Out-File $DebugFile -Append
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment