Nastavení LDAP
From LimeSurvey Manual
Obecné
Abyste mohli tuto funkci používat, musíte povolit podporu LDAP v souboru config.php a nakonfigurovat parametry LDAP v souboru config/ldap.php.
Povolení LDAP v config.php
- $enableLdap: pokud chcete v LimeSurvey používat funkce LDAP, musíte tento parametr nastavit na true (ve výchozím nastavení je false):
'config'=>array( 'debug'=>0, 'debugsql'=>0, 'enableLdap'=>true, )
Definování serverů LDAP
Nejprve definujte možnosti připojení k serveru LDAP v souboru "application/config/ldap.php". Pro každý server jsou k dispozici následující možnosti:
- $serverId: Celé číslo, které identifikuje tento server LDAP. Používá se v definicích dotazů k přiřazení serveru ke konkrétnímu dotazu;
- $ldap_server[$serverId]['server']: IP adresa nebo název DNS serveru LDAP. Pokud používáte zabezpečená připojení SSL (LDAPs nebo LDAP+Start-TLS), musí tento název odpovídat položce CN certifikátu serveru (nebo SubjectAlternativeName);
- $ldap_server[$serverId]['port']: Port TCP, na kterém server LDAP naslouchá. Obvykle je to 389 pro LDAP a LDAP+Start-TLS a 636 pro LDAPs;
- $ldap_server[$serverId]['protoversion']: Může být 'ldapv2' nebo 'ldapv3' podle protokolu, který váš server podporuje. Preferovaným protokolem je 'ldapv3'. Pokud však chcete používat šifrovaná připojení, mějte na paměti, že LDAPs je podporováno v režimu 'ldapv2', zatímco Start-TLS je metoda šifrování pro 'ldapv3';
- $ldap_server[$serverId]['encrypt']: Definuje použitou metodu šifrování. 'ldaps' je podporováno pro servery 'ldapv2', 'start-tls' pro servery 'ldapv3'. Klíčové slovo 'none' se používá pro nešifrovanou komunikaci LDAP;
- Nezapomeňte, že u šifrování 'ldaps' nebo 'start-tls' musí být webový server schopen ověřit certifikát serveru LDAP. Proto musíte ve své knihovně openldap definovat svou certifikační autoritu (v systému Linux se to obvykle provádí v souboru /etc/openldap/ldap.conf).
- $ldap_server[$serverId]['referrals']: Logický parametr, který určuje, zda se mají následovat odkazy (referrals), nebo ne (pro ActiveDirectory použijte false);
- $ldap_server[$serverId]['encoding']: Nepovinný parametr, který určuje kódování, jež adresář LDAP používá k ukládání řetězců. Tento parametr obvykle nemusíte nastavovat, protože výchozí předpokládané kódování 'utf-8' je standardním kódováním adresářů LDAP. Pokud však používáte Active Directory a máte problémy s importem řetězců s diakritikou, zkuste tento parametr nastavit na kódování používané ve vaší oblasti (například 'cp850' pro západní Evropu). Úplný seznam podporovaných kódování najdete v rozbalovacím seznamu "Znaková sada souboru" v rozhraní Import tokenů ze souboru CSV.
Dále je třeba definovat, jaká autentizace je nutná pro přístup k adresáři. Pokud je povolen 'anonymní' přístup, NENASTAVUJTE následující dva parametry, jinak je nastavte odpovídajícím způsobem:
- $ldap_server[$serverId]['binddn']: DN uživatele 'LDAP', který smí číst adresář;
- $ldap_server[$serverId]['bindpw']: Heslo výše uvedeného uživatele LDAP.
Pokud potřebujete definovat další servery LDAP, přidejte následující řádek, který zvýší hodnotu serverID, a definujte nové parametry:
- $serverId++.
Definování dotazů v config/ldap.php
Upozornění: pokud je v některém z těchto parametrů vyžadován název atributu LDAP, používejte pouze malá písmena: například displayname a NE displayName.
Vzorové konfigurace najdete v souboru config/ldap.php.
Jednoduché dotazy
Začněme jednoduchými dotazy. Tyto dotazy filtrují záznamy LDAP pouze na základě jejich vlastních atributů a umístění. Pro dotazování ActiveDirectory obvykle stačí.
- $query_id: je ID dotazu LDAP;
- $ldap_queries[$query_id]['ldapServerId']: Přiřadí dotaz ke konkrétnímu serveru;
- $ldap_queries[$query_id]['name']: Řetězec popisující dotaz. Zobrazí se v rozhraní;
- $ldap_queries[$query_id]['userbase']: Kořenové DN pro vyhledávání uživatelů;
- $ldap_queries[$query_id]['userfilter']: Filtr používaný k výběru potenciálních záznamů uživatelů. Musí být uzavřen v závorkách;
- $ldap_queries[$query_id]['userscope']: rozsah vyhledávání uživatelů v LDAP ('base', 'one' nebo 'sub');
- $ldap_queries[$query_id]['firstname_attr']: Atribut LDAP, který bude namapován na pole Jméno v záznamu tokenu;
- $ldap_queries[$query_id]['lastname_attr']: Atribut LDAP, který bude namapován na pole Příjmení v záznamu tokenu;
- $ldap_queries[$query_id]['email_attr']: Atribut LDAP, který bude namapován na pole e-mailové adresy v záznamu tokenu.
Volitelně můžete z adresáře získat další informace:
- $ldap_queries[$query_id]['token_attr']: Atribut LDAP, který bude namapován na kód tokenu;
- $ldap_queries[$query_id]['language']: Atribut LDAP, který bude namapován na kód jazyka uživatele;
- $ldap_queries[$query_id]['attr1']: Atribut LDAP, který bude namapován na pole attribute_1;
- $ldap_queries[$query_id]['attr2']: Atribut LDAP, který bude namapován na pole attribute_2.
Kombinované skupinové dotazy s členy podle DN
Nyní se podívejme, jak definovat složitější dotaz.
Následující dotazy používají první vyhledávání LDAP, které prohledává skupiny LDAP. Skupina LDAP je záznam LDAP obsahující odkazy na záznamy uživatelů ve formě:
- ID uživatelů (například posixGroups) ==> viz další část
- Nebo DN uživatelů (například groupofnames a groupofuniquenames) ==> viz níže
Zde se zabýváme skupinami obsahujícími DN uživatelů:
- definujte $query_id, $ldap_queries[$query_id]['ldapServerId'], $ldap_queries[$query_id]['name'] jak je vysvětleno výše.
Poté definujte parametry filtru skupin:
- $ldap_queries[$query_id]['groupbase']: Kořenové DN, od kterého chcete začít vyhledávat záznamy skupin;
- $ldap_queries[$query_id]['groupfilter']: Filtr LDAP, který vybere potenciální záznamy skupin;
- $ldap_queries[$query_id]['groupscope']: Rozsah vyhledávání skupin v LDAP ('one', 'base' nebo 'sub');
- $ldap_queries[$query_id]['groupmemberattr']: Název atributu LDAP v záznamu skupiny, který bude obsahovat odkazy na záznamy uživatelů;
- $ldap_queries[$query_id]['groupmemberisdn']: TRUE.
V tuto chvíli je vše nastaveno tak, aby první vyhledávání LDAP našlo uživatele odpovídající vybraným skupinám. Můžete však omezit, kteří z těchto „kandidátů“ budou vybráni, použitím dalšího filtru. To je samozřejmě nepovinné:
- $ldap_queries[$query_id]['userbase']: Základní DN pro vyhledávání uživatelů v LDAP (budou vybráni pouze kandidáti odpovídající této bázi);
- $ldap_queries[$query_id]['userscope']: Rozsah vyhledávání uživatelů v LDAP (budou vybráni pouze kandidáti odpovídající userbase+scope);
- $ldap_queries[$query_id]['userfilter']: Filtr, který se použije na záznam každého kandidáta (podle jeho atributů) a přidá další výběr.
Kombinované skupinové dotazy s členy podle UID
Nyní se podívejme, jak definovat kombinovaný skupinový dotaz, pokud jsou členy skupiny UID uživatelů, a nikoli DN uživatelů.
Stejně jako u skupinových dotazů s členy podle DN tyto dotazy používají první vyhledávání LDAP, které hledá záznamy skupin LDAP a získává jejich členy. Hodnoty těchto členů se pak použijí ve filtru vyhledávání uživatelů k nalezení odpovídajících záznamů. Proto je nutné nakonfigurovat další parametr, který definuje atribut v záznamu uživatele, jenž by měl odpovídat UID člena nalezenému ve skupinách.
Projděme si požadované parametry:
- definujte $query_id, $ldap_queries[$query_id]['ldapServerId'], $ldap_queries[$query_id]['name'] jak je vysvětleno výše
Poté definujte parametry filtru skupin:
- $ldap_queries[$query_id]['groupbase']: Kořenové DN, od kterého chcete začít vyhledávat záznamy skupin;
- $ldap_queries[$query_id]['groupfilter']: Filtr LDAP, který vybere potenciální záznamy skupin;
- $ldap_queries[$query_id]['groupscope']: Rozsah vyhledávání skupin v LDAP ('one', 'base' nebo 'sub');
- $ldap_queries[$query_id]['groupmemberattr']: Název atributu LDAP v záznamu skupiny, který bude obsahovat odkazy na záznamy uživatelů;
- $ldap_queries[$query_id]['groupmemberisdn']: FALSE;
- $ldap_queries[$query_id]['useridattr']: název atributu uživatele, který musí odpovídat UID nalezenému mezi členy skupiny.
V tuto chvíli je vše nastaveno tak, aby první vyhledávání LDAP našlo UID uživatelů odpovídající vybraným skupinám a filtr vyhledávání uživatelů se vyplní automaticky.
Můžete však omezit, kteří z těchto „kandidátů“ budou vybráni, doplněním automatického filtru uživatelů vypočteného z UID členů. To je samozřejmě nepovinné:
- $ldap_queries[$query_id]['userbase']: Základní DN pro vyhledávání uživatelů v LDAP (budou vybráni pouze kandidáti odpovídající této bázi);
- $ldap_queries[$query_id]['userscope']: Rozsah vyhledávání uživatelů v LDAP (budou vybráni pouze kandidáti odpovídající userbase+scope);
- $ldap_queries[$query_id]['userfilter']: Filtr, který se použije na záznam každého kandidáta (podle jeho atributů) a přidá další výběr.
Co Active Directory?
Active Directory (AD) je registr společnosti Microsoft, do kterého lze zadávat dotazy pomocí protokolu LDAP.
Jeho obsah je tedy možné použít pro dotazy na tokeny v LimeSurvey, vyžaduje to však znalost toho, jak je AD organizován.
- Kořen LDAP je dc=my_windows_domain_name,dc=dns_suffix2,dc=dns_suffix1
==> Pokud například vaše společnost vlastní doménu DNS 'my-company.com' a vaše doména Windows je 'employees', pak je váš kořen dc=employees,dc=my-company,dc=com
- Uživatelé a skupiny uživatelů jsou uloženi pod cn=Users,dc=my_windows_domain_name,dc=dns_suffix2,dc=dns_suffix1 (upozornění: nejde o ou=users);
- Skupiny Active Directory:
- Objekty skupin obsahují DN členů ve svém atributu 'member';
- Členství ve skupinách je rovněž uloženo v atributu memberOf každého záznamu uživatele. Tento atribut obsahuje DN skupin, do kterých uživatel patří;
- některé skupiny se nacházejí v CN=Builtin,dc=my_windows_domain_name,dc=dns_suffix2,dc=dns_suffix1:
- Například: cn=Administrator,CN=Builtin,dc=my_windows_domain_name,dc=dns_suffix2,dc=dns_suffix1;
V některých případech není dotazování do Active Directory tak snadné, proto zde uvádíme ukázkovou konfiguraci pro získání některých informací z 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'] = '';
Další příklad dotazu na uživatele:
$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
- Zvažte přidání (mail=*) do filtrů uživatelů, aby se přeskočili uživatelé bez e-mailové adresy.
Příklad dotazu na skupinu:
$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.
Automatické vytvoření jednoho dotazu pro každou skupinu Active Directory
Pokud skupiny svých respondentů uchováváte v jedné organizační jednotce (OU), nemusíte psát dotaz pro každou skupinu zvlášť. Následující kód vypíše všechny skupiny v dané OU a vytvoří pro každou skupinu jeden dotaz. Dotaz zahrnuje všechny povolené členy skupiny, včetně členů vnořených skupin.
Přidejte kód do souboru config/ldap.php za definice serveru a dotazů a před řádek //DO NOT CHANGE BELOW HERE. Poté nastavte čtyři proměnné na začátku:
- $groupServerId: hodnota $serverId serveru, který se má použít;
- $groupContainer: DN organizační jednotky, která obsahuje skupiny. Vypisují se pouze skupiny přímo v této OU, nikoli skupiny v podřízených OU;
- $groupUserBase: kořenové DN, pod kterým se vyhledávají členové skupin;
- $groupNameAttr: atribut skupiny (malými písmeny), který se použije jako název dotazu v GUI, například 'info' (pole „Poznámky“ v „Active Directory Users and Computers“) nebo 'description'. Pokud skupina v tomto atributu nemá žádnou hodnotu, použije se její cn.
$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);
}
Na co je třeba pamatovat:
- Kód se připojuje k adresáři pokaždé, když se otevře nebo odešle stránka „Importovat respondenty z LDAP“, takže se nové skupiny objeví bez změny konfigurace. Pokud se připojení nebo bind nezdaří, zobrazí se na stránce pouze dotazy, které jste definovali ručně.
- Párovací pravidlo 1.2.840.113556.1.4.1941 (LDAP_MATCHING_RULE_IN_CHAIN) řeší vnořené skupiny. Existuje pouze v Active Directory, takže tento příklad nefunguje s jinými servery LDAP. Na nich použijte pro každou skupinu raději kombinovaný dotaz na skupiny.
- Chcete-li vypsat i skupiny v podřízených OU v $groupContainer, nahraďte ldap_list za ldap_search.
- Chcete-li vypsat skupiny z více než jedné OU, zopakujte kód s jinými hodnotami čtyř proměnných.
Další informace o struktuře LDAP v Active Directory naleznete v dokumentech Active Directory Architecture a Active Directory Technical Specification.