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