Revision: 1912
Author: olavmrk
Date: Mon Oct 26 07:55:35 2009
Log: Improvements to the aggregator module. Added documentation, and  
re-written more OO-oriented.

Merged into 1.5 branch from r1894.
http://code.google.com/p/simplesamlphp/source/detail?r=1912

Added:
   
/branches/simplesamlphp-1.5/modules/aggregator/config-templates/module_aggregator.php
  /branches/simplesamlphp-1.5/modules/aggregator/docs
  /branches/simplesamlphp-1.5/modules/aggregator/docs/aggregator.txt
  /branches/simplesamlphp-1.5/modules/aggregator/lib
  /branches/simplesamlphp-1.5/modules/aggregator/lib/Aggregator.php
Deleted:
   
/branches/simplesamlphp-1.5/modules/aggregator/config-templates/aggregator.php
Modified:
  /branches/simplesamlphp-1.5/modules/aggregator/www/index.php

=======================================
--- /dev/null
+++  
/branches/simplesamlphp-1.5/modules/aggregator/config-templates/module_aggregator.php
    
Mon Oct 26 07:55:35 2009
@@ -0,0 +1,45 @@
+<?php
+
+/* Configuration for the aggregator module. */
+$config = array(
+
+       /* List of aggregators. */
+       'aggregators' => array(
+               'example' => array(
+                       'source' => array(
+                               array('type' => 'flatfile'),  /* Metadata from 
metadata-directory. */
+                               array('type' => 'xml', 'url' => 
'https://idp.example.org/Metadata'),
+                               array('type' => 'xml', 'file' => 
'static-metadata.xml'),
+                       ),
+               ),
+               'example2' => array(
+                       'source' => array(
+                               array('type' => 'xml', 'url' => 
'https://idp.example.org/Metadata2'),
+                       ),
+                       'set' => 'saml2',
+                       'sign.privatekey' => 'server2.key',
+                       'sign.certificate' => 'server2.crt',
+               )
+       ),
+
+
+       'maxDuration'   => 60*60*24*5, // Maximum 5 days duration on ValidUntil.
+
+       // If base64 encoded for entity is already cached in the entity, should 
we
+       // reconstruct the XML or re-use.
+       'reconstruct' => FALSE,
+
+       /* Whether metadata should be signed. */
+       'sign.enable' => FALSE,
+
+       /* Private key which should be used when signing the metadata. */
+       'sign.privatekey' => 'server.key',
+
+       /* Password to decrypt private key, or NULL if the private key is  
unencrypted. */
+       'sign.privatekey_pass' => NULL,
+
+       /* Certificate which should be included in the signature. Should  
correspond to the private key. */
+       'sign.certificate' => 'server.crt',
+
+);
+
=======================================
--- /dev/null
+++ /branches/simplesamlphp-1.5/modules/aggregator/docs/aggregator.txt  Mon  
Oct 26 07:55:35 2009
@@ -0,0 +1,90 @@
+aggregator Module
+=================
+
+<!--
+       This file is written in Markdown syntax.
+       For more information about how to use the Markdown syntax, read here:
+       http://daringfireball.net/projects/markdown/syntax
+-->
+
+  * Version: `$Id$`
+  * Author: Andreas Åkre Solberg <[email protected]>, UNINETT AS
+  * Package: simpleSAMLphp
+
+This module, aggregates a set of metadata of SAML entities to SAML 2.0  
documents with an `EntitiesDescriptor` with multiple entities inside.
+
+Multiple aggregates can be configured.
+
+
+
+The configuration file: module_aggregate.php
+--------------------------------------------
+
+The configuration file includes an option `aggregators`, which includes a  
indexed list of different aggregator configurations that all can be  
accessed independently. The structure is as follows:
+
+       'aggregators' => array(
+               'aggr1' => array(
+                       'sources' => [...]
+                       [...local params...]
+               ),
+               'aggr2' => ...
+       )
+       [...global params...]
+
+All of the global parameters can be overriden for each aggregator. Here is  
a list of the available (global) paramters:
+
+`set`
+: By default all SAML types are available, including:  
`array('saml20-idp-remote', 'saml20-sp-remote', 'shib13-idp-remote', 
'shib13-sp-remote')`.  
This list can be reduced by specifying one of the following values:
+
+  * `saml20-idp-remote`
+  * `saml20-sp-remote`
+  * `shib13-idp-remote`
+  * `shib13-sp-remote`
+  * `saml2`
+  * `shib13`
+
+`foo`
+: sldkfjdslkjf
+
+`reconstruct`
+: Whether simpleSAMLphp should regenerate the metadata XML (TRUE) or  
pass-through the input metadata XML (FALSE).
+
+`maxDuration`
+: Max validity of metadata (duration) in seconds.
+
+`sign.enable`
+: Enable signing of metadata document
+
+`sign.privatekey`
+: Private key to use when signing
+
+`sign.privatekey_pass`
+: Optionally a passphrase to the private key
+
+`sign.certificate`
+: Certificate to embed, corresponding to the private key.
+
+
+Accessing the aggregate
+-----------------------
+
+On the SimpleSAMLphp frontpage on the federation tab, there is a link to  
the aggregator named *Metadata aggregator*.
+
+When accessing the aggregator endpoint without specifying an aggregate ID,  
a list of available aggregators will be presented, with different options  
for mime-type presenting the result.
+
+The endpoint supports the following query parameter:
+
+`id`
+: The ID of the aggregator (From configuration file)
+
+`set`
+: Subset the available types of SAML entities. Similar to the `set`  
parameter described over in the configuration file description.
+
+`exclude`
+: Specify a `tag` that will be excluded from the metadata set. Useful for  
leaving out your own federation metadata.
+
+`mimetype`
+: Select Mime-Type that will be used. Default is  
`application/samlmetadata+xml`.
+
+
+
=======================================
--- /dev/null
+++ /branches/simplesamlphp-1.5/modules/aggregator/lib/Aggregator.php   Mon  
Oct 26 07:55:35 2009
@@ -0,0 +1,247 @@
+<?php
+
+/**
+ * Aggregates metadata for multiple sources into one signed file
+ *
+ * @author Andreas Åkre Solberg <[email protected]>
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+
+class sspmod_aggregator_Aggregator {
+
+       // Configuration for the whole aggregator module
+       private $gConfig;
+
+       // Configuration for the specific aggregate
+       private $aConfig;
+
+       private $sets;
+
+       private $excludeTags = array();
+
+       private $id;
+
+       /**
+        * Constructor for the Aggregator.
+        *
+        */
+       public function __construct($gConfig, $aConfig, $id) {
+               $this->gConfig = $gConfig;
+               $this->aConfig = $aConfig;
+               $this->id = $id;
+
+               $this->sets =  
array('saml20-idp-remote', 'saml20-sp-remote', 'shib13-idp-remote', 
'shib13-sp-remote');
+
+               if ($this->aConfig->hasValue('set')) {
+                       $this->limitSets($this->aConfig->getString('set'));
+               }
+       }
+
+
+
+       public function limitSets($set) {
+
+
+               if (is_array($set)) {
+                       $this->sets = array_intersect($this->sets, $set);
+                       return;
+               }
+
+               switch($set) {
+                       case 'saml2' :
+                               $this->sets = array_intersect($this->sets,  
array('saml20-idp-remote', 'saml20-sp-remote')); break;
+                       case 'shib13' :
+                               $this->sets = array_intersect($this->sets,  
array('shib13-idp-remote', 'shib13-sp-remote')); break;
+                       case 'idp' :
+                               $this->sets = array_intersect($this->sets,  
array('saml20-idp-remote', 'shib13-idp-remote')); break;
+                       case 'sp' :
+                               $this->sets = array_intersect($this->sets,  
array('saml20-sp-remote', 'shib13-sp-remote')); break;
+
+                       default:
+                               $this->sets = array_intersect($this->sets, 
array($set));
+               }
+       }
+
+       /**
+        * Add tag to excelude when collecting source metadata.
+        *
+        * $exclude     May be string or array identifying a tag to exclude.
+        */
+       public function exclude($exclude) {
+               $this->excludeTags = array_merge($this->excludeTags,  
SimpleSAML_Utilities::arrayize($exclude));
+       }
+
+       /**
+        * Returns a list of entities with metadata
+        */
+       public function getSources() {
+
+               $sourcesDef = $this->aConfig->getArray('sources');
+
+               try {
+                       $sources =  
SimpleSAML_Metadata_MetaDataStorageSource::parseSources($sourcesDef);
+               } catch (Exception $e) {
+                       throw new Exception('Invalid aggregator source 
configuration for  
aggregator ' .
+                               var_export($id, TRUE) . ': ' . 
$e->getMessage());
+               }
+
+
+               #echo $exclude; exit;
+               /* Find list of all available entities. */
+               $entities = array();
+               #echo '<pre>'; print_r($this->sets); exit;
+
+               foreach ($sources as $source) {
+                       foreach ($this->sets as $set) {
+
+                               foreach ($source->getMetadataSet($set) as 
$entityId => $metadata) {
+
+                                       if (isset($metadata['tags']) &&
+                                                       
count(array_intersect($this->excludeTags, $metadata['tags'])) > 0) {
+
+                                               
SimpleSAML_Logger::debug('Excluding entity ID [' . $entityId . ']  
becuase it is tagged with one of [' .
+                                                       
var_export($this->excludeTags, TRUE) . ']');
+                                               continue;
+                                       } else {
+                                               #echo('<pre>'); 
print_r($metadata); exit;
+                                       }
+                                       if (!array_key_exists($entityId, 
$entities))
+                                               $entities[$entityId] = array();
+
+                                       if (array_key_exists($set, 
$entities[$entityId])) {
+                                               /* Entity already has metadata 
for the given set. */
+                                               continue;
+                                       }
+
+                                       $entities[$entityId][$set] = $metadata;
+                               }
+                       }
+               }
+               return $entities;
+
+       }
+
+       public function getMaxDuration() {
+               if ($this->aConfig->hasValue('maxDuration'))
+                       return $this->aConfig->getInteger('maxDuration');
+               if ($this->gConfig->hasValue('maxDuration'))
+                       return $this->gConfig->getInteger('maxDuration');
+               return NULL;
+       }
+
+
+
+       public function getReconstruct() {
+               if ($this->aConfig->hasValue('reconstruct'))
+                       return $this->aConfig->getBoolean('reconstruct');
+               if ($this->gConfig->hasValue('reconstruct'))
+                       return $this->gConfig->getBoolean('reconstruct');
+               return FALSE;
+       }
+
+       public function shouldSign() {
+               if ($this->aConfig->hasValue('sign.enable'))
+                       return $this->aConfig->getBoolean('sign.enable');
+               if ($this->gConfig->hasValue('sign.enable'))
+                       return $this->gConfig->getBoolean('sign.enable');
+               return FALSE;
+       }
+
+
+       public function getSigningInfo() {
+               if ($this->aConfig->hasValue('sign.privatekey')) {
+                       return array(
+                               'privatekey' => 
$this->aConfig->getString('sign.privatekey'),
+                               'privatekey_pass' => 
$this->aConfig->getString('sign.privatekey_pass',  
NULL),
+                               'certificate' => 
$this->aConfig->getString('sign.certificate'),
+                               'id' => 'ID'
+                       );
+               }
+
+               return array(
+                       'privatekey' => 
$this->gConfig->getString('sign.privatekey'),
+                       'privatekey_pass' => 
$this->gConfig->getString('sign.privatekey_pass',  
NULL),
+                       'certificate' => 
$this->gConfig->getString('sign.certificate'),
+                       'id' => 'ID'
+               );
+       }
+
+
+
+       public function getMetadataDocument() {
+
+               // Get metadata entries
+               $entities = $this->getSources();
+
+
+               // Generate XML Document
+               $xml = new DOMDocument();
+               $entitiesDescriptor =  
$xml->createElementNS('urn:oasis:names:tc:SAML:2.0:metadata', 
'EntitiesDescriptor');
+               $entitiesDescriptor->setAttribute('Name', $this->id);
+               $xml->appendChild($entitiesDescriptor);
+
+
+               $maxDuration = $this->getMaxDuration();
+               $reconstruct = $this->getReconstruct();
+
+
+               /* Build EntityDescriptor elements for them. */
+               foreach ($entities as $entity => $sets) {
+
+                       $entityDescriptor = NULL;
+                       foreach ($sets as $set => $metadata) {
+                               if (!array_key_exists('entityDescriptor', 
$metadata)) {
+                                       /* One of the sets doesn't contain an 
EntityDescriptor element. */
+                                       $entityDescriptor = FALSE;
+                                       break;
+                               }
+
+                               if ($entityDescriptor == NULL) {
+                                       /* First EntityDescriptor elements. */
+                                       $entityDescriptor = 
$metadata['entityDescriptor'];
+                                       continue;
+                               }
+
+                               assert('is_string($entityDescriptor)');
+                               if ($entityDescriptor !== 
$metadata['entityDescriptor']) {
+                                       /* Entity contains multiple different 
EntityDescriptor elements. */
+                                       $entityDescriptor = FALSE;
+                                       break;
+                               }
+                       }
+
+                       if (is_string($entityDescriptor) && !$reconstruct) {
+                               /* All metadata sets for the entity contain the 
same entity  
descriptor. Use that one. */
+                               $tmp = new DOMDocument();
+                               $tmp->loadXML(base64_decode($entityDescriptor));
+                               $entityDescriptor = $tmp->documentElement;
+                       } else {
+
+                               $tmp = new 
SimpleSAML_Metadata_SAMLBuilder($entity, $maxDuration,  
$maxDuration);
+
+                               $orgmeta = NULL;
+                               foreach ($sets as $set => $metadata) {
+                                       $tmp->addMetadata($set, $metadata);
+                                       $orgmeta = $metadata;
+                               }
+                               $tmp->addOrganizationInfo($orgmeta);
+                               $entityDescriptor = $tmp->getEntityDescriptor();
+                       }
+
+                       
$entitiesDescriptor->appendChild($xml->importNode($entityDescriptor,  
TRUE));
+               }
+
+
+               /* Sign the metadata if enabled. */
+               if ($this->shouldSign()) {
+                       $signer = new 
SimpleSAML_XML_Signer($this->getSigningInfo());
+                       $signer->sign($entitiesDescriptor, $entitiesDescriptor, 
 
$entitiesDescriptor->firstChild);
+               }
+
+
+               return $xml;
+       }
+
+
+}
=======================================
---  
/branches/simplesamlphp-1.5/modules/aggregator/config-templates/aggregator.php  
 
Tue Jun 16 04:50:53 2009
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-/* Configuration for the aggregator module. */
-$config = array(
-
-       /* List of aggregators. */
-       'aggregators' => array(
-               'example' => array(
-                       array('type' => 'flatfile'),  /* Metadata from 
metadata-directory. */
-                       array('type' => 'xml', 'url' => 
'https://idp.example.org/Metadata'),
-                       array('type' => 'xml', 'file' => 'static-metadata.xml'),
-               ),
-       ),
-
-
-       'maxCache'              => 60*60*24, // 24 hour cache time
-       'maxDuration'   => 60*60*24*5, // Maximum 5 days duration on ValidUntil.
-
-       // If base64 encoded for entity is already cached in the entity, should 
we
-       // reconstruct the XML or re-use.
-       'reconstruct' => TRUE,
-
-       /* Whether metadata should be signed. */
-       'sign.enable' => FALSE,
-
-       /* Private key which should be used when signing the metadata. */
-       'sign.privatekey' => 'server.key',
-
-       /* Password to decrypt private key, or NULL if the private key is  
unencrypted. */
-       'sign.privatekey_pass' => NULL,
-
-       /* Certificate which should be included in the signature. Should  
correspond to the private key. */
-       'sign.certificate' => 'server.crt',
-
-);
-
-?>
=======================================
--- /branches/simplesamlphp-1.5/modules/aggregator/www/index.php        Tue Jun 
16  
05:14:31 2009
+++ /branches/simplesamlphp-1.5/modules/aggregator/www/index.php        Mon Oct 
26  
07:55:35 2009
@@ -1,159 +1,36 @@
  <?php

-$globalConfig = SimpleSAML_Configuration::getInstance();
-$aggregatorConfig = SimpleSAML_Configuration::getConfig('aggregator.php');
+$config = SimpleSAML_Configuration::getInstance();
+$gConfig = SimpleSAML_Configuration::getConfig('module_aggregator.php');


-$reconstruct = $aggregatorConfig->getBoolean('reconstruct', FALSE);
-$aggregators = $aggregatorConfig->getArray('aggregators');
-
-$metadataSets =  
array('saml20-idp-remote', 'saml20-sp-remote', 'shib13-idp-remote', 
'shib13-sp-remote');
-if ($aggregatorConfig->hasValue('default-set')) {
-       $metadataSets = $aggregatorConfig->getArray('default-set');
-}
-if (isset($_REQUEST['set'])) {
-       switch($_REQUEST['set']) {
-               case 'saml2' :
-                       $metadataSets = array('saml20-idp-remote', 
'saml20-sp-remote'); break;
-               case 'shib13' :
-                       $metadataSets = array('shib13-idp-remote', 
'shib13-sp-remote'); break;
-               case 'idp' :
-                       $metadataSets = array('saml20-idp-remote', 
'shib13-idp-remote'); break;
-               case 'sp' :
-                       $metadataSets = array('saml20-sp-remote', 
'shib13-sp-remote'); break;
-
-               default:
-                       $metadataSets = array($_REQUEST['set']);
-       }
-}
-
-// print_r($metadataSets); exit;
-
+// Get list of aggregators
+$aggregators = $gConfig->getConfigItem('aggregators');
+
+// If aggregator ID is not provided, show the list of available aggregates
  if (!array_key_exists('id', $_GET)) {
-       $t = new SimpleSAML_XHTML_Template($globalConfig, 
'aggregator:list.php');
-       $t->data['sources'] = array_keys($aggregators);
+       $t = new SimpleSAML_XHTML_Template($config, 'aggregator:list.php');
+       $t->data['sources'] = $aggregators->getOptions();
        $t->show();
        exit;
  }
-
  $id = $_GET['id'];
-if (!array_key_exists($id, $aggregators)) {
+if (!in_array($id, $aggregators->getOptions()))
        throw new SimpleSAML_Error_NotFound('No aggregator with id ' .  
var_export($id, TRUE) . ' found.');
-}
-
-
-/* Parse metadata sources. */
-$sources = $aggregators[$id];
-if (!is_array($sources)) {
-       throw new Exception('Invalid aggregator source configuration for  
aggregator ' .
-               var_export($id, TRUE) . ': Aggregator wasn\'t an array.');
-};
-
-try {
-       $sources =  
SimpleSAML_Metadata_MetaDataStorageSource::parseSources($sources);
-} catch (Exception $e) {
-       throw new Exception('Invalid aggregator source configuration for  
aggregator ' .
-               var_export($id, TRUE) . ': ' . $e->getMessage());
-}
-
-$exclude = NULL;
-if (array_key_exists('exclude', $_REQUEST)) $exclude =  
$_REQUEST['exclude'];
-
-#echo $exclude; exit;
-/* Find list of all available entities. */
-$entities = array();
-foreach ($sources as $source) {
-       foreach ($metadataSets as $set) {
-               foreach ($source->getMetadataSet($set) as $entityId => 
$metadata) {
-                       if (isset($exclude) &&
-                                       array_key_exists('tags', $metadata) &&
-                                       in_array($exclude, $metadata['tags'])) {
-                               SimpleSAML_Logger::debug('Excluding entity ID 
[' . $entityId . ']  
becuase it is tagged with [' . $exclude . ']');
-                               continue;
-                       } else {
-                               #echo('<pre>'); print_r($metadata); exit;
-                       }
-                       if (!array_key_exists($entityId, $entities))
-                               $entities[$entityId] = array();
-
-                       if (array_key_exists($set, $entities[$entityId])) {
-                               /* Entity already has metadata for the given 
set. */
-                               continue;
-                       }
-
-                       $entities[$entityId][$set] = $metadata;
-               }
-       }
-}
-
-$xml = new DOMDocument();
-$entitiesDescriptor =  
$xml->createElementNS('urn:oasis:names:tc:SAML:2.0:metadata', 
'EntitiesDescriptor');
-$entitiesDescriptor->setAttribute('Name', $id);
-$xml->appendChild($entitiesDescriptor);
-
-
-
-/* Build EntityDescriptor elements for them. */
-foreach ($entities as $entity => $sets) {
-
-       $entityDescriptor = NULL;
-       foreach ($sets as $set => $metadata) {
-               if (!array_key_exists('entityDescriptor', $metadata)) {
-                       /* One of the sets doesn't contain an EntityDescriptor 
element. */
-                       $entityDescriptor = FALSE;
-                       break;
-               }
-
-               if ($entityDescriptor == NULL) {
-                       /* First EntityDescriptor elements. */
-                       $entityDescriptor = $metadata['entityDescriptor'];
-                       continue;
-               }
-
-               assert('is_string($entityDescriptor)');
-               if ($entityDescriptor !== $metadata['entityDescriptor']) {
-                       /* Entity contains multiple different EntityDescriptor 
elements. */
-                       $entityDescriptor = FALSE;
-                       break;
-               }
-       }
-
-       if (is_string($entityDescriptor) && !$reconstruct) {
-               /* All metadata sets for the entity contain the same entity 
descriptor.  
Use that one. */
-               $tmp = new DOMDocument();
-               $tmp->loadXML(base64_decode($entityDescriptor));
-               $entityDescriptor = $tmp->documentElement;
-       } else {
-               $tmp = new SimpleSAML_Metadata_SAMLBuilder($entity,
-                       $aggregatorConfig->getValue('maxCache', NULL),  
$aggregatorConfig->getValue('maxDuration', NULL));
-
-               $orgmeta = NULL;
-               foreach ($sets as $set => $metadata) {
-                       $tmp->addMetadata($set, $metadata);
-                       $orgmeta = $metadata;
-               }
-               $tmp->addOrganizationInfo($orgmeta);
-               $entityDescriptor = $tmp->getEntityDescriptor();
-       }
-
-       $entitiesDescriptor->appendChild($xml->importNode($entityDescriptor,  
TRUE));
-}
-
-
-/* Sign the metadata if enabled. */
-if ($aggregatorConfig->getBoolean('sign.enable', FALSE)) {
-       $privateKey = $aggregatorConfig->getString('sign.privatekey');
-       $privateKeyPass = $aggregatorConfig->getString('sign.privatekey_pass',  
NULL);
-       $certificate = $aggregatorConfig->getString('sign.certificate');
-
-       $signer = new SimpleSAML_XML_Signer(array(
-               'privatekey' => $privateKey,
-               'privatekey_pass' => $privateKeyPass,
-               'certificate' => $certificate,
-               'id' => 'ID',
-               ));
-       $signer->sign($entitiesDescriptor, $entitiesDescriptor,  
$entitiesDescriptor->firstChild);
-}
+
+$aConfig = $aggregators->getConfigItem($id);
+
+
+$aggregator = new sspmod_aggregator_Aggregator($gConfig, $aConfig, $id);
+
+if (isset($_REQUEST['set']))
+       $aggregator->limitSets($_REQUEST['set']);
+
+if (isset($_REQUEST['exclude']))
+       $aggregator->exclude($_REQUEST['exclude']);
+
+
+$xml = $aggregator->getMetadataDocument();


  /* Show the metadata. */

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"simpleSAMLphp commits" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/simplesamlphp-commits?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to