Skip to content
Snippets Groups Projects
Commit 1e7c1113 authored by Jaime Pérez Crespo's avatar Jaime Pérez Crespo
Browse files

Merge pull request #334 from mrvanes/gen-affiliation

Add AttributeValueMap Authentication Processing Filter and unittest. 
parents a6ec24e4 027790e3
No related branches found
No related tags found
No related merge requests found
`core:AttributeValueMap`
===================
Filter that creates a target attribute based on one or more value(s) in source attribute.
%replace can be used to replace all existing values in target with new ones (any existing values will be lost)
%keep can be used to keep the source attribute, otherwise it will be removed.
Examples
--------
Add student affiliation based on LDAP groupmembership.
Will add eduPersonAffiliation containing value "student" if memberOf attribute contains
either 'cn=student,o=some,o=organization,dc=org' or 'cn=student,o=other,o=organization,dc=org'.
'memberOf' attribute will be removed (use %keep, to keep it) and existing values in
'eduPersonAffiliation' will be merged (use %replace to replace them).
'authproc' => array(
50 => array(
'class' => 'core:AttributeValueMap',
'sourceattribute' => 'memberOf',
'targetattribute' => 'eduPersonAffiliation',
'values' => array(
'student' => array(
'cn=student,o=some,o=organization,dc=org',
'cn=student,o=other,o=organization,dc=org',
),
),
),
)
Multiple assignments.
Add student, employee and both affiliation based on LDAP groupmembership in memberOf attribute.
'authproc' => array(
50 => array(
'class' => 'core:AttributeValueMap',
'sourceattribute' => 'memberOf',
'targetattribute' => 'eduPersonAffiliation',
'values' => array(
'student' => array(
'cn=student,o=some,o=organization,dc=org',
'cn=student,o=other,o=organization,dc=org',
),
'employee' => array(
'cn=employees,o=some,o=organization,dc=org',
'cn=employee,o=other,o=organization,dc=org',
'cn=workers,o=any,o=organization,dc=org',
),
'both' => array(
'cn=student,o=some,o=organization,dc=org',
'cn=student,o=other,o=organization,dc=org',
'cn=employees,o=some,o=organization,dc=org',
'cn=employee,o=other,o=organization,dc=org',
'cn=workers,o=any,o=organization,dc=org',
),
),
),
)
Replace and Keep.
Replace any existing 'affiliation' attribute values and keep 'groups' attribute.
'authproc' => array(
50 => array(
'class' => 'core:AttributeValueMap',
'sourceattribute' => 'groups',
'targetattribute' => 'affiliation',
'%replace',
'%keep',
'values' => array(
'student' => array(
'cn=student,o=some,o=organization,dc=org',
'cn=student,o=other,o=organization,dc=org',
),
'employee' => array(
'cn=employees,o=some,o=organization,dc=org',
'cn=employee,o=other,o=organization,dc=org',
'cn=workers,o=any,o=organization,dc=org',
),
),
),
)
<?php
/**
* Filter to create target attribute based on value(s) in source attribute
*
* @author Martin van Es, m7
* @package simpleSAMLphp
*/
class sspmod_core_Auth_Process_AttributeValueMap extends SimpleSAML_Auth_ProcessingFilter {
/**
* The attributename we should assign values to (ie target)
*/
private $targetattribute;
/**
* The attributename we should create values from
*/
private $sourceattribute;
/**
* The required $sourceattribute values and target affiliations
*/
private $values = array();
/**
* Wether $sourceattribute should be kept
*/
private $keep = false;
/**
* Wether $target attribute values should be replaced by new values
*/
private $replace = false;
/**
* Initialize this filter.
*
* @param array $config Configuration information about this filter.
* @param mixed $reserved For future use.
*/
public function __construct($config, $reserved) {
parent::__construct($config, $reserved);
assert('is_array($config)');
/* Validate configuration. */
foreach ($config as $name => $value) {
if (is_int($name)) {
// check if this is an option
if ($value === '%replace') {
$this->replace = true;
} elseif ($value === '%keep') {
$this->keep = true;
} else {
throw new SimpleSAML_Error_Exception('Unknown flag : ' . var_export($value, true));
}
continue;
}
// Set targetattribute
if ($name === 'targetattribute') {
$this->targetattribute = $value;
}
// Set sourceattribute
if ($name === 'sourceattribute') {
$this->sourceattribute = $value;
}
// Set values
if ($name === 'values') {
$this->values = $value;
}
}
}
/**
* Apply filter to add groups attribute.
*
* @param array &$request The current request
*/
public function process(&$request) {
SimpleSAML_Logger::debug('AttributeValueMap - process');
assert('is_array($request)');
assert('array_key_exists("Attributes", $request)');
$attributes =& $request['Attributes'];
// Make sure sourceattribute exists
assert('array_key_exists($this->sourceattribute, $attributes)');
// Make sure the targetattribute is set
assert('is_string($this->targetattribute)');
$sourceattribute = $attributes[$this->sourceattribute];
$targetvalues = array();
if (is_array($sourceattribute)) {
foreach ($this->values as $value => $require) {
if (count(array_intersect($require, $sourceattribute)) > 0) {
SimpleSAML_Logger::debug('AttributeValueMap - intersect match for ' . $value);
$targetvalues[] = $value;
}
}
}
if (count($targetvalues) > 0) {
if ($this->replace or !@is_array($attributes[$this->targetattribute])) {
$attributes[$this->targetattribute] = $targetvalues;
} else {
$attributes[$this->targetattribute] = array_unique(array_merge($attributes[$this->targetattribute], $targetvalues));
}
}
if (!$this->keep) {
unset($attributes[$this->sourceattribute]);
}
}
}
<?php
/**
* Test for the core:AttributeValueMap filter.
*/
class Test_Core_Auth_Process_AttributeValueMap extends PHPUnit_Framework_TestCase
{
/**
* Helper function to run the filter with a given configuration.
*
* @param array $config The filter configuration.
* @param array $request The request state.
* @return array The state array after processing.
*/
private static function processFilter(array $config, array $request) {
$filter = new sspmod_core_Auth_Process_AttributeValueMap($config, null);
$filter->process($request);
return $request;
}
/**
* Test the most basic functionality.
*/
public function testBasic() {
$config = array(
'sourceattribute' => 'memberOf',
'targetattribute' => 'eduPersonAffiliation',
'values' => array(
'member' => array(
'theGroup',
'otherGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayNotHasKey('memberOf', $attributes);
$this->assertArrayHasKey('eduPersonAffiliation', $attributes);
$this->assertEquals($attributes['eduPersonAffiliation'], array('member'));
}
/**
* Test basic functionality, remove duplicates
*/
public function testNoDuplicates() {
$config = array(
'sourceattribute' => 'memberOf',
'targetattribute' => 'eduPersonAffiliation',
'values' => array(
'member' => array(
'theGroup',
'otherGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup', 'otherGroup'),
'eduPersonAffiliation' => array('member', 'someValue'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayNotHasKey('memberOf', $attributes);
$this->assertArrayHasKey('eduPersonAffiliation', $attributes);
$this->assertEquals($attributes['eduPersonAffiliation'], array('member', 'someValue'));
}
/**
* Test the %replace functionality.
*/
public function testReplace() {
$config = array(
'sourceattribute' => 'memberOf',
'targetattribute' => 'eduPersonAffiliation',
'%replace',
'values' => array(
'member' => array(
'theGroup',
'otherGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
'eduPersonAffiliation' => array('someValue'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayNotHasKey('memberOf', $attributes);
$this->assertArrayHasKey('eduPersonAffiliation', $attributes);
$this->assertEquals($attributes['eduPersonAffiliation'], array('member'));
}
/**
* Test the %keep functionality.
*/
public function testKeep() {
$config = array(
'sourceattribute' => 'memberOf',
'targetattribute' => 'eduPersonAffiliation',
'%keep',
'values' => array(
'member' => array(
'theGroup',
'otherGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
'eduPersonAffiliation' => array('someValue'),
),
);
$result = self::processFilter($config, $request);
$attributes = $result['Attributes'];
$this->assertArrayHasKey('memberOf', $attributes);
$this->assertArrayHasKey('eduPersonAffiliation', $attributes);
$this->assertEquals($attributes['eduPersonAffiliation'], array('someValue','member'));
}
/**
* Test unknown flag Exception
*
* @expectedException Exception
*/
public function testUnknownFlag() {
$config = array(
'%test',
'values' => array(
'member' => array(
'theGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
),
);
$result = self::processFilter($config, $request);
}
/**
* Test missing Source attribute
*
* @expectedException Exception
*/
public function testMissingSourceAttribute() {
$config = array(
'targetattribute' => 'affiliation',
'values' => array(
'member' => array(
'theGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
),
);
$result = self::processFilter($config, $request);
}
/**
* Test missing Target attribute
*
* @expectedException Exception
*/
public function testMissingTargetAttribute() {
$config = array(
'sourceattribute' => 'memberOf',
'values' => array(
'member' => array(
'theGroup',
),
),
);
$request = array(
'Attributes' => array(
'memberOf' => array('theGroup'),
),
);
$result = self::processFilter($config, $request);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment