Skip to content

Instantly share code, notes, and snippets.

@paulchubatyy
Last active October 5, 2018 14:55
Show Gist options
  • Save paulchubatyy/b43e82905d6b84bf593f77f73cb0dfd4 to your computer and use it in GitHub Desktop.
Save paulchubatyy/b43e82905d6b84bf593f77f73cb0dfd4 to your computer and use it in GitHub Desktop.
Snippets to map ldap groups to security roles in Symfony framework
<?php
namespace AppBundle;
use AppBundle\DependencyInjection\Compiler\LdapCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class AppBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new LdapCompilerPass());
}
}
<?php
namespace AppBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class LdapCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('security.user.provider.ldap');
$definition->setClass('AppBundle\Security\LdapUserProvider');
}
}
<?php
namespace AppBundle\Security;
use Symfony\Component\Ldap\Entry;
use Symfony\Component\Security\Core\User\LdapUserProvider as SymfonyLdapUserProvider;
use Symfony\Component\Security\Core\User\User;
/**
* Handles the mapping of ldap groups to security roles.
* Class LdapUserProvider
* @package AppBundle\Security
*/
class LdapUserProvider extends SymfonyLdapUserProvider
{
/** @var array maps ldap groups to roles */
private $groupMapping = [ // Definitely requires modification for your setup
'managers' => 'ROLE_ADMIN',
'devops' => 'ROLE_SUPER_ADMIN'
];
/** @var string extracts group name from dn string */
private $groupNameRegExp = '/^CN=(?P<group>[^,]+),ou.*$/i'; // You might want to change it to match your ldap server
protected function loadUser($username, Entry $entry)
{
$roles = ['ROLE_USER']; // Actually we should be using $this->defaultRoles, but it's private. Has to be redesigned.
if (!$entry->hasAttribute('memberOf')) { // Check if the entry has attribute with the group
return new User($username, '', $roles);
}
foreach ($entry->getAttribute('memberOf') as $groupLine) { // Iterate through each group entry line
$groupName = strtolower($this->getGroupName($groupLine)); // Extract and normalize the group name fron the line
if (array_key_exists($groupName, $this->groupMapping)) { // Check if the group is in the mapping
$roles[] = $this->groupMapping[$groupName]; // Map the group to the role the user will have
}
}
return new User($username, '', $roles); // Create and return the user object
}
/**
* Get the group name from the DN
* @param string $dn
* @return string
*/
private function getGroupName($dn)
{
$matches = [];
return preg_match($this->groupNameRegExp, $dn, $matches) ? $matches['group'] : '';
}
}
@netfeld
Copy link

netfeld commented Oct 5, 2018

If you need to add custom services to youre LdapUserProvider you can do so by adding arguments in the process function:

    $argument = new Reference("your service ID");

    $definition = $container->getDefinition('security.user.provider.ldap');
    $definition->setClass('AppBundle\Security\LdapUserProvider');
    $definition->addArgument($argument );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment