Manual:Active Directory Integration
Appearance
From mediawiki.org
PluggableAuth with Active-Directory LDAP
[edit ]With the evolution of Extension:PluggableAuth and LDAP Stack, getting integrated with Active-Directory LDAP is possible, but somewhat complex for new-comers.
A configuration example is provided here, to ease the setup process for those wishing to integrate with MS-AD via LDAP.
Objectives / Aims
[edit ]- Configure Mediawiki to use LDAP settings from a single location - ldap.json
- Users will login with NT-Logon Username, also known as SAMAccountName attribute in a standard AD-schema.
Method
[edit ]- LDAP Stack extensions use a number of LDAP attributes to auto-configure the Mediawiki User: SAMAccountName, DisplayName, Mail.
- LDAP Stack extensions use memberof attribute values to determine if any Security-Groups / Distribution-Lists map to Mediawiki Groups
Versioning
[edit ]- LDAP Stack extensions should all be at the same version - Long Term Support (LTS) versions are recommended (e.g. 1.35)
- Direct downloads can be performed from: https://extdist.wmflabs.org/dist/extensions/
- Check the PluggableAuth Compatibility Matrix to see which versions of each LDAP Stack extensions are supported.
MediaWiki Release | Recommended Extension Version | Test Status | Latest Test Date |
---|---|---|---|
1.35 (LTS) | LDAPxxx_master | Tested | March 2020 |
Required Extensions
[edit ]- Extension:LDAPAuthorization
- Extension:LDAPAuthentication2
- Extension:LDAPGroups
- Extension:LDAPProvider
- Extension:LDAPUserInfo
- Extension:PluggableAuth
Required AD Bind-Account
[edit ]- Mediawiki uses an LDAP Bind-User / Bind-Password for communications with Active-Directory.
- Ensure an AD user is provisioned, and grab the LDAP Distinguished Name for the User
- Sample: CN=MediawikiAuthenticator,OU=Users,DC=acme,DC=com
LDAP Environment
[edit ]The important configuration entities are detailed below - replace the default-values with your own when tuning ldap.json
Entity | Value | Comments |
---|---|---|
Domain | acme.com | AD-Forest Domain Name |
Root Distinguished-Name (DN) | dc=acme,dc=com | Use MS "Domains and Trusts" console, with Advanced-View enabled, to view domain LDAP attribute (DN) |
User Distinguished-Name (DN) | dc=acme,dc=com | Use MS "Domains and Trusts" console, with Advanced-View enabled, to view domain LDAP attribute (DN) |
Bind-Account Distinguished-Name (DN) | CN=MediawikiAuthenticator,OU=Users,DC=acme,DC=com | Use MS "Domains and Trusts" console, with Advanced-View enabled, to view AD User attribute (DN)
This value is case-sensitive. |
Encryption | clear | No TLS/SSL is used in the example. |
User Search Attribute | samaccountname | Utilise MS-AD samaccountname attribute to locate a single LDAP record. |
User Group Membership Attribute | memberof | Utilise MS-AD memberof attribute, to get list of Group-DNs that user is a member of. |
Configuration Example: LDAP Configuration with 1 Group-Mapping
[edit ]This example works for a small single-domain forest, or multi-domain forest (by using the parent domain).
Install Mediawiki and Extensions
[edit ]- Install PHP, and the php-ldap module (usually available on the same package-manager as PHP)
- Install Mediawiki, perform install and update routines.
- Install all extensions listed above (Required Extensions) into /extensions/
Prepare ldap.json
[edit ]Create an LDAP configuration file. For simplicity, we place this new file at /var/www/ldap.json then protect it for reading by the web-server.
touch/var/www/ldap.json chownwww-data:www-data/var/www/ldap.json chmod600/var/www/ldap.json # use your favourite editor to add the following json vi/var/www/ldap.json
{ "acme.com":{ "connection":{ "server":"my-domain-controller.acme.com", "port":"389",#636forssl "use-tls":"true", "user":"CN=MediawikiAuthenticator,OU=Users,DC=acme,DC=com", "pass":"foobar", "enctype":"clear",#"ssl"ifneeded "options":{ "LDAP_OPT_DEREF":1 }, "basedn":"dc=acme,dc=com", "userbasedn":"dc=acme,dc=com", "groupbasedn":"dc=acme,dc=com", "searchattribute":"samaccountname", "usernameattribute":"samaccountname", "realnameattribute":"cn", "emailattribute":"mail", "grouprequest":"MediaWiki\\Extension\\LDAPProvider\\UserGroupsRequest\\UserMemberOf::factory", "presearchusernamemodifiers":["spacestounderscores","lowercase"] }, "userinfo":[], "authorization":[], "groupsync":{ "mapping":{ "engineering":"CN=EngineeringCoreTeam,OU=Groups,DC=acme,DC=com", "bureaucrat":"CN=Mediawiki Admins,OU=Groups,DC=acme,DC=com", "interface-admin":"CN=Mediawiki Admins,OU=Groups,DC=acme,DC=com", "sysop":"CN=Mediawiki Admins,OU=Groups,DC=acme,DC=com" } } } }
- A critical piece of configuration is the acme.com key in line #2 of the JSON.
- Replace this with your AD Domain
- Replace the following values in connection
- server
- user
- pass
- basedn
- userbasedn
- Replace the groupsync -> mapping values with some valid Group-DNs taken from MS "Domains and Trusts" console.
- This allows you to specify a DN which provides sysop privileges
Tune LocalSettings.php
[edit ]// Safe IP or not (for bypassing external login via AD) $safeIPs = array('127.0.0.1','localhost'); $ipsVars = array('HTTP_X_FORWARDED_FOR','HTTP_X_REAL_IP','REMOTE_ADDR'); foreach ($ipsVars as $ipsVar) { if (isset($_SERVER[$ipsVar]) && mb_strlen($_SERVER[$ipsVar]) > 3 ) { $wikiRequestIP = $_SERVER[$ipsVar]; break; } } $wikiRequestSafe = ( isset($wikiRequestIP ) && ( in_array($wikiRequestIP,$safeIPs) )); // Create Wiki-Group 'engineering' from default user group $wgGroupPermissions['engineering'] = $wgGroupPermissions['user']; // Private Wiki. External LDAP login. Default NS requires login. $wgEmailConfirmToEdit = false; $wgGroupPermissions['*']['edit'] = false; $wgGroupPermissions['*']['read'] = false; $wgGroupPermissions['*']['createaccount'] = false; $wgGroupPermissions['sysop']['createaccount'] = false; $wgGroupPermissions['*']['autocreateaccount'] = true; $wgBlockDisablesLogin = true; // Load LDAP Config from JSON $ldapJsonFile = "/var/www/ldap.json"; $ldapConfig = false; if (is_file($ldapJsonFile) && is_dir("$IP/extensions/LDAPProvider")) { $testJson = @json_decode(file_get_contents($ldapJsonFile),true); if (is_array($testJson)) { $ldapConfig = true; } else { error_log("Found invalid JSON in file: /var/www/ldap.json"); } } // Activate Extension if ( $ldapConfig ) { wfLoadExtension( 'PluggableAuth' ); wfLoadExtension( 'LDAPProvider' ); wfLoadExtension( 'LDAPAuthentication2' ); wfLoadExtension( 'LDAPAuthorization' ); wfLoadExtension( 'LDAPUserInfo' ); wfLoadExtension( 'LDAPGroups' ); $LDAPProviderDomainConfigs = $ldapJsonFile; // Force LDAPGroups to sync by choosing a domain (e.g. first JSON object in ldap.json) $LDAPProviderDefaultDomain = array_key_first(json_decode(file_get_contents($LDAPProviderDomainConfigs), true)); $wgPluggableAuth_Config = array( array( 'plugin' => 'LDAPAuthentication2', 'buttonLabelMessage' => 'pt-login-button', 'data' => ['domain'=> $LDAPProviderDefaultDomain] ), array('plugin' => 'LDAPAuthorization'), ); if ($wikiRequestSafe) { $LDAPAuthentication2AllowLocalLogin = true; } }
Run update.php and test LDAP login
[edit ]- After configuring LocalSettings.php and browsing to your Wiki, you should be able to load the public index / Main Page.
- LDAP login will fail until you run: php /.../mediawiki/maintenance/update.php
- This is because the LDAP extensions require some new SQL tables.
- After running update.php, start a fresh browser session and perform a test login.
Debugging
[edit ]- If you encounter problems, enable debug and review the output during login.
- Validate config values and system connectivity using ldapsearch
ldapsearch-hserver-pport-D"user"-w"pass"-x-v-b"basedn"
- Validate config files and PHP Connectivity to LDAP using CheckLogin and ShowUserInfo located in extensions/LDAPProvider/maintenance/
- If running SELinux check to see if webserver (Apache) is allowed to connect to LDAP
# getsebool -a | grep ldap authlogin_nsswitch_use_ldap-->off httpd_can_connect_ldap-->off # setsebool -P httpd_can_connect_ldap on # getsebool -a | grep ldap authlogin_nsswitch_use_ldap-->off httpd_can_connect_ldap-->on
- Also see Manual:How to debug/Login problems