Configurações do LDAP
From LimeSurvey Manual
Geral
Para utilizar esta função, você precisa ativar o suporte a LDAP no config.php e configurar os parâmetros do LDAP em config/ldap.php.
Ativando o LDAP no config.php
- $enableLdap: se você quiser usar as funções LDAP no LimeSurvey, deve definir este parâmetro como true (por padrão, ele está definido como false):
'config'=>array( 'debug'=>0, 'debugsql'=>0, 'enableLdap'=>true, )
Definindo servidores LDAP
Primeiro, defina as opções de conexão do servidor LDAP em "application/config/ldap.php". Para cada servidor, as seguintes opções estão disponíveis:
- $serverId: Um número inteiro que identifica este servidor LDAP. Ele é usado nas definições de consulta para associar um servidor a uma consulta específica;
- $ldap_server[$serverId]['server']: O Endereço IP ou o nome DNS do servidor LDAP. Se você usar conexões protegidas por SSL (LDAPs ou LDAP+Start-TLS), este nome deve corresponder ao CN do certificado do servidor (ou ao SubjectAlternativeName);
- $ldap_server[$serverId]['port']: A porta TCP na qual o servidor LDAP escuta. Normalmente é 389 para LDAP e LDAP+Start-TLS, e 636 para LDAPs;
- $ldap_server[$serverId]['protoversion']: Pode ser 'ldapv2' ou 'ldapv3', dependendo do protocolo suportado pelo seu servidor. 'ldapv3' é o protocolo preferido. No entanto, se você quiser usar conexões criptografadas, observe que LDAPs é suportado no modo 'ldapv2', enquanto Start-TLS é o método de criptografia para 'ldapv3';
- $ldap_server[$serverId]['encrypt']: Define o método de criptografia utilizado. 'ldaps' é suportado para servidores 'ldapv2' e 'start-tls' para servidores 'ldapv3'. A palavra-chave 'none' é usada para comunicações LDAP em texto simples;
- Não se esqueça de que, para a criptografia 'ldaps' ou 'start-tls', o servidor web deve ser capaz de verificar o certificado do servidor LDAP. Portanto, você precisa definir sua Autoridade Certificadora na biblioteca openldap (normalmente isso é feito no arquivo /etc/openldap/ldap.conf no Linux).
- $ldap_server[$serverId]['referrals']: É um parâmetro booleano que define se os referrals devem ser seguidos ou não (use false para o ActiveDirectory);
- $ldap_server[$serverId]['encoding']: É um parâmetro opcional que informa a codificação usada pelo diretório LDAP para armazenar strings. Normalmente você não precisa configurar este parâmetro, pois a codificação padrão assumida, 'utf-8', é a codificação padrão para diretórios LDAP. No entanto, se você estiver usando o Active Directory e tiver problemas ao importar strings acentuadas, tente definir este parâmetro com a codificação usada na sua região (por exemplo, 'cp850' para a Europa Ocidental). Você pode consultar a lista suspensa "Conjunto de caracteres do arquivo" na interface Importar código de um arquivo CSV para ver a lista completa de codificações suportadas.
Em seguida, você precisa definir qual autenticação é necessária para acessar o diretório. Se o acesso 'anonymous' for permitido, NÃO defina os dois parâmetros a seguir; caso contrário, defina-os de acordo:
- $ldap_server[$serverId]['binddn']: DN do usuário 'LDAP' que tem permissão para ler o diretório;
- $ldap_server[$serverId]['bindpw']: Senha do usuário LDAP acima.
Se precisar definir outros servidores LDAP, adicione a seguinte linha para incrementar o serverID e defina os novos parâmetros:
- $serverId++.
Definindo consultas em config/ldap.php
Cuidado: quando um nome de atributo ldap for necessário em um destes parâmetros, use apenas nomes em minúsculas: por exemplo, displayname e NÃO displayName.
Consulte o arquivo config/ldap.php, pois ele contém exemplos de configuração.
Consultas simples
Vamos começar com consultas simples. Estas consultas apenas filtram as entradas LDAP com base em seus próprios atributos e localização. Normalmente são suficientes para consultar o ActiveDirectory.
- $query_id: é o id da consulta LDAP;
- $ldap_queries[$query_id]['ldapServerId']: Associa a consulta a um servidor específico;
- $ldap_queries[$query_id]['name']: String que descreve a consulta. Ela será exibida na interface;
- $ldap_queries[$query_id]['userbase']: DN raiz a ser usado nas buscas de usuários;
- $ldap_queries[$query_id]['userfilter']: É um filtro usado para selecionar as entradas de usuários em potencial. Deve estar entre parênteses;
- $ldap_queries[$query_id]['userscope']: escopo da busca LDAP por usuários ('base', 'one' ou 'sub');
- $ldap_queries[$query_id]['firstname_attr']: Atributo Ldap que será mapeado para o campo Nome da entrada do código;
- $ldap_queries[$query_id]['lastname_attr']: Atributo Ldap que será mapeado para o campo Sobrenome da entrada do código;
- $ldap_queries[$query_id]['email_attr']: Atributo Ldap que será mapeado para o campo E-mail da entrada do código.
Opcionalmente, você pode obter mais informações do diretório:
- $ldap_queries[$query_id]['token_attr']: Atributo Ldap que será mapeado para o código;
- $ldap_queries[$query_id]['language']: Atributo Ldap que será mapeado para o Código de língua do usuário;
- $ldap_queries[$query_id]['attr1']: Atributo Ldap que será mapeado para o campo attribute_1;
- $ldap_queries[$query_id]['attr2']: Atributo Ldap que será mapeado para o campo attribute_2.
Consultas combinadas de grupos com membros DN
Vamos ver agora como definir uma consulta mais complexa.
As consultas a seguir usam uma primeira busca LDAP que procura em grupos LDAP. Um grupo LDAP é uma entrada LDAP que contém referências a entradas de usuários na forma de:
- ids de usuário (por exemplo, os posixGroups) ==> Veja a próxima seção
- Ou DNs de usuário (por exemplo, groupofnames e groupofuniquenames) ==> veja abaixo
Aqui tratamos de grupos que contêm DNs de usuário:
- defina $query_id, $ldap_queries[$query_id]['ldapServerId'], $ldap_queries[$query_id]['name'] conforme explicado acima.
Em seguida, defina os parâmetros do filtro de grupo:
- $ldap_queries[$query_id]['groupbase']: O DN raiz a partir do qual você quer começar a buscar entradas de grupo;
- $ldap_queries[$query_id]['groupfilter']: O filtro LDAP que selecionará as entradas de grupo em potencial;
- $ldap_queries[$query_id]['groupscope']: O escopo da busca LDAP por grupos ('one', 'base' ou 'sub');
- $ldap_queries[$query_id]['groupmemberattr']: O nome do atributo LDAP na entrada do grupo que conterá referências às entradas de usuários;
- $ldap_queries[$query_id]['groupmemberisdn']: TRUE.
Neste ponto, tudo está configurado para que a primeira busca LDAP encontre os usuários correspondentes aos grupos selecionados. No entanto, você pode restringir quais desses "usuários candidatos" serão selecionados aplicando outro filtro a eles. Isso, é claro, é opcional:
- $ldap_queries[$query_id]['userbase']: DN base para a busca LDAP de usuários (somente os usuários candidatos correspondentes a esta base serão selecionados);
- $ldap_queries[$query_id]['userscope']: Escopo da busca LDAP de usuários (somente os usuários candidatos correspondentes a userbase+scope serão selecionados);
- $ldap_queries[$query_id]['userfilter']: É um filtro aplicado a cada entrada de usuário candidato (em seus atributos) para acrescentar outra seleção.
Consultas combinadas de grupos com membros UID
Vamos ver agora como definir uma consulta combinada de grupo quando os membros do grupo são UIDs de usuário e não DNs de usuário.
Assim como nas consultas de grupo com membros DN, estas consultas usam uma primeira busca LDAP que procura entradas de grupos LDAP e obtém seus membros. Esses valores de membros são então usados em um filtro de busca de usuários para encontrar as entradas correspondentes. Assim, outro parâmetro deve ser configurado para definir o atributo, na entrada do usuário, que deve corresponder ao UID do membro encontrado nos grupos.
Vamos revisar os parâmetros necessários:
- defina $query_id, $ldap_queries[$query_id]['ldapServerId'], $ldap_queries[$query_id]['name'] conforme explicado acima
Em seguida, defina os parâmetros do filtro de grupo:
- $ldap_queries[$query_id]['groupbase']: O DN raiz a partir do qual você quer começar a buscar entradas de grupo;
- $ldap_queries[$query_id]['groupfilter']: O filtro LDAP que selecionará as entradas de grupo em potencial;
- $ldap_queries[$query_id]['groupscope']: O escopo da busca LDAP por grupos ('one', 'base' ou 'sub');
- $ldap_queries[$query_id]['groupmemberattr']: O nome do atributo LDAP na entrada do grupo que conterá referências às entradas de usuários;
- $ldap_queries[$query_id]['groupmemberisdn']: FALSE;
- $ldap_queries[$query_id]['useridattr']: nome do atributo de usuário que deve corresponder ao UID encontrado nos Membros do grupo.
Neste ponto, tudo está configurado para que a primeira busca LDAP encontre os UIDs de usuários correspondentes aos grupos selecionados, e um filtro de busca de usuários será preenchido automaticamente.
No entanto, você pode restringir quais desses "usuários candidatos" serão selecionados, completando o filtro de usuário automático calculado a partir dos UIDs dos membros. Isso é, claro, opcional:
- $ldap_queries[$query_id]['userbase']: DN base para a busca LDAP de usuários (somente os usuários candidatos que correspondem a essa base serão selecionados);
- $ldap_queries[$query_id]['userscope']: escopo da busca LDAP de usuários (somente os usuários candidatos que correspondem a userbase+scope serão selecionados);
- $ldap_queries[$query_id]['userfilter']: é um filtro aplicado a cada entrada de usuário candidato (em seus atributos) para adicionar outra seleção.
E quanto ao Active Directory?
O Active Directory (AD) é um registro da Microsoft que pode ser consultado por meio do protocolo LDAP.
Portanto, é possível usar seu conteúdo em consultas de códigos do LimeSurvey, mas isso exige conhecimento de como o AD é organizado.
- A base raiz do LDAP é dc=my_windows_domain_name,dc=dns_suffix2,dc=dns_suffix1
==> Por exemplo, se sua empresa possui o domínio DNS 'my-company.com' e seu domínio Windows é 'employees', sua base raiz é dc=employees,dc=my-company,dc=com
- Usuários e grupos de usuários ficam armazenados abaixo de cn=Users,dc=my_windows_domain_name,dc=dns_suffix2,dc=dns_suffix1 (observe que não é ou=users);
- Grupos do Active Directory:
- Os objetos de grupo contêm os DNs dos membros em seu atributo 'member';
- As associações a grupos também são armazenadas no atributo memberOf de cada entrada de usuário. Esse atributo contém os DNs dos grupos aos quais o usuário pertence;
- alguns grupos estão em CN=Builtin,dc=my_windows_domain_name,dc=dns_suffix2,dc=dns_suffix1:
- Por exemplo: cn=Administrator,CN=Builtin,dc=my_windows_domain_name,dc=dns_suffix2,dc=dns_suffix1;
Em alguns casos, consultar um Active Directory não é tão simples; por isso, segue um exemplo de configuração para obter algumas informações de um Active Directory:
//Connection to the active directory Server:
$serverId=0;
$ldap_server[$serverId]['server'] = "10.10.10.10";
$ldap_server[$serverId]['port'] = "389";
$ldap_server[$serverId]['protoversion'] = "ldapv2";
$ldap_server[$serverId]['encrypt'] = "none"; // Most AD LDAP servers will not have encryption set by default
$ldap_server[$serverId]['referrals'] = false;
$ldap_server[$serverId]['binddn'] = "domain\\user";
$ldap_server[$serverId]['bindpw'] = "userpassword";
//$ldap_server[$serverId]['binddn'] = "CN=user,OU=user_group,DC=xxx,DC=yyy"; this one will not work with active directory, that´s why you need to use "domain\\user"
//Here is a sample query for getting all active users of an active directory:
$query_id=0;
$ldap_queries[$query_id]['ldapServerId'] = 0;
$ldap_queries[$query_id]['name'] = 'Staff with an enabled account';
$ldap_queries[$query_id]['userbase'] = 'OU=USER_GROUP,DC=xxx,DC=yyy';
$ldap_queries[$query_id]['userfilter'] = '(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))';
//AD has no "account is enabled" attribute, so the filter excludes accounts that have the "disabled" flag (bit 2) set in userAccountControl
$ldap_queries[$query_id]['userscope'] = 'sub';
$ldap_queries[$query_id]['firstname_attr'] = 'givenname';
$ldap_queries[$query_id]['lastname_attr'] = 'sn';
$ldap_queries[$query_id]['email_attr'] = 'mail';
$ldap_queries[$query_id]['token_attr'] = ''; // Leave empty for Auto Token generation by phpsv
$ldap_queries[$query_id]['language'] = '';
$ldap_queries[$query_id]['attr1'] = '';
$ldap_queries[$query_id]['attr2'] = '';
//You can also filter on group membership through the memberOf attribute of the user. Here is a sample query for getting all active users that are member of the group "samplegroup" in active directory:
$query_id++;
$ldap_queries[$query_id]['ldapServerId'] = 0;
$ldap_queries[$query_id]['name'] = 'All members of samplegroup';
$ldap_queries[$query_id]['userbase'] = 'OU=USER_GROUP,DC=xxx,DC=yyy';
$ldap_queries[$query_id]['userfilter'] = '(&(objectClass=user)(memberOf=CN=samplegroup,OU=Group Global,OU=USER_GROUP,DC=xxx,DC=yyy)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))';
$ldap_queries[$query_id]['userscope'] = 'sub';
$ldap_queries[$query_id]['firstname_attr'] = 'givenname';
$ldap_queries[$query_id]['lastname_attr'] = 'sn';
$ldap_queries[$query_id]['email_attr'] = 'mail';
$ldap_queries[$query_id]['token_attr'] = ''; // Leave empty for Auto Token generation by phpsv
$ldap_queries[$query_id]['language'] = '';
$ldap_queries[$query_id]['attr1'] = '';
$ldap_queries[$query_id]['attr2'] = '';
Outro exemplo de consulta de usuários:
$ldap_queries[$query_id]['userfilter'] = '(&(objectCategory=Person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))'; // AD doesn't recognise enabled accounts in the normal way, so instead, we check users are not disabled
- Considere adicionar (mail=*) aos seus filtros de usuário para ignorar usuários sem endereço de e-mail.
Exemplo de consulta de grupo:
$ldap_queries[$query_id]['groupfilter'] = '(&(objectClass=group)(cn=Domain Admins))'; // AD doesn't use the standard attribute name for groups, so use this example instead.
Criando automaticamente uma consulta por grupo do Active Directory
Se você mantém os grupos dos participantes do seu questionário em uma única unidade organizacional (OU), não é necessário escrever uma consulta para cada grupo. O código a seguir lista todos os grupos dessa OU e cria uma consulta por grupo. A consulta inclui todos os membros habilitados do grupo, inclusive os membros de grupos aninhados.
Adicione o código ao arquivo config/ldap.php depois das definições de servidor e de consultas e antes da linha //DO NOT CHANGE BELOW HERE. Em seguida, defina as quatro variáveis no início:
- $groupServerId: o $serverId do servidor a ser usado;
- $groupContainer: o DN da OU que contém os grupos. Somente os grupos diretamente nessa OU são listados, não os grupos em sub-OUs;
- $groupUserBase: o DN raiz sob o qual os membros do grupo são pesquisados;
- $groupNameAttr: o atributo do grupo (em minúsculas) usado como nome da consulta na interface, por exemplo 'info' (o campo "Notes" em "Active Directory Users and Computers") ou 'description'. Se um grupo não tiver valor nesse atributo, seu cn será usado.
$groupServerId = 0;
$groupContainer = 'OU=Survey groups,DC=xxx,DC=yyy';
$groupUserBase = 'DC=xxx,DC=yyy';
$groupNameAttr = 'info';
$srv = $ldap_server[$groupServerId];
$ds = ldap_connect(($srv['encrypt'] == 'ldaps' ? 'ldaps://' : 'ldap://') . $srv['server'] . ':' . $srv['port']);
if ($ds) {
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $srv['protoversion'] == 'ldapv3' ? 3 : 2);
ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
// Never send the bind password if Start-TLS was requested but failed
$secure = $srv['encrypt'] != 'start-tls' || @ldap_start_tls($ds);
$bound = $secure && (empty($srv['binddn']) ? @ldap_bind($ds) : @ldap_bind($ds, $srv['binddn'], $srv['bindpw']));
$result = $bound ? @ldap_list($ds, $groupContainer, '(objectCategory=group)', array('cn', $groupNameAttr)) : false;
$groups = $result ? ldap_get_entries($ds, $result) : array('count' => 0);
for ($i = 0; $i < $groups['count']; $i++) {
$query_id++;
$ldap_queries[$query_id]['ldapServerId'] = $groupServerId;
$ldap_queries[$query_id]['name'] = isset($groups[$i][$groupNameAttr][0]) ? $groups[$i][$groupNameAttr][0] : $groups[$i]['cn'][0];
$ldap_queries[$query_id]['userbase'] = $groupUserBase;
// Enabled users with an email address that are members of the group, directly or through nested groups
$ldap_queries[$query_id]['userfilter'] = '(&(objectCategory=person)(objectClass=user)(mail=*)'
. '(!(userAccountControl:1.2.840.113556.1.4.803:=2))'
. '(memberOf:1.2.840.113556.1.4.1941:=' . ldap_escape($groups[$i]['dn'], '', LDAP_ESCAPE_FILTER) . '))';
$ldap_queries[$query_id]['userscope'] = 'sub';
$ldap_queries[$query_id]['firstname_attr'] = 'givenname';
$ldap_queries[$query_id]['lastname_attr'] = 'sn';
$ldap_queries[$query_id]['email_attr'] = 'mail';
$ldap_queries[$query_id]['token_attr'] = '';
$ldap_queries[$query_id]['language'] = '';
$ldap_queries[$query_id]['attr1'] = '';
$ldap_queries[$query_id]['attr2'] = '';
}
ldap_unbind($ds);
}
Pontos a ter em mente:
- O código se conecta ao diretório sempre que a página "Importar participantes de LDAP" é aberta ou enviada, de modo que novos grupos aparecem sem alterar a configuração. Se a conexão ou o bind falhar, a página mostrará apenas as consultas que você definiu manualmente.
- A regra de correspondência 1.2.840.113556.1.4.1941 (LDAP_MATCHING_RULE_IN_CHAIN) resolve grupos aninhados. Ela existe somente no Active Directory, portanto este exemplo não funciona com outros servidores LDAP. Nesses casos, use uma consulta de grupo combinada para cada grupo.
- Para listar também os grupos em sub-OUs de $groupContainer, substitua ldap_list por ldap_search.
- Para listar grupos de mais de uma OU, repita o código com outros valores para as quatro variáveis.
Encontre mais informações sobre a estrutura LDAP do Active Directory em Active Directory Architecture e Active Directory Technical Specification.