Sincronizando Bases OpenLDAP e Active Directory

O objetivo do artigo é a centralização da base de usuários, ou seja, por um fim a vários logins e senhas de uma rede com vários serviços autenticados. Abordarei um cenário que replica alterações na base OpenLDAP para o Active Directory.

[ Hits: 56.058 ]

Por: Evandro Nabor em 14/02/2013


Instalação e configuração



Não abordarei a instalação do Active Directory e nem do OpenLDAP, pois existem centenas de artigos a respeito na internet.

AD01

Crie um usuário com privilégio administrador chamado LSC no Active Directory, o programa irá usá-lo para as importações.

Instalar o serviço de Active Directory Certificate Services e exportar uma chave para utilizarmos no GNU/Linux:

LX01

Java:

# cd /usr/src
# wget
http://javadl.sun.com/webapps/download/AutoDL?BundleId=73850 -O java.tar.gz -O java.tar.gz
# tar zxvf java.tar.gz
# mv jre1.7.0_13 /usr/local/java
# export JAVA_HOME=/usr/local/java && echo "export JAVA_HOME=/usr/local/java" >> ~/.bashrc


Certificado:

# $JAVA_HOME/bin/keytool -import -keystore $JAVA_HOME/lib/security/cacerts -file ChaveDoWin2008.crt

Obs.: Quando for solicitada, a senha padrão é: changeit

LSC

# cd /usr/src
# wget
http://tools.lsc-project.org/attachments/download/317/lsc-core-1.2.2-dist.tar.gz
# tar zxvf lsc-core-1.2.2-dist.tar.gz
# mv lsc-1.2.2/ /usr/local/lsc && cd /usr/local/lsc


O arquivo de configuração do LSC é o etc/lsc.properties.

Este é um exemplo que montei para fazer a sincronia do nosso cenário. Você deverá modificá-lo conforme suas necessidades. Todas as documentações são encontradas na página do LSC, mas de qualquer maneira, este arquivo foi extremamente comentado por min:

#/usr/local/lsc/etc/lsc.properties
# Evandro Nabor
##############
### Origem ###
##############
# base OpenLDAP

src.java.naming.security.principal=cn=Manager,dc=texas,dc=local
src.java.naming.security.credentials=3v4ndrO
src.java.naming.security.authentication=simple
src.java.naming.referral=ignore
src.java.naming.provider.url=ldap://172.31.1.28/dc=texas,dc=local
src.java.naming.ldap.version=3
src.java.naming.ldap.derefAliases=never
src.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory


###################
### Destino ###
###################
# base ActiveDirectory
# repare que utilizo SSL com exportacao do certificado do AD e importacao pro java do linux

dst.java.naming.security.principal=CN=LSC,CN=Users,DC=texas,DC=local
dst.java.naming.security.credentials=3v4ndrO
dst.java.naming.security.authentication=simple
dst.java.naming.referral=ignore
dst.java.naming.provider.url=ldaps://172.31.1.99/DC=texas,DC=local
dst.java.naming.ldap.version=3
dst.java.naming.ldap.derefAliases=never
dst.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
dst.java.naming.ldap.pageSize = 1000
#dst.java.naming.tls = true


###############
### Tarefas ###
###############
#definindo tarefa para sincronia de usuarios

lsc.tasks=user
#definindo tarefa para sincronia de grupos
lsc.tasks=group

### User ###
#opcoes de permissao para update, deletar e criar em ambas as bases

lsc.tasks.user.condition.create = 1
lsc.tasks.user.condition.update = 1
lsc.tasks.user.condition.delete = 1
lsc.tasks.user.condition.modrdn = 1

#esta opcao serve pra decidir como sera criado o usuario no activedirectory. ex. cn=evandro.nabor,cn=users,dc=texas,dc=local
lsc.tasks.user.bean=org.lsc.beans.SimpleBean
lsc.tasks.user.dn = "CN=" + srcBean.getAttributeValueById("uid") + ",CN=Users"

# Source
#opcoes de selecao dos usurios no ldap, perceba os filtros para que o programa funciona dos dois lados, tanto quando cria um usuario e ele eh replicado pra o
#AD quanto pra quando deleta um usuario ele compara as duas bases e deleta o usuario no AD

lsc.tasks.user.srcService=org.lsc.jndi.SimpleJndiSrcService
lsc.tasks.user.srcService.filterAll=(&(objectClass=inetOrgPerson)(uid=*)(!(givenName=MailList)))
lsc.tasks.user.srcService.filterId = (&(objectClass=inetOrgPerson)(|(uid={uid})(uid={sAMAccountName})))
lsc.tasks.user.srcService.baseDn=ou=pessoas
# campos que serao replicados, eh importante colocar todos que serao replicados e mais tarde nas opcoes de sincronia definir como sera a sincronia
lsc.tasks.user.srcService.attrs= uid sambaLogonScript homeDirectory postalCode postOfficeBox
# campo de volta, eh a pesquisa reversa que ele faz para que quando seja deletado algum usuario do OpenLDAP ele seja tambem deletado do AD
lsc.tasks.user.srcService.pivotAttrs = uid


# Destination
# opcoes para selecao de usuarios no AD repare que filtro algumas contas padrao do windows para q elas nunca sofrao alteracoes e nao tenha problema

lsc.tasks.user.dstService=org.lsc.jndi.SimpleJndiDstService
lsc.tasks.user.dstService.baseDn=cn=Users
# idem source
lsc.tasks.user.dstService.attrs = sAMAccountName userAccountControl objectClass userPrincipalName pwdLastSet scriptPath homeDirectory displayName givenName unicodePwd
lsc.tasks.user.dstService.filterAll=(&(sAMAccountName=*)(objectClass=user)(!(sAMAccountName=Administrator))(!(sAMAccountName=Guest))(!(sAMAccountName=krbtgt))(!(sAMAccountName=LSC)))
lsc.tasks.user.dstService.filterId = (&(objectClass=user)(sAMAccountName={uid}))
# idem source
lsc.tasks.user.dstService.pivotAttrs = sAMAccountName


### Group ###
# tarefa para sincronizar grupos
#regras de update, criar e deletar

lsc.tasks.group.condition.create = 1
lsc.tasks.group.condition.update = 1
lsc.tasks.group.condition.delete = 1
lsc.tasks.group.condition.modrdn = 1

# como sera criado o grupo no AD, ex. cn=IT,cn=users,dc=texas,dc=local
lsc.tasks.group.dn = "CN=" + srcBean.getAttributeValueById("cn") + ",CN=Users"
lsc.tasks.group.bean=org.lsc.beans.SimpleBean

# Source
# opcoes para selecao de grupos no OpenLDAP, repare os filtros para alguns grupos nunca sejam replicados pro AD como Domain Users, para nao confindir com os padroes do Win.

lsc.tasks.group.srcService=org.lsc.jndi.SimpleJndiSrcService
lsc.tasks.group.srcService.filterAll = (&(objectClass=posixGroup)(cn=*)(!(cn=Print Operators))(!(cn=Backup Operators))(!(cn=Administrators))(!(cn=Domain Users))(!(cn=Admins))(!(cn=Default))(!(cn=Domain Admins))(!(cn=Domain Computers))(!(cn=Domain Guests))(!
(cn=Replicators))(!(cn=Account Operators)))
lsc.tasks.group.srcService.filterId = (&(objectClass=posixGroup)(cn={cn}))
lsc.tasks.group.srcService.baseDn=ou=Grupos
lsc.tasks.group.srcService.attrs=cn objectClass memberUid
lsc.tasks.group.srcService.pivotAttrs = cn

# Destination
# opcpes para o destino, mesmo padrao de selecao para q os grupos default do Win nao sejam deletados

lsc.tasks.group.dstService=org.lsc.jndi.SimpleJndiDstService
lsc.tasks.group.dstService.baseDn=cn=Users
lsc.tasks.group.dstService.attrs = cn objectClass member sAMAccountName
lsc.tasks.group.dstService.pivotAttrs = cn
lsc.tasks.group.dstService.filterAll = (&(objectClass=group)(sAMAccountName=*)(!(sAMAccountName=DnsAdmins))(!(sAMAccountName=DnsUpdateProxy))(!(sAMAccountName=Domain Computers))(!(sAMAccountName=Domain Controllers))(!
(sAMAccountName=Schema Admins))(!(sAMAccountName=Enterprise Admins))(!(sAMAccountName=Cert Publishers))(!(sAMAccountName=Domain Admins))(!(sAMAccountName=Domain Users))(!(sAMAccountName=Domain Guests))(!(sAMAccountName=Group Policy
Creator Owners))(!(sAMAccountName=RAS and IAS Servers))(!(sAMAccountName=Allowed RODC Password Replication Group))(!(sAMAccountName=Denied RODC Password Replication Group))(!(sAMAccountName=Read-only Domain Controllers))(!
(sAMAccountName=Enterprise Read-only Domain Controllers)))
lsc.tasks.group.dstService.filterId = (&(objectClass=group)(cn={cn}))


###################
### Syncoptions ###
###################
# opcoes de sicronia, ou seja, quais campos serao sincornizados entre bases e se eh necessario algum remanejamento de campo, ou incluir texto,
# ex. o campo de script de logon no ldap do AD chama-se scriptPath no openldap chama-se sambaLogonScript portanto
# eh preciso fazer um mapemaento para que o campo sambaLogonScript do OpenLDAP seja escrito no scriptPath do AD.

# OpenLDAP -> AD
### User ###

lsc.syncoptions.user = org.lsc.beans.syncoptions.PropertiesBasedSyncOptions
lsc.syncoptions.user.default.action = F
lsc.syncoptions.user.objectClass.action = F
# o que inserir de atributos
lsc.syncoptions.user.objectClass.force_value = "top";"user";"person";"organizationalPerson"
# uid -> DisplayName
lsc.syncoptions.user.displayName.create_value = srcBean.getAttributeValueById("uid")
# uid -> givenName
lsc.syncoptions.user.givenName.create_value = srcBean.getAttributeValueById("uid")
# uid -> sAMAccountName
lsc.syncoptions.user.sAMAccountName.create_value = srcBean.getAttributeValueById("uid")
# sambaLogonScript -> scriptPath
lsc.syncoptions.user.scriptPath.action = F
lsc.syncoptions.user.scriptPath.force_value = srcBean.getAttributeValueById("postalCode")
# uid -> userPrincipalName
lsc.syncoptions.user.userPrincipalName.force_value = srcBean.getAttributeValueById("uid") + "@texas.local"
# homeDirectory -> homeDirectory
lsc.syncoptions.user.homeDirectory.action = F
lsc.syncoptions.user.homeDirectory.force_value = srcBean.getAttributeValueById("postOfficeBox")
# opcoes de controle do AD
lsc.syncoptions.user.userAccountControl.create_value = AD.userAccountControlSet( "0", [ AD.UAC_SET_PASSWD_NOTREQD,AD.UAC_SET_NORMAL_ACCOUNT ])
# password nao precisa ser mudado no proximo logon
lsc.syncoptions.user.pwdLastSet.create_value = "-1"
# senha padrao setada na importacao do usuario do OpenLDAP pro AD
lsc.syncoptions.user.unicodePwd.action = F
lsc.syncoptions.user.unicodePwd.create_value = AD.getUnicodePwd("3v4ndrO")

### Group ### # opcoes de sincronia para grupos
lsc.syncoptions.group = org.lsc.beans.syncoptions.PropertiesBasedSyncOptions
# nome do grupo
# cn -> sAMAccountName

lsc.syncoptions.group.sAMAccountName.create_value = srcBean.getAttributeValueById("cn")
lsc.syncoptions.group.default.action = F
# atributos de grupo
lsc.syncoptions.group.objectClass.force_value = "top";"group"
# membro dos grupos, eh um javascript que entra dentro dos grupos do OpenLDAP e busca usuarios
# e replica para o determinado grupo no AD

lsc.syncoptions.group.member.delimiter = $
lsc.syncoptions.group.member.force_value = \
  var umembers = \
    srcBean.getAttributeValuesById("memberUid").toArray() ; \
  for (var i=0; i    p\try { \
        umembers[i] = ldap.attribute(ldap.list("CN=Users","(sAMAccountName=" + (umembers[i]) + ")").get(0), 'distinguishedName').get(0) \
    } catch (e) { \
        umembers[i]=null; \
    } \
  } \
  var members = new Array(); \
  var j=0; \
  for (var i=0; i<umembers.length; i++) { \
    if (umembers[i]!=null) members[j++]=umembers[i]; \
  } \
  members;

OpenLDAP

Para exemplificar, criei uma base com seis usuários e três grupos, insira o conteúdo em um arquivo ldif e importe para dentro do seu servidor LDAP:

# baseteste.ldif
dn: dc=texas,dc=local
objectClass: top
objectClass: dcObject
objectClass: organization
dc: texas
o: Texas LDAP

dn: ou=pessoas,dc=texas,dc=local
objectClass: top
objectClass: organizationalUnit
ou: pessoas

dn: ou=grupos,dc=texas,dc=local
ou: grupos
objectClass: organizationalUnit
objectClass: top

dn: uid=enabor,ou=pessoas,dc=texas,dc=local
objectClass: posixAccount
objectClass: top
objectClass: inetOrgPerson
gidNumber: 0
givenName: evandro
sn: nabor
displayName: enabor
uid: enabor
homeDirectory: /home/enabor
cn: enabor
uidNumber: 27635

dn: uid=sman,ou=pessoas,dc=texas,dc=local
objectClass: posixAccount
objectClass: top
objectClass: inetOrgPerson
gidNumber: 0
givenName: super
sn: man
displayName: sman
uid: sman
homeDirectory: /home/sman
cn: sman
uidNumber: 10548

dn: uid=lluthor,ou=pessoas,dc=texas,dc=local
objectClass: posixAccount
objectClass: top
objectClass: inetOrgPerson
gidNumber: 0
givenName: lex
sn: luthor
displayName: lluthor
uid: lluthor
homeDirectory: /home/lluthor
cn: lluthor
uidNumber: 37975

dn: uid=lverde,ou=pessoas,dc=texas,dc=local
objectClass: posixAccount
objectClass: top
objectClass: inetOrgPerson
gidNumber: 0
givenName: lanterna
sn: verde
displayName: lverde
uid: lverde
homeDirectory: /home/lverde
cn: lverde
uidNumber: 24873

dn: uid=bwayne,ou=pessoas,dc=texas,dc=local
objectClass: posixAccount
objectClass: top
objectClass: inetOrgPerson
gidNumber: 0
givenName: bruce
sn: wayne
displayName: bwayne
uid: bwayne
homeDirectory: /home/bwayne
cn: bwayne
uidNumber: 25788

dn: cn=it,ou=grupos,dc=texas,dc=local
objectClass: posixGroup
objectClass: top
cn: it
memberUid: enabor
memberUid: bwayne
memberUid: sman
gidNumber: 58946

dn: cn=managers,ou=grupos,dc=texas,dc=local
objectClass: posixGroup
objectClass: top
cn: managers
gidNumber: 61470
memberUid: lluthor
memberUid: lverde

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Instalação e configuração
   3. Iniciando a sincronização
   4. Senhas
Outros artigos deste autor

Bind consultando zonas em base LDAP

Leitura recomendada

Servidor de logs para Routers e Switches Cisco

AWS - VPN IPSEC com Libreswan

Trabalhando com subredes

JMeter - Saiba como testar o desempenho dos principais serviços de rede

A camada de enlace de dados

  
Comentários
[1] Comentário enviado por jfernandes em 16/02/2013 - 18:01h

Amigo, parabéns pelo artigo.
Tenho uma questão pra todos ...
Tenho um cliente que tem sua base em LDAP, e por enquanto não quer migrar para o AD da Microsoft, porém, contudo, todavia, ele quer uma solução que vamos instalar ( Xen Desktop ) que precisa do Active Directory da Microsoft para autenticação de seus usuários, não sei se conhecem o Xen Desktop, mas é uma solução de virtualização de estação de trabalho, e necessita de um login no AD.
Pergunta..... com esse seu tutorial, poderei implementar essa solução no cliente ?
Fico no aguardo, e mais uma vez, parabéns pelo artigo.
Joel Fernandes

[2] Comentário enviado por evandronabor em 17/02/2013 - 09:59h

Com certeza voce poderá usa-lo para isso.
Voce pode subir um servidor AD e seguir o meu artigo que todas as suas contas do OpenLDAP serão replicadas para o AD.
Quando a base estiver replicada é so voce colocar o comando de sincronização no crontab para ser executada quando voce quiser para manter a integridade das bases.

A unica questao que é preciso atençao é com relação as senhas pois como eu havia dito não é possivel sincroniza-las.
De uma boa lida no artigo e porcure mais informações no site do LSC. é possivel sim implementa-lo do jeito que voce precisa sem problemas.

Att.

[3] Comentário enviado por fernandofrauches em 22/02/2013 - 09:41h

Parabéns pelo artigo....
Muito bom...
Estou com um problema aqui na empresa relacionado a seu artigo.
No seu artigo vc faz a sincronização nesse sentido OpenLDAP -> Active Directory, é possivel fazer a sincronização no sentido contrario? OpenLDAP <- Active Directory? Se sim, tem alguma dica de como?
Desde ja obrigado.

[4] Comentário enviado por evandronabor em 22/02/2013 - 09:48h

Sim é possivel fazer. Basicamente voce vai inverter o SRC e o DST, verifique no site do LSC tem muitos exemplos de como fazer lá.

[5] Comentário enviado por acunhasp em 26/02/2013 - 14:13h

bom tarde amigo, o meu retorna o seguinte erro:
Error opening the LDAP connection to the destination!
Fev 26 14:05:23 - ERROR - Error while synchronizing ID {uid=edsonb}: java.lang.RuntimeException: java.lang.RuntimeException: Error getting context DN from LDAP provider url
Será que pode me ajudar?

[6] Comentário enviado por lanzao em 10/09/2013 - 12:09h

tem como migrar do ad para o ldap?

[7] Comentário enviado por geowany em 12/03/2014 - 00:51h


[1] Comentário enviado por jfernandes em 16/02/2013 - 18:01h:

Amigo, parabéns pelo artigo.
Tenho uma questão pra todos ...
Tenho um cliente que tem sua base em LDAP, e por enquanto não quer migrar para o AD da Microsoft, porém, contudo, todavia, ele quer uma solução que vamos instalar ( Xen Desktop ) que precisa do Active Directory da Microsoft para autenticação de seus usuários, não sei se conhecem o Xen Desktop, mas é uma solução de virtualização de estação de trabalho, e necessita de um login no AD.
Pergunta..... com esse seu tutorial, poderei implementar essa solução no cliente ?
Fico no aguardo, e mais uma vez, parabéns pelo artigo.
Joel Fernandes


Acredito que instalar o AD não é a melhor solução. Já tentou colocar o samba.schema nesse ldap e adicionar os atributos na contas de usuário para que se tornem samba accounts? Assim fica compatível com os atributos necessários do AD.


Contribuir com comentário