Skip to content
Snippets Groups Projects
Commit 58235ac5 authored by Martin van Es's avatar Martin van Es
Browse files

Create AttributeValueMap processing filter

parent fc1837b2
No related branches found
No related tags found
No related merge requests found
`core:AttributeValueMap`
===================
Filter that creates a target attribute based on 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