DESCRIPTION
Active Roles has the ability to move a user account between domains, but by default, this ability is hidden on the user interface. Possible, an error will be raised during cross-domain moving if a moving user is a member of a global group. To avoid that, a user membership should be cleared before cross-domain moving.
Technical notes:
- We can't remove a group from a user membership directly. We should remove a user from the group.
- The cross-domain move is always made from source DC that have the RID master role. This behavior is defined in Active Directory by Microsoft, and we can't change it.
Thus we should clear a user membership on the RID master DC rather than other Domain Controllers. This will allow us to move a user account to another domain instantly, without any delay for domain replication between DCs.
This script demonstrates how to enable cross-domain moving, and how to clear a user membership before moving to another domain.
Note This code may use functions from the Active Roles Script Policy Best Practices. Please, follow the link to obtain instructions and code for those functions.
SCRIPT
'*********************************************************************************
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
' EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
' WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
'
' IF YOU WANT THIS FUNCTIONALITY TO BE CONDITIONALLY SUPPORTED,
' PLEASE CONTACT ONE IDENTITY PROFESSIONAL SERVICES.
'*********************************************************************************
Option Explicit
'***********************************************************************************
'** EVENT HANDLERS
'***********************************************************************************
Function onGetPolicyMarker()
'-- Identify your policy with the same policy ID that is used for a built-in policy
onGetPolicyMarker=EDS_APE_TYPE_MOVE_TARGETS
End Function
Sub onPostGet(Request)
'-- Optimization: process user account only
If (LCase(Request.Class) <> "user") Then Exit Sub
'-- Optimization: respond to target container requests only
If (Not Request.IsAttributeRequested("edsvaMoveTargets")) Then Exit Sub
'-- Provide a list of target allowed target containers
Call Request.PutEx(ADS_PROPERTY_UPDATE, "edsvaMoveTargets", _
Array ("DC=testenv,DC=msk,DC=lab", "DC=orange,DC=msk,DC=qsft"))
End Sub
Sub onPreMove(Request)
'-- Optimization: process user account only
If (LCase(Request.Class) <> "user") Then Exit Sub
Call ClearMembership()
End Sub
'***********************************************************************************
Sub ClearMembership()
Dim strDN, strDomainDN, objEDMS, objGroup
Dim arrMemberOfDN, strMemberOfDN, strObjectCategory, boolIsDynamicGroup
Dim objRIDMasterFsmo, objRIDMasterFsmoNTDS, objRIDMasterFsmoServer, strRIDMasterFsmoServer
Call DirObj.GetInfoEx(Array("distinguishedName", "memberOf", "edsvaDomainDN"), 0)
'-- Get a user account membership
On Error Resume Next
arrMemberOfDN = DirObj.GetEx("memberOf")
On Error GoTo 0
'-- Skip if a membership is empty
If (IsEmpty(arrMemberOfDN)) Then Exit Sub
'-- Get a user account distinguished name
On Error Resume Next
strDN = DirObj.GetEx("distinguishedName")
On Error GoTo 0
'-- Get a user account domain distinguished name
strDomainDN = DirObj.Get("edsvaDomainDN")
'-- Get a FSMO RID Server
Set objRIDMasterFsmo = GetObject("EDMS://CN=RID Manager$,CN=System," & strDomainDN)
Set objRIDMasterFsmoNTDS = GetObject("EDMS://" & objRIDMasterFsmo.Get("fSMORoleOwner"))
Set objRIDMasterFsmoServer = GetObject(objRIDMasterFsmoNTDS.Parent)
strRIDMasterFsmoServer = objRIDMasterFsmoServer.Get("dNSHostName")
'-- Get a EDMS provider
Set objEDMS = GetObject("EDMS:")
For Each strMemberOfDN In arrMemberOfDN
'-- Bind for each object of membership
Set objGroup = objEDMS.OpenDSObject("EDMS://" & strRIDMasterFsmoServer & "/" & strMemberOfDN, vbNullString, vbNullString, ADS_SERVER_BIND)
Call objGroup.GetInfoEx(Array("objectCategory", "edsaIsDynamicGroup"), 0)
'-- Get an object category
On Error Resume Next
strObjectCategory = objGroup.Get("objectCategory")
On Error GoTo 0
'-- Process groups only
If (StringStartsWith(LCase(strObjectCategory), LCase("CN=Group,CN=Schema,CN=Configuration"))) Then
'-- Get an info if a group is dynamic
On Error Resume Next
boolIsDynamicGroup = CBool(objGroup.Get("edsaIsDynamicGroup"))
On Error GoTo 0
'-- Skip dynamic groups
If (Not boolIsDynamicGroup) Then
'-- Remove a user account from the group
Call objGroup.PutEx(ADS_PROPERTY_DELETE, "member", strDN)
Call objGroup.SetInfo()
End If
End If
Next
End Sub
Function StringStartsWith(ByVal strWhere, ByVal strWhat)
StringStartsWith = (Left(strWhere, Len(strWhat)) = strWhat)
End Function
'***** END OF CODE ***************************************************************