Un requisito reciente para un proyecto era tener usuarios y grupos aprovisionados desde el dominio B al dominio A. Bastante simple, pero un inconveniente era que, a medida que las aplicaciones se migraban al dominio A, sus grupos serían "propiedad" del dominio A, que ahora sería la fuente autorizada para todos los atributos de grupo (en este caso, la fuente autorizada está determinada por la OU en la que se encuentra el grupo en el dominio B. El nombre de esta OU se almacena en el archivo de configuración de extensión de reglas).
Se utiliza una extensión de reglas personalizadas para determinar qué agente de gestión es autoritativo y asegurarse de que los objetos de usuario que se añaden al atributo de miembro pertenecen al dominio adecuado.
Al establecer un flujo de atributos avanzado de miembro a miembro aparece este mensaje:
"No se permite definir un flujo de atributos de importación de extensión de reglas a un atributo de referencia metaverso."
Pero hay una forma de evitarlo.
Este es el montaje:
- Dominio A: Es el dominio de la organización matriz.
- Dominio B: es el dominio de la organización que se fusiona con la organización matriz.
- Todos los grupos de seguridad comienzan su andadura en el dominio B. A medida que avanza la fusión, su fuente autoritativa cambiará al dominio A grupo por grupo.
Esto se indica cuando el grupo se mueve manualmente a la OU denominada "Dominio A Administrado" en el Dominio B.
He aquí la solución. El código para cada paso seguirá a este resumen:
- Crea un nuevo atributo multivaluado de cadena indexada en el metaverso llamado memberString.
- Cree un nuevo atributo llamado SourceCSEntryDN para mantener el valor DN en el Dominio B para el grupo de seguridad. (Esto se utiliza para buscar la OU a la que pertenece el grupo en el Dominio B cuando la MA del Dominio A está sincronizando el grupo).
- Escribe una función en el código de extensión de reglas para determinar en qué OU está el grupo.
- Cree un flujo de atributos de importación avanzada en ambos agentes de gestión para que los miembros fluyan al nuevo atributo memberString si ese MA es autoritativo. Este valor tendrá el DN de los usuarios miembros del grupo.
- Escriba una regla de flujo de atributos de exportación en ambos agentes de gestión para hacer fluir miembros desde memberString al atributo member si ese MA es autoritativo. Parte de esta función es encontrar el conector para el dominio apropiado en el mventry para el CN de usuario que está en el atributo memberString.
En los pasos 4 y 5, se realiza la comprobación del paso 3 para asegurarse de que se tratan como autorizados los valores de atributo correctos.
Para el código compartido, se creó un dll general de Utils llamado "UtilsForFIM". También se añadió código a las reglas de flujo de atributos de importación y exportación en las respectivas extensiones de reglas.
Para el paso 2, el flujo de atributos en el agente de gestión del dominio B es:
<dn>, cn ->SourceCSEntryDN
Este código pone el DN completo del objeto usuario en el atributo SourceCSEntryDN.
Aquí está el código para el paso 2:
Case “cd.group:<dn>,cn->mv.group:SourceCSEntryDN”
Dim sDNPath As String
Dim dn As ReferenceValue = csentry.DN
sDNPath = (dn.Subcomponentes(0, dn.Profundidad).ToString())
mventry("SourceCSEntryDN").Value = sDNPath
Para el paso 3, el código es un poco diferente para los agentes de gestión del Dominio A y del Dominio B. El agente de gestión del dominio A se basa en el SourceCSEntryDN, mientras que el agente de gestión del dominio B puede acceder al dn desde el csentry directamente.
Ambos tienen el siguiente flujo de atributos en el agente de gestión:
<dn>,member -> memberString
Este código comprueba si el DN del grupo contiene el OU que indica que el grupo debe ser gestionado por el Dominio A. Hay diferentes funciones para cada dominio. El dominio A necesita confiar en el valor que se puso en el atributo SourceCSEntryDN, mientras que el dominio B puede leer el DN directamente del objeto csentry.
Aquí está el código del paso 3 para el Dominio A:
Public Shared Function IsGroupManagedByDomAByDN(ByVal sDNPath As String) As Boolean
Dim bIsGroupManagedByDomA As Boolean
Dim sDomAManagedGroupOU As String
bIsGroupManagedByDomA = False
sDomAManagedGroupOU = UtilsForFIM.CommonUtils.ReadAppSetting("FIMConfig/General", "DomAManagedGroupOU").ToString()
If (InStr(sDNPath.ToLower(), sDomAManagedGroupOU.ToLower())) < 1 Then
'Grupo sigue siendo gestionado por el dominio de adquisición.
bIsGroupManagedByDomA = False
Si no
El grupo está ahora gestionado por DomA.
bIsGroupManagedByDomA = Verdadero
Fin If
Devolver bIsGroupManagedByDomA
Fin de la función
Aquí está el código del paso 3 para el Dominio B:
Public Shared Function IsGroupManagedByDomA(ByVal csentry As CSEntry) As Boolean
Dim bIsGroupManagedByDomA As Boolean
Dim dn As ReferenceValue = csentry.DN
Dim sDomAManagedGroupOU As String
bIsGroupManagedByDomA = False
sDomAManagedGroupOU = UtilsForFIM.CommonUtils.ReadAppSetting("FIMConfig/General", "DomAManagedGroupOU").ToString()
Dim sDNPath As String
sDNPath = (dn.Subcomponentes(0, dn.Profundidad).ToString())
If (InStr(sDNPath.ToLower(), sDomAManagedGroupOU.ToLower())) < 1 Then
'Grupo sigue siendo gestionado por el dominio de adquisición.
bIsGroupManagedByDomA = False
Si no
El grupo está ahora gestionado por DomA.
bIsGroupManagedByDomA = Verdadero
Fin If
Devolver bIsGroupManagedByDomA
Fin de la función
Para ambos dominios, el código está leyendo los miembros del grupo y escribiendo el valor dn de los usuarios en un atributo multivaluado llamado memberString. Aquí está el flujo de atributos para el paso 4 y el código:
<dn>,member -> memberString
El código de esta transformación para el agente de gestión del dominio A es:
Case “cd.group:<dn>,member->mv.group:memberString”
If (mventry("SourceCSEntryDN").IsPresent) Then
Dim bIsGroupManagedByDomA As Boolean = UtilsForFIM.CommonUtils.IsGroupManagedByDomAByDN(mventry("SourceCSEntryDN").Value)
If (bIsGroupManagedByDomA = True) Then
mventry("memberString").Values.Clear()
Dim i As Integer
For i = 0 To (csentry("member").Values.Count - 1)
Dim sMember As String = csentry("member").Values.Item(i).ToString()
mventry("memberString").Values.Add(sMember)
Siguiente
Fin If
Fin If
El código para esta transformación cuando el agente de gestión es el Dominio B es:
Caso "cd.group:member->mv.group:memberString"
Dim bIsGroupManagedByDomA As Boolean
bIsGroupManagedByDomA = UtilsForFIM.CommonUtils.IsGroupManagedByDomA(csentry)
If (bIsGroupManagedByDomA = False) Then
mventry("memberString").Values.Clear()
Dim i As Integer
For i = 0 To (csentry("member").Values.Count - 1)
Dim sMember As String = csentry("member").Values.Item(i).ToString()
mventry("memberString").Values.Add(sMember)
Siguiente
Fin If
Para el paso 5, ambos agentes de gestión tienen la siguiente regla de flujo de atributos:
member <- memberString
Esta es la regla de flujo de atributos de exportación para el dominio A:
Case “cd.group:member<-mv.group:memberString”
Dim bIsGroupManagedByDomA As Boolean
If (mventry("SourceCSEntryDN").IsPresent) Then
bIsGroupManagedByDomA = UtilsForFIM.CommonUtils.IsGroupManagedByDomAByDN(mventry("SourceCSEntryDN").Value)
If (bIsGroupManagedByDomA = False) Then
csentry("miembro").Values.Clear()
UtilsForFIM.CommonUtils.memberStringToMembers(mventry, csentry, csentry.MA.Name)
Fin If
Si no
'Source csentry dn is missing
Fin If
Y para el Dominio B:
Case “cd.group:member<-mv.group:memberString”
Dim bIsGroupManagedByDomA As Boolean
bIsGroupManagedByDomA = UtilsForFIM.CommonUtils.IsGroupManagedByDomA(csentry)
If (bIsGroupManagedByDomA = True) Then
csentry("miembro").Values.Clear()
UtilsForFIM.CommonUtils.memberStringToMembers(mventry, csentry, csentry.MA.Name)
Fin If
Aquí está la función memberStringToMembers que traduce la membresía del valor de cadena al csentry apropiado para el dominio al que se está exportando el grupo. Tenga en cuenta que esto está tomando el conector en el mventry del miembro para el MA que está procesando la ejecución actual para que tengamos el objeto de usuario en el dominio apropiado.
Public Shared Sub memberStringToMembers(ByVal mventry As MVEntry, ByVal csentry As CSEntry, ByVal sMAName As String)
Dim i As Integer
For i = 0 To (mventry("memberString").Values.Count - 1)
Dim sMember As String = mventry("memberString").Values.Item(i).ToString()
'Necesito encontrar el mventry para este conector y luego determinar el DomA csentry.
Dim mvEntryMember() As MVEntry
Dim arrMVEntryCN As Array
Dim sMemberCN As String
arrMVEntryCN = sMember.Split(",")
sMemberCN = arrMVEntryCN(0).Replace("CN=", "").Replace("cn=", "")
mvEntryMember = Utils.FindMVEntries("cn", sMemberCN, 1)
If (mvEntryMember.Length > 0) Then
Dim ManagementAgent As ConnectedMA
Dim Conectores As Integer
ManagementAgent = mvEntryMember(0).ConnectedMAs(sMAName)
Conectores = GestorAgente.Conectores.Contar
Si (Conectores > 0) Entonces
Dim csentryFound As CSEntry
csentryFound = ManagementAgent.Connectors.ByIndex(0)
csentry("member").Values.Add(mvEntryMember(0).ConnectedMAs.Item(sMAName).Connectors.ByIndex(0).DN.ToString().ToLower())
Fin If
Fin If
Siguiente
Fin Sub