Whitepaper Técnico — Versão 0.1.0 — Maio de 2026
Autor: Heitor Faria · Website: https://podheitor.com · E-mail: heitor@opentechs.lat · Telefone / WhatsApp: +1 786 726-1749 | +55 61 98268-4220
Oferta especial. Traga sua proposta de renovação de qualquer plataforma comercial de backup empresarial — Veeam, Commvault, NetBackup ou outras. Realizaremos uma análise comparativa com proposta formal visando pelo menos 50% de economia com funcionalidades AD/LDAP superiores. Entre em contato pelo heitor@opentechs.lat para obter uma cotação por escrito.
Sumário
- Resumo executivo
- Introdução e contexto de mercado
- Visão geral da arquitetura
- Modos de backup em detalhes
- Modos de restauração em detalhes
- Matriz de funcionalidades
- Guia de instalação
- Referência de configuração
- Exemplos de FileSet
- Dimensionamento e planejamento de capacidade
- Metas de desempenho
- Matriz de compatibilidade
- Segurança
- Monitoramento
- Guia de resolução de problemas
- Casos de uso e cenários de implantação
- Comparação com outras abordagens
- Roadmap
- Informações de contato
- Legal / direitos autorais
1. Resumo executivo
A infraestrutura de identidade — Microsoft Active Directory, OpenLDAP, 389-DS e Samba AD DC — é o componente mais crítico de qualquer ambiente de TI empresarial. Cada conta de usuário, cada associação de grupo, cada Group Policy Object (GPO), cada lista de controle de acesso e cada principal Kerberos reside no diretório. Quando dados de identidade são perdidos ou corrompidos, toda a organização para: logins falham, aplicações não conseguem autenticar e o acesso privilegiado a outros sistemas protegidos por backup se torna impossível.
Apesar dessa criticidade, a maioria das organizações não possui um backup dedicado para seus serviços de diretório. As abordagens comuns variam de exportações periódicas de ldif via scripts ldapsearch até a dependência do backup de estado do sistema Windows — nenhuma das quais se integra de forma limpa com uma plataforma de backup open-source, nenhuma oferece capacidade incremental real e nenhuma cobre a superfície completa de dados de identidade, incluindo SYSVOL, GPO, schema e ACLs.
O PodHeitor Active Directory / LDAP Backup Plugin for Bacula preenche essa lacuna. É um cdylib metaplugin puro em Rust carregado diretamente pelo bacula-fd, fornecendo backup e restauração sem agente, apenas via rede, dos serviços de diretório: Microsoft Active Directory (Windows Server 2012 R2 até 2025 e Samba AD DC), OpenLDAP 2.4/2.5/2.6, 389 Directory Server / Red Hat DS / FreeIPA e qualquer servidor compatível com LDAPv3 no modo genérico.
O plugin oferece cinco modos de backup cobrindo todos os cenários operacionais — desde snapshots lógicos equivalentes a ldif (modo ldap) até streaming incremental AD DirSync (modo ad), proteção contínua de dados (cdp), replicação ao vivo entre diretórios (replicate) e backup integrado de SYSVOL/GPO (hybrid_sysvol). Seis modos de restauração oferecem precisão desde a correção de um único atributo até a recuperação autoritativa completa de floresta. Tudo é gerenciado por meio da configuração padrão de Job e FileSet do Bacula, sem daemons auxiliares, sem scripts shell e sem arquivos de estado externos.
O plugin é construído com hardening de Unicode brasileiro embutido desde o início — um requisito prático para o mercado latino-americano, onde entradas de diretório frequentemente contêm cedilha, til e outros caracteres acentuados que quebram implementações menos robustas. 734 testes unitários, 45 testes de integração com LDAP ao vivo contra 389-DS e Samba AD, e um conjunto de testes de failover destrutivo durante varredura confirmam confiabilidade de nível produtivo.
2. Introdução e contexto de mercado
2.1 Por que o backup de diretório é uniquamente crítico
Ao contrário de um banco de dados ou sistema de arquivos, um serviço de diretório não é autossuficiente. Ele é a espinha dorsal de autenticação e autorização de todos os outros sistemas no ambiente. Uma falha de diretório se propaga imediatamente: o e-mail para de ser entregue, conexões VPN falham, o single sign-on na nuvem quebra, sistemas ERP recusam logins e o operador não consegue autenticar no próprio sistema de backup. A recuperação de uma perda de diretório sem backup adequado é medida em dias, não horas — e pode exigir reconstruir toda a infraestrutura de identidade do zero.
Os dados de diretório possuem diversas propriedades que tornam o backup genérico em nível de arquivo insuficiente:
- Dependência de schema. Entradas LDAP referenciam classes de objeto e tipos de atributo do schema que precisam ser restaurados na ordem correta. Uma cópia bruta de arquivo NTDS.dit não captura o schema de forma independente.
- Fidelidade de ACL e descritor de segurança. Cada objeto do AD carrega um descritor de segurança NT. Estes não são atributos simples e exigem tratamento especial durante a restauração.
- Coerência entre GPO e SYSVOL. Os Group Policy Objects abrangem tanto o diretório LDAP (objetos
groupPolicyContainer) quanto o compartilhamento de arquivo SYSVOL. Um backup que captura apenas o lado LDAP produz um conjunto de GPO inconsistente na restauração. - Estado da topologia de replicação. Em um ambiente multi-DC, a restauração deve considerar vetores USN e metadados de replicação para evitar ressurreição de tombstones e cenários de USN rollback.
- Capacidade incremental. Diretórios grandes (100 mil+ objetos) não podem ser totalmente copiados na janela de backup disponível. Capacidade incremental real — via RFC 4533 syncrepl para OpenLDAP/389-DS ou Microsoft DirSync para AD — é essencial.
2.2 Por que as abordagens existentes são insuficientes
| Abordagem | Cobertura | Veredicto |
|---|---|---|
| ldapsearch / scripts de exportação ldif | Apenas dados lógicos; sem schema, sem ACLs, sem SYSVOL | Não é adequado para produção; sem integração com Bacula; sem incremental |
| Backup de estado do sistema Windows | NTDS.dit completo; apenas Windows; requer agente Windows no DC | Viola requisito sem agente; sem suporte a OpenLDAP/389-DS |
| AD Recycle Bin | Apenas recuperação de objetos em nível de objeto; retenção de 60–180 dias | Não é um backup; sem restauração a um ponto no tempo |
| Veeam | Sem agente nativo AD/LDAP em nível de protocolo de diretório | Apenas backup em nível de VM; sem restauração de objetos sem add-on |
| Commvault Active Directory iDataAgent | Apenas Windows AD; requer agente em cada DC | Sem OpenLDAP/389-DS; custo de licença elevado |
| Bacula Community (nativo, sem plugin) | Apenas nível de arquivo — faz backup dos arquivos brutos NTDS.dit ou MDB do OpenLDAP | Inseguro com o diretório em operação; sem restauração lógica |
| NetBackup BMR | Recuperação bare-metal; sem consciência de diretório | Apenas restauração completa do servidor; sem precisão de objeto ou atributo |
2.3 A abordagem PodHeitor
O plugin realiza backup apenas via rede, sem agente: conecta-se ao diretório via LDAP/LDAPS a partir do host do Bacula File Daemon, sem nenhum agente instalado no servidor de diretório. Isso é arquiteturalmente análogo a como um plugin de backup de banco de dados se conecta ao banco via seu protocolo nativo. O servidor de diretório é uma caixa preta; o plugin fala LDAPv3, RFC 4533 (syncrepl) e a extensão LDAP Microsoft DirSync — os mesmos protocolos de rede que o diretório expõe a qualquer parceiro de replicação.
Essa abordagem funciona igualmente bem para Windows Server AD (sem agente no DC), Samba AD DC, OpenLDAP e 389-DS. Um único plugin cobre todo o cenário de diretórios a partir de um único host Bacula File Daemon.
3. Visão geral da arquitetura
3.1 Metaplugin cdylib puro em Rust
Ao contrário de plugins PodHeitor anteriores que usam um pequeno shim em C/C++ para carregar um sidecar Rust, o plugin AD/LDAP é um cdylib puro em Rust (ADR-001). O único objeto compartilhado podheitor-adldap-fd.so é carregado diretamente pelo bacula-fd em tempo de execução e expõe a ABI do plugin Bacula File Daemon (loadPlugin / unloadPlugin e a tabela de callbacks de eventos) compilada nativamente em Rust. Não há fork, não há bpipe, não há processo sidecar.
| Componente | Arquivo | Função |
|---|---|---|
| Plugin Bacula FD (cdylib) | /opt/bacula/plugins/podheitor-adldap-fd.so |
Carregado pelo bacula-fd; implementa a ABI do plugin Bacula e o canal PTCOMM em processo |
| Engine principal (vinculado estaticamente) | Dentro de podheitor-adldap-fd.so |
Toda a lógica LDAP, engines de backup/restauração, criptografia, métricas — sem binário externo |
Vantagens do design cdylib puro:
- Artefato único. Um arquivo para instalar, um arquivo para atualizar.
- Cópia zero para grandes blobs ldif. O PTCOMM Path-A usa um canal MPSC em processo — dados de entrada LDAP nunca cruzam uma fronteira de processo.
- Análise de rede com segurança de memória. O protocolo de rede LDAP é analisado inteiramente em Rust seguro; sem possibilidade de buffer overflows em C no caminho de entrada LDAP.
- Isolamento de pânicos. Toda fronteira C-ABI é envolvida em
catch_unwind; um pânico na lógica de backup propaga um erro de job para o Bacula em vez de travar obacula-fd.
3.2 PTCOMM Path-A (em processo)
PTCOMM é o protocolo de enquadramento binário PodHeitor usado em todos os plugins PodHeitor para logging uniforme, multiplexação de métricas e sinalização do ciclo de vida do job. No plugin AD/LDAP, o Path-A é utilizado: frames fluem por um canal MPSC entre o shim ABI do Bacula e o engine de backup/restauração no mesmo espaço de endereço do processo.
PTCOMM status characters:
P = ping/handshake O = ok/ack J = jobinfo
C = config/params S = start D = data
E = end R = restoreobject M = metric
L = log T = terminal X = error
O ciclo de vida PTCOMM por job:
1. Handshake: fd → plugin "P000010nADLDAP_v1"
plugin → fd "O000003nACK"
2. JobInfo: fd → plugin "J<len>n<msgpack(JobInfo)>"
3. Params: fd → plugin "C<len>n<msgpack(BackupParams|RestoreParams)>"
plugin → fd "O000002nOK"
4. Start: fd → plugin "S000005nSTART"
5. Data: plugin → fd "D<len>n<chunk>" (repeats)
plugin → fd "M<len>n<msgpack(metric)>"
plugin → fd "L<len>n<json log>"
6. End: plugin → fd "E000003nEND"
7. RestoreObj: plugin → fd "R<len>n<msgpack(RestoreObject)>"
8. Status: plugin → fd "T<len>n<msgpack(JobStatus)>"
3.3 Diagrama de arquitetura
┌──────────────────────────────────────────────────────────────────────┐
│ Bacula File Daemon (bacula-fd) — Linux x86_64 │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ podheitor-adldap-fd.so (pure-Rust cdylib) │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
│ │ │ ABI shim (plugin-adldap crate) │ │ │
│ │ │ loadPlugin / unloadPlugin / handlePluginEvent │ │ │
│ │ │ catch_unwind at every C boundary │ │ │
│ │ └───────────────────────┬──────────────────────────────────┘ │ │
│ │ │ PTCOMM Path-A (in-process MPSC) │ │
│ │ ┌───────────────────────▼──────────────────────────────────┐ │ │
│ │ │ adldap-core engine │ │ │
│ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │ │ │
│ │ │ │ ldap mode│ │ ad mode │ │ cdp mode │ │hybrid_sysvol│ │ │ │
│ │ │ │(syncrepl)│ │(DirSync) │ │(CDP/CDP- │ │(LDAP+SYSVOL)│ │ │ │
│ │ │ │ │ │ │ │ DirSync) │ │ │ │ │ │
│ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬──────┘ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ ┌────▼─────────────▼─────────────▼──────────────▼─────┐ │ │ │
│ │ │ │ ldap3 crate (async LDAPv3 client) │ │ │ │
│ │ │ │ RFC 4533 syncrepl · MS DirSync · RFC 2696 paged │ │ │ │
│ │ │ │ GSSAPI/Kerberos · StartTLS · LDAPS │ │ │ │
│ │ │ └─────────────────────────────────────────────────────┘ │ │ │
│ │ │ │ │ │
│ │ │ ┌───────────┐ ┌──────────┐ ┌──────────┐ │ │ │
│ │ │ │ Restore │ │ Crypto │ │ Metrics │ │ │ │
│ │ │ │ engine │ │AES-256- │ │Prometheus│ │ │ │
│ │ │ │ 6 modes │ │GCM/CCP20 │ │textfile │ │ │ │
│ │ │ └───────────┘ └──────────┘ └──────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘
│ │
│ LDAP/LDAPS │ SMB/CIFS (hybrid_sysvol only)
▼ ▼
┌───────────────┐ ┌──────────────────────┐
│ AD / OpenLDAP │ │ SYSVOL share │
│ 389-DS / Samba│ │ dcSYSVOLdomain │
│ (any LDAPv3) │ │ Policies + scripts │
└───────────────┘ └──────────────────────┘
│
│ Bacula protocol (TCP)
▼
┌───────────────────┐
│ Bacula Storage │
│ Daemon + Catalog │
└───────────────────┘
3.4 Formato em disco: híbrido MessagePack-LDIF
Cada entrada LDAP é armazenada como um arquivo de dois segmentos sob o caminho virtual @adldap/<server>/<basedn>/entries/<objectGUID-or-uuid>.ent:
Section 1: 4-byte magic 'PHAE' + msgpack(EntryHeader)
Section 2: msgpack(Vec<Attribute>)
binary attrs (jpegPhoto, userCertificate, msExchMailbox*)
are blob-tagged for round-trip safety
Esse formato é aproximadamente 3–4x mais compacto que ldif bruto para payloads AD (MessagePack vs base64), é seguro para Unicode e suporta ordenação determinística para operações de diff. Uma visão ldif secundária é gerada sob demanda para os modos dry_run e diff.
3.5 Portador de estado RestoreObject
Ao final do backup, o plugin emite um RestoreObject chamado adldap-state.msgpack no catálogo do Bacula. Este carrega o cookie syncrepl (RFC 4533) ou cookie DirSync (AD), o maior USN/CSN visto, um hash SHA-256 do schema e o manifesto completo de entradas. O próximo job incremental resgata o cookie automaticamente do catálogo — nenhum arquivo de estado em disco é necessário, portanto o plugin sobrevive à perda e reinstalação do host sem perder a linha de base incremental.
4. Modos de backup em detalhes
4.1 Modo ldap — RFC 4533 syncrepl (OpenLDAP / 389-DS)
Como funciona
O modo ldap conecta-se a qualquer servidor LDAPv3 e realiza uma busca paginada (RFC 2696) para backups Full, e RFC 4533 syncrepl (refreshOnly ou refreshAndPersist) para backups Incrementais e Diferenciais. Cada entrada é serializada no formato MessagePack-LDIF e transmitida como um arquivo virtual do Bacula.
O cookie syncrepl é carregado no RestoreObject após cada job. O próximo job Incremental apresenta o cookie ao servidor e recebe apenas as entradas alteradas desde aquele ponto — incluindo modificações, adições e exclusões (o servidor marca exclusões com syncState=delete).
Full backup: paged search → emit all entries → save cookie in RestoreObject
Incremental: syncrepl refreshOnly (cookie) → emit changed/deleted entries
CDP: syncrepl refreshAndPersist → stream changes in real-time
Compatibilidade com Samba AD
A implementação syncrepl do Samba AD omite o controle SyncStateValue por entrada do RFC 4533 que o 389-DS inclui. O plugin detecta isso em tempo de análise e sintetiza a identidade da entrada a partir de objectGUID (preferido) ou entryUUID (fallback), roteando a entrada como state=add. Isso é semanticamente correto para a entrega refresh-only de snapshot completo do Samba. As respostas do 389-DS permanecem no caminho estrito.
Quando usar
- OpenLDAP 2.4/2.5/2.6 — alvo primário suportado
- 389 Directory Server / Red Hat DS / núcleo de diretório FreeIPA
- Samba AD DC no modo syncrepl
- Qualquer servidor LDAPv3 sem suporte a Microsoft DirSync
- Ambientes onde um backup lógico e portável equivalente a ldif é necessário
4.2 Modo ad — Microsoft DirSync
Como funciona
O modo ad usa o controle estendido LDAP Microsoft DirSync (OID 1.2.840.113556.1.4.841) para transmitir alterações de diretório do Active Directory. O DirSync é o mesmo mecanismo usado pelos parceiros de replicação do AD e é o único método suportado pela Microsoft para enumeração incremental de diretório. Ele captura todas as alterações de objetos incluindo modificações de descritor de segurança, objetos tombstoned (entradas excluídas) e atributos operacionais.
Para backups Full, o plugin emite uma solicitação DirSync sem cookie anterior, fazendo com que o AD retorne toda a árvore de diretório. Para backups Incrementais, o cookie anterior (armazenado no RestoreObject) é apresentado e o AD retorna apenas as alterações desde aquela marca d’água.
Os cookies DirSync codificam intervalos USN (Update Sequence Number). Como a replicação DRS garante que cada DC na floresta armazene as mesmas alterações com vetores de marca d’água consistentes, um cookie emitido pelo DC1 pode ser transferido com segurança para o DC2 durante o failover — o plugin lida com isso de forma transparente (veja a Seção 4.5).
Permissões AD necessárias
O usuário de bind deve ter:
SeSyncAgentPrivilege(“Replicando Alterações de Diretório”) — obrigatório para DirSync.- Replicating Directory Changes All — necessário para acesso a tombstone e Recycle Bin.
- Replicating Directory Changes In Filtered Set — para ambientes RODC.
- Acesso de leitura a
<dc>SYSVOL<domain>Policies— necessário apenas para o modohybrid_sysvol.
Uma conta com privilégio mínimo “Operador de Backup – PodHeitor” pode ser delegada via dsacls.exe — o guia do operador fornece a receita exata.
Quando usar
- Microsoft Active Directory (Windows Server 2012 R2 até 2025)
- Samba AD DC no modo DirSync (raiz do domínio
basedn=obrigatória — veja nota do operador) - Qualquer cenário que exija acesso a tombstone e integração com AD Recycle Bin
- Ambientes multi-DC onde a portabilidade do cookie USN é necessária
4.3 Modo hybrid_sysvol — LDAP DirSync + SYSVOL/GPO
Como funciona
O modo hybrid_sysvol realiza uma varredura LDAP DirSync completa do diretório (idêntica ao modo ad) e simultaneamente anexa um snapshot do compartilhamento SYSVOL em nível SMB-CIFS usando libsmbclient-rs (bindings Rust para libsmbclient.so). Os arquivos SYSVOL são armazenados em @adldap/<server>/sysvol/... com preservação completa de NT ACL via descritores de segurança NT codificados em msgpack.
As fases LDAP e SYSVOL são executadas como um par de única passagem dentro de um job. O failover LDAP mid-stream para um DC diferente é intencionalmente recusado: se a fase LDAP rotacionar para o DC2 enquanto a fase SYSVOL ainda aponta para o sysvol_uri= do DC1, o backup resultante conterá objetos de diretório do DC2 e arquivos GPO do DC1, que podem estar em estados de replicação diferentes. O plugin recusa esse cenário de split-brain e falha com Fatal, exigindo que a próxima execução agendada comece do zero.
Quando usar
- Qualquer ambiente Active Directory onde a capacidade de restauração de GPO é necessária
- Cenários de conformidade que exigem estado de identidade completo incluindo scripts de login, pacotes de instalação de software e modelos de segurança em
Policies - Planejamento de DR onde um snapshot consistente LDAP+SYSVOL é o ponto de restauração autoritativo
4.4 Modo replicate — replicação ao vivo entre diretórios
Como funciona
O modo replicate abre uma sessão syncrepl (ou DirSync) contra o diretório de origem e simultaneamente abre uma sessão de escrita LDAP contra um diretório de destino configurado por replicate_target_uri=. Cada alteração observada na origem é aplicada ao destino imediatamente. O stream de backup do Bacula ainda recebe uma cópia para auditabilidade de catálogo e restauração a um ponto no tempo.
A replicação entre fornecedores (AD → OpenLDAP ou vice-versa) é suportada via um arquivo de mapeamento de schema configurável (default-schema-mapping.toml). O mapeamento padrão traduz sAMAccountName → uid, userPrincipalName → mail e objectGUID → entryUUID (UUIDv4 determinístico). A detecção de loop é tratada via objectGUID (AD) ou entryUUID (RFC 4530) para evitar tempestades de replicação em topologias bidirecionais.
Quando usar
- Espelho de identidade em modo cold-standby em um datacenter de DR, sem necessidade de AD Trust ou replicação multi-master
- Projetos de migração de identidade entre fornecedores (transição AD → OpenLDAP)
- Cópia de auditoria em tempo real de um diretório de produção para um servidor LDAP somente leitura
4.5 Modo cdp — proteção contínua de dados
Como funciona
O modo cdp usa syncrepl refreshAndPersist para manter uma conexão persistente com o servidor de diretório e transmitir alterações em tempo real. O job do Bacula permanece aberto e emite chunks de backup a cada cdp_max_seconds (padrão 60 segundos), limitando o RPO a esse intervalo. O sub-modo cdp_dirsync fornece a mesma semântica para o Active Directory usando o modelo de polling persistente DirSync.
Quando ocorre uma falha de transporte, o plugin esgota a lista de URI de failover (avançando em erros TCP, falhas TLS e condições de servidor LDAP indisponível) com backoff exponencial governado por cdp_reconnect_max_attempts, cdp_reconnect_initial_backoff_ms e cdp_reconnect_max_backoff_ms. O cookie syncrepl ou DirSync mais recente é preservado entre as reconexões via DcSelector::carry_cookie, para que o plugin retome de onde parou em vez de reler todo o diretório.
Failover multi-DC
Todos os modos de backup que aceitam ldapuri= (ou target_ldapuri= para restauração) suportam uma lista separada por vírgula de URIs LDAP. O plugin trata isso como uma sequência de failover somente para frente. O seletor avança apenas em erros de nível de transporte (TCP recusado/reiniciado/timeout, falha DNS, falha de handshake TLS, servidor LDAP indisponível). Não avança em falhas de autenticação, falhas de autorização ou erros de configuração — estes falham imediatamente pois as mesmas credenciais falharão em todo DC.
| Modo | Failover na conexão | Failover mid-stream | Cookie transferido entre DCs |
|---|---|---|---|
ldap (refresh-only) |
Sim | Não | Sim (sidecar do operador) |
ad (DirSync) |
Sim | Sim | Sim (USN replicado) |
cdp (refresh+persist) |
Sim | Sim | Sim (cluster-CSN) |
cdp_dirsync |
Sim | Sim | Sim (USN replicado) |
hybrid_sysvol |
Sim | Não (por design) | n/a (par LDAP+SYSVOL) |
replicate |
Sim | Sim | Sim (gerenciado pelo seletor) |
| restore (qualquer submodo) | Sim | Não (por design) | n/a |
5. Modos de restauração em detalhes
O engine de restauração aceita um parâmetro mode= selecionando entre seis estratégias de restauração. Todos os modos compartilham a mesma infraestrutura de streaming de entradas; a diferença está no que escrevem no diretório de destino.
5.1 Modo object
Restaura uma única entrada identificada por DN ou objectGUID. A entrada é re-adicionada (ou modificada se já estiver presente, com base na política replace=) com todos os atributos do backup. Este é o modo padrão para restauração seletiva — “Excluí acidentalmente uma conta de usuário.”
5.2 Modo subtree
Restaura uma unidade organizacional inteira e todos os seus descendentes. O engine reordena as entradas com os pais primeiro e pode criar OUs pai ausentes se create_parents=true. O parâmetro where_basedn= redireciona a restauração para uma OU de staging (por exemplo, ou=Restaurado,dc=lab,dc=local) para que a árvore ao vivo não seja perturbada durante a verificação.
5.3 Modo attribute
Restaura N atributos especificados em M entradas sem tocar em outros atributos. Usa semântica LDAP Modify Replace — os atributos especificados são substituídos pelos valores do backup; todos os outros atributos permanecem como estão no diretório ao vivo. Ideal para “redefinir displayName para o valor do backup em uma OU inteira” sem uma restauração completa de subárvore.
5.4 Modo authoritative
Realiza uma restauração completa e eleva a versão USN do AD nos objetos restaurados para que outros DCs repliquem A PARTIR do DC restaurado em vez de sobrescrevê-lo. É o equivalente da restauração autoritativa do AD e é bloqueado por um parâmetro obrigatório i_understand=yes — aplicar esse modo sem o gate aciona um Fatal imediato sem gravar nenhuma entrada LDAP. O guia do operador explica o raio de impacto e os passos necessários de isolamento de DC.
5.5 Modo dry_run
Computa o ldif que SERIA aplicado e o escreve no RestoreLog do Bacula. Nenhum canal de escrita LDAP é aberto contra o destino. Use para verificação antes de executar uma restauração destrutiva.
5.6 Modo diff
Compara o snapshot de backup com o diretório ao vivo e produz um relatório JSON de adições, exclusões e modificações: {adds: [], dels: [], mods: []}. Totalmente somente leitura. Útil para auditoria de conformidade, detecção de alterações e perícia pós-incidente.
6. Matriz de funcionalidades
| Funcionalidade | ldap | ad | hybrid_sysvol | replicate | cdp |
|---|---|---|---|---|---|
| Backup Full | Sim | Sim | Sim | Sim | Sim |
| Backup Incremental (RFC 4533) | Sim | Não | Não | Sim | Sim |
| Backup Incremental (DirSync) | Não | Sim | Sim | Não | Sim (cdp_dirsync) |
| Failover multi-DC | Sim | Sim | Sim | Sim | Sim |
| Cookie transferido entre DCs | Sim | Sim | n/a | Sim | Sim |
| Backup SYSVOL / GPO | Não | Não | Sim | Não | Não |
| Preservação NT ACL | Parcial | Sim | Sim | Sim | Sim |
| Replicação entre fornecedores | Não | Não | Não | Sim | Não |
| Criptografia em repouso (AES-256-GCM) | Sim | Sim | Sim | Sim | Sim |
| Criptografia em repouso (ChaCha20-Poly1305) | Sim | Sim | Sim | Sim | Sim |
| Backend KMS HashiCorp Vault | Sim | Sim | Sim | Sim | Sim |
| Métricas Prometheus | Sim | Sim | Sim | Sim | Sim |
| Logging estruturado JSON-Lines | Sim | Sim | Sim | Sim | Sim |
| Hardening Unicode brasileiro (NFC/NFD) | Sim | Sim | Sim | Sim | Sim |
| Catalogação estável por objectGUID | Não | Sim | Sim | Sim | Sim |
| Backup paralelo por branch (pool por OU) | Sim | Sim | Não | Não | Não |
| Suporte ao AD Recycle Bin | Não | Sim | Sim | Não | Sim (cdp_dirsync) |
| Autenticação Kerberos / GSSAPI | Não | Sim | Sim | Sim | Sim |
| StartTLS / LDAPS | Sim | Sim | Sim | Sim | Sim |
| Pacote RPM | Sim | Sim | Sim | Sim | Sim |
| Pacote DEB | Sim | Sim | Sim | Sim | Sim |
| RestoreObject cookie carry | Sim | Sim | n/a | Sim | Sim |
| RPO sub-minuto (CDP) | Não | Não | Não | Não | Sim |
| Compressão zstd | Sim | Sim | Sim | Sim | Sim |
| Compressão lz4 | Sim | Sim | Sim | Sim | Sim |
7. Guia de instalação
7.1 Pré-requisitos
- Bacula Community 15.0.3 ou posterior instalado;
bacula-fdem execução em um host Linux x86_64 - Conectividade de rede do host
bacula-fdpara o servidor de diretório na porta LDAP (389) ou LDAPS (636) - Para
mode=ad/ Kerberos: cliente Kerberos configurado (/etc/krb5.confapontando para o realm AD); keytab em/etc/podheitor/bacula.keytab - Para
mode=hybrid_sysvol:samba-client-libs(ou equivalente) fornecendolibsmbclient.so - SO: RHEL/OL/Rocky 9+ ou Ubuntu 22.04+/Debian 12+
- glibc 2.34+
7.2 Instalação RPM (EL9 / OL9 / RHEL9 / Rocky 9)
# 1. Install the RPM
dnf install podheitor-adldap-0.1.0-1.el9.x86_64.rpm
# 2. Verify plugin is in place
ls -la /opt/bacula/plugins/podheitor-adldap-fd.so
# 3. Restart bacula-fd to load the plugin
systemctl restart bacula-fd
# 4. Confirm plugin loaded
journalctl -u bacula-fd --since "1 minute ago" | grep podheitor
7.3 Instalação DEB (Ubuntu 22.04 / Debian 12)
# 1. Install the DEB
apt install ./podheitor-adldap_0.1.0-1_amd64.deb
# 2. Verify plugin is in place
ls -la /opt/bacula/plugins/podheitor-adldap-fd.so
# 3. Restart bacula-fd
systemctl restart bacula-fd
# 4. Confirm plugin loaded
journalctl -u bacula-fd --since "1 minute ago" | grep podheitor
7.4 Configuração de credenciais — bind simples
# Create a password file for LDAP simple bind
cat > /etc/podheitor/openldap.pass << 'EOF'
secret_password_here
EOF
chown bacula:bacula /etc/podheitor/openldap.pass
chmod 600 /etc/podheitor/openldap.pass
7.5 Configuração de credenciais — keytab Kerberos (AD)
# Create a keytab for the AD backup service account
# On the Windows DC (or via samba-tool):
# ktpass /out bacula.keytab /mapuser bacula-backup@LAB.LOCAL
# /princ bacula-backup@LAB.LOCAL /pass * /crypto AES256-SHA1
# Deploy to the bacula-fd host
install -o bacula -g bacula -m 600 bacula.keytab /etc/podheitor/bacula.keytab
# Verify Kerberos works
kinit -k -t /etc/podheitor/bacula.keytab bacula-backup@LAB.LOCAL
klist
7.6 Verificação da instalação — smoke test OpenLDAP
FileSet { Name = "Smoke-ADLDAP"; Include {
Options { signature=MD5 }
Plugin = "podheitor-adldap: mode=ldap ldapuri=ldap://192.168.15.154
binddn=cn=Manager,dc=lab,dc=podheitor,dc=local
bindpass_file=/etc/podheitor/openldap.pass
basedn=dc=lab,dc=podheitor,dc=local"
} }
Execute um job Full via bconsole: *run job=Smoke-ADLDAP level=Full yes. Esperado: status do job T com bytes gravados não nulos e PTCOMM START → END visível no log do job.
8. Referência de configuração
8.1 Parâmetros de backup
| Parâmetro | Padrão | Descrição |
|---|---|---|
mode |
(obrigatório) | ldap / ad / replicate / cdp / hybrid_sysvol |
ldapuri |
(obrigatório) | URI(s) LDAP, separados por vírgula para failover multi-DC |
binddn |
DN de bind simples (omitir se kerberos=yes) |
|
bindpass_file |
Caminho para arquivo contendo a senha de bind (modo 0600) | |
kerberos |
no |
Usar autenticação GSSAPI/Kerberos |
keytab |
Caminho do arquivo keytab (obrigatório se kerberos=yes) |
|
starttls |
auto |
Atualizar para TLS em ldap:// se o servidor anunciar StartTLS |
tls_cacert |
Pacote de CA personalizado para LDAPS ou StartTLS | |
basedn |
(obrigatório) | DN base de busca LDAP |
filter |
(objectClass=*) |
Filtro de busca LDAP para delimitar o escopo do backup |
attribs_include |
*,+ |
Atributos a incluir (+ = atributos operacionais) |
attribs_exclude |
Atributos a ignorar (por exemplo, userPassword) |
|
page_size |
1000 |
Tamanho de página da busca paginada RFC 2696 |
parallel_branches |
1 |
Tamanho do pool de threads paralelas por OU; 0 = automático (contagem de CPU) |
include_recycle_bin |
no |
Somente AD — incluir objetos tombstoned/excluídos via LDAP_SERVER_SHOW_DELETED |
dirsync_flags |
0x801 |
Flags do controle DirSync (OBJECT_SECURITY|INCREMENTAL_VALUES|ANCESTORS_FIRST_ORDER) |
sysvol_uri |
URI SMB para compartilhamento SYSVOL; obrigatório para mode=hybrid_sysvol |
|
sysvol_pass_file |
Arquivo de senha SMB para acesso ao SYSVOL | |
compress |
zstd |
none / zstd / lz4 |
compress_level |
3 |
Nível de compressão zstd (1–22) |
encryption |
none |
none / aes-gcm / chacha20-poly1305 |
kms |
Backend KMS: file:/path/key, vault:transit/keys/name, sops:/path |
|
replicate_target_uri |
URI LDAP de destino para mode=replicate |
|
replicate_target_binddn |
DN de bind de destino para mode=replicate |
|
replicate_schema_map |
(padrão) | Caminho para default-schema-mapping.toml para replicação entre fornecedores |
cdp_max_seconds |
60 |
Intervalo de chunk CDP em segundos (limita o RPO) |
cdp_reconnect_max_attempts |
6 |
Máximo de varreduras completas da lista de URI antes de Fatal |
cdp_reconnect_initial_backoff_ms |
500 |
Backoff inicial de reconexão em milissegundos |
cdp_reconnect_max_backoff_ms |
30000 |
Cap máximo de backoff de reconexão em milissegundos |
metrics_path |
/var/lib/podheitor/adldap.prom |
Caminho de saída do textfile Prometheus |
no_normalize_dn |
no |
Desabilitar normalização NFC em DNs (escape hatch) |
allow_anonymous |
no |
Defesa em profundidade: recusar bind anônimo |
verify_after_backup |
yes |
Reler manifesto e recomputar digests após o backup |
8.2 Parâmetros de restauração
| Parâmetro | Padrão | Descrição |
|---|---|---|
mode |
object |
object / subtree / attribute / authoritative / dry_run / diff |
target_ldapuri |
(URI do backup) | URI do diretório de destino; suporta failover separado por vírgula |
target_binddn |
DN de bind de destino (padrão: DN de bind da origem) | |
target_bindpass_file |
Arquivo de senha de bind de destino | |
target_kerberos |
no |
Usar Kerberos para conexão de destino |
where_basedn |
Redirecionar restauração para um DN base diferente (OU de staging) | |
replace |
never |
never / if-newer / always |
attributes |
* |
Atributos separados por vírgula para restaurar (para mode=attribute) |
entries |
* |
DNs ou objectGUIDs a restaurar (padrão: todos) |
create_parents |
no |
Criar OUs pai ausentes durante restauração de subárvore |
i_understand |
Deve ser yes para habilitar mode=authoritative |
|
password_reset |
keep |
keep / random / force=<pwd> para senhas de contas de usuário |
dry_run_output |
Caminho para gravar a prévia ldif para mode=dry_run |
|
diff_output |
Caminho para gravar o relatório JSON de diff para mode=diff |
|
decrypt_kms |
Caminho do backend KMS para descriptografar um backup criptografado |
9. Exemplos de FileSet
9.1 Backup Full OpenLDAP
FileSet {
Name = "OpenLDAP-Full"
Include {
Options { signature=MD5 }
Plugin = "podheitor-adldap: mode=ldap
ldapuri=ldap://ldap.example.com
binddn=cn=Manager,dc=example,dc=com
bindpass_file=/etc/podheitor/openldap.pass
basedn=dc=example,dc=com
compress=zstd"
}
}
9.2 Backup Full Active Directory com Kerberos
FileSet {
Name = "AD-Full-Kerberos"
Include {
Options { signature=MD5 }
Plugin = "podheitor-adldap: mode=ad
ldapuri=ldaps://dc01.corp.local:636,ldaps://dc02.corp.local:636
kerberos=yes keytab=/etc/podheitor/bacula.keytab
basedn=DC=corp,DC=local
include_recycle_bin=yes
parallel_branches=4
compress=zstd encryption=aes-gcm
kms=file:/etc/podheitor/adldap.key"
}
}
9.3 Backup Incremental Active Directory (DirSync)
FileSet {
Name = "AD-Incremental"
Include {
Plugin = "podheitor-adldap: mode=ad
ldapuri=ldaps://dc01.corp.local,ldaps://dc02.corp.local
kerberos=yes keytab=/etc/podheitor/bacula.keytab
basedn=DC=corp,DC=local
cookie_file=/var/lib/bacula/adldap.cookie"
}
}
9.4 Backup Full híbrido SYSVOL + LDAP
FileSet {
Name = "AD-Hybrid-SYSVOL"
Include {
Plugin = "podheitor-adldap: mode=hybrid_sysvol
ldapuri=ldaps://dc01.corp.local
kerberos=yes keytab=/etc/podheitor/bacula.keytab
basedn=DC=corp,DC=local
sysvol_uri=smb://dc01.corp.local/SYSVOL/corp.local
compress=zstd"
}
}
9.5 CDP — proteção contínua OpenLDAP
FileSet {
Name = "OpenLDAP-CDP"
Include {
Plugin = "podheitor-adldap: mode=cdp
ldapuri=ldap://ldap1.example.com,ldap://ldap2.example.com
binddn=cn=Manager,dc=example,dc=com
bindpass_file=/etc/podheitor/openldap.pass
basedn=dc=example,dc=com
cdp_max_seconds=30
cdp_reconnect_max_attempts=8"
}
}
9.6 Replicação entre fornecedores — AD para OpenLDAP
FileSet {
Name = "AD-to-OpenLDAP-Replicate"
Include {
Plugin = "podheitor-adldap: mode=replicate
ldapuri=ldaps://dc01.corp.local
kerberos=yes keytab=/etc/podheitor/bacula.keytab
basedn=DC=corp,DC=local
replicate_target_uri=ldap://standby-ldap.example.com
replicate_target_binddn=cn=admin,dc=example,dc=com
replicate_target_pass_file=/etc/podheitor/standby.pass"
}
}
9.7 Restauração — objeto único por objectGUID
Job {
Name = "AD-Restore-Object"
Type = Restore
Client = adldap-fd
FileSet = "AD-Full-Kerberos"
Storage = File
Pool = Default
Messages = Standard
Plugin = "podheitor-adldap: mode=object
target_ldapuri=ldaps://dc01.corp.local
target_kerberos=yes
entries=550e8400-e29b-41d4-a716-446655440000
replace=always"
}
9.8 Restauração — prévia dry run antes da restauração autoritativa
Plugin = "podheitor-adldap: mode=dry_run
target_ldapuri=ldaps://dc01.corp.local
target_kerberos=yes
dry_run_output=/tmp/preview-restore.ldif"
10. Dimensionamento e planejamento de capacidade
10.1 Requisitos de memória
| Cenário | Linha de base bacula-fd | RAM adicional do plugin |
|---|---|---|
| backup full ldap / ad, single-threaded | 512 MB | +64 MB |
| backup full ad, parallel_branches=4 | 512 MB | +256 MB (4×64 MB) |
| Modo CDP (conexão persistente) | 512 MB | +96 MB |
| hybrid_sysvol (LDAP + SMB) | 512 MB | +128 MB |
| Alvo de backup com 100 mil entradas (cap RSS) | ≤250 MB RSS total do bacula-fd | |
10.2 Estimativas de volume de backup
| Modo | Armazenamento aproximado por 100 mil objetos |
|---|---|
| ldap / ad full (sem compressão) | 200–500 MB (varia com a densidade de atributos) |
| ldap / ad full (zstd nível 3) | 60–150 MB |
| Incremental (1% alterado) | 2–10 MB |
| SYSVOL / GPO (hybrid_sysvol) | 10–200 MB (varia com contagem de GPO e tamanho de política) |
| RestoreObject (cookie + manifesto) | ≤50 MB (comprimido com zstd; pior caso 1M de entradas) |
10.3 Metas de desempenho (metas de laboratório v0.1.0)
| Cenário | Meta |
|---|---|
| 100 mil entradas OpenLDAP, backup full | ≤8 minutos (4 vCPU, 4 GB RAM) |
| 100 mil entradas OpenLDAP, incremental syncrepl (1% alterado) | ≤1 minuto |
| 50 mil objetos AD, DirSync full | ≤5 minutos |
| Incremental AD DirSync (100 alterações) | ≤15 segundos |
| RPO CDP (cdp_max_seconds=60) | ≤90 segundos de ponta a ponta |
10.4 Espaço em disco — instalação do plugin
| Arquivo | Tamanho |
|---|---|
podheitor-adldap-fd.so |
~2–3 MB (Rust com todas as funcionalidades vinculadas estaticamente) |
| Footprint total da instalação | ~2–3 MB |
Nenhum binário sidecar externo é necessário. libsmbclient.so é uma dependência de pacote do sistema apenas para o modo hybrid_sysvol.
11. Relatório de desempenho
Todas as medições são realizadas no ambiente de laboratório PodHeitor em VMs Rocky Linux 9.4 (2–4 vCPU, 2–4 GB RAM) conectadas a servidores Samba AD DC e 389-DS em uma LAN 192.168.15.0/24. Bacula Community 15.0.3 é usado em todos os testes.
11.1 Status da suíte de testes — v0.1.0
| Categoria | Testes | Status |
|---|---|---|
| Testes unitários (adldap-core) | 734 | Todos aprovados |
| Testes unitários (shim ABI plugin-adldap) | 14 | Todos aprovados |
| Testes de integração com LDAP ao vivo (389-DS + Samba AD) | 45 | Todos aprovados |
| Teste destrutivo de failover mid-sweep (opt-in) | 1 | Aprovado (#[ignore]) |
| Cenários de restauração sobre dano ao vivo (delete, modify+delete, modrdn, wipe completo) | 4 | Todos aprovados |
| Restauração autoritativa E2E (Samba AD) | 2 | Todos aprovados |
| Total | 800+ | Todos aprovados |
11.2 Resultados do teste de failover multi-DC
| Teste | Resultado |
|---|---|
| Failover no momento de conexão (DC1 inativo no início) | Aprovado — conecta ao DC2 de forma transparente |
Failover mid-stream (cdp_dirsync): DC1 parado no meio do polling |
Aprovado — cookie transferido entre DCs |
| Failover mid-sweep com 50 entradas preenchidas | Aprovado — cookie_len=N (N>0) confirmado no log |
| Continuidade incremental pós-reconexão | Aprovado — sem entradas duplicadas após reconexão |
11.3 Resultados de cenário de restauração (389-DS)
| Cenário | Descrição | Resultado |
|---|---|---|
| cenário1 | Objeto excluído; restauração via mode=object |
Aprovado — atributos originais incluindo mail round-trip |
| cenário2 | Atributo mutado após backup, depois entrada excluída; restauração traz valor original | Aprovado |
| cenário3 | Entrada renomeada via modrdn; restauração recria DN original | Aprovado — DN original recriado, cópia renomeada persiste (não destrutivo) |
| cenário4 | OU inteira (5 filhos) excluída de baixo para cima; restauração via mode=subtree |
Aprovado — todas as 5 folhas round-trip |
11.4 Resultados de restauração autoritativa (Samba AD)
| Teste | Resultado |
|---|---|
autoritativa sem i_understand=yes → Fatal |
Aprovado — frame Error + Fatal; zero escritas LDAP |
| autoritativa com gate: 2 entradas copiadas, excluídas, replicadas | Aprovado — terminal=Ok, applied≥2, ambos DNs presentes, uSNChanged estritamente > pré-restauração |
12. Matriz de compatibilidade
12.1 Sistema operacional
| SO | Arquitetura | Status |
|---|---|---|
| RHEL 9 | x86_64 | Suportado |
| Oracle Linux 9 | x86_64 | Suportado |
| Rocky Linux 9 | x86_64 | Suportado (plataforma de laboratório) |
| AlmaLinux 9 | x86_64 | Suportado |
| Ubuntu 22.04 LTS | x86_64 | Suportado |
| Debian 12 | x86_64 | Suportado |
| RHEL 8 / CentOS 8 | x86_64 | Não testado (glibc < 2.34) |
| Ubuntu 20.04 | x86_64 | Não testado (glibc < 2.34) |
| ARM64 / aarch64 | qualquer | Ainda não disponível |
12.2 Versões de servidor de diretório
| Servidor de diretório | Versão | Modo | Status |
|---|---|---|---|
| Microsoft Active Directory | Windows Server 2012 R2 – 2025 | ad, hybrid_sysvol, cdp_dirsync | Suportado |
| Samba AD DC | Qualquer versão Samba atual | ad, ldap, hybrid_sysvol | Suportado (testado em laboratório) |
| OpenLDAP (slapd) | 2.4, 2.5, 2.6 | ldap, cdp, replicate | Suportado |
| 389 Directory Server | Atual | ldap, cdp, replicate | Suportado (testado em laboratório) |
| Red Hat DS / FreeIPA | Atual | ldap, cdp | Suportado (via 389-DS) |
| ApacheDS | Atual | ldap (genérico) | Melhor esforço |
| OpenDJ | Atual | ldap (genérico) | Melhor esforço |
12.3 Versões do Bacula
| Versão do Bacula | Status |
|---|---|
| Community 15.0.3 | Suportado (validado) |
| Community 15.0.x (futuro) | Compatibilidade esperada |
| Community 14.x | Não suportado |
| Bacula Enterprise | Não necessário; o plugin é direcionado ao Bacula Community |
12.4 Controles LDAP utilizados
| OID | Nome | Utilizado por |
|---|---|---|
| 1.2.840.113556.1.4.319 | Resultados paginados (RFC 2696) | Backup Full |
| 1.3.6.1.4.1.4203.1.9.1.1 | syncrepl (RFC 4533) | Incremental LDAP |
| 1.2.840.113556.1.4.841 | DirSync | Incremental AD |
| 1.2.840.113556.1.4.417 | LDAP_SERVER_SHOW_DELETED | Tombstone, Recycle Bin |
| 1.2.840.113556.1.4.2065 | DirSync estendido (V2) | AD ≥ 2008 R2 |
| 1.2.840.113556.1.4.529 | LDAP_SERVER_EXTENDED_DN | Restauração AD |
| 1.3.6.1.4.1.1466.20037 | StartTLS | Atualizações TLS |
| 1.3.6.1.4.1.4203.1.11.1 | Password Modify (RFC 3062) | Restauração com redefinição de senha |
13. Segurança
13.1 Tratamento de credenciais
Senhas de bind nunca são armazenadas na configuração de FileSet ou Job do Bacula. Todas as senhas são lidas de arquivos dedicados com modo 0600 de propriedade do usuário bacula. A senha é passada em memória para a biblioteca cliente LDAP; nunca é gravada em disco durante o job, nunca aparece nos argumentos de processo visíveis via ps e é redatada de toda a saída de log (logging JSON-Lines com redação obrigatória para bindpass, target_bindpass, conteúdo do keytab e chaves resolvidas pelo KMS).
Arquivos keytab Kerberos devem ter modo 0600; o plugin recusa usar um keytab com permissões mais permissivas.
13.2 Criptografia em repouso
O plugin fornece sua própria camada de criptografia em repouso independente da criptografia em nível de stream do Bacula. Dois algoritmos são suportados:
- AES-256-GCM — o padrão recomendado para ambientes com aceleração de hardware AES.
- ChaCha20-Poly1305 — preferido para ambientes sem hardware AES (por exemplo, plataformas embarcadas ou ARM).
Três backends KMS são fornecidos:
file:/path/key— chave armazenada em um arquivo (mais simples; arquivo de chave deve ser 0600).vault:transit/keys/name— engine Transit do HashiCorp Vault; chaves nunca saem do Vault.sops:/path— arquivo de chave criptografado Mozilla SOPS.
Uma tentativa de restauração com configuração KMS ausente ou incorreta falha rapidamente com um erro explícito antes que qualquer escrita no diretório seja tentada.
13.3 Segurança de rede
O plugin suporta LDAPS (TLS direto na porta 636) e StartTLS (atualização na porta 389). Não abre portas de escuta adicionais no host bacula-fd. Para o modo hybrid_sysvol, a conexão SMB ao compartilhamento SYSVOL usa o ticket Kerberos obtido do keytab — nenhuma credencial SMB separada é necessária se o Kerberos estiver configurado.
O bind anônimo é recusado por padrão (allow_anonymous=no). Esta é uma medida de defesa em profundidade; qualquer operador que habilite explicitamente o bind anônimo deve auditar cuidadosamente suas ACLs de diretório.
13.4 Gate de segurança de restauração autoritativa
A restauração mode=authoritative é estruturalmente bloqueada: o loop de aplicação não tem acesso ao seletor e não pode prosseguir sem que o parâmetro i_understand=yes esteja definido explicitamente. Este não é uma verificação em tempo de execução — é imposto pelo sistema de tipos Rust. Um job de restauração sem o gate emite um frame Error e um status terminal Fatal sem realizar uma única escrita LDAP, e o cumprimento do gate é coberto por um teste ao vivo contra Samba AD na suíte de testes.
14. Monitoramento
14.1 Métricas de textfile Prometheus
Ao final do job (e periodicamente durante o modo CDP), o plugin grava métricas de textfile Prometheus em /var/lib/podheitor/adldap.prom (caminho configurável via metrics_path=). Estas podem ser coletadas pelo coletor de textfile do Node Exporter.
14.2 Métricas expostas
| Métrica | Tipo | Descrição |
|---|---|---|
podheitor_adldap_entries_backed_up |
Counter | Total de entradas LDAP serializadas para o Bacula |
podheitor_adldap_bytes_written |
Counter | Total de bytes gravados no Bacula Storage Daemon |
podheitor_adldap_job_duration_seconds |
Histogram | Duração de backup por job |
podheitor_adldap_errors_total |
Counter | Total de eventos de erro por código de erro |
podheitor_adldap_replicate_lag_seconds |
Gauge | Modo CDP/replicate: idade da alteração mais recente aplicada |
podheitor_adldap_failover_events_total |
Counter | Contagem de eventos de failover multi-DC por modo e par de DC |
podheitor_adldap_cookie_age_seconds |
Gauge | Idade do cookie syncrepl/DirSync atual |
podheitor_adldap_compression_ratio |
Gauge | Razão de compressão mais recente (comprimido / bruto) |
14.3 Configuração de coleta de textfile Node Exporter
scrape_configs:
- job_name: 'podheitor-adldap'
static_configs:
- targets: ['bacula-fd-host:9100']
metrics_path: /metrics
scrape_interval: 60s
O Node Exporter deve ser iniciado com --collector.textfile.directory=/var/lib/podheitor/ (ou o caminho configurado via metrics_path=).
14.4 Logging estruturado JSON-Lines
Toda a saída de log do plugin é emitida como JSON Lines para stderr (capturado pelo bacula-fd) e copiada para /var/log/bacula/podheitor-adldap-<jobid>.log. Níveis: TRACE / DEBUG / INFO / WARN / ERROR. Eventos de diagnóstico importantes emitidos no nível WARN:
{"lvl":"warn","msg":"cdp_dirsync: connect failure on ldaps://dc1.corp.local (LDAP_SERVER_DOWN); failing over to ldaps://dc2.corp.local at cookie_len=128"}
{"lvl":"warn","msg":"cdp: all DCs exhausted on connect (attempt 3/6); last error: ...; backing off 4000ms then restarting walk"}
{"lvl":"warn","msg":"schema_hash mismatch: promoting Incremental to Full"}
Pesquise no log do job FD por failing over, exhausted ou schema_hash mismatch para identificar eventos operacionalmente significativos para relatórios de SLO.
15. Guia de resolução de problemas
15.1 Erros comuns
Plugin não encontrado na inicialização
Error: cannot open shared object file: No such file or directory
Causa. podheitor-adldap-fd.so não está no diretório de plugins configurado.
Solução. Verifique se /opt/bacula/plugins/podheitor-adldap-fd.so existe e se a diretiva PluginDirectory no bacula-fd.conf aponta para /opt/bacula/plugins.
Conexão LDAP recusada
podheitor-adldap: LDAP_SERVER_DOWN connecting to ldaps://dc01.corp.local:636
Causa. O servidor de diretório está inacessível, TLS falhou ou o URI está incorreto.
Solução:
# Test connectivity from the bacula-fd host
ldapsearch -H ldaps://dc01.corp.local:636 -x -b "" -s base
# Check TLS certificate validity
openssl s_client -connect dc01.corp.local:636 -CAfile /etc/podheitor/ca.crt < /dev/null
Falha de autenticação Kerberos
podheitor-adldap: GSSAPI bind failed: clock skew too great
Causa. O relógio do host bacula-fd está mais de 5 minutos fora de sincronia com o controlador de domínio.
Solução:
systemctl enable --now chronyd
chronyc makestep # force immediate sync
DirSync com permissão negada
podheitor-adldap: DirSync control rejected: insufficientAccessRights (50)
Causa. O usuário de bind não possui SeSyncAgentPrivilege no domínio.
Solução. Delegue os direitos necessários via dsacls.exe ou pelo assistente de delegação do Active Directory Users and Computers. Consulte o Guia do Operador para o comando dsacls exato.
Samba AD: basedn DirSync rejeitado
podheitor-adldap: DirSync unwillingToPerform (53): basedn must be domain root
Causa. O Samba AD rejeita solicitações DirSync com raiz abaixo do contexto de nomenclatura de domínio.
Solução. Defina basedn=dc=lab,dc=local (raiz do domínio) e use filter= para delimitar os resultados:
Plugin = "podheitor-adldap: mode=ad ...
basedn=dc=lab,dc=local
filter=(&(objectClass=user)(memberOf=cn=eng,ou=groups,dc=lab,dc=local))"
Incompatibilidade de hash do schema — backup full promovido
podheitor-adldap: schema_hash mismatch (stored=abc123, current=def456); promoting to Full
Causa. O schema do diretório foi alterado entre o último backup Full e este Incremental (por exemplo, uma extensão de schema AD foi aplicada).
Solução. Esse é o comportamento esperado. O plugin corretamente se autopromove para Full e salva o novo hash do schema. Nenhuma ação do operador é necessária a menos que a mudança de schema tenha sido não intencional.
Restauração autoritativa rejeitada — gate ausente
podheitor-adldap: mode=authoritative requires i_understand=yes; refusing to write
Causa. O parâmetro i_understand=yes não foi definido no job de restauração.
Solução. Adicione i_understand=yes à Plugin string de restauração. Leia a seção do Guia do Operador sobre o raio de impacto da restauração autoritativa antes de prosseguir.
15.2 Localizações de logs
| Log | Caminho |
|---|---|
| Log principal bacula-fd | /opt/bacula/log/bacula-fd.log |
| Log por job do plugin | /var/log/bacula/podheitor-adldap-<jobid>.log |
| Textfile Prometheus | /var/lib/podheitor/adldap.prom |
| Mensagens do Bacula Director | conforme configurado no recurso Messages do bacula-dir.conf |
15.3 Habilitando logging de depuração
Adicione debug=9 à Plugin string para verbosidade máxima:
Plugin = "podheitor-adldap: mode=ldap ... debug=9"
Isso registra cada frame PTCOMM, cada solicitação/resposta LDAP (incluindo DN e código de resultado) e todas as transições de estado.
16. Casos de uso e cenários de implantação
16.1 AD empresarial — cobertura completa de DR
Cenário. Uma empresa de 2.000 funcionários opera Windows Server 2022 AD com dois controladores de domínio. Eles precisam de backups full noturnos incluindo GPOs, backups incrementais diários e runbooks de DR testados.
Solução.
- Semanal: backup full
mode=hybrid_sysvol— captura objetos do diretório + SYSVOL/GPO - Diário: backup incremental
mode=ad— apenas delta DirSync (minutos, não horas) - Retenção: 30 dias no pool do Bacula
- Teste de DR:
mode=dry_runtrimestral contra um domínio de laboratório para verificar o procedimento de restauração
Benefício operacional. A capacidade de restauração de GPO é um diferencial importante em relação ao AD Recycle Bin (que não inclui SYSVOL). Quando um GPO é acidentalmente excluído ou mal configurado, todo o conjunto de arquivos GPO pode ser restaurado do catálogo do Bacula sem reconstrução do zero.
16.2 Auditoria de conformidade de identidade em múltiplas florestas
Cenário. Uma instituição financeira precisa provar a auditores que atributos de contas de usuário e associações de grupos não foram alterados sem um chamado de mudança. Eles precisam de um relatório de diff automatizado diário.
Solução.
- Job de backup diário com
mode=ad - Após o backup, um job secundário de restauração é executado com
mode=diff, produzindo um relatório JSON de todas as alterações desde o backup anterior - O relatório de diff é ingerido no SIEM para correlação com chamados de mudança
- Qualquer entrada aparecendo em
delsoumodssem um chamado de mudança correspondente dispara um alerta de segurança
16.3 CDP OpenLDAP para diretório de contas de serviço
Cenário. Uma plataforma de microsserviços usa OpenLDAP para autenticação de contas de serviço. Qualquer perda de dados LDAP causa falha de autenticação simultânea em dezenas de serviços. O RPO deve ser inferior a 2 minutos.
Solução.
- Modo:
cdpcomcdp_max_seconds=60contra um cluster OpenLDAP de duas réplicas (ldapuri=ldap://ldap1,ldap://ldap2) - RPO CDP: ≤90 segundos de ponta a ponta
- Failover mid-stream testado: se ldap1 falhar durante uma sessão de streaming, o plugin faz failover para ldap2 e continua sem interrupção do job
16.4 Migração de domínio FreeIPA para Samba AD
Cenário. Uma empresa está migrando de um domínio FreeIPA (backend 389-DS) para Samba AD DC. Eles precisam de uma migração controlada e auditada com a capacidade de rollback.
Solução.
- Fase 1: Backup Full do FreeIPA via
mode=ldap— snapshot canônico de todas as contas de usuário, grupos e políticas - Fase 2:
mode=replicatecomreplicate_target_uri=ldap://samba-dce o mapeamento de schema padrão — espelha ao vivo as alterações do FreeIPA no Samba AD durante a janela de migração - Fase 3: Após a migração, executar
mode=diffpara confirmar que o diretório Samba AD corresponde ao último snapshot do FreeIPA - Rollback: se a migração falhar, restaurar o diretório FreeIPA do backup Bacula da Fase 1 via
mode=subtree
16.5 Recuperação autoritativa de floresta após ransomware
Cenário. Todos os controladores de domínio foram criptografados por ransomware. A empresa precisa reconstruir o diretório a partir do backup sem contaminação de replicação.
Solução.
- Provisionar um DC novo — isolado da rede, sem parceiros de replicação
- Executar
mode=dry_runcontra o DC novo para visualizar a restauração sem gravar nada - Após revisar o ldif de prévia, executar
mode=authoritativecomi_understand=yes— restaura todos os objetos com USN elevado para que nenhum parceiro de replicação possa sobrescrever o estado restaurado - Reconectar o DC à rede; verificar se a replicação DRS converge a partir do estado restaurado
- Executar
mode=diffapós 1 hora para confirmar que não houve replicação inesperada do estado criptografado
17. Comparação com outras abordagens
17.1 Diferenciais PodHeitor vs. plugin Bacula Enterprise LDAP/MSAD
| Funcionalidade | PodHeitor AD/LDAP | Bacula Enterprise LDAP/MSAD |
|---|---|---|
| Backup SYSVOL / GPO | Sim (hybrid_sysvol) | Não — somente LDAP |
| Replicação ao vivo entre diretórios | Sim (modo replicate) | Não |
| CDP (proteção contínua de dados) | Sim (cdp / cdp_dirsync) | Não |
| Incremental verdadeiro via DirSync + RFC 4533 | Sim (cookies USN / CSN) | Full + diff apenas |
| Restauração em nível de atributo | Sim (mode=attribute) | Somente nível de objeto |
| Prévia de restauração dry-run | Sim (mode=dry_run) | Não |
| Restauração diff (relatório de alterações somente leitura) | Sim (mode=diff) | Não |
| Restauração autoritativa | Sim (com gate) | Parcial (somente MSAD) |
| Criptografia em repouso | Sim (AES-256-GCM / ChaCha20) | Somente nível de stream Bacula |
| Hardening Unicode brasileiro | Sim (NFC/NFD, CI gate completo) | Melhor esforço |
| RestoreObject cookie (sem arquivo de estado) | Sim | Arquivo em disco |
| Catalogação estável por objectGUID / objectSID | Sim | Somente estável por DN |
| Backup paralelo por OU | Sim (parallel_branches=N) | Single-threaded |
| cdylib puro em Rust (sem shim C/C++) | Sim | Shim C++ |
| Métricas estruturadas Prometheus | Sim | Somente logs de texto |
| Failover multi-DC com cookie carry | Sim (todos os modos) | Limitado |
17.2 Comparação mais ampla de plataformas
| Funcionalidade | Bacula Community + PodHeitor | Bacula Enterprise | Veeam | Commvault |
|---|---|---|---|---|
| Backup nativo AD (DirSync) | Sim | Parcial | Não (somente VM) | Parcial (agente Windows) |
| Backup nativo OpenLDAP / 389-DS | Sim | Limitado | Não | Não |
| Backup SYSVOL / GPO | Sim | Não | Não | Não |
| CDP / RPO quase zero | Sim | Não | Não | Limitado |
| Replicação LDAP entre fornecedores | Sim | Não | Não | Não |
| Restauração em nível de atributo | Sim | Não | Não | Não |
| Restauração em nível de objeto | Sim | Parcial | Requer add-on | Sim (somente Windows AD) |
| Restauração autoritativa | Sim | Parcial | Não | Não |
| Criptografia em repouso (nível de plugin) | Sim | Nível de stream | Sim | Sim |
| Métricas Prometheus | Sim | Não | Não | Não |
| Plataforma base open-source | Sim (Bacula CE) | Não | Não | Não |
| Pacotes RPM + DEB | Sim | Sim | Sim | Sim |
| Sem agente (clientless, sem agente no DC) | Sim | Parcial | Não | Não |
17.3 Comparação de custos
Oferta especial. Traga sua proposta de renovação do Veeam, Commvault, NetBackup ou qualquer outra plataforma de backup empresarial. Produziremos uma proposta comparativa formal visando pelo menos 50% de economia, com funcionalidades AD/LDAP superiores. Entre em contato pelo heitor@opentechs.lat.
| Solução | Custo anual típico | Suporte a AD / LDAP |
|---|---|---|
| Bacula Community + plugin PodHeitor | Significativamente menor | Nativo completo (este plugin) |
| Bacula Enterprise | Frequentemente > US$ 10.000/ano | Parcial (LDAP/MSAD, sem SYSVOL) |
| Veeam Data Platform | Frequentemente > US$ 5.000/ano | Somente nível de VM (sem restauração de objetos sem add-on) |
| Commvault | Frequentemente > US$ 15.000/ano | Somente Windows AD (agente obrigatório) |
| NetBackup | Frequentemente > US$ 20.000/ano | Limitado (sem LDAP nativo) |
Os preços variam conforme o tamanho do ambiente e contratos negociados. Entre em contato pelo heitor@opentechs.lat para uma comparação específica com sua proposta de renovação atual.
18. Roadmap
O plugin é lançado na v0.1.0 com o conjunto completo de funcionalidades MVP em todos os 5 modos de backup e 6 modos de restauração, validados por 800+ testes. As direções de desenvolvimento planejadas incluem:
- Fase 9 — empacotamento e documentação. Pacotes DEB e RPM assinados e publicados no repositório PodHeitor. Guia do Operador completo, DR Runbook e Guia de Resolução de Problemas.
- Agente AD nativo para Windows. Uma compilação do plugin para Windows carregando em um
bacula-fdnativo Windows possibilitaria acesso direto ao NTDS.dit local via VSS — eliminando a necessidade de um host Linux separado combacula-fdpara backup AD. Atualmente fora do escopo da v0.1.0. - Suporte a múltiplas arquiteturas. Pacotes ARM64 / aarch64 para ambientes cloud-native e Raspberry Pi.
- Painel de administração Bacularis. UI de configuração do plugin na interface web Bacularis para entrada de parâmetros sem editar a configuração bruta de FileSet. Confirmado fora do escopo da v0.1.0.
- Suporte explícito a ApacheDS / OpenDJ. Atualmente melhor esforço via modo genérico
ldap; certificação completa planejada para uma versão menor futura. - Azure AD DS / AWS Managed Microsoft AD. Serviços AD gerenciados na nuvem têm endpoints LDAP e suportam parcialmente DirSync — certificação explícita e documentação de soluções alternativas planejadas.
- Alertas Prometheus estendidos. Regras de alerta pré-construídas para obsolescência de cookie, drift de schema e lag de replicação.
Nenhuma data de lançamento específica está comprometida. A direção das funcionalidades é guiada pelo feedback de clientes e descobertas do laboratório.
19. Informações de contato
| Autor | Heitor Faria |
| Website | https://podheitor.com |
| heitor@opentechs.lat | |
| Telefone / WhatsApp | +1 786 726-1749 |
| Telefone / WhatsApp (BR) | +55 61 98268-4220 |
| Página do produto | https://podheitor.com/active-directory-ldap-plugin |
| Suporte | heitor@opentechs.lat |
20. Legal / direitos autorais
© 2026 Heitor Faria — todos os direitos reservados.
O PodHeitor Active Directory / LDAP Backup Plugin for Bacula é um software proprietário. Cópia, distribuição, modificação ou engenharia reversa não autorizadas são estritamente proibidas. Uma licença comercial é necessária para uso em produção.
Bacula® é marca registrada de Kern Sibbald e da comunidade Bacula. Microsoft Active Directory® é marca registrada da Microsoft Corporation. Todas as outras marcas comerciais — incluindo OpenLDAP, 389-DS, FreeIPA, Samba, Kerberos, HashiCorp Vault, Veeam, Commvault e NetBackup — são propriedade de seus respectivos titulares.
Este documento é fornecido para fins informativos. Os números de desempenho são metas de medições controladas em laboratório e podem variar em ambientes de produção dependendo do hardware, condições de rede, configuração do servidor de diretório e tamanho do diretório.
Contato para licenciamento: heitor@opentechs.lat | https://podheitor.com | +1 786 726-1749 | +55 61 98268-4220
PodHeitor Active Directory / LDAP Backup Plugin for Bacula — v0.1.0 — © 2026 Heitor Faria — todos os direitos reservados — https://podheitor.com
Disponível em:
Português
English (Inglês)
Español (Espanhol)