LDAP support improvment (issue #6) + some bugs corrected

This commit is contained in:
Crivaledaz 2017-08-26 15:54:24 +02:00
parent b57fa59ea9
commit a375cdd9eb
13 changed files with 254 additions and 109 deletions

View File

@ -80,7 +80,7 @@ class { 'mattermostldap':
ldap_base => 'o=Company',
ldap_uri => 'ldap://company.org',
ldap_port => 389,
ldap_rdn => 'ou=People,o=Company',
ldap_attribute => 'uid',
db_user => 'oauth',
db_pass => 'oauth_secure-pass',
db_name => 'oauth_db',
@ -152,7 +152,7 @@ Below, there is an example of Mattermost-LDAP Puppet module using Mattermost and
ldap_base => 'o=Company',
ldap_uri => 'ldap://company.com',
ldap_port => 389,
ldap_rdn => 'ou=People,o=Company',
ldap_attribute => 'uid',
db_user => 'oauth',
db_pass => 'oauth_secure-pass',
db_name => 'oauth_db',
@ -186,13 +186,13 @@ Directory where the Oauth server will be installed, by default /var/www/html/. T
#### ldap_base (Required)
The base directory name of your LDAP server. (ex : ou=People,o=Company)
#### ldap_filter (Optional)
Additional filters for your LDAP, see LDAP.php class for more information (use by resource.php to get user informations)
Additional filters to search in LDAP (used to get user informations). (ex : objectClass=person)
#### ldap_uri (Required)
Your LDAP hostname or LDAP IP, to connect the LDAP server.
#### ldap_port (Optional)
Your LDAP port, to connect the LDAP server. By default : 389.
#### ldap_rdn (Required)
The LDAP Relative Directory Name suffixto identify a user in LDAP, see LDAP.php class for more information (use by authorize.php to check user credentials on LDAP)
#### ldap_attribute (Required)
The attribute used to identify user on your LDAP. Should be uid, email, cn or sAMAccountName.
#### db_user (Optional)
Oauth user in the database. This user must have right on the oauth database to store oauth tokens. By default : oauth
#### db_pass (Optional)

View File

@ -6,7 +6,7 @@ class mattermostldap (
$ldap_filter = $mattermostldap::params::ldap_filter,
$ldap_uri = $mattermostldap::params::ldap_uri,
$ldap_port = $mattermostldap::params::ldap_port,
$ldap_rdn = $mattermostldap::params::ldap_rdn,
$ldap_attribute = $mattermostldap::params::ldap_attribute,
$db_user = $mattermostldap::params::db_user,
$db_pass = $mattermostldap::params::db_pass,
$db_host = $mattermostldap::params::db_host,
@ -20,7 +20,7 @@ class mattermostldap (
$scope = $mattermostldap::params::scope,
$user_id = $mattermostldap::params::user_id,
$timezone = $mattermostldap::params::timezone,
$ldap_bind_rdn = $mattermostldap::params::ldap_bind_rdn,
$ldap_bind_dn = $mattermostldap::params::ldap_bind_dn,
$ldap_bind_pass = $mattermostldap::params::ldap_bind_pass,
) inherits mattermostldap::params {
@ -32,7 +32,7 @@ class mattermostldap (
validate_string($ldap_filter)
validate_string($ldap_uri)
validate_integer($ldap_port)
validate_string($ldap_rdn)
validate_string($ldap_attribute)
validate_string($db_user)
validate_string($db_pass)
validate_string($db_host)
@ -47,7 +47,7 @@ class mattermostldap (
validate_string($scope)
validate_string($user_id)
validate_string($timezone)
validate_string($ldap_bind_rdn)
validate_string($ldap_bind_dn)
validate_string($ldap_bind_pass)

View File

@ -6,7 +6,7 @@ class mattermostldap::params {
$ldap_filter = ''
$ldap_uri = 'ldap://hostname.com'
$ldap_port = 389
$ldap_rdn = 'ou=People,o=Company'
$ldap_attribute = 'uid'
$db_user = 'oauth'
$db_pass = 'oauth_secure-pass'
$db_host = 'localhost'
@ -19,6 +19,6 @@ class mattermostldap::params {
$scope = 'api'
$user_id = ''
$timezone = 'Europe/Paris'
$ldap_bind_rdn = '',
$ldap_bind_pass = '',
$ldap_bind_dn = ''
$ldap_bind_pass = ''
}

View File

@ -56,7 +56,7 @@ node 'bepo'
ldap_filter => '',
ldap_uri => 'ldap://company.com',
ldap_port => 389,
ldap_rdn => 'ou=People,o=Company',
ldap_attribute => 'uid',
db_user => 'oauth',
db_pass => 'oauth_secure-pass',
db_name => 'oauth_db',

View File

@ -3,24 +3,15 @@
$hostname = "<%= @ldap_uri %>";
$port = <%= @ldap_port %>;
// variable use in connexion.php
$rdn_suffix = "<%= @ldap_rdn %>";
// Attribute use to identify user on LDAP (used in connexion.php, replace $rdn_suffix) - ex : uid, mail, sAMAccountName
$search_attribute = "<%= @ldap_attribute %>";
// variable use in resource.php
// Base directory name of the LDAP
$base = "<%= @ldap_base %>";
// An optional filter to search in LDAP - ex : objectClass=person
$filter = "<%= @ldap_filter %>";
// ldap service user to allow search in ldap
$bind_dn = "<%= @ldap_bind_rdn %>";
$bind_pass = "<%= @ldap_bind_pass %>";
//add virgule to concat in php script
if ($filter != "")
{
$filter = "," . $filter;
}
if ($rdn_suffix != "")
{
$rdn_suffix = "," . $rdn_suffix;
}
$bind_dn = "<%= @ldap_bind_dn %>";
$bind_pass = "<%= @ldap_bind_pass %>";

View File

@ -140,22 +140,22 @@ Oauth user in the database. This user must have right on the oauth database to s
Oauth user password in the database. If you use init script make sure to use the same database user. (ex : oauth_secure-pass)
* LDAP config
Edit oauth/LDAP/onfig_ldap.php :
Edit oauth/LDAP/config_ldap.php :
1. Provide your ldap address and port.
2. Change the base directory name ($base) and the filter ($filter) to comply with your LDAP configuration, these variables will be use in resource.php.
3. Change the relative directory name suffix ($rdn) to comply with your LDAP configuration, this variable will be use in connexion.php.
2. Change the base directory name ($base) and the filter ($filter) to comply with your LDAP configuration.
3. Change the user ID attribute ($ldap_attribute) to comply with your LDAP configuration (uid, sAMAccountName, email, cn ..).
4. If necessary, you can provide a LDAP account to allow search in LDAP (only restrictive LDAP).
#### $hostname
Your LDAP hostname or LDAP IP, to connect to the LDAP server.
#### $port
Your LDAP port, to connect to the LDAP server. By default : 389.
#### $rdn
The LDAP Relative Directory Name suffix to identify a user in LDAP, see LDAP.php class for more information (use to check user credentials on LDAP). Note that user id (uid) will be add to this suffix to produce a complete relative directory name. The uid is provided by username field in the form from oauth/index.php. For more information, refer to ldap_bind() in php documentation.
#### $search_attribute
The attribute used to identify user on your LDAP. Should be uid, email, cn or sAMAccountName.
#### $base
The base directory name of your LDAP server. (ex : ou=People,o=Company)
#### $filter
Additional filters for your LDAP, see LDAP.php class for more information (used to get user informations). Note that the user id (uid) will be add to the filter (concat) to get only user data from the LDAP. The uid is provided by username field in the form from oauth/index.php.
Additional filters to search in LDAP (used to get user informations). (ex : objectClass=person)
#### $bind_dn
The LDAP Directory Name of an service account to allow LDAP search. This ption is required if your LDAP is restrictive, else put an empty string (""). (ex : cn=mattermost_ldap,dc=Example,dc=com)
#### $bind_pass

View File

@ -42,26 +42,95 @@ class LDAP implements LDAPInterface
}
/**
* @param string @rdn
* A ldap user relative directory name
* @param string @user
* A ldap username or email or sAMAccountName
* @param string @password
* An optional password linked to the specified rdn account, if not provided an anonymous bind is attempted
* An optional password linked to the user, if not provided an anonymous bind is attempted
* @param string @search_attribute
* The attribute used on your LDAP to identify user (uid, email, cn, sAMAccountName)
* @param string @filter
* An optional filter to search in LDAP (ex : objectClass = person).
* @param string @base_dn
* The LDAP base DN.
* @param string @bind_dn
* The directory name of a service user to bind before search. Must be a user with read permission on LDAP.
* @param string @bind_pass
* The password associated to the service user to bind before search.
*
* @return
* TRUE if the user is identified and can access to the LDAP server
* and FALSE if it isn't
*/
public function checkLogin($rdn,$password = null) {
if (!is_string($rdn))
public function checkLogin($user, $password = null, $search_attribute, $filter = null, $base_dn,$bind_dn, $bind_pass) {
if (!is_string($user))
{
throw new InvalidArgumentException('First argument to LDAP/checkLogin must be the relative directory name of a ldap user (string). Ex: uid=jdupont,ou=People,o=Company');
throw new InvalidArgumentException('First argument to LDAP/checkLogin must be the username or email of a ldap user (string). Ex: jdupont or jdupont@company.com');
}
if (!is_string($password) && $password != null)
{
throw new InvalidArgumentException('Second argument to LDAP/checkLogin must be the password associated to the relative directory name (string).');
}
if (!is_string($search_attribute))
{
throw new InvalidArgumentException('Third argument to LDAP/checkLogin must be the attribute to identify users (ex : uid, email, sAMAccountName) (string).');
}
if (!is_string($filter) && $filter != null)
{
throw new InvalidArgumentException('Fourth argument to LDAP/checkLogin must be an optional filter to search in LDAP (string).');
}
if (!is_string($base_dn))
{
throw new InvalidArgumentException('Fifth argument to LDAP/checkLogin must be the ldap base directory name (string). Ex: o=Company');
}
if (!is_string($bind_dn) && $bind_dn != null)
{
throw new InvalidArgumentException('Sixth argument to LDAP/checkLogin must be an optional service account on restrictive LDAP (string).');
}
if (!is_string($bind_pass) && $bind_pass != null)
{
throw new InvalidArgumentException('Seventh argument to LDAP/checkLogin must be an optional password for the service account on restrictive LDAP (string).');
}
// If LDAP service account for search is specified, do an ldap_bind with this account
if ($bind_dn != '' && $bind_dn != null)
{
$bind_result=ldap_bind($this->ldap_server,$bind_dn,$bind_pass);
// If authentification failed, throw an exception
if (!$bind_result)
{
throw new Exception('An error has occured during ldap_bind execution. Please check parameter of LDAP/checkLogin, and make sure that user provided have read permission on LDAP.');
}
}
if ($filter!="" && $filter != null)
{
$search_filter = '(&(' . $search_attribute . '=' . $user . ')(' . $filter .'))';
}
else
{
$search_filter = $search_attribute . '=' . $user;
}
return ldap_bind($this->ldap_server,$rdn,$password);
$result = ldap_search($this->ldap_server, $base_dn, $search_filter, array(), 0, 1, 500);
if (!$result)
{
throw new Exception('An error has occured during ldap_search execution. Please check parameter of LDAP/checkLogin.');
}
$data = ldap_first_entry($this->ldap_server, $result);
if (!$data)
{
throw new Exception('An error has occured during ldap_first_entry execution. Please check parameter of LDAP/checkLogin.');
}
$dn = ldap_get_dn($this->ldap_server, $data);
if (!$dn)
{
throw new Exception('An error has occured during ldap_get_values execution (dn). Please check parameter of LDAP/checkLogin.');
}
return ldap_bind($this->ldap_server,$dn,$password);
}
/**
@ -72,12 +141,16 @@ class LDAP implements LDAPInterface
* @param string @bind_dn
* The directory name of a service user to bind before search. Must be a user with read permission on LDAP.
* @param string @bind_pass
* The password associated to the service user to bind before search.
* The password associated to the service user to bind before search.
* @param string @search_attribute
* The attribute used on your LDAP to identify user (uid, email, cn, sAMAccountName)
* @param string @user
* A ldap username or email or sAMAccountName
*
* @return
* An array with the user's mail and complete name.
*/
public function getDataForMattermost($base_dn, $filter, $bind_dn, $bind_pass) {
public function getDataForMattermost($base_dn, $filter, $bind_dn, $bind_pass, $search_attribute, $user) {
$attribute=array("cn","mail");
@ -89,6 +162,22 @@ class LDAP implements LDAPInterface
{
throw new InvalidArgumentException('Second argument to LDAP/getData must be a filter to get relevant data. Often is the user id in ldap (string). Ex : uid=jdupont');
}
if (!is_string($bind_dn) && $bind_dn != null)
{
throw new InvalidArgumentException('Third argument to LDAP/getData must be an optional service account on restrictive LDAP (string).');
}
if (!is_string($bind_pass) && $bind_pass != null)
{
throw new InvalidArgumentException('Fourth argument to LDAP/getData must be an optional password for the service account on restrictive LDAP (string).');
}
if (!is_string($search_attribute))
{
throw new InvalidArgumentException('Fifth argument to LDAP/getData must be the attribute to identify users (ex : uid, email, sAMAccountName) (string).');
}
if (!is_string($user))
{
throw new InvalidArgumentException('Sixth argument to LDAP/getData must be the username or email of a ldap user (string). Ex: jdupont or jdupont@company.com');
}
// If LDAP service account for search is specified, do an ldap_bind with this account
if ($bind_dn != '' && $bind_dn != null)
@ -102,7 +191,16 @@ class LDAP implements LDAPInterface
}
}
$result = ldap_search($this->ldap_server, $base_dn, $filter, $attribute, 0, 1, 500);
if ($filter!="" && $filter != null)
{
$search_filter = '(&(' . $search_attribute . '=' . $user . ')(' . $filter .'))';
}
else
{
$search_filter = $search_attribute . '=' . $user;
}
$result = ldap_search($this->ldap_server, $base_dn, $search_filter, array(), 0, 1, 500);
if (!$result)
{

View File

@ -7,34 +7,44 @@
*/
interface LDAPInterface
{
/**
* Check user credentials
*
* @param string @rdn
* A ldap user relative directory name
/**
* @param string @user
* A ldap username or email or sAMAccountName
* @param string @password
* An optional password linked to the specified rdn account, if not provided an anonymous bind is attempted
* An optional password linked to the user, if not provided an anonymous bind is attempted
* @param string @search_attribute
* The attribute used on your LDAP to identify user (uid, email, cn, sAMAccountName)
* @param string @filter
* An optional filter to search in LDAP (ex : objectClass = person).
* @param string @base_dn
* The LDAP base DN.
* @param string @bind_dn
* The directory name of a service user to bind before search. Must be a user with read permission on LDAP.
* @param string @bind_pass
* The password associated to the service user to bind before search.
*
* @return
* TRUE if the user is identified and can access to the LDAP server
* and FALSE if it isn't
*/
public function checkLogin($rdn,$password = null);
public function checkLogin($user,$password = null,$search_attribute,$filter = null,$base_dn,$bind_dn,$bind_pass);
/**
* Return only necessary data for Mattermost
*
* @param string @base_dn
* The LDAP base DN.
* @param string @filter
* A filter to get relevant data. Often the user id in ldap (uid or sAMAccountName).
* A filter to get relevant data. Often the user id in ldap (uid or sAMAccountName).
* @param string @bind_dn
* The directory name of a service user to bind before search. Must be a user with read permission on LDAP.
* @param string @bind_pass
* The password associated to the service user to bind before search.
*
* The password associated to the service user to bind before search.
* @param string @search_attribute
* The attribute used on your LDAP to identify user (uid, email, cn, sAMAccountName)
* @param string @user
* A ldap username or email or sAMAccountName
*
* @return
* An array with the user's mail and complete name.
*/
public function getDataForMattermost($base_dn, $filter,$bind_dn,$bind_pass);
public function getDataForMattermost($base_dn, $filter, $bind_dn, $bind_pass, $search_attribute, $user);
}

View File

@ -1,25 +1,14 @@
<?php
$hostname = "ldap://ldap.company.com/";
$hostname = "ldap://company.com/";
$port = 389;
// variable use in connexion.php (rdn_suffix is often the same than base)
$rdn_suffix = 'ou=People,o=Company';
// Attribute use to identify user on LDAP - ex : uid, mail, sAMAccountName
$search_attribute = "uid";
// variable use in resource.php (base is often the same than rdn_suffix)
$base = "o=Company";
$filter = "";
// variable use in resource.php
$base = "ou=People,o=Company";
$filter = "objectClass=*";
// ldap service user to allow search in ldap
$bind_dn = "";
$bind_pass = "";
//add virgule to concat in php script
if ($filter != "")
{
$filter = "," . $filter;
}
if ($rdn_suffix != "")
{
$rdn_suffix = "," . $rdn_suffix;
}

View File

@ -33,11 +33,79 @@ if (!isset($_SESSION['uid']))
// display an authorization form
if (empty($_POST)) {
exit('
<form method="post">
<label>Mattermost souhaite accéder à vos données LDAP (Identifiant, nom complet, mail) </label><br />
<input type="submit" name="authorized" value="Authorize">
<input type="submit" name="authorized" value="Deny">
</form>');
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="./style.css">
<title>Authorisation Mattermost</title>
</head>
<body>
<center>
<table background="../images/login.png" border="0" width="729" height="343" cellspacing="1" cellpadding="4">
<tr>
<td width="40%">&nbsp;</td>
<td width="60%">
<table border="0" width="100%">
<tr>
<td align="center">
<div class="LoginTitle">Mattermost souhaite accéder à vos données LDAP :</div>
<form method="post">
<table border="0" width="90%" cellpadding="1">
<tr>
<td colspan="2" align="left">
<div class="messageLogin" align="center">
</div>
&nbsp;
</td>
</tr>
<tr>
<td align="center" width="100%" class="LoginUsername">
Connecté en tant que : <b>' . $_SESSION['uid'] . ' </b>
</td>
</tr>
<tr>
<td align="left" width="100%" class="LoginUsername">
<br/>
Données souhaitées : <br/>
&nbsp; -> Identifiant,<br/>
&nbsp; -> Nom complet,<br/>
&nbsp; -> Email
</td>
</tr>
<tr><td colspan="2">&nbsp;</td></tr>
<tr>
<td colspan="2" align="center"> <input type="submit" class="GreenButton" name="authorized" value="Authorize" >
<input type="submit" class="GreenButton" name="authorized" value="Deny" > </td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</td>
</tr>
</table>
</center>
</body>
</html>
');
}
// print the authorization code if the user has authorized your client
@ -53,4 +121,11 @@ if ($is_authorized)
}
// Send message in case of error
$response->send();
$response->send();
/*<form method="post">
<label>Mattermost souhaite accéder à vos données LDAP (Identifiant, nom complet, mail) </label><br />
<input type="submit" name="authorized" value="Authorize">
<input type="submit" name="authorized" value="Deny">
</form>
*/

View File

@ -1,6 +1,5 @@
<?php
session_start();
/**
* @author Denis CLAVIER <clavierd at gmail dot com>
*/
@ -9,6 +8,7 @@ session_start();
require_once __DIR__.'/LDAP/LDAP.php';
require_once __DIR__.'/LDAP/config_ldap.php';
// Verify all fields have been filled
if (empty($_POST['user']) || empty($_POST['password']))
{
@ -38,18 +38,9 @@ else
// Open a LDAP connection
$ldap = new LDAP($hostname,$port);
//##################################################\\
// /!\ Adapt here with your LDAP config /!\ \\
// Now you can do this in ldap_config.php \\
//##################################################\\
$rdn = 'uid=' . $user . $rdn_suffix;
/****************************************************/
// Check user credential on LDAP
if ($ldap->checkLogin($rdn,$password))
if ($ldap->checkLogin($user,$password,$search_attribute,$filter,$base,$bind_dn,$bind_pass))
{
$_SESSION['uid']=$user;

View File

@ -5,20 +5,20 @@ session_start();
<!DOCTYPE html>
<html>
<head>
<title>Interface de connexion LDAP</title>
<title>LDAP Connection Interface</title>
</head>
<body>
<form method="post" action="connexion.php">
<fieldset>
<legend>Connexion</legend>
<legend>Connection</legend>
<p>
<label for="user">Identifiant :</label><input name="user" type="text" id="user" /><br />
<label for="password">Mot de Passe :</label><input type="password" name="password" id="password" />
<label for="user">Username :</label><input name="user" type="text" id="user" /><br />
<label for="password">Password :</label><input type="password" name="password" id="password" />
</p>
</fieldset>
<p><input type="submit" value="Connexion" /></p>
<p><input type="submit" value="Connect" /></p>
</form>
</body>
</html>

View File

@ -23,26 +23,17 @@ $resp = array("error" => "Unknow error", "message" => "An unknown error has occu
// get information on user associated to the token
$info_oauth = $server->getAccessTokenData(OAuth2\Request::createFromGlobals());
$uid = $info_oauth["user_id"];
$user = $info_oauth["user_id"];
$assoc_id = $info_oauth["assoc_id"];
//##################################################\\
// /!\ Adapt here with your LDAP config /!\ \\
// Now you can do this in ldap_config.php \\
//##################################################\\
$filter = $filter . "uid=" . $uid;
/****************************************************/
// Open a LDAP connection
$ldap = new LDAP($hostname,$port);
// Try to get user data on the LDAP
try
{
$data = $ldap->getDataForMattermost($base,$filter,$bind_dn,$bind_pass);
$resp = array("name" => $data['cn'],"username" => $uid,"id" => $assoc_id,"state" => "active","email" => $data['mail']);
$data = $ldap->getDataForMattermost($base,$filter,$bind_dn,$bind_pass,$search_attribute,$user);
$resp = array("name" => $data['cn'],"username" => $user,"id" => $assoc_id,"state" => "active","email" => $data['mail']);
}
catch (Exception $e)
{