DESCRIPTION
Quest's ActiveRoles Server has an ability to move a user account between domains, but by default this ability is hidden on the user interface. Possible, an error will be rised during cross-domain moving if a moving user is a member of 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.
- Cross-domain move is always made from source DC that have RID master role. This behavior is defined in Active Directory by Microsoft, and we can't change it.
Thus we should clear a user memebership on the RID master DC rather others DCs. This will allow us to move a user account to another domain instantly, without any delaying for domain replication between DCs.
This script demonstates how to enable cross-domain moving, and how to clear a user membership before moving to another domain. Special thanks to Alexandr Skripnik, Moscow and Andrey Biryukov, Moscow.
Note This code may use functions from the ARS 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 MERCHANTBILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
'
' IF YOU WANT THIS FUNCTIONALITY TO BE CONDITIONALLY SUPPORTED,
' PLEASE CONTACT QUEST PROFESSIONAL SERVICES.
'*********************************************************************************
'
' This code is published on the ActiveRoles Script Center:
' http://communities.quest.com/docs/DOC-9991
'
' This code may use functions from the ARS Script Policy Best Practices:
' http://communities.quest.com/docs/DOC-10016
'
' Please, follow the link to obtain instructions and code for those functions.
'*********************************************************************************
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 ***************************************************************
COMPATIBILITY
Script compatible with the following version(s): <Not specified>