Skip to main content

Introdução



O LDAP (Lightweight Directory Access Protocol) é um protocolo utilizado para acessar e gerenciar serviços de diretório distribuídos, que armazenam informações sobre usuários, grupos, dispositivos, e outras entidades. O LDAP é amplamente utilizado em redes corporativas para autenticação centralizada, onde diferentes sistemas e aplicações consultam o servidor LDAP para verificar as credenciais dos usuários e determinar se eles estão autorizados a acessar determinados recursos.


Este protocolo é eficiente e leve, facilitando a busca e modificação de informações armazenadas em diretórios de forma rápida e organizada, sendo uma peça-chave em sistemas de autenticação e gerenciamento de identidades, ou seja, é ideal quando você precisa de um sistema centralizado para gerenciar e armazenar dados que devem ser acessíveis de maneira consistente e padronizada em várias aplicações ou sistemas.


É importante adotar o serviço de diretório correto, algumas aplicações devem ser levadas em conta antes de adotar um serviço desses, algumas são:

  • Base de autenticação de usuário;
  • Cadastrar domínio de DNS;
  • Catálogo compartilhado de e-mails;
  • Cadastro de Clientes;
  • Permissão para administrar os diretórios;
  • Fácil gerenciamento.

Você pode ver alguns dos serviços de diretórios que existem aqui, em nossos testes, vamos usar o OpenLDAP.



Arquitetura do LDAP


O funcionamento do LDAP segue um modelo cliente-servidor, onde um ou mais servidores LDAP armazenam os dados organizados na chamada árvore de informações do diretório (DIT - Directory Information Tree). Essa árvore é uma estrutura hierárquica que representa a organização e os dados do diretório. Quando um cliente deseja acessar informações, ele se conecta a um servidor LDAP e faz uma consulta. O servidor processa a consulta e responde de acordo. A resposta pode conter os dados solicitados ou um redirecionamento para outro servidor LDAP que contenha as informações específicas, o que é especialmente útil em redes distribuídas com múltiplos servidores.


Um aspecto crucial do LDAP é a consistência e uniformidade da visão do diretório. Isso significa que, independentemente de qual servidor LDAP seja acessado, o cliente sempre verá a mesma estrutura de diretório e os mesmos dados para um dado nome ou caminho na DIT. Essa uniformidade é fundamental para um serviço de diretório global, pois garante que os usuários ou aplicativos que utilizam o LDAP possam obter informações consistentes, mesmo que a consulta seja redirecionada entre diferentes servidores.



Estrutura do serviço de diretório


A estrutura de dados do serviço de diretório foi desenvolvida para representar limites geográficos ou organizacionais. Essa estrutura é comumente organizada na forma de uma árvore hierárquica, semelhante ao DNS, onde cada nó representa uma unidade organizacional, localização, ou entidade dentro da organização.


ldap_structure


Vamos entender como funciona essa estrutura:


EntradaDescrição
cCountry - Representa o país.
stStateOrProvinceName - Representa o estado ou província.
llocalityName - Representa a cidade.
streetstreetAddress - Representa o endereço ou rua.
oorganizationName - Nome da organização.
ouorganizationUnit - Unidade organizacional, equivalente ao setor ou departamento.
cncommonName - Nome comum ou nome do usuário.

Para identificar um usuário no serviço de diretório LDAP, utilizamos o Distinguished Name (DN) ou Nome Distinto. O DN deve sempre incluir todos os ramos da árvore LDAP, ou seja, não pode faltar nenhuma parte da estrutura onde exista informação. Assim, o DN para a usuária Barbara seria:

cn=Barbara Jensen, ou=Sales, o=Acme, st=California, c=US


Outra forma de construir essa árvore é usando o Domain Component (DC), que também é conhecido como Domínio de Internet. Esse método tem sido cada vez mais utilizado porque permite o uso de DNS. Neste caso, substituímos os componentes c e o por dc (domainComponent), replicando o formato do DNS.


ldap_dc_structure


Com essa abordagem, a estrutura se torna ligeiramente diferente. Ao invés de usar país, estado, e outros elementos geográficos, começamos o mapeamento a partir do domínio. Agora, o DN ficaria assim:

uid=babs, ou=people, dc=exemple, dc=com

Além disso, podemos definir regras para que determinada ação seja permitida somente se uma condição específica for atendida. Um exemplo seria permitir a autenticação apenas para usuários que pertencem ao grupo SysAdmin. Isso é feito por meio de um atributo chamado objectClass.



O que são esses diretórios?


Os diretórios, no contexto de sistemas de diretórios como o LDAP, são bases de dados especializadas que armazenam e organizam informações de forma hierárquica. Esses diretórios são usados para gerenciar e fornecer acesso a informações sobre usuários, dispositivos, recursos de rede, e outras entidades dentro de uma organização.


Os diretórios organizam dados em uma estrutura de árvore, onde cada entrada (ou nó) pode representar uma entidade, como uma pessoa, um departamento, ou um recurso de rede. Essa estrutura hierárquica facilita a busca e a administração de grandes volumes de informações, permitindo consultas rápidas e eficientes. A função dos diretórios é armazenar diversos tipos de informações, como credenciais de autenticação, perfis de usuários, permissões de acesso, listas de contatos, e muito mais. As informações são armazenadas como atributos associados a uma entrada específica na árvore do diretório.


Os diretórios são utilizados para autenticar usuários e controlar seu acesso a recursos na rede, garantindo que apenas usuários autorizados possam acessar determinados serviços ou dados. Eles também ajudam a organizar informações sobre recursos de rede (como impressoras, servidores, etc.), facilitando a gestão e o acesso a esses recursos.



Entendendo melhor a Estrutura


A estrutura do LDAP é organizada em uma árvore hierárquica de entradas (entries), onde cada entrada representa um objeto, como um usuário ou um grupo, e é identificada por um DN (Distinguished Name). No topo dessa árvore, temos a entrada "cn=config", que é um ponto central para a configuração do servidor LDAP. Dentro de cn=config, temos diversas subestruturas que controlam diferentes aspectos do servidor LDAP, como:


  1. Schemas: Os schemas no LDAP são coleções de definições que descrevem os tipos de objetos e os atributos que podem ser armazenados no diretório. Eles definem a estrutura dos dados no LDAP, como quais atributos um usuário pode ter (ex.: nome, email, senha) e quais são obrigatórios ou opcionais. Cada esquema inclui definições de objectClasses (que definem quais atributos uma entrada pode ter) e attributeTypes (que definem os atributos em si).

  2. Modules: Os módulos são componentes que podem ser carregados no servidor LDAP para estender sua funcionalidade. Eles permitem adicionar novos recursos ou modificar o comportamento do servidor sem alterar seu código base. Um exemplo comum de módulo é o suporte a autocompletar ou autenticação específica. Esses módulos são configurados em cn=config para serem ativados ou desativados conforme necessário.

  3. Database: As bases de dados (databases) dentro do LDAP armazenam as entradas propriamente ditas. Cada base de dados pode ser configurada com diferentes parâmetros, como a localização no sistema de arquivos ou as políticas de segurança. No cn=config, a configuração de databases define como e onde as informações são armazenadas e gerenciadas pelo servidor LDAP.



Schemas


No LDAP o schema é fundamental para a organização e validação dos dados armazenados no diretório. Ele define um conjunto de regras que especificam como os dados são estruturados e manipulados dentro do diretório. Tanto os atributos quanto as classes de objetos em um servidor LDAP são definidos em arquivos de schema.


Os schemas ficam no diretório /etc/ldap/schema/.



Classe de objetos


Todas as entradas de um diretório são padronizadas, podendo uma entrada pertencer a uma ou mais classe, essas classes vão identificar quais dados podem ser armazenados naquela entrada. A Classe (de objeto) também vai especificar quais atributos são obrigatórios e quais são opcionais. A estrutura das classes dentro do LDAP segue uma hierarquia, onde a classe top está no nível mais alto, servindo como a base para todas as outras classes. A imagem abaixo exibe a relação de algumas Classes dentro do Schema chamado core.schema:


classes


Existem três tipos de classes de objetos:

  • Estruturais
    Indica os atributos que uma entrada pode possuir e não depende de outras classes de objetos para existir, permitindo que os dados sejam inseridos diretamente no Diretório LDAP.

  • Auxiliares
    São usadas para adicionar atributos adicionais a uma entrada que já possui uma classe estrutural, ou seja, não podem existir de forma independente.

  • Abstratas
    Possui especificação parcial da hierarquia de uma determinada classe, apenas subclasses estruturais e auxiliares permitem o uso desta classe.


Um exemplo de Classe de objeto é a inetOrgPerson, ela é uma classe de objeto que herda os atributos obrigatórios de organizationalPerson, amplamente utilizada para representar indivíduos em diretórios que seguem o padrão LDAPv3. A posixAccount representa uma conta de usuário em sistemas baseados em UNIX, usada para armazenar informações necessárias para login e permissões. As classes de objeto serão listadas no atributo objectClasses.



Atributos


Os atributos são elementos fundamentais que descrevem as propriedades e características das entradas (ou objetos) armazenadas no diretório. Cada entrada no LDAP é composta por uma série de atributos, que seguem um formato de pares "nome-valor". Esses atributos definem informações como nomes, endereços, números de telefone, e outras propriedades relevantes de um objeto, dependendo de sua classe de objeto.


Cada atributo é identificado por um nome único, também chamado de descritor. Esse nome serve para identificar o tipo de dado que o atributo contém. Por exemplo, cn (common name) é um nome de atributo comum que pode armazenar o nome de uma pessoa ou entidade. Um atributo pode ter um ou mais valores associados a ele. Por exemplo, o atributo mail pode ter vários endereços de e-mail associados, se permitido pelo esquema.


Os atributos são definidos por um Schema que especifica quais atributos são válidos para uma determinada classe de objeto. O schema define se um atributo é obrigatório ou opcional para uma classe específica. Por exemplo, a classe de objeto person pode ter atributos obrigatórios como sn (sobrenome) e cn (nome comum), enquanto outros atributos como telephoneNumber podem ser opcionais.


As classes de objeto podem herdar atributos de outras classes. Por exemplo, uma classe de objeto pode herdar atributos de uma classe superior na hierarquia, como a classe top, que fornece um conjunto básico de atributos comuns a todas as entradas no diretório. Cada atributo no LDAP tem uma sintaxe específica, que define o tipo de dados que o atributo pode armazenar, como cadeias de caracteres, números, ou dados binários.


Assim como as classes de objeto são definidas e listadas no atributo objectClasses, os tipos de atributos disponíveis são definidos e listados no atributo attributeTypes.



Instalando o OpenLDAP


O OpenLDAP implementa o servidor de diretórios LDAP, pode ser configurado de duas maneiras principais: usando um arquivo de configuração de texto ou utilizando um sistema de configuração dinâmica. O modo de configuração de arquivo de texto é o método tradicional, onde as configurações do OpenLDAP são feitas em um único arquivo chamado slapd.conf. Nesse arquivo, você define vários parâmetros, como os esquemas LDAP, ACLs (Access Control Lists), índices, e outras opções de servidor.


No entanto, uma limitação significativa desse modo é que qualquer alteração feita no arquivo slapd.conf só entra em vigor após a reinicialização do serviço LDAP. Isso pode ser inconveniente em ambientes de produção, pois cada reinicialização do serviço pode causar interrupções. Devido a essas limitações, o uso do slapd.conf é considerado obsoleto e não é mais recomendado para novos ambientes.


O modo de configuração dinâmica é o método mais moderno e recomendado para configurar o OpenLDAP, especialmente em ambientes de produção. Em vez de utilizar um único arquivo de configuração, todas as configurações são armazenadas em um banco de dados LDAP especial, geralmente localizado no diretório /etc/ldap/slapd.d/. Esse banco de dados, conhecido como cn=config, permite que as configurações do servidor LDAP sejam modificadas dinamicamente, ou seja, as alterações podem ser aplicadas em tempo real sem a necessidade de reiniciar o serviço.


Para exemplificar todo conteúdo abordado, vou configurar o servidor OpenLDAP para trabalhar no modo de configuração dinâmica (que é o modo recomendado de uso).


Terminal
# Antes configure corretamente o 'hosts' para criar o DN correto.
# Segue um exemplo:
$ cat /etc/hosts
127.0.1.1 ldap.testempresa.com.br

# Agora configure o hostname:
$ sudo hostnamectl set-hostname ldap.testempresa.com.br

# Agora instale o LDAP:
$ sudo apt install -y slapd ldap-utils

# slapd = Daemon do servidor LDAP, é o "ldap-server" rsrs.
# ldap-utils = São os utilitários que vão acessar uma base LDAP (cliente).

No momento da configuração é necessário fornecer uma senha de administrador. Para fins didáticos, vou usar a senha: #@%e23SJIOdsrB.


Os arquivos de configuração ficam dentro da pasta /etc/ldap/, sendo o arquivo ldap.conf o arquivo principal para a configuração do servidor.


Terminal
$ ls -lh /etc/ldap/
total 16K
-rw-r--r-- 1 root root 332 Jun 12 2020 ldap.conf
drwxr-xr-x 2 root root 4.0K Apr 8 2021 sasl2
drwxr-xr-x 2 root root 4.0K Dec 4 18:03 schema
drwxr-xr-x 3 openldap openldap 4.0K Dec 4 18:03 slapd.d


Nesse momento podemos ver quais schemas nós temos carregados no LDAP.


Terminal
$ sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=schema,cn=config dn
dn: cn=schema,cn=config

dn: cn={0}core,cn=schema,cn=config

dn: cn={1}cosine,cn=schema,cn=config

dn: cn={2}nis,cn=schema,cn=config

dn: cn={3}inetorgperson,cn=schema,cn=config


# Podemos ver a configuração atual com o comando abaixo:
$ sudo slapcat
dn: dc=testempresa,dc=com,dc=br
objectClass: top
objectClass: dcObject
objectClass: organization
o: testempresa.com.br
dc: testempresa
structuralObjectClass: organization
entryUUID: da8fd786-faa8-103e-8836-4bf19c0261db
creatorsName: cn=admin,dc=testempresa,dc=com,dc=br
createTimestamp: 20240829231915Z
entryCSN: 20240829231915.936997Z#000000#000#000000
modifiersName: cn=admin,dc=testempresa,dc=com,dc=br
modifyTimestamp: 20240829231915Z


# Podemos ver as bases de dados que temos no servidor LDAP:
$ sudo ldapsearch -H ldapi:/// -Y EXTERNAL -b "cn=config" -LLL -Q "olcDatabase=*" dn
dn: olcDatabase={-1}frontend,cn=config

dn: olcDatabase={0}config,cn=config

dn: olcDatabase={1}mdb,cn=config


Arquivos LDIF


O LDAP possibilita a manipulação de dados tanto em modo batch quanto em modo online. No modo batch, utilizamos arquivos no formato LDIF (LDAP Data Interchange Format) para realizar operações como inserções, atualizações ou exclusões em massa. Esses arquivos seguem um formato específico que o servidor LDAP pode processar.


Ao inserir informações no diretório LDAP, como usuários, grupos e domínios, é essencial definir quais atributos farão parte de cada entrada. Isso é feito através do uso de objectClasses. Cada objectClass define um conjunto de atributos que podem ou devem estar presentes em uma entrada. Abaixo, estão alguns exemplos de tipos de objectClass comuns:


Tipo de ObjectClassDescrição
topA objectClass raiz que é herdada por todas as outras. Não define atributos.
organizationUsado para definir uma organização, como uma empresa. Atributos comuns incluem o (nome da organização) e description.
countryUsado para representar um país no diretório. Atributos comuns incluem c (código do país de duas letras) e description.
organizationalUnitUsado para definir uma Unidade Organizacional (OU) dentro de uma organização. Atributos comuns incluem ou (nome da unidade) e description.
personUsado para definir uma pessoa física. Atributos comuns incluem cn (nome comum), sn (sobrenome), e telephoneNumber.
organizationalPersonExtensão de person, adiciona atributos relacionados à organização, como title (cargo) e ou (Unidade Organizacional).
groupOfNamesUsado para definir um grupo de objetos LDAP, normalmente pessoas. O atributo principal é member, que contém uma lista de DNs dos membros do grupo.

Como exemplo, vamos criar nosso LDIF informando os dados do nosso domínio (testempresa.com.br), esse arquivo pode ser criado em qualquer lugar (por organização, você pode sempre deixar esses arquivos dentro de /etc/ldap/schema/), depois de criarmos, vamos carregar ele na base do LDAP. Agora vamos criar uma OU (organizationalUnit) chamada accounts para criarmos as contas dos usuários.


Terminal
# Crie o arquivo 'accounts.ldif':
$ cat << 'EOF' > accounts.ldif
dn: ou=accounts,dc=testempresa,dc=com,dc=br
objectClass: top
objectClass: organizationalUnit
ou: accounts
description: Criar os usuarios
EOF

# Carregando informações na Base do LDAP:
$ sudo ldapadd -x -D "cn=admin,dc=testempresa,dc=com,dc=br" -W -f accounts.ldif
Enter LDAP Password:
adding new entry "ou=accounts,dc=testempresa,dc=com,dc=br"

# -x = Faz uma autenticação simples;
# -D = Usuário que fará a operação;
# -W = Solicita senha para executar o comando;
# -f = Informa o nome do arquivo que será processado.


Agora vamos fazer um teste, o comando abaixo vai procurar em toda a nossa base qualquer objectClass que possa existir.


Terminal
$ sudo ldapsearch -x -b 'dc=testempresa,dc=com,dc=br' '(objectclass=*)'
# extended LDIF
#
# LDAPv3
# base <dc=testempresa,dc=com,dc=br> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# testempresa.com.br
dn: dc=testempresa,dc=com,dc=br
objectClass: top
objectClass: dcObject
objectClass: organization
o: testempresa.com.br
dc: testempresa

# accounts, testempresa.com.br
dn: ou=accounts,dc=testempresa,dc=com,dc=br
objectClass: top
objectClass: organizationalUnit
ou: accounts
description: Criar os usuarios

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2


Agora vamos criar a unidade organizacional onde ficarão os grupos:


Terminal
# Crie o arquivo 'groups.ldif':
$ cat << 'EOF' > groups.ldif
dn: ou=groups,dc=testempresa,dc=com,dc=br
objectClass: top
objectClass: organizationalUnit
ou: groups
EOF

# Carregando informações na Base do LDAP:
$ ldapadd -x -D "cn=Manager,dc=testempresa,dc=com,dc=br" -W -f groups.ldif
Enter LDAP Password:
adding new entry "ou=groups,dc=testempresa,dc=com,dc=br"


##
## Agora podemos listar todas as entradas que foram bem sucedidas:
##
$ sudo ldapsearch -x -b 'dc=testempresa,dc=com,dc=br' '(objectclass=*)'

# testempresa.com.br
dn: dc=testempresa,dc=com,dc=br
objectClass: top
objectClass: dcObject
objectClass: organization
o: testempresa.com.br
dc: testempresa

# accounts, testempresa.com.br
dn: ou=accounts,dc=testempresa,dc=com,dc=br
objectClass: top
objectClass: organizationalUnit
ou: accounts
description: Criar os usuarios

# groups, testempresa.com.br
dn: ou=groups,dc=testempresa,dc=com,dc=br
objectClass: top
objectClass: organizationalUnit
ou: groups

Agora temos criado o nosso Topo da Árvore de Diretório e abaixo dele temos as Unidades Organizacionais, sendo duas unidades, a Usuários e a Grupos.

Ao definir essas 3 objectClass, nós separamos onde cada registro vai se encontrar, por exemplo, registros de usuários ficaram na ou=usuarios e registros de grupos ficaram na ou=grupos. As definições de cada ObjectClass e de cada atributo estão dentro de arquivos Schemas, sua função é manter a estrutura de diretório e definir a padronização dos mesmos.


O próximo passo é criar as entradas de usuários, como estamos começando a nos acostumar com tudo isso, vamos criar entradas simples como: nome e sobrenome, esses dados poderão ser visualizados por outros aplicativos, e todo usuário ficará sob a unidade organizacional Usuários.


Vamos usar o arquivo deste link.

# Obtendo o arquivo 'usuarios.ldif':
$ wget -O usuarios.ldif https://gitlab.com/sysnetbr/codes/-/raw/main/ldap/usuarios.ldif

# Adicione a entrada de usuario:
$ ldapadd -x -D "cn=Manager,dc=testempresa,dc=com,dc=br" -W -f usuarios.ldif
Enter LDAP Password:
adding new entry "cn=Joao,ou=usuarios,dc=testempresa,dc=com,dc=br"

Se você analisar o conteúdo de usuarios.ldif verá que usamos o objectClass do tipo person, essa é uma classe estrutural (ela define atributos essenciais para que um registro possa ser criado), além de definir informações simples de usuários. Veja parte da definição dessa classe:

objectclass ( 2.5.6.6 NAME 'person'
DESC 'RFC2256: a person'
SUP top STRUCTURAL
MUST ( sn $ cn )
MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )

Podemos ver que além dos dados inseridos, poderíamos inserir senha, número de telefone, descrição e um "veja mais".


Agora crie outro arquivo chamado usuarios2.ldif contendo o conteúdo do deste link, e faça a inserção na base, assim vamos ter mais usuários para trabalhar, veja abaixo o procedimento para facilitar.

# Obtendo o arquivo 'usuarios2.ldif':
$ wget -O usuarios2.ldif https://gitlab.com/sysnetbr/codes/-/raw/main/ldap/usuarios2.ldif

# Adicione a entrada de usuario:
$ ldapadd -x -D "cn=Manager,dc=testempresa,dc=com,dc=br" -W -f usuarios2.ldif


Pesquisando na Base


Com mais registros dentro da base vamos ver como realizar algumas pesquisas dentro da base de dados do LDAP.

# Exibindo todas as entradas que possuem o atributo 'sn' igual a 'silva':
$ ldapsearch -x -LLL '(sn=silva)'
dn: cn=Rodrigo,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Rodrigo
sn: Silva
objectClass: person

Também podemos usar caracteres curingas do Shell para fazer uma busca, vamos listar todos os usuários que tenham o sobrenome terminando com os:

$ ldapsearch -x -LLL '(sn=*os)'
dn: cn=Leticia,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Leticia
sn: Pinheiros
objectClass: person

dn: cn=Danilo,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Danilo
sn: Santos
objectClass: person

Também podemos usar mais de um filtro, para isso vamos usar a sintaxe ((expression1)(expression2)), vejamos alguns exemplos:

# Listando sobrenomes com 'silva' ou 'dias' (mostrará todas as ocorrencias, 
# graças ao caractere '|'):

$ ldapsearch -x -LLL '(|(sn=silva)(sn=dias))'
dn: cn=Joao,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Joao
sn: Dias
objectClass: person

dn: cn=Rodrigo,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Rodrigo
sn: Silva
objectClass: person

Podemos adicionar a opção -LLL para suprimir mensagens do comando ldapsearch como as informações abaixo:

# extended LDIF
#
# LDAPv3
# base <dc=testempresa,dc=com,dc=br> (default) with scope subtree
# filter: (|(sn=silva)(sn=*os))
# requesting: ALL
#


# search result
search: 2
result: 0 Success

# numResponses: 4
# numEntries: 3

Faça um teste e veja a diferença:

##
## Suprimindo informações do LDAP:
##
$ ldapsearch -x -LLL '(|(sn=silva)(sn=*os))'
dn: cn=Rodrigo,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Rodrigo
sn: Silva
objectClass: person

dn: cn=Leticia,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Leticia
sn: Pinheiros
objectClass: person

dn: cn=Danilo,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Danilo
sn: Santos
objectClass: person

##
## Deixando as mensagens do LDAP:
##
$ ldapsearch -x '(|(sn=silva)(sn=*os))'
# extended LDIF
#
# LDAPv3
# base <dc=testempresa,dc=com,dc=br> (default) with scope subtree
# filter: (|(sn=silva)(sn=*os))
# requesting: ALL
#

# Rodrigo, usuarios, testempresa.com.br
dn: cn=Rodrigo,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Rodrigo
sn: Silva
objectClass: person

# Leticia, usuarios, testempresa.com.br
dn: cn=Leticia,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Leticia
sn: Pinheiros
objectClass: person

# Danilo, usuarios, testempresa.com.br
dn: cn=Danilo,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Danilo
sn: Santos
objectClass: person

# search result
search: 2
result: 0 Success

# numResponses: 4
# numEntries: 3

Podemos também especificar o que queremos que seja exibido, como no exemplo abaixo, vamos apenas exibir o cn e o sn, observe que o atributo dn sempre vai ser exibido:

$ ldapsearch -x -LLL '(|(sn=silva)(sn=*os))' cn sn
dn: cn=Rodrigo,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Rodrigo
sn: Silva

dn: cn=Leticia,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Leticia
sn: Pinheiros

dn: cn=Danilo,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Danilo
sn: Santos


Modificando informações


Qualquer mudança pode ser realizada usando a ferramenta ldapmodify, para isso, deve-se existir um arquivo no formato ldif com a mudança que deva ser realizada. O primeiro usuário criado foi o joao, vamos adicionar um atributo a ele, o conteúdo que vamos usar está neste link, mais abaixo tem o procedimento para fazer download do arquivo.

# Obtendo o arquivo 'modificacao.ldif':
$ wget -O modificacao.ldif https://gitlab.com/sysnetbr/codes/-/raw/main/ldap/modificacao.ldif

# Antes de mudarmos, veja como está 'joao' na base:
$ ldapsearch -x -LLL '(cn=Joao)'
dn: cn=Joao,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Joao
sn: Dias
objectClass: person

# Agora faça a alteração:
$ ldapmodify -x -D "cn=Manager,dc=testempresa,dc=com,dc=br" -W -f modificacao.ldif
Enter LDAP Password:
modifying entry "cn=Joao,ou=usuarios,dc=testempresa,dc=com,dc=br"

# Depois de mudarmos, veja como está 'joao' na base:
$ ldapsearch -x -LLL '(cn=Joao)'
dn: cn=Joao,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Joao
sn: Dias
objectClass: person
description: Acrescentando informacao

Esse arquivo ldif é bem similar aos que estamos usando, porém, traz algumas mudanças, vamos ver algumas delas:

OpçãoDescrição
changetypeIndica o tipo de ação a ser realizada, neste caso é modificar um registro existente, veja as opções possíveis para alteração de registro.
Opções do CHANGETYPEDescrição
addAdiciona um atributo, caso o atributo já exista, será acrescentado mais de um valor ao atributo.
deleteRemove o valor do atributo, caso o valor seja único, o atributo será removido.
replaceSubstitui o valor do atributo pelo novo valor.

Caso você queira fazer mais de uma modificação simultânea, se atente ao formato do arquivo, veja aqui.

Basicamente, você deve ter uma linha em branco entre cada usuário que for alterar, e para cada adição (add), delete ou replace, você deve usar uma linha apenas com o caractere -, como no link acima.



Deletando um usuário


Para deletar um usuário podemos fazer isso direto da linha de comando, veja abaixo:

# Deletando o usuário Felipe:
$ sudo ldapdelete -x -D "cn=Manager,dc=testempresa,dc=com,dc=br" -W -v "cn=Felipe,ou=usuarios,dc=testempresa,dc=com,dc=br"


ACL - Access Control List


O acesso a base do LDAP deve ser controlado ou pelo menos deve ter diferentes níveis de acesso. Para isso nós usamos ACL, ela nos permite alguns níveis de acesso, veja abaixo:

Nível de acessoTipo de permissão
writePermite gravar/atualizar dados nos atributos.
readPermite ler o resultado de pesquisas.
searchPermite aplicar filtros de pesquisas.
comparePermite comparar atributos.
authPermite autenticação.
noneAcesso negado.

Para aplicar o controle de acesso, fazemos isso diretamente no arquivo de configuração, em /etc/ldap/ldap.conf adicione as opções abaixo ao final do arquivo.

# controle de acesso - ACL
access to attrs=userPassword
by anonymous auth
by self write
by * none

access to *
by * read

Após isso, reinicie o serviço do slapd:

$ sudo systemctl restart slapd

Veja uma consulta antes de adicionarmos a ACL:

$ ldapsearch -x -b "dc=testempresa,dc=com,dc=br" -LLL cn=Joao
dn: cn=Joao,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Joao
sn: Dias
objectClass: person
description: Acrescentando informacao
telephoneNumber: 8376-2837
userPassword:: e1NTSEF9TVpyWElFa1Q0SmUwVnhSdmdRRU5Ka2tOZWh0QytHcWY=

Agora veja depois de adicionarmos a ACL:

$ ldapsearch -x -b "dc=testempresa,dc=com,dc=br" -LLL cn=Joao
dn: cn=Joao,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Joao
sn: Dias
objectClass: person
description: Acrescentando informacao
telephoneNumber: 8376-2837

Para ter acesso aos dados, você deve autenticar:

$ ldapsearch -x -LLL -D "cn=Joao,ou=usuarios,dc=testempresa,dc=com,dc=br" -W cn=Joao
Enter LDAP Password:
dn: cn=Joao,ou=usuarios,dc=testempresa,dc=com,dc=br
cn: Joao
sn: Dias
objectClass: person
description: Acrescentando informacao
telephoneNumber: 8376-2837
userPassword:: e1NTSEF9TVpyWElFa1Q0SmUwVnhSdmdRRU5Ka2tOZWh0QytHcWY=

Esse tipo de ACL é uma das mais básicas e não oferece a proteção necessária, vamos ver como aplicar um nível de proteção mais detalhado, para isso vamos usar DN para especificar o controle de acesso ou por filtros.

DNDescrição
dn.basePermite acesso apenas ao item específicado.
dn.onePermite acesso a um nível abaixo do específicado.
dn.subtreePermite acesso ao item específicado e toda a estrutura abaixo dele.
dn.childrenPermite acesso a estrutura abaixo do item específicado.


Backup do LDAP


Colocamos nossa base do LDAP para ser armazenada em /var/lib/ldap, aqui temos aquivo da base e arquivos de log que armazenam inclusões, exclusões e alterações de atributos. Podemos copiar todo esse diretório para fazer backup da nossa base do LDAP.


Outro tipo de backup é através do dump, e nesse caso vamos usar apenas um txt para recuperar tudo. É sempre uma das melhores escolhas fazer o backup usando os dois métodos.


Para realizar o Backup usamos o comando ldapsearch e como existe um limite de linhas retornado por ele, adicione as duas linhas abaixo em /etc/ldap/ldap.conf:

SIZELIMIT 0
sizelimit unlimited

# Agora reinicie o serviço:
$ sudo systemctl restart slapd

Segue abaixo o comando que vamos usar para fazer o dump da base de dados (no comando abaixo o base de dados já está especificada no arquivo de configuração, caso precise, adicione a opção -b para adicionar a base de dados):

$ ldapsearch -x -LLL -D "cn=Manager,dc=testempresa,dc=com,dc=br" -w tux > backup.ldif


Usando PAM com LDAP