Skip to content
Snippets Groups Projects
Commit f426d4fc authored by Jaime Perez's avatar Jaime Perez
Browse files

aggregator2: add filtering (by sets, as in the aggregator module) and entity...

aggregator2: add filtering (by sets, as in the aggregator module) and entity exclusion (by entity ID). Both options can be set by request and as a default by configuration (per aggregate, not source). Both options accept multiple values (exclude several entity IDs, filter by several criteria). Results are cached according to the filtering and exclusion parameters.
parent d8e47c31
No related branches found
No related tags found
No related merge requests found
...@@ -67,6 +67,41 @@ class sspmod_aggregator2_Aggregator { ...@@ -67,6 +67,41 @@ class sspmod_aggregator2_Aggregator {
protected $cacheGenerated; protected $cacheGenerated;
/**
* An array of entity IDs to exclude from the aggregate.
*
* @var string[]|null
*/
protected $excluded;
/**
* An indexed array of protocols to filter the aggregate by. keys can be any of:
*
* - urn:oasis:names:tc:SAML:1.1:protocol
* - urn:oasis:names:tc:SAML:2.0:protocol
*
* Values will be true if enabled, false otherwise.
*
* @var string[]|null
*/
protected $protocols;
/**
* An array of roles to filter the aggregate by. Keys can be any of:
*
* - SAML2_XML_md_IDPSSODescriptor
* - SAML2_XML_md_SPSSODescriptor
* - SAML2_XML_md_AttributeAuthorityDescriptor
*
* Values will be true if enabled, false otherwise.
*
* @var string[]|null
*/
protected $roles;
/** /**
* The key we should use to sign the metadata. * The key we should use to sign the metadata.
* *
...@@ -151,6 +186,12 @@ class sspmod_aggregator2_Aggregator { ...@@ -151,6 +186,12 @@ class sspmod_aggregator2_Aggregator {
$this->cacheTag = sha1(serialize($config)); $this->cacheTag = sha1(serialize($config));
} }
// configure entity IDs excluded by default
$this->excludeEntities($config->getArrayize('exclude', null));
// configure filters
$this->setFilters($config->getArrayize('filter', null));
$this->validLength = $config->getInteger('valid.length', 7*24*60*60); $this->validLength = $config->getInteger('valid.length', 7*24*60*60);
$globalConfig = SimpleSAML_Configuration::getInstance(); $globalConfig = SimpleSAML_Configuration::getInstance();
...@@ -424,6 +465,159 @@ class sspmod_aggregator2_Aggregator { ...@@ -424,6 +465,159 @@ class sspmod_aggregator2_Aggregator {
} }
/**
* Recursively traverse the children of an EntitiesDescriptor, removing those entities listed in the $entities
* property. Returns the EntitiesDescriptor with the entities filtered out.
*
* @param SAML2_XML_md_EntitiesDescriptor $descriptor The EntitiesDescriptor from where to exclude entities.
*
* @return SAML2_XML_md_EntitiesDescriptor The EntitiesDescriptor with excluded entities filtered out.
*/
protected function exclude(SAML2_XML_md_EntitiesDescriptor $descriptor)
{
if (empty($this->excluded)) {
return $descriptor;
}
$filtered = array();
foreach ($descriptor->children as $child) {
if ($child instanceof SAML2_XML_md_EntityDescriptor) {
if (in_array($child->entityID, $this->excluded)) {
continue;
}
$filtered[] = $child;
}
if ($child instanceof SAML2_XML_md_EntitiesDescriptor) {
$filtered[] = $this->exclude($child);
}
}
$descriptor->children = $filtered;
return $descriptor;
}
/**
* Recursively traverse the children of an EntitiesDescriptor, keeping only those entities with the roles listed in
* the $roles property, and support for the protocols listed in the $protocols property. Returns the
* EntitiesDescriptor containing only those entities.
*
* @param SAML2_XML_md_EntitiesDescriptor $descriptor The EntitiesDescriptor to filter.
*
* @return SAML2_XML_md_EntitiesDescriptor The EntitiesDescriptor with only the entities filtered.
*/
protected function filter(SAML2_XML_md_EntitiesDescriptor $descriptor)
{
if ($this->roles === null || $this->protocols === null) {
return $descriptor;
}
$enabled_roles = array_keys($this->roles, true);
$enabled_protos = array_keys($this->protocols, true);
$filtered = array();
foreach ($descriptor->children as $child) {
if ($child instanceof SAML2_XML_md_EntityDescriptor) {
foreach ($child->RoleDescriptor as $role) {
if (in_array(get_class($role), $enabled_roles)) {
// we found a role descriptor that is enabled by our filters, check protocols
if (array_intersect($enabled_protos, $role->protocolSupportEnumeration) !== array()) {
// it supports some protocol we have enabled, add it
$filtered[] = $child;
break;
}
}
}
}
if ($child instanceof SAML2_XML_md_EntitiesDescriptor) {
$filtered[] = $this->filter($child);
}
}
$descriptor->children = $filtered;
return $descriptor;
}
/**
* Set this aggregator to exclude a set of entities from the resulting aggregate.
*
* @param array|null $entities The entity IDs of the entities to exclude.
*/
public function excludeEntities($entities)
{
assert('is_array($entities) || is_null($entities)');
if ($entities === null) {
return;
}
$this->excluded = $entities;
sort($this->excluded);
$this->cacheId = sha1($this->cacheId . serialize($this->excluded));
}
/**
* Set the internal filters according to one or more options:
*
* - 'saml2': all SAML2.0-capable entities.
* - 'shib13': all SHIB1.3-capable entities.
* - 'saml20-idp': all SAML2.0-capable identity providers.
* - 'saml20-sp': all SAML2.0-capable service providers.
* - 'saml20-aa': all SAML2.0-capable attribute authorities.
* - 'shib13-idp': all SHIB1.3-capable identity providers.
* - 'shib13-sp': all SHIB1.3-capable service providers.
* - 'shib13-aa': all SHIB1.3-capable attribute authorities.
*
* @param array|null $set An array of the different roles and protocols to filter by.
*/
public function setFilters($set)
{
assert('is_array($set) || is_null($set)');
if ($set === null) {
return;
}
// configure filters
$this->protocols = array(
SAML2_Const::NS_SAMLP => TRUE,
'urn:oasis:names:tc:SAML:1.1:protocol' => TRUE,
);
$this->roles = array(
'SAML2_XML_md_IDPSSODescriptor' => TRUE,
'SAML2_XML_md_SPSSODescriptor' => TRUE,
'SAML2_XML_md_AttributeAuthorityDescriptor' => TRUE,
);
// now translate from the options we have, to specific protocols and roles
// check SAML 2.0 protocol
$options = array('saml2', 'saml20-idp', 'saml20-sp', 'saml20-aa');
$this->protocols[SAML2_Const::NS_SAMLP] = (array_intersect($set, $options) !== array());
// check SHIB 1.3 protocol
$options = array('shib13', 'shib13-idp', 'shib13-sp', 'shib13-aa');
$this->protocols['urn:oasis:names:tc:SAML:1.1:protocol'] = (array_intersect($set, $options) !== array());
// check IdP
$options = array('saml2', 'shib13', 'saml20-idp', 'shib13-idp');
$this->roles['SAML2_XML_md_IDPSSODescriptor'] = (array_intersect($set, $options) !== array());
// check SP
$options = array('saml2', 'shib13', 'saml20-sp', 'shib13-sp');
$this->roles['SAML2_XML_md_SPSSODescriptor'] = (array_intersect($set, $options) !== array());
// check AA
$options = array('saml2', 'shib13', 'saml20-aa', 'shib13-aa');
$this->roles['SAML2_XML_md_AttributeAuthorityDescriptor'] = (array_intersect($set, $options) !== array());
$this->cacheId = sha1($this->cacheId . serialize($this->protocols) . serialize($this->roles));
}
/** /**
* Retrieve the complete, signed metadata as text. * Retrieve the complete, signed metadata as text.
* *
...@@ -435,6 +629,8 @@ class sspmod_aggregator2_Aggregator { ...@@ -435,6 +629,8 @@ class sspmod_aggregator2_Aggregator {
public function updateCachedMetadata() { public function updateCachedMetadata() {
$ed = $this->getEntitiesDescriptor(); $ed = $this->getEntitiesDescriptor();
$ed = $this->exclude($ed);
$ed = $this->filter($ed);
$this->addSignature($ed); $this->addSignature($ed);
$xml = $ed->toXML(); $xml = $ed->toXML();
......
...@@ -5,7 +5,19 @@ if (!isset($_REQUEST['id'])) { ...@@ -5,7 +5,19 @@ if (!isset($_REQUEST['id'])) {
} }
$id = (string) $_REQUEST['id']; $id = (string) $_REQUEST['id'];
$set = null;
if (isset($_REQUEST['set'])) {
$set = explode(',', $_REQUEST['set']);
}
$excluded_entities = null;
if (isset($_REQUEST['exclude'])) {
$excluded_entities = explode(',', $_REQUEST['exclude']);
}
$aggregator = sspmod_aggregator2_Aggregator::getAggregator($id); $aggregator = sspmod_aggregator2_Aggregator::getAggregator($id);
$aggregator->setFilters($set);
$aggregator->excludeEntities($excluded_entities);
$xml = $aggregator->getMetadata(); $xml = $aggregator->getMetadata();
$mimetype = 'application/samlmetadata+xml'; $mimetype = 'application/samlmetadata+xml';
......
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