Jump to content

Topic on Extension talk:LDAPProvider

Can't fetch group membership when using POSIX groups (memberUid: user1)

41
Sebastian19276 (talkcontribs)

Please find my plugin versions, LDAP domain config, etc below the error details. The issue I am running into is that the search string when looking up groups is malformed, and I don't know how to fix it. Does anyone have an actual working config for when groups are in LDAP like so:


dn: cn=admins,ou=groups,dc=example,dc=com

objectClass: top

objectClass: posixGroup

cn: admins

memberUid: user1

memberUid: user2


So to match my group membership, I would run the below


ldapsearch -x "(&(objectClass=*)(memberUid=users))" dn -LLL -b ou=groups,dc=example,dc=com


The output of the above is


dn: cn=admins,ou=groups,dc=example,dc=com


Yet I cannot get this same functionality with LDAPProvider. When I run


php maintenance/ShowUserGroups.php --domain "LDAP" --username "user1"


I get empty output, and see the following in the mwdebug.log


2019-12-10 19:54:14 example wikidb-w: ldap_search( $linkID, $baseDN = 'ou=groups,dc=example,dc=com', $filter = '(&(objectclass=*)(memberUid=uid=user1,ou=users,dc=example,dc=com))', $attributes = [ 'dn' ], $attrsonly = , $sizelimit = , $timelimit = , $deref =  );

2019-12-10 19:54:14 example wikidb-w: # returns Resource id #216

2019-12-10 19:54:14 example wikidb-w: ldap_get_entries( $linkID, $resultID );

2019-12-10 19:54:14 example wikidb-w: # returns: array (

  'count' => 0,

)

Full DNs:

Short names:


It is successfully connecting, as the ShowUserInfo.php script works great!


php maintenance/ShowUserInfo.php --domain "LDAP" --username "user1"

uid => user1

loginshell => /bin/bash

<etc>


Yet the group config isn't working - what gives?


MediaWiki: 1.33.1

PluggableAuth: 5.7

LDAPAuthentication2: 1.0.0

LDAPAuthorization: 1.0.0

LDAPProvider: 1.0.1

LDAPGroups: 1.0.1


LocalSettings.php:

$LDAPProviderDomainConfigs = "/etc/ldap/ldapprovider.json";


/etc/ldap/ldapprovider.json:

{

       "LDAP": {

               "connection": {

                       "server": "ldap.example.com",

                       "user": "cn=admin,dc=example,dc=com",

                       "pass": "password",

                       "options": [],

                       "enctype": "clear",

                       "basedn": "dc=example,dc=com",

                       "groupbasedn": "ou=groups,dc=example,dc=com",

                       "userbasedn": "ou=users,dc=example,dc=coma",

                       "searchattribute": "uid",

                       "searchstring": "uid=USER-NAME,ou=users,dc=example,dc=com",

                       "realnameattribute": "cn",

                       "emailattribute": "mail",

                       "grouprequest": "MediaWiki\\Extension\\LDAPProvider\\UserGroupsRequest\\Configurable::factory",

                       "groupobjectclass": "*",

                       "groupattribute": "memberUid"

               },

               "authorization": {

                       "rules": {

                               "groups": {

                                       "required": ["cn=admins,ou=groups,dc=example,dc=com"]

                               }

                       }

               },

               "groupsync": {

                       "mechanism": "allgroups",

                       "locally-managed": ["local", "wiki", "group", "names" ]

               },

               "authentication": {

                       "usernameattribute": "uid",

                       "realnameattribute": "cn",

                       "emailattribute": "mail"

               }

       }

}

Osnard (talkcontribs)

Configuration looks good so far. You say ldapsearch -x "(&(objectClass=*)(memberUid=users))" dn -LLL -b ou=groups,dc=example,dc=com will give you a proper result, but ldap_search( $linkID, $baseDN = 'ou=groups,dc=example,dc=com', $filter = '(&(objectclass=*)(memberUid=uid=user1,ou=users,dc=example,dc=com))', $attributes = [ 'dn' ], $attrsonly = , $sizelimit = , $timelimit = , $deref =  ); will not?

But the userDN uid=user1,ou=users,dc=example,dc=com is okay?

Sebastian19276 (talkcontribs)

Hi Osnard,


In the constructed search filter the memberUid= parameter should be searching for just a uid, not for a full DN. It should search for "memberUid=user1" because this is how it's actually stored in LDAP; but for some reason it's searching for "memberUid=uid=user1,ou=users" which makes no sense. That user DN on its own is valid, yes.


I tried fiddling with the domain config and couldn't get a proper search filter no matter what I entered. I thought perhaps it was pulling it from "searchstring" but even when I changed it, set it to "", or removed it altogether, it wasn't changing the search filter when using ShowUserGroups.php


Thanks!

Sebastian19276 (talkcontribs)

One tiny note, just a typo in my original post where I said the ldapsearch gives me a proper result, I meant to say "memberUid=user1" not "memberUid=users".

Osnard (talkcontribs)
Sebastian19276 (talkcontribs)

Hey, that fixed it! I just changed userDN to username, and that's exactly what I needed. I was having trouble understanding all the PHP pieces, I don't know any PHP, and I hadn't come across that exact file yet. Cheers!

Sebastian19276 (talkcontribs)

It is fairly ridiculous that I'd have to edit the source code to get this working. Does nobody ever use POSIX groups? I take it the DN is what's used in AD implementations for group membership; but what about classic OpenLDAP on GNU/Linux systems? There must be some way to change this using just a config file, not just by editing code. Any insight would be great!

Sebastian19276 (talkcontribs)

Fun fact: this still was broken for a time because uid is not case sensitive, but memberUid is, so MediaWiki automatically capitalizing usernames didn't quite work. I copied the getUserDN function and created getUserUID, then used the output of that to search for user groups instead of using the username. So this way LDAP can take the wrongly capitalized username, match it to a user account, extract the correctly capitalized UID, use it to search for groups since memberUid is case sensitive (standard NIS schema), and then correctly return the groups. I don't have the time to get developer access, make the necessary changes, create files, etc, but hopefully this does give some insight for other people going forward.


               $useruid = $this->userInfo[0]["uid"][0];


               $userUID = new EscapedString( $this->ldapClient->getUserUID( $username ) );


                       "(&(objectclass=$objectClass)($groupAttribute=$userUID))",


Osnard (talkcontribs)

Awesome, thanks for sharing this. I have opened a Phabricator task to adress this issue in the future: https://phabricator.wikimedia.org/T240750

Unfortunately I can not make any promises regarding a time schedule. Actually, most usecases I know are binding to a Microsoft Active Directory. But my goal would be to also support other backends.


Sebastian19276 (talkcontribs)

Great! Glad I could help, and thank you for your time. Cheers

151.41.62.123 (talkcontribs)

Hi. I'm having the same issue of the original post (trouble setting up the openldap group). I want to restrict login to a certain group of ldap user. I changed the userDN in username in configurable.php as suggested in previous post. Now I can have the right output running /maintenance/showusergroup.php but still no luck with the login restriction. I read the rest of the thread, and maybe the problem is related to the "capitalization" of username, but I can't understand how to fix it: what files I have to edit and how ? Any help appreciated. Thanks

Fabio

Osnard (talkcontribs)

If it really comes to "capitalization", have a look at the presearchusernamemodifiers configuration of Extension:LDAPProvider. But if ShowUserGroups.php lists the proper groups then maybe there is just an issue with the authorization configuration. You can share your config and/or enable debugging to get more information.

151.41.62.123 (talkcontribs)

hi, thanks for the reply. I can confirm that /maintenance/showusergroup.php shows the correct result.

my ldap.json file is this one:


{

        "diism.unisi.it": {

                "connection": {

                        "server": "ldap.diism.unisi.it",

                        "port": "389",

                        "user": "cn=Manager,dc=diism,dc=unisi,dc=it",

                        "pass": "******",

                        "enctype": "clear",

                        "options": {

                                "LDAP_OPT_DEREF": 1

                        },

                        "basedn": "dc=diism,dc=unisi,dc=it",

                        "userbasedn": "ou=Users,dc=diism,dc=unisi,dc=it",

                        "groupbasedn": "ou=Groups,dc=diism,dc=unisi,dc=it",

                        "searchattribute": "uid",

                        "usernameattribute": "uid",

                        "realnameattribute": "cn",

                        "emailattribute": "mail",

                        "grouprequest": "MediaWiki\\Extension\\LDAPProvider\\UserGroupsRequest\\Configurable::factory",

                       "groupobjectclass": "*",

                       "groupattribute": "memberUid",

                        "presearchusernamemodifiers": [ "spacestounderscores", "lowercase" ]

                },

                "userinfo": [],

                "authorization": {

                        "rules":{

                               "group": {

                                        "required": ["cn=wiki,ou=Groups,dc=diism,dc=unisi,dc=it"]

                                }

                        }

                },

                "groupsync": []

               

        }

}

151.41.62.123 (talkcontribs)

just for clarification: we want to restrict access to "wiki" group on our openldap and right now, the login process let everyone in (with correct password obv.)

thank you

Osnard (talkcontribs)

Config looks good. This might be a stupid question, but you have Extension:LDAPAuthorization installed and enabled, right? Maybe you can share the logs too?

151.41.62.123 (talkcontribs)

yes LDAPAuthorization is installed and enabled (it shows in "version" special page). What logs do you need ? don't even know if / where the extension save logs ...

Osnard (talkcontribs)
151.41.62.123 (talkcontribs)

OK. thanks for the help. I enabled the log and I get it working when I use the /maintenance/showusergroup.php (and as I already told you it's working right) but nothing adds to the log file when I login from the mediawiki regular web interface... so it seems it's not workin' right ?


Osnard (talkcontribs)

In this case the extensions seem not so be enabled when in web context.

151.41.62.123 (talkcontribs)

but it let me in when I use correct username / password and shows me error messages when use wrong ones.... moreover, I tried changing " $wgPluggableAuth_ButtonLabel " parameter, and it displays the string I put there on the web interface... so strange .....


Osnard (talkcontribs)

Sorry. Without debugging I can't help. If the logs don't show anything I don't know where to start. Maybe it's just the log-config that is not enabled in web-context? Please double check this. Maybe use the generic Manual:$wgDebugLogFile configuration.

151.41.49.198 (talkcontribs)

Ok, so I got the "generic" logging working setting the $wgDebugLogFile, and in the logfile specified some LDAP related messages shows. Since the logfile generated is not so small, I tried to share it via external link on my drive, but it seems that this is not allowed here as I get this error:

"This action has been automatically identified as harmful, and therefore disallowed."

how can I show you the log ?

Thank you very much for your support


Osnard (talkcontribs)

Can you just extract the lines with the keyword "ldap" (e.g. by using `grep`) and share them here? Otherwise you might want to try another sharing service, like https://pastebin.com

151.41.49.198 (talkcontribs)

root@wiki:~# cat /var/log/mediawiki.log  | grep -i LDAP

[session] SessionBackend "r3oa0124nk3f7b0r3e8jk37cuup15u9b" data dirty due to dirty(): MediaWiki\Extension\LDAPAuthentication2\PluggableAuth->authenticate/MediaWiki\Auth\AuthManager->setAuthenticationSessionData/MediaWiki\Session\Session->setSecret/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty

[DBQuery] SqlBagOStuff::fetchBlobMulti [0.001s] localhost: SELECT  keyname,value,exptime  FROM `newwikiobjectcache`    WHERE keyname = 'new_diismwiki-newwiki:ldap-provider:user-info:test:'  

[DBQuery] MediaWiki\Extension\LDAPProvider\UserDomainStore::getDomainForUser [0s] localhost: SELECT  domain  FROM `newwikildap_domains`    WHERE user_id = '4'  LIMIT 1  

[session] SessionBackend "jbtcl1ebdrulhif3dju9dtavjhqkmh9f" data dirty due to dirty(): MediaWiki\Extension\LDAPProvider\Hook\UserLoadAfterLoadFromSession::callback/MediaWiki\Extension\LDAPProvider\Hook\UserLoadAfterLoadFromSession->process/MediaWiki\Extension\LDAPProvider\Hook\UserLoadAfterLoadFromSession->doProcess/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty

[DBQuery] SqlBagOStuff::fetchBlobMulti [0.001s] localhost: SELECT  keyname,value,exptime  FROM `newwikiobjectcache`    WHERE keyname = 'new_diismwiki-newwiki:ldap-provider:user-info:Test:'  

[DBQuery] MediaWiki\Extension\LDAPProvider\UserDomainStore::getDomainForUser [0s] localhost: SELECT  domain  FROM `newwikildap_domains`    WHERE user_id = '4'  LIMIT 1  

[session] SessionBackend "jbtcl1ebdrulhif3dju9dtavjhqkmh9f" data dirty due to dirty(): MediaWiki\Extension\LDAPProvider\Hook\UserLoadAfterLoadFromSession::callback/MediaWiki\Extension\LDAPProvider\Hook\UserLoadAfterLoadFromSession->process/MediaWiki\Extension\LDAPProvider\Hook\UserLoadAfterLoadFromSession->doProcess/MediaWiki\Session\Session->set/MediaWiki\Session\SessionBackend->dirty

[DBQuery] SqlBagOStuff::fetchBlobMulti [0.001s] localhost: SELECT  keyname,value,exptime  FROM `newwikiobjectcache`    WHERE keyname = 'new_diismwiki-newwiki:ldap-provider:user-groups:Test:'  

151.41.49.198 (talkcontribs)

pastebin can't do ... file is too big


Osnard (talkcontribs)

Can you please again ahre your whole LDAP related config. Including enabled extensions and the domain config. Thanks!

151.41.49.198 (talkcontribs)

apart from ldap.json (already posted just before), I think the only relevant part is in Localconfig.conf in which I added this (following an example in one of the extension's page):


# End of automatically generated settings.

# Add more configuration options below.

// 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 = "$IP/ldap.json";

$ldapConfig = false;

//$ldapConfig = true;

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: $IP/ldap.json");

  }

}

// Activate Extension

if ( $ldapConfig ) {

  wfLoadExtension( 'PluggableAuth' );

  wfLoadExtension( 'LDAPProvider' );

  wfLoadExtension( 'LDAPAuthentication2' );

  wfLoadExtension( 'LDAPAuthorization' );

  wfLoadExtension( 'LDAPUserInfo' );

  wfLoadExtension( 'LDAPGroups' );

  $LDAPProviderDomainConfigs = $ldapJsonFile;

  $wgPluggableAuth_ButtonLabel = "Log IN TEST";

  if ($wikiRequestSafe) { $LDAPAuthentication2AllowLocalLogin = true; }

  $LDAPAuthentication2AllowLocalLogin = true;

}

Osnard (talkcontribs)

Maybe it's just the log files that can not be written when in web context. Is the webserver user allowed to access the debug log files?

But I may have found the issue in your ldap.json. It says

 "authorization": {
                        "rules":{
                               "group": {
                                        "required": ["cn=wiki,ou=Groups,dc=diism,dc=unisi,dc=it"]
                                }
                        }
                },

where it should say

 "authorization": {
                        "rules":{
                               "groups": {
                                        "required": ["cn=wiki,ou=Groups,dc=diism,dc=unisi,dc=it"]
                                }
                        }
                },

It's "groups" instead of "group"

Schlagmichdoch (talkcontribs)

Hi Osnard,

I've got a similar problem when upgrading from mediawiki 1.31 to 1.35 and migrating to LDAPProvider at the same time.


Situation:

LDAP Group:

dn: cn=wiki,ou=groups,dc=example,dc=com

objectClass: top

objectClass: posixGroup

cn: wiki

memberUid: user1

memberUid: user2

to match group membership, the following query works.

ldapsearch -x "(&(objectClass=*)(memberUid=user1))" dn -LLL -b ou=groups,dc=example,dc=com


LDAP user:

dn: uid=t.test, ou=users, dc=example, dc=com

objectClass: top

objectClass: posixUser

uid: t.test

displayname: Thorsten Test

cn: Thorsten Test

mail: t.test@example.com


I migrated from Extension:LdapAuthentication to LDAP Stack:

From old config:

require_once 'extensions/LdapAuthentication/LdapAuthentication.php';
require_once 'includes/AuthPlugin.php';
$wgAuth = new LdapAuthenticationPlugin();

$wgLDAPDebug = 3;
$wgDebugLogGroups['ldap'] = "/var/log/mediawiki/mediawiki-ldap.log" ;

$wgLDAPDomainNames = array( 'LDAP' );
$wgLDAPServerNames = array( 'example.com' => 'localhost' );

$wgLDAPNameMapperServerName = "localhost";
$wgLDAPNameMapperBaseDN = "dc=example,dc=com";

$wgLDAPUseLocal = false;

$wgLDAPEncryptionType = array(  'example.com' => 'clear');

$wgLDAPSearchAttributes = array( 'example.com' => 'displayname' );
$wgLDAPBaseDNs = array( 'example.com' => 'dc=example,dc=com' );

# To pull e-mail address from LDAP
$wgLDAPPreferences = array( 'example.com' => array( 'email' => 'mail') );

# Group based restriction
$wgLDAPGroupUseFullDN = array( "example.com" => false );
$wgLDAPGroupObjectclass = array( "example.com" => "posixgroup" );
$wgLDAPGroupAttribute = array( "example.com" => "memberuid" );
$wgLDAPGroupSearchNestedGroups = array( "example.com" => false );
$wgLDAPGroupNameAttribute = array( "example.com" => "cn" );
$wgLDAPRequiredGroups = array( "example.com" => array("cn=wiki,ou=groups,dc=example,dc=com"));
$wgLDAPLowerCascomsername = array(  'example.com' => false,
$wgLDAPGroupUseRetrievedUsername = array( "example.com" => true );
$wgLDAPDisableAutoCreate = array(  "example.com" => false );

$wgGroupPermissions['*']['autocreateaccount'] = true;

$wgLDAPUseLDAPGroups = array( 'example.com' => true );


To new config:

wfLoadExtensions( [
        'PluggableAuth',
        'Auth_remotcomser',
        'LDAPProvider',
        'LDAPAuthentication2',
        'LDAPAuthorization',
        'LDAPUserInfo',
        'LDAPGroups'
] );

$LDAPAuthorizationAutoAuthRemotcomserStringParser = 'username-at-domain';

$LDAPAuthentication2AllowLocalLogin = false;
$wgAuthRemotcomserAllowUserSwitch = false;
$wgPluggableAuth_EnableLocalLogin = false;

$wgAuthRemotcomserUserName = function() {
        $user = '';
        if( isset( $_SERVER[ 'REMOTE_USER' ] ) ) {
                $user = strtolower( $_SERVER[ 'REMOTE_USER' ] );
        }

        return $user;
};

$LDAPProviderDomainConfigProvider = function() {
        $config = [
                'LDAP' => [
                        'connection' => [
                                "server" => "localhost",
                                "options" => [
                                        "LDAP_OPT_DEREF" => 1
                                ],
								"basedn" => "dc=example,dc=com",
                                "groupbasedn" => "ou=groups,dc=example,dc=com",
                                "userbasedn" => "ou=users,dc=example,dc=com",
                                "searchattribute" => "uid",
                                "searchstring" => "uid=USER-NAME,ou=users,dc=example,dc=com",
                                "usernameattribute" => "cn",
                                "realnameattribute" => "cn",
                                "emailattribute" => "mail",
                                "grouprequest" => "MediaWiki\\Extension\\LDAPProvider\\UserGroupsRequest\\Configurable::factory",
                                "groupobjectclass" => "posixGroup",
                                "groupattribute" => "memberUid",
                        ],
                        'authorization' => [
                                'rules' => [
                                        'groups' => [
                                                'required' => [ "cn=wiki,ou=groups,dc=example,dc=com" ]
                                        ]
                                ]
                        ],
                        'userinfo' => [
                                'attributes-map' => [
                                        'email' => 'mail',
                                        'realname' => 'cn'
                                ]
                        ],
				]
		];
		
        return new \MediaWiki\Extension\LDAPProvider\DomainConfigProvider\InlinePHPArray( $config );
};


#####Error logging######
##PHP Error ###
error_reporting( -1 );
ini_set( 'display_errors', 1 );
$wgShowExceptionDetails = true;
$wgShowDBErrorBacktrace = true;

##Debug log to file ###
$wgDebugLogFile = '/var/log/mediawiki/debuglogfile.log';
$wgDebugComments = true;

$wgDebugLogGroups['LDAP'] =
$wgDebugLogGroups['MediaWiki\\Extension\\LDAPProvider\\Client'] =
$wgDebugLogGroups['LDAPUserInfo'] =
$wgDebugLogGroups['LDAPAuthorization'] = '/var/log/mediawiki/LDAPProvider.log';

$wgGroupPermissions['*']['autocreateaccount'] = true;

The users wiki username is its fullname, so attribute displayname or cn. The old setup offered the possibility to login via LDAP uid or via fullname. If it's not possible to have both, I'd prefer login by uid.


As you can see the mediawiki usernameattribute is cn, which is firstname lastname.

So I need verify the groups by uid and then bind to LDAP User with attribute cn.


As the problem seemed to be the same as Sebastians, I changed the UserGroupRequest/Configurable.php from $userDN to $username as suggested.

Since then the ShowUserGroup.php maintance script works as expected and returns all groups the user is part of. Many thanks @Sebastian19276!


Sadly the login still does not work.

When I login via browser, the following error is shown:

The user Thorsten Test is not authenticated.


The LDAP log shows the following:

2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_connect( $hostname = 'ldap://localhost:389', $port = 389 );
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # __METHOD__ returns Resource id #36
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: Setting LDAP_OPT_PROTOCOL_VERSION to 3
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_set_option( $linkID, $option = 17, $newval = 3 );
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # returns 1
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: Setting LDAP_OPT_REFERRALS to 0
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_set_option( $linkID, $option = 8, $newval = 0 );
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # returns 1
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: Setting LDAP_OPT_DEREF to 1
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_set_option( $linkID, $option = 2, $newval = 1 );
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # returns 1
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_bind( $linkID, $bindRDN = '', $bindPassword = 'XXXX' );
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # returns 1
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: MediaWiki\Extension\LDAPProvider\Client::getSearchString: User DN is: 'uid=t.test,ou=users,dc=example,dc=com'
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_bind( $linkID, $bindRDN = 'uid=t.test,ou=users,dc=example,dc=com', $bindPassword = 'XXXX' );
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # returns 1
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_search( $linkID, $baseDN = 'ou=users,dc=example,dc=com', $filter = '(uid=t.test)', $attributes = [ '*', 'memberof' ], $attrsonly = , $sizelimit = , $timelimit = , $deref =  );2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # returns Resource id #54
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_get_entries( $linkID, $resultID );
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # returns: array (
  'count' => 1,
  0 =>
  array (
    'uid' =>
    array (
      'count' => 1,
      0 => 't.test',
    ),
    0 => 'uid',
    'uidnumber' =>
    array (
      'count' => 1,
      0 => '0',
    ),
    1 => 'uidnumber',
    'mail' =>
    array (
      'count' => 1,
      0 => 't.test@example.com',
    ),
    2 => 'mail',
    'homedirectory' =>
    array (
      'count' => 1,
      0 => '/t.test',
    ),
    3 => 'homedirectory',
    'givenname' =>
    array (
      'count' => 1,
      0 => 'Thorsten',
    ),
    4 => 'givenname',
    'gidnumber' =>
    array (
      'count' => 1,
      0 => '0',
    ),
    5 => 'gidnumber',
    'displayname' =>
    array (
      'count' => 1,
      0 => 'Thorsten Test',
    ),
    6 => 'displayname',
    'sn' =>
    array (
      'count' => 1,
      0 => 'Test',
    ),
    7 => 'sn',
    'cn' =>
    array (
      'count' => 1,
      0 => 'Thorsten Test',
    ),
    8 => 'cn',
    'objectclass' =>
    array (
      'count' => 3,
      0 => 'inetOrgPerson',
      1 => 'posixAccount',
      2 => 'top',
    ),
    9 => 'objectclass',
    'userpassword' =>
    array (
      'count' => 1,
      0 => '{SSHA}xxxxx',
    ),
    10 => 'userpassword',
    'employeetype' =>
    array (
      'count' => 1,
      0 => 'aktiv',
    ),
    11 => 'employeetype',
    'count' => 12,
    'dn' => 'uid=t.test,ou=users,dc=example,dc=com',
  ),
)
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: Ran LDAP search for '(uid=t.test)' in 0.00060606002807617 seconds.

2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: MediaWiki\Extension\LDAPProvider\Client::getUserDN: search with array (
  'base' => 'dc=example,dc=com',
  'filter' => '(uid=Thorsten Test)',
  'attributes' =>
  array (
    0 => '*',
    1 => 'memberof',
  ),
)
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_search( $linkID, $baseDN = 'dc=example,dc=com', $filter = '(uid=Thorsten Test)', $attributes = [ '*', 'memberof' ], $attrsonly = , $sizelimit = , $timelimit = , $deref =  );
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # returns Resource id #66
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_count_entries( $linkiID, $result = 'Resource id #66' );
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # returns 0
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: Could not get user DN!
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_search( $linkID, $baseDN = 'ou=groups,dc=example,dc=com', $filter = '(&(objectclass=posixGroup)(memberUid=Thorsten Test))', $attributes = [ 'dn' ], $attrsonly = , $sizelimit = , $timelimit = , $deref =  );
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # returns Resource id #72
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: ldap_get_entries( $linkID, $resultID );
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: # returns: array (
  'count' => 0,
)
2020-11-10 14:57:36 xxxxx.xxxxx.xx wiki: Ran LDAP search for '(&(objectclass=posixGroup)(memberUid=Thorsten Test))' in 0.00049185752868652 seconds.


Somehow it first queries a ldap_search with uid=t.test but later with uid=Thorsten Test.


Can you please help me to figure out, what to do to make it work?


Cheers

Dominik

Osnard (talkcontribs)

It is using "usernameattribute" => "cn" to set the on-wiki-username and then uses this one in the "searchstring" => "uid=USER-NAME,ou=users,dc=example,dc=com". Try to just unset the "searchstring" or use "usernameattribute" => "uid".

Schlagmichdoch (talkcontribs)

Commenting out "searchstring" => "uid=USER-NAME,ou=users,dc=example,dc=com" does not seem to have any impact at all.


Using "usernameattribute" => "uid" does result in an error on every page loaded after:

"Call to a member function canExist() on null"


The goal remains to have "usernameattribute" => "cn", but still have a ldap query with uid as off: "searchstring" => "uid=UID,ou=users,dc=example,dc=com"


Thanks in advance!

Osnard (talkcontribs)

How about setting "searchstring" => "cn=USER-NAME,ou=users,dc=example,dc=com". But this will probably not solve the issue with he "group request". Can a "cn" be used as "groupattribute" instead of "memberUid"? If not, you may need to implement a custom IUserGroupRequest class.

Schlagmichdoch (talkcontribs)

I would like to keep our current ldap schema, as other apps are dependent on it too. So only "memberUid" is provided as possible "groupattribute".


Your suggestion with cn=USER-NAME seems promising though. After applying it, ShowUserGroups.php and ShowUserInfo.php do work with the ldap uid as userparameter. Perfect! Sadly CheckLogin.php does not work anymore and login via Web obviously does not work either. Is this behaviour as you had expected?


Where do I find theIUserGroupRequest class that I need to customize?

Osnard (talkcontribs)

I see... please go back to the original search-string, so login works again. Have a look at the class UserGroupsRequest\Configurable. Try to change line 18 [1] in a way you have a proper $userDN in line 37 [2]. You may need to run $this->ldapClient->getUserInfo( $username ) to obtain the uid from the wiki username (which is the cn).

If you succeed, please share you change, so I can incorporate it into the extension. If not, tell me also, I will then check what I can do.

[1] https://github.com/wikimedia/mediawiki-extensions-LDAPProvider/blob/1.0.4/src/UserGroupsRequest/Configurable.php#L18 [2] https://github.com/wikimedia/mediawiki-extensions-LDAPProvider/blob/1.0.4/src/UserGroupsRequest/Configurable.php#L37

Schlagmichdoch (talkcontribs)

Are you sure I need to change the Configurable again?

With the fix provided by @Sebastian19276 ($groupattribute=$username instead of $groupattribute=$userDN) the file currently looks like this:

 1<?php
 2
 3namespace MediaWiki\Extension\LDAPProvider\UserGroupsRequest;
 4
 5use MediaWiki\Extension\LDAPProvider\ClientConfig;
 6use MediaWiki\Extension\LDAPProvider\EscapedString;
 7use MediaWiki\Extension\LDAPProvider\GroupList;
 8use MediaWiki\Extension\LDAPProvider\UserGroupsRequest;
 9use MWException;
10
11class Configurable extends UserGroupsRequest {
12
13        /**
14         * @param string $username to get the groups for
15         * @return GroupList
16         */
17         public function getUserGroups( $username ) {
18                $userDN = new EscapedString( $this->ldapClient->getUserDN( $username ) );
19                $baseDN = $this->config->get( ClientConfig::GROUP_BASE_DN );
20                $dn = 'dn';
21                
22                if ( $baseDN === '' ) {
23                        $baseDN = null;
24                }
25                
26                $ret = [];
27                $objectClass = $this->config->get( ClientConfig::GROUP_OBJECT_CLASS );
28                if ( empty( trim( $objectClass ) ) ) {
29                        throw new MWException( sprintf(
30                                "Parameter %s must be set when configurable groups request is used",
31                                ClientConfig::GROUP_OBJECT_CLASS
32                        ) );
33                }
34                $groupAttribute = $this->config->get( ClientConfig::GROUP_ATTRIBUTE );
35                
36                $groups = $this->ldapClient->search(
37                        "(&(objectclass=$objectClass)($groupAttribute=$username))",
38                        $baseDN, [ $dn ]
39                );
40                
41                foreach ( $groups as $key => $value ) {
42                        if ( is_int( $key ) ) {
43                                $ret[] = $value[$dn];
44                        }
45                }
46                return new GroupList( $ret );
47        }
48
49}

Since the fix the maintenance script ShowUserGroups.php does work properly and includes the groupdn specified with:

'authorization' => [
        'rules' => [
                'groups' => [
                        'required' => [ "cn=wiki,ou=groups,dc=example,dc=com" ]
                ]
        ]
],


So I'm not sure whether it's really a Problem with the UsergroupsRequest, since the result of your approach of changing UserGroupsRequest\Configurable should be a working ShowUserGroups.php, isn't it?


The LDAPProvider.log also shows

ldap_bind( $linkID, $bindRDN = 'uid=t.test,ou=users,dc=example,dc=com', $bindPassword = 'XXXX' );

2020-12-15 10:12:17 xxxxx.xxxxx.xx wiki: # returns 1

which seems correct, doesn't it?


When logging in with correct credentials it says: "The user Thorsten Test does not have permission"

When logging in with false credentials it says: "Could not authenticate credentials against domain "LDAP""


What do you think? How could I proceed?

Schlagmichdoch (talkcontribs)
Osnard (talkcontribs)

Well, the issue is not the "authentication" (binding with user DN and provided password apparently works), but with the "authorization". This means it can not get the list of groups for your user and therefor the "required groups rule" can not be fullfilled. But you say `ShowUserGroups` lists the proper group DN that you have configured as a requirement? If this is the case authorization should also work, as the very same mechanism for fetching the groups is used.

Schlagmichdoch (talkcontribs)

Exactly. 'ShowUserGroups' lists all group DNs for the user including 'wiki' configured with

authorization' => [

'rules' => [

'groups' => [

'required' => [ "cn=wiki,ou=groups,dc=example,dc=com" ]

]

]

],


Still the login page throws "The user Thorsten Test does not have permission"


What can I do?

Osnard (talkcontribs)

When you run ShowUserGroups do us use "Thorsten_Test" or "t.test" as username? In the login form which of those do you enter?

Schlagmichdoch (talkcontribs)

"t.test" for both.


in the login form:

- When I use "Thorsten Test" it says "Could not authenticate credentials against domain "LDAP""

- When I use "t.test" with wrong password it says "Could not authenticate credentials against domain "LDAP""

- When I use "t.test" with correct password it says "The user Thorsten Test is not permitted"

Osnard (talkcontribs)

This is an issue with how the LDAP-Stack extensions work with the username. After login LDAP's "t.test" will be transformed to "Thorsten Test" for the wiki. Authentication will then use "Torsten Test" for authentication, which clearly fails. Please file a feature request task on Phabricator.

Reply to "Can't fetch group membership when using POSIX groups (memberUid: user1)"