This file is intended to be record every configuration that is made in MediaWiki. It is meant to reside in ldap-demo/README.org
and use org-tangle to extract the configuration files. “Tangling” is from Donald Knuth’s idea for literate programming.
Any time a part of the configuration needs to be changed, the following process should be followed:
- Edit the relevant parts of this file
- Tangle the file by opening it in emacs and, from within the file, typing “CTRL-C CTRL-v t” or, in the terms used by emacs,
C-c C-v t
. - Check the resulting files into the git repository.
- git checkout with submodules
if [ ! -x mediawiki/.git ]; then
git submodule add -f -b REL1_31 https://gerrit.wikimedia.org/r/p/mediaiwki/core mediawiki
else
( cd mediawiki && git fetch origin && git checkout REL1_31 )
fi
ls -l mediawiki/extensions
- ran through basic installer, get LocalSettings.php:
<?php
# This file was automatically generated by the MediaWiki 1.27.4
# installer. If you make manual changes, please keep track in case you
# need to recreate them later.
#
# See includes/DefaultSettings.php for all configurable settings
# and their default values, but don't forget to make changes in _this_
# file, not there.
#
# Further documentation for configuration settings may be found at:
# https://www.mediawiki.org/wiki/Manual:Configuration_settings
# Protect against web entry
if ( !defined( 'MEDIAWIKI' ) ) {
exit;
}
## Uncomment this to disable output compression
# $wgDisableOutputCompression = true;
$wgSitename = "LDAP Demo";
$wgMetaNamespace = "LDAP_Demo";
## The URL base path to the directory containing the wiki;
## defaults for all runtime URL paths are based off of this.
## For more information on customizing the URLs
## (like /w/index.php/Page_title to /wiki/Page_title) please see:
## https://www.mediawiki.org/wiki/Manual:Short_URL
$wgScriptPath = "/mediawiki";
## The protocol and server name to use in fully-qualified URLs
$wgServer = "http://debiankde.local";
## The URL path to static resources (images, scripts, etc.)
$wgResourceBasePath = $wgScriptPath;
## The URL path to the logo. Make sure you change this from the default,
## or else you'll overwrite your logo when you upgrade!
$wgLogo = "$wgResourceBasePath/resources/assets/wiki.png";
## UPO means: this is also a user preference option
$wgEnableEmail = true;
$wgEnableUserEmail = true; # UPO
$wgEmergencyContact = "[email protected]";
$wgPasswordSender = "[email protected]";
$wgEnotifUserTalk = false; # UPO
$wgEnotifWatchlist = false; # UPO
$wgEmailAuthentication = true;
## Database settings
$wgDBtype = "mysql";
$wgDBserver = "10.5.5.1";
$wgDBname = "ldap-demo";
$wgDBuser = "wikiuser";
$wgDBpassword = "wikipass";
# MySQL specific settings
$wgDBprefix = "";
# MySQL table options to use during installation or update
$wgDBTableOptions = "ENGINE=InnoDB, DEFAULT CHARSET=binary";
# Experimental charset support for MySQL 5.0.
$wgDBmysql5 = false;
## Shared memory settings
$wgMainCacheType = CACHE_MEMCACHED;
$wgMemCachedServers = [ '10.5.5.1:11211' ];
## To enable image uploads, make sure the 'images' directory
## is writable, then set this to true:
$wgEnableUploads = true;
$wgUseImageMagick = true;
$wgImageMagickConvertCommand = "/usr/bin/convert";
# InstantCommons allows wiki to use images from https://commons.wikimedia.org
$wgUseInstantCommons = false;
## If you use ImageMagick (or any other shell command) on a
## Linux server, this will need to be set to the name of an
## available UTF-8 locale
$wgShellLocale = "en_US.utf8";
## Set $wgCacheDirectory to a writable directory on the web server
## to make your wiki go slightly faster. The directory should not
## be publically accessible from the web.
#$wgCacheDirectory = "$IP/cache";
# Site language code, should be one of the list in ./languages/data/Names.php
$wgLanguageCode = "en";
$wgSecretKey = "828af370037801add29264e58507376f4769244d6d99b624a607b96727a78aae";
# Changing this will log out all existing sessions.
$wgAuthenticationTokenVersion = "1";
# Site upgrade key. Must be set to a string (default provided) to turn on the
# web installer while LocalSettings.php is in place
$wgUpgradeKey = "cd79c75b8c0cb68d";
## For attaching licensing metadata to pages, and displaying an
## appropriate copyright notice / icon. GNU Free Documentation
## License and Creative Commons licenses are supported so far.
$wgRightsPage = ""; # Set to the title of a wiki page that describes your license/copyright
$wgRightsUrl = "";
$wgRightsText = "";
$wgRightsIcon = "";
# Path to the GNU diff3 utility. Used for conflict resolution.
$wgDiff3 = "/usr/bin/diff3";
# The following permissions were set based on your choice in the installer
$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['*']['read'] = false;
## Default skin: you can change the default skin. Use the internal symbolic
## names, ie 'vector', 'monobook':
$wgDefaultSkin = "vector";
# End of automatically generated settings.
# Add more configuration options below.
- Add loader to LocalSettings:
wfLoadSkin( 'Vector' );
- Symlink LocalSettings:
rm -f mediawiki/LocalSettings.php
ln -s ../LocalSettings.php mediawiki
ls -ld mediawiki/LocalSettings.php
error_reporting( -1 );
ini_set( 'display_errors', 1 );
$wgShowSQLErrors = true;
$wgDebugDumpSql = true;
$wgShowDBErrorBacktrace = true;
$wgShowExceptionDetails = true;
$wgDebugLogFile = "/var/log/mediawiki/debug.log";
$wgMainCacheType = CACHE_MEMCACHED;
For this demonstration, we’ll set up a local OpenLDAP server and populate it with data from ForumSys’s LDAP test server.
Note that the \025 here is C-u so that readline erases everything on the line.
#!/usr/bin/expect
spawn dpkg-reconfigure slapd -freadline
expect "Omit OpenLDAP server configuration?"
send "\025n\r"
expect "DNS domain name:"
send "\025example.com\r"
expect "Organization name:"
send "\025nodomain\r"
expect "Administrator password:"
send "password\r"
expect "Confirm password:"
send "password\r"
expect "Database backend to use:"
send "\0253\r"
expect "Do you want the database to be removed when slapd is purged?"
send "\025yes\r"
# done
expect eof
In order to make this idempotent, we erase all the data and reconfigure with the above script. We also install gosa-schema to get gender attributes.
sudo dpkg --purge slapd
sudo DEBIAN_FRONTEND=noninteractive apt -y install slapd gosa-schema
sudo service slapd stop
sudo rm -rf /var/lib/ldap
sudo expect slapd-config
sudo chown -R openldap:openldap /etc/ldap/slapd.d
sudo service slapd start
Get a database from the sample server
ldapsearch -w password -D "cn=read-only-admin,dc=example,dc=com" -b "dc=example,dc=com" -H ldap://ldap.forumsys.com -LLL | \
grep -v ^userPassword:: | sed '/dn: dc=example,dc=com/,/^$/d' | sed '/dn: cn=admin,dc=example,dc=com/,/^$/d' | \
sed 's,objectClass: inetOrgPerson,userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9\nobjectClass: inetOrgPerson,'
The following is the results of the above command saved here for later
dn: uid=newton,dc=example,dc=com
sn: Newton
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
uid: newton
mail: [email protected]
cn: Isaac Newton
dn: uid=einstein,dc=example,dc=com
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Albert Einstein
sn: Einstein
uid: einstein
mail: [email protected]
telephoneNumber: 314-159-2653
dn: uid=tesla,dc=example,dc=com
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
objectClass: posixAccount
cn: Nikola Tesla
sn: Tesla
uid: tesla
mail: [email protected]
uidNumber: 88888
gidNumber: 99999
homeDirectory: home
dn: uid=galieleo,dc=example,dc=com
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Galileo Galilei
sn: Galilei
uid: galieleo
mail: [email protected]
dn: uid=euler,dc=example,dc=com
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
uid: euler
sn: Euler
cn: Leonhard Euler
mail: [email protected]
dn: uid=gauss,dc=example,dc=com
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Carl Friedrich Gauss
sn: Gauss
uid: gauss
mail: [email protected]
dn: uid=riemann,dc=example,dc=com
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Bernhard Riemann
sn: Riemann
uid: riemann
mail: [email protected]
dn: uid=euclid,dc=example,dc=com
uid: euclid
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Euclid
sn: Euclid
mail: [email protected]
dn: ou=mathematicians,dc=example,dc=com
uniqueMember: uid=euclid,dc=example,dc=com
uniqueMember: uid=riemann,dc=example,dc=com
uniqueMember: uid=euler,dc=example,dc=com
uniqueMember: uid=gauss,dc=example,dc=com
uniqueMember: uid=test,dc=example,dc=com
ou: mathematicians
cn: Mathematicians
objectClass: groupOfUniqueNames
objectClass: top
dn: ou=scientists,dc=example,dc=com
uniqueMember: uid=einstein,dc=example,dc=com
uniqueMember: uid=galieleo,dc=example,dc=com
uniqueMember: uid=tesla,dc=example,dc=com
uniqueMember: uid=newton,dc=example,dc=com
uniqueMember: uid=training,dc=example,dc=com
uniqueMember: uid=jmacy,dc=example,dc=com
ou: scientists
cn: Scientists
objectClass: groupOfUniqueNames
objectClass: top
dn: cn=read-only-admin,dc=example,dc=com
sn: Read Only Admin
cn: read-only-admin
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
dn: ou=italians,ou=scientists,dc=example,dc=com
uniqueMember: uid=tesla,dc=example,dc=com
ou: italians
cn: Italians
objectClass: groupOfUniqueNames
objectClass: top
dn: uid=test,dc=example,dc=com
objectClass: posixAccount
objectClass: top
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
gidNumber: 0
givenName: Test
sn: Test
displayName: Test
uid: test
initials: TS
homeDirectory: home
cn: Test
uidNumber: 24601
o: Company
dn: ou=chemists,dc=example,dc=com
ou: chemists
objectClass: groupOfUniqueNames
objectClass: top
uniqueMember: uid=curie,dc=example,dc=com
uniqueMember: uid=boyle,dc=example,dc=com
uniqueMember: uid=nobel,dc=example,dc=com
uniqueMember: uid=pasteur,dc=example,dc=com
cn: Chemists
dn: uid=curie,dc=example,dc=com
uid: curie
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Marie Curie
sn: Curie
mail: [email protected]
dn: uid=nobel,dc=example,dc=com
uid: nobel
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
mail: [email protected]
sn: Nobel
cn: Alfred Nobel
dn: uid=boyle,dc=example,dc=com
uid: boyle
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Robert Boyle
sn: Boyle
mail: [email protected]
telephoneNumber: 999-867-5309
dn: uid=pasteur,dc=example,dc=com
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
sn: Pasteur
cn: Louis Pasteur
uid: pasteur
telephoneNumber: 602-214-4978
mail: [email protected]
dn: uid=nogroup,dc=example,dc=com
uid: nogroup
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: No Group
mail: [email protected]
sn: Group
dn: uid=training,dc=example,dc=com
uid: training
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: FS Training
sn: training
mail: [email protected]
telephoneNumber: 888-111-2222
dn: uid=jmacy,dc=example,dc=com
uid: jmacy
telephoneNumber: 888-111-2222
sn: training
cn: FS Training
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
mail: [email protected]
The following command loads the above output into the ldap
ldapmodify -a -c -w password -D "cn=admin,dc=example,dc=com" -H ldap://localhost < ldap.ldif
- Check out LDAPProvider, LDAPAuthentication, LDAPUserInfo, LDAPGroups
for ext in LDAPProvider LDAPAuthentication LDAPUserInfo LDAPGroups; do
dir=extensions/$ext
if [ ! -d $dir ]; then
git submodule add -f https://github.com/mwstake/mediawiki-extensions-$ext $dir
git submodule update --init $dir
else
( cd $dir && git checkout master && git pull origin )
fi
done
dir=extensions/PluggableAuth
if [ ! -d $dir ]; then
git submodule add -f https://github.com/wikimedia/mediawiki-extensions-PluggableAuth $dir
git submodule update --init $dir
else
( cd $dir && git checkout master && git pull origin )
fi
Note that LDAPAuthentication depends on mediawiki/pluggable-auth, but it needs to be registered with Composer. See I532f9b4784106ac0cf40371f10601c4a8334412b.
{
"require": {
"mediawiki/ldap-provider": "dev-master",
"mediawiki/ldap-user-info": "dev-master",
"mediawiki/ldap-groups": "dev-master",
"mediawiki/ldap-authentication": "dev-master"
},
"minimum-stability": "dev",
"prefer-stable": false,
"config": {
"minimum-stability": "dev",
"prefer-stable": false,
"prefer": "source"
},
"repositories": [
{
"type": "vcs",
"url": "../extensions/LDAPGroups"
},
{
"type": "vcs",
"url": "../extensions/LDAPUserInfo"
},
{
"type": "vcs",
"url": "../extensions/LDAPAuthentication"
},
{
"type": "vcs",
"url": "../extensions/LDAPProvider"
},
{
"type": "vcs",
"url": "../extensions/PluggableAuth"
}
]
}
- Set up symlink for file
ln -s ../composer.local.json mediawiki
ls -dl composer.local.json mediawiki/composer.local.json
- Run composer update
( cd mediawiki && composer update -vv -n --no-ansi )
- Enable extensions in LocalSettings.php:
wfLoadExtensions( [ 'LDAPProvider', 'LDAPAuthentication', 'LDAPUserInfo', 'LDAPGroups', 'PluggableAuth' ] );
- Allow automatic creation of accounts
Note that you if you still have problems you may be blacklisted (debug log will show [authentication] MediaWiki\Auth\AuthManager::autoCreateUser: blacklisted in session
). To fix, clear cookies.
$wgGroupPermissions['*']['autocreateaccount'] = true;
- Update the schema
cd mediawiki && MW_INSTALL_PATH=`pwd` php maintenance/update.php
searchstring
how we construct a user name to bind with
searchattribute
is the attribute that we look for once we have successfully logged in to get our user id.
userbasedn
is where to look for users
usernameattribute
, realnameattribute
, and emailattribute
are used for extracting the cooresponding user info from LDAP.
A search string will be constructed from searchattribute
and userbasedn
if searchstring
is not provided.
The userinfo
here is used by LDAPProvider, but should be in LDAPUserInfo.
Also, if no sections are found an error with directions should be printed.
{
"LDAP Demo": {
"connection": {
"server": "10.5.5.1",
"user": "cn=read-only-admin,dc=example,dc=com",
"pass": "password",
"basedn": "dc=example,dc=com",
"userbasedn": "dc=example,dc=com",
"searchattribute": "uid",
"usernameattribute": "uid",
"realnameattribute": "cn",
"emailattribute": "mail"
},
"userinfo": {
"attributes-map": {
"email": "mail",
"realname": "cn",
"nickname": "uid",
"language": "preferredlanguage"
}
}
}
}
$LDAPProviderDomainConfigs = "$IP/../ldapprovider.json";
$LDAPProviderCacheTime = 300;
$LDAPProviderCacheType = CACHE_MEMCACHED;
# Following are only for testing and should be removed when this is done.
$LDAPProviderCacheTime = 1;
$LDAPProviderCacheType = CACHE_NONE;
groupOfUniqueNames
and uniqueMember
to handle groups.[fn:1] Tell LDAPProvider
to use UniqueMember
in the ldapprovider.json:
jq '.["LDAP Demo"]["groupsync"]["grouplookup"] = "UniqueMember"' ldapprovider.json | sponge ldapprovider.json
jq '.["LDAP Demo"]["groupsync"]["mapping"] = { "Mathematicians": "ou=mathematicians,dc=example,dc=com","Scientists": "ou=scientists,dc=example,dc=com","Italian scientists": "ou=italians,ou=scientists,dc=example,dc=com","Chemists": "ou=chemists,dc=example,dc=com"}' ldapprovider.json | sponge ldapprovider.json
You can do a UniqueMember search from the command line like this:
for user in einstein euclid pasteur tesla; do
echo For $user
echo =========
ldapsearch -LLL -D cn=read-only-admin,dc=example,dc=com -w password -b dc=example,dc=com "(&(objectclass=groupOfUniqueNames)(uniqueMember=uid=$user,dc=example,dc=com))" dn
done
- Math namespace is only writable by mathematicians
- Main namespace is writable by all users
- Chemistry namespace is readable and writable only by chemists
NamespaceManager is a MediaWiki extension which is intended to help you manage namespace configuration by putting all configuration in a seperate json file.
- Add mediawiki/namespace-manager to composer.local.json
jq '.["require"]["mediawiki/namespace-manager"] = "dev-master"' composer.local.json | sponge composer.local.json
- Run composer update
( cd mediawiki && composer update -vv -n --no-ansi )
- Load NamespaceManager and point to the namespace map file in LocalSettings.php
wfLoadExtension( "NamespaceManager" );
$NamespaceManagerMapFile = "$IP/../ns.json";
- Create a namespace mapping file
{
"globalAdmin": "sysop",
"Math": {
"constant": "NS_MATH",
"id": 5000,
"includable": false,
"lockdown": [
"move", "edit", "create", "createpage", "createtalk"
],
"group": "Mathematicians",
"permission": "edit-math"
},
"Chemistry": {
"constant": "NS_CHEMISTRY",
"id": 5002,
"includable": false,
"lockdown": [
"read", "move", "edit", "create", "createpage", "createtalk"
],
"group": "Chemists",
"permission": "edit-chemistry"
}
}
Add Lockdown so Namespaces can actually be hidden
- Check it out as a submodule
dir=extensions/Lockdown
if [ ! -d $dir ]; then
git submodule add -b REL1_31 -f ssh://gerrit.wikimedia.org:29418/mediawiki/$dir $dir
git submodule update --init $dir
else
( cd $dir && git checkout REL1_31 && git pull origin )
fi
rm -f mediawiki/$dir
ln -s ../../$dir mediawiki/$dir
- Call it from LocalSettings.php
wfLoadExtension( "Lockdown" );
[fn:1] See GroupOfUniqueNames vs groupOfNames and memberOf for information on different ways directory servers manage groups.