Compare commits
2 Commits
master
...
metarefres
Author | SHA1 | Date |
---|---|---|
Benjamin Dauvergne | c40927bfec | |
Benjamin Dauvergne | db940492bd |
|
@ -0,0 +1,79 @@
|
|||
Fork du module metarefresh du projet SimpleSAMLPhp (SSP) pour le cas particulier de
|
||||
la fédération Éducation-Recherche Renater
|
||||
|
||||
Ce fork ajouter la gestion des règles de filtrage d'attribut au format Shibboleth.
|
||||
|
||||
Il est nécessaire de copier les fichiers du module metarefreshsupann/ dans le
|
||||
répertoire modules/ de SSP et le fichier supann_name2oid.php dans le répertoire
|
||||
attributemap/ de SSP.
|
||||
|
||||
Dans le fichier config/config.php on configurera les sources de métadonnés de
|
||||
sorte à lire celles générées par le script metarefresh, comme cela:
|
||||
|
||||
'metadata.sources' => array(
|
||||
array('type' => 'flatfile'),
|
||||
array('type' => 'flatfile', 'directory' => 'metadata/federation/'),
|
||||
),
|
||||
|
||||
Dans le fichier de configuration de l'IdP metadata/saml20-idp-hosted.php, on
|
||||
ajoutera les clés suivantes (la clé authproc est pensé en fonction de la
|
||||
configuration par défaut dans config/config.php si vous n'utilitisez pas cette
|
||||
configuration, il faut penser à activer le module 'core:AttributeLimit').
|
||||
|
||||
'AttributeNameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri'
|
||||
|
||||
'authproc' => array(
|
||||
100 => array(
|
||||
'class' => 'core:AttributeMap',
|
||||
'name2oid',
|
||||
),
|
||||
101 => array(
|
||||
'class' => 'core:AttributeMap',
|
||||
'supann_name2oid',
|
||||
),
|
||||
)
|
||||
|
||||
Pour permettre l'accès aux services nécessitant l'attribut eduPersonTargetedID
|
||||
ajouter la clé suivante à la clé 'authproc':
|
||||
|
||||
10 => array( # il faut quand même vérifier que userid.attribute = uid dans la configuration
|
||||
'class' => 'core:TargetedID',
|
||||
'attributename' => 'eduPersonTargetedID',
|
||||
),
|
||||
|
||||
Finalement il sera possible de charger les métadonnées manuellement via la commande:
|
||||
|
||||
./modules/metarefreshsupann/bin/metarefresh.php \
|
||||
--output-dir=metadata/federation/ \
|
||||
--shibboleth-afp=https://federation.renater.fr/renater/filtres/renater-attribute-filters-all.xml \
|
||||
https://federation.renater.fr/renater/renater-metadata.xml
|
||||
|
||||
ou bien l'on pourra utiliser le module cron de SSP via la configuration
|
||||
suivante dans le fichier config/config-metarefresh.php:
|
||||
|
||||
$config = array( 'sets' => array(
|
||||
|
||||
'renater' => array(
|
||||
'cron' => array('hourly'),
|
||||
'sources' => array(
|
||||
array(
|
||||
'src' => 'https://federation.renater.fr/renater/renater-metadata.xml',
|
||||
'template' => array(
|
||||
'tags' => array('renater'),
|
||||
),
|
||||
),
|
||||
),
|
||||
'afps' => array('https://federation.renater.fr/renater/filtres/renater-attribute-filters-all.xml'),
|
||||
'expireAfter' => 60*60*24*4, // Maximum 4 days cache time.
|
||||
'outputDir' => 'metadata/federation/',
|
||||
/*
|
||||
* Which output format the metadata should be saved as.
|
||||
* Can be 'flatfile' or 'serialize'. 'flatfile' is the default.
|
||||
*/
|
||||
'outputFormat' => 'flatfile',
|
||||
),
|
||||
));
|
||||
|
||||
On pourra se référ à la documentation de référence de SSP pour plus de détail
|
||||
sur la configuration du mode cron ou du module metarefresh:
|
||||
https://simplesamlphp.org/docs/1.5/simplesamlphp-automated_metadata
|
|
@ -0,0 +1,184 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This script can be used to generate metadata for simpleSAMLphp
|
||||
* based on an XML metadata file.
|
||||
*/
|
||||
|
||||
|
||||
/* This is the base directory of the simpleSAMLphp installation. */
|
||||
$baseDir = dirname(dirname(dirname(dirname(__FILE__))));
|
||||
|
||||
/* Add library autoloader. */
|
||||
require_once($baseDir . '/lib/_autoload.php');
|
||||
|
||||
SimpleSAML_Session::useTransientSession(); /* No need to try to create a session here. */
|
||||
|
||||
if(!SimpleSAML_Module::isModuleEnabled('metarefreshsupann')) {
|
||||
echo("You need to enable the metarefresh module before this script can be used.\n");
|
||||
echo("You can enable it by running the following command:\n");
|
||||
echo(' echo >"' . $baseDir . '/modules/metarefresh/enable' . "\"\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Initialize the configuration. */
|
||||
SimpleSAML_Configuration::setConfigDir($baseDir . '/config');
|
||||
|
||||
/* $outputDir contains the directory we will store the generated metadata in. */
|
||||
$outputDir = $baseDir . '/metadata-generated';
|
||||
|
||||
|
||||
/* $toStdOut is a boolean telling us wheter we will print the output to stdout instead
|
||||
* of writing it to files in $outputDir.
|
||||
*/
|
||||
$toStdOut = FALSE;
|
||||
|
||||
/* $validateFingerprint contains the fingerprint of the certificate which should have been used
|
||||
* to sign the EntityDescriptor in the metadata, or NULL if fingerprint validation shouldn't be
|
||||
* done.
|
||||
*/
|
||||
$validateFingerprint = NULL;
|
||||
|
||||
|
||||
/* This variable contains the files we will parse. */
|
||||
$files = array();
|
||||
|
||||
/* This variable contains the Shibboleth attribute filters policies */
|
||||
$afps = array();
|
||||
|
||||
/* Parse arguments. */
|
||||
|
||||
$progName = array_shift($argv);
|
||||
|
||||
foreach($argv as $a) {
|
||||
if(strlen($a) === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if($a[0] !== '-') {
|
||||
/* Not an option. Assume that it is a file we should parse. */
|
||||
$files[] = $a;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(strpos($a, '=') !== FALSE) {
|
||||
$p = strpos($a, '=');
|
||||
$v = substr($a, $p + 1);
|
||||
$a = substr($a, 0, $p);
|
||||
} else {
|
||||
$v = NULL;
|
||||
}
|
||||
|
||||
/* Map short options to long options. */
|
||||
$shortOptMap = array(
|
||||
'-h' => '--help',
|
||||
'-o' => '--out-dir',
|
||||
'-s' => '--stdout',
|
||||
);
|
||||
if(array_key_exists($a, $shortOptMap)) {
|
||||
$a = $shortOptMap[$a];
|
||||
}
|
||||
|
||||
switch($a) {
|
||||
case '--validate-fingerprint':
|
||||
if($v === NULL || strlen($v) === 0) {
|
||||
echo('The --validate-fingerprint option requires an parameter.' . "\n");
|
||||
echo('Please run `' . $progName . ' --help` for usage information.' . "\n");
|
||||
exit(1);
|
||||
}
|
||||
$validateFingerprint = $v;
|
||||
break;
|
||||
case '--help':
|
||||
printHelp();
|
||||
exit(0);
|
||||
case '--out-dir':
|
||||
if($v === NULL || strlen($v) === 0) {
|
||||
echo('The --out-dir option requires an parameter.' . "\n");
|
||||
echo('Please run `' . $progName . ' --help` for usage information.' . "\n");
|
||||
exit(1);
|
||||
}
|
||||
$outputDir = $baseDir . ($v[0] == '/' ? $v : '/' . $v);
|
||||
break;
|
||||
case '--shibboleth-afp':
|
||||
if($v === NULL || strlen($v) === 0) {
|
||||
echo('The --shibboleth-afp option requires a parameter.' . "\n");
|
||||
echo('Please run `' . $progName . ' --help` for usage information.' . "\n");
|
||||
exit(1);
|
||||
}
|
||||
$afps[] = $v;
|
||||
break;
|
||||
case '--stdout':
|
||||
$toStdOut = TRUE;
|
||||
break;
|
||||
default:
|
||||
echo('Unknown option: ' . $a . "\n");
|
||||
echo('Please run `' . $progName . ' --help` for usage information.' . "\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if(count($files) === 0) {
|
||||
echo($progName . ': Missing input files. Please run `' . $progName . ' --help` for usage information.' . "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* The metadata global variable will be filled with the metadata we extract. */
|
||||
$metaloader = new sspmod_metarefreshsupann_MetaLoader();
|
||||
|
||||
if ($afps) {
|
||||
foreach($afps as $afp) {
|
||||
$metaloader->loadAfp($afp);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($files as $f) {
|
||||
$source = array('src' => $f);
|
||||
if (isset($validateFingerprint)) $source['validateFingerprint'] = $validateFingerprint;
|
||||
$metaloader->loadSource($source);
|
||||
}
|
||||
|
||||
if($toStdOut) {
|
||||
$metaloader->dumpMetadataStdOut();
|
||||
} else {
|
||||
$metaloader->writeMetadataFiles($outputDir);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
|
||||
/**
|
||||
* This function prints the help output.
|
||||
*/
|
||||
function printHelp() {
|
||||
global $progName;
|
||||
|
||||
/* '======================================================================' */
|
||||
echo('Usage: ' . $progName . ' [options] [files]' . "\n");
|
||||
echo("\n");
|
||||
echo('This program parses a SAML metadata files and output pieces that can' . "\n");
|
||||
echo('be added to the metadata files in metadata/.' . "\n");
|
||||
echo("\n");
|
||||
echo('Options:' . "\n");
|
||||
echo(' --validate-fingerprint=<FINGERPRINT>' . "\n");
|
||||
echo(' Check the signature of the metadata,' . "\n");
|
||||
echo(' and check the fingerprint of the' . "\n");
|
||||
echo(' certificate against <FINGERPRINT>.' . "\n");
|
||||
echo(' -h, --help Print this help.' . "\n");
|
||||
echo(' -o=<DIR>, --out-dir=<DIR> Write the output to this directory. The' . "\n");
|
||||
echo(' default directory is metadata-generated/.' . "\n");
|
||||
echo(' Path will be relative to the simpleSAMLphp' . "\n");
|
||||
echo(' base directory.' . "\n");
|
||||
echo(' --shibboleth-afp=<FILE> Generate attributes parameters using an' . "\n");
|
||||
echo(' existing Attribute Filter Policy file.' . "\n");
|
||||
echo(' -s, --stdout Write the output to stdout instead of' . "\n");
|
||||
echo(' seperate files in the output directory.' . "\n");
|
||||
echo("\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
$config = array(
|
||||
|
||||
/*
|
||||
* Global blacklist: entityIDs that should be excluded from ALL sets.
|
||||
*/
|
||||
#'blacklist' = array(
|
||||
# 'http://my.own.uni/idp'
|
||||
#),
|
||||
|
||||
/*
|
||||
* Conditional GET requests
|
||||
* Efficient downloading so polling can be done more frequently.
|
||||
* Works for sources that send 'Last-Modified' or 'Etag' headers.
|
||||
* Note that the 'data' directory needs to be writable for this to work.
|
||||
*/
|
||||
#'conditionalGET' => TRUE,
|
||||
|
||||
'sets' => array(
|
||||
|
||||
'kalmar' => array(
|
||||
'cron' => array('hourly'),
|
||||
'sources' => array(
|
||||
array(
|
||||
/*
|
||||
* entityIDs that should be excluded from this src.
|
||||
*/
|
||||
#'blacklist' => array(
|
||||
# 'http://some.other.uni/idp',
|
||||
#),
|
||||
|
||||
/*
|
||||
* Whitelist: only keep these EntityIDs.
|
||||
*/
|
||||
#'whitelist' => array(
|
||||
# 'http://some.uni/idp',
|
||||
# 'http://some.other.uni/idp',
|
||||
#),
|
||||
|
||||
#'conditionalGET' => TRUE,
|
||||
'src' => 'https://kalmar2.org/simplesaml/module.php/aggregator/?id=kalmarcentral&set=saml2&exclude=norway',
|
||||
'validateFingerprint' => '59:1D:4B:46:70:46:3E:ED:A9:1F:CC:81:6D:C0:AF:2A:09:2A:A8:01',
|
||||
'template' => array(
|
||||
'tags' => array('kalmar'),
|
||||
'authproc' => array(
|
||||
51 => array('class' => 'core:AttributeMap', 'oid2name'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'expireAfter' => 60*60*24*4, // Maximum 4 days cache time.
|
||||
'outputDir' => 'metadata/metadata-kalmar-consuming/',
|
||||
|
||||
/*
|
||||
* Which output format the metadata should be saved as.
|
||||
* Can be 'flatfile' or 'serialize'. 'flatfile' is the default.
|
||||
*/
|
||||
'outputFormat' => 'flatfile',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
This file indicates that the default state of this module
|
||||
is disabled. To enable, create a file named enable in the
|
||||
same directory as this file.
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
/**
|
||||
* Hook to run a cron job.
|
||||
*
|
||||
* @param array &$croninfo Output
|
||||
*/
|
||||
function metarefreshsupann_hook_cron(&$croninfo) {
|
||||
assert('is_array($croninfo)');
|
||||
assert('array_key_exists("summary", $croninfo)');
|
||||
assert('array_key_exists("tag", $croninfo)');
|
||||
|
||||
SimpleSAML_Logger::info('cron [metarefreshsupann]: Running cron in cron tag [' . $croninfo['tag'] . '] ');
|
||||
|
||||
try {
|
||||
$config = SimpleSAML_Configuration::getInstance();
|
||||
$mconfig = SimpleSAML_Configuration::getOptionalConfig('config-metarefreshsupann.php');
|
||||
|
||||
$sets = $mconfig->getConfigList('sets', array());
|
||||
$stateFile = $config->getPathValue('datadir', 'data/') . 'metarefreshsupann-state.php';
|
||||
|
||||
foreach ($sets AS $setkey => $set) {
|
||||
// Only process sets where cron matches the current cron tag.
|
||||
$cronTags = $set->getArray('cron');
|
||||
if (!in_array($croninfo['tag'], $cronTags)) continue;
|
||||
|
||||
SimpleSAML_Logger::info('cron [metarefreshsupann]: Executing set [' . $setkey . ']');
|
||||
|
||||
$expireAfter = $set->getInteger('expireAfter', NULL);
|
||||
if ($expireAfter !== NULL) {
|
||||
$expire = time() + $expireAfter;
|
||||
} else {
|
||||
$expire = NULL;
|
||||
}
|
||||
|
||||
$outputDir = $set->getString('outputDir');
|
||||
$outputDir = $config->resolvePath($outputDir);
|
||||
$outputFormat = $set->getValueValidate('outputFormat', array('flatfile', 'serialize'), 'flatfile');
|
||||
|
||||
$oldMetadataSrc = SimpleSAML_Metadata_MetaDataStorageSource::getSource(array(
|
||||
'type' => $outputFormat,
|
||||
'directory' => $outputDir,
|
||||
));
|
||||
|
||||
$metaloader = new sspmod_metarefreshsupann_MetaLoader($expire, $stateFile, $oldMetadataSrc);
|
||||
|
||||
# Get global blacklist, whitelist and caching info
|
||||
$blacklist = $mconfig->getArray('blacklist', array());
|
||||
$whitelist = $mconfig->getArray('whitelist', array());
|
||||
$conditionalGET = $mconfig->getBoolean('conditionalGET', FALSE);
|
||||
|
||||
foreach($set->getArray('afps') AS $afp) {
|
||||
$metaload->loadAfp($afp);
|
||||
}
|
||||
|
||||
foreach($set->getArray('sources') AS $source) {
|
||||
|
||||
# Merge global and src specific blacklists
|
||||
if(isset($source['blacklist'])) {
|
||||
$source['blacklist'] = array_unique(array_merge($source['blacklist'], $blacklist));
|
||||
} else {
|
||||
$source['blacklist'] = $blacklist;
|
||||
}
|
||||
|
||||
# Merge global and src specific whitelists
|
||||
if(isset($source['whitelist'])) {
|
||||
$source['whitelist'] = array_unique(array_merge($source['whitelist'], $whitelist));
|
||||
} else {
|
||||
$source['whitelist'] = $whitelist;
|
||||
}
|
||||
|
||||
# Let src specific conditionalGET override global one
|
||||
if(!isset($source['conditionalGET'])) {
|
||||
$source['conditionalGET'] = $conditionalGET;
|
||||
}
|
||||
|
||||
SimpleSAML_Logger::debug('cron [metarefreshsupann]: In set [' . $setkey . '] loading source [' . $source['src'] . ']');
|
||||
$metaloader->loadSource($source);
|
||||
}
|
||||
|
||||
// Write state information back to disk
|
||||
$metaloader->writeState();
|
||||
|
||||
switch ($outputFormat) {
|
||||
case 'flatfile':
|
||||
$metaloader->writeMetadataFiles($outputDir);
|
||||
break;
|
||||
case 'serialize':
|
||||
$metaloader->writeMetadataSerialize($outputDir);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$croninfo['summary'][] = 'Error during metarefreshsupann: ' . $e->getMessage();
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/**
|
||||
* Hook to add links to the frontpage.
|
||||
*
|
||||
* @param array &$links The links on the frontpage, split into sections.
|
||||
*/
|
||||
function metarefreshsupann_hook_frontpage(&$links) {
|
||||
assert('is_array($links)');
|
||||
assert('array_key_exists("links", $links)');
|
||||
|
||||
$links['federation'][] = array(
|
||||
'href' => SimpleSAML_Module::getModuleURL('metarefreshsupann/fetch.php'),
|
||||
'text' => array('en' => 'MetarefreshSupann: fetch metadata'),
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
/*
|
||||
* @author Andreas Åkre Solberg <andreas.solberg@uninett.no>
|
||||
* @package simpleSAMLphp
|
||||
* @version $Id$
|
||||
*/
|
||||
class sspmod_metarefresh_ARP {
|
||||
|
||||
|
||||
private $metadata;
|
||||
private $attributes;
|
||||
private $prefix;
|
||||
private $suffix;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param
|
||||
*/
|
||||
public function __construct($metadata, $attributemap, $prefix, $suffix) {
|
||||
$this->metadata = $metadata;
|
||||
|
||||
$this->prefix = $prefix;
|
||||
$this->suffix = $suffix;
|
||||
|
||||
if (isset($attributemap)) $this->loadAttributeMap($attributemap);
|
||||
}
|
||||
|
||||
private function loadAttributeMap($attributemap) {
|
||||
$config = SimpleSAML_Configuration::getInstance();
|
||||
include($config->getPathValue('attributemap', 'attributemap/') . $attributemap . '.php');
|
||||
$this->attributes = $attributemap;
|
||||
|
||||
# print_r($attributemap); exit;
|
||||
}
|
||||
|
||||
private function surround($name) {
|
||||
$ret = '';
|
||||
if (!empty($this->prefix)) $ret .= $this->prefix;
|
||||
$ret .= $name;
|
||||
if (!empty($this->suffix)) $ret .= $this->suffix;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
private function getAttributeID($name) {
|
||||
if (empty($this->attributes)) {
|
||||
return $this->surround($name);
|
||||
}
|
||||
if (array_key_exists($name, $this->attributes)) {
|
||||
return $this->surround($this->attributes[$name]);
|
||||
}
|
||||
return $this->surround($name);
|
||||
}
|
||||
|
||||
public function getXML() {
|
||||
|
||||
$xml = '<?xml version="1.0" encoding="UTF-8"?>
|
||||
<AttributeFilterPolicyGroup id="urn:mace:funet.fi:haka:kalmar" xmlns="urn:mace:shibboleth:2.0:afp"
|
||||
xmlns:basic="urn:mace:shibboleth:2.0:afp:mf:basic" xmlns:saml="urn:mace:shibboleth:2.0:afp:mf:saml"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="urn:mace:shibboleth:2.0:afp classpath:/schema/shibboleth-2.0-afp.xsd
|
||||
urn:mace:shibboleth:2.0:afp:mf:basic classpath:/schema/shibboleth-2.0-afp-mf-basic.xsd
|
||||
urn:mace:shibboleth:2.0:afp:mf:saml classpath:/schema/shibboleth-2.0-afp-mf-saml.xsd">
|
||||
';
|
||||
|
||||
|
||||
foreach($this->metadata AS $metadata) {
|
||||
#$print_r($metadata); exit;
|
||||
$xml .= $this->getEntryXML($metadata['metadata']);
|
||||
}
|
||||
|
||||
$xml .= '</AttributeFilterPolicyGroup>';
|
||||
return $xml;
|
||||
}
|
||||
|
||||
private function getEntryXML($entry) {
|
||||
$entityid = $entry['entityid'];
|
||||
return ' <AttributeFilterPolicy id="' . $entityid . '">
|
||||
<PolicyRequirementRule xsi:type="basic:AttributeRequesterString" value="' . $entityid . '" />
|
||||
' . $this->getEntryXMLcontent($entry) . '
|
||||
</AttributeFilterPolicy>
|
||||
';
|
||||
}
|
||||
|
||||
private function getEntryXMLcontent($entry) {
|
||||
$ids = array();
|
||||
if (!array_key_exists('attributes', $entry))
|
||||
return '';
|
||||
|
||||
$ret = '';
|
||||
foreach($entry['attributes'] AS $a) {
|
||||
|
||||
$ret .= ' <AttributeRule attributeID="' . $this->getAttributeID($a) . '">
|
||||
<PermitValueRule xsi:type="basic:ANY" />
|
||||
</AttributeRule>
|
||||
';
|
||||
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,544 @@
|
|||
<?php
|
||||
/*
|
||||
* @author Andreas Åkre Solberg <andreas.solberg@uninett.no>
|
||||
* @package simpleSAMLphp
|
||||
* @version $Id$
|
||||
*/
|
||||
class sspmod_metarefreshsupann_MetaLoader {
|
||||
|
||||
|
||||
private $expire;
|
||||
private $metadata;
|
||||
private $oldMetadataSrc;
|
||||
private $stateFile;
|
||||
private $changed;
|
||||
private $attributes;
|
||||
private static $types = array('saml20-idp-remote', 'saml20-sp-remote',
|
||||
'shib13-idp-remote', 'shib13-sp-remote', 'attributeauthority-remote');
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $sources Sources...
|
||||
* @param
|
||||
*/
|
||||
public function __construct($expire = NULL, $stateFile = NULL, $oldMetadataSrc = NULL) {
|
||||
$this->expire = $expire;
|
||||
$this->metadata = array();
|
||||
$this->attributes = array();
|
||||
$this->oldMetadataSrc = $oldMetadataSrc;
|
||||
$this->stateFile = $stateFile;
|
||||
$this->changed = FALSE;
|
||||
|
||||
// Read file containing $state from disk
|
||||
if(is_readable($stateFile)) {
|
||||
require($stateFile);
|
||||
}
|
||||
|
||||
$this->state = (isset($state)) ? $state : array();
|
||||
|
||||
}
|
||||
|
||||
public function getChildNodes($dom_element) {
|
||||
$ret = array();
|
||||
foreach($dom_element->childNodes as $child) {
|
||||
if ($child instanceof DOMText || $child instanceof DOMComment) {
|
||||
continue;
|
||||
}
|
||||
$ret[] = $child;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* This functions process a Shibboleth Attribute Filter Policy files
|
||||
*
|
||||
* @params $afps
|
||||
*/
|
||||
public function loadAfp($afp) {
|
||||
$AFP = 'urn:mace:shibboleth:2.0:afp';
|
||||
$BASIC = 'urn:mace:shibboleth:2.0:afp:mf:basic';
|
||||
$XSI = 'http://www.w3.org/2001/XMLSchema-instance';
|
||||
$AF_POLICY_GROUP = 'AttributeFilterPolicyGroup';
|
||||
$AF_POLICY = 'AttributeFilterPolicy';
|
||||
$AF_POLICY_REQUIREMENT_RULE = 'PolicyRequirementRule';
|
||||
$AF_ATTRIBUTE_RULE = 'AttributeRule';
|
||||
$AF_PERMIT_VALUE_RULE = 'PermitValueRule';
|
||||
$XSI_TYPE = 'type';
|
||||
$BASIC_ATTRIBUTE_REQUESTER_STRING = 'AttributeRequesterString';
|
||||
$BASIC_ANY = 'ANY';
|
||||
$VALUE = 'value';
|
||||
$ATTRIBUTE_ID = 'attributeID';
|
||||
$ID = 'id';
|
||||
|
||||
$data = SimpleSAML_Utilities::fetch($afp);
|
||||
|
||||
$doc = new DOMDocument();
|
||||
$res = $doc->loadXML($data);
|
||||
$element = $doc->documentElement;
|
||||
if (! SimpleSAML_Utilities::isDOMElementOfType($element,
|
||||
$AF_POLICY_GROUP, $AFP)) {
|
||||
throw new Exception('Unexpected root node: [' . $element->namespaceURI . ']:' .
|
||||
$element->localName);
|
||||
}
|
||||
foreach ($this->getChildNodes($element) as $child) {
|
||||
if (! SimpleSAML_Utilities::isDOMElementOfType($child,
|
||||
$AF_POLICY, $AFP)) {
|
||||
throw new Exception('Unexpected child node: [' . $child->namespaceURI . ']:' .
|
||||
$child->localName);
|
||||
}
|
||||
$subchildren = $this->getChildNodes($child);
|
||||
if (! $subchildren) {
|
||||
throw new Exception('Missing subchild');
|
||||
}
|
||||
$prr = $subchildren[0];
|
||||
if (! SimpleSAML_Utilities::isDOMElementOfType($prr,
|
||||
$AF_POLICY_REQUIREMENT_RULE, $AFP)) {
|
||||
throw new Exception('Unexpected policy requirement rule node: [' . $prr->namespaceURI . ']:' .
|
||||
$prr->localName);
|
||||
}
|
||||
if (! $prr->hasAttributeNS($XSI, $XSI_TYPE)) {
|
||||
throw new Exception('Missing xsi:type attribute');
|
||||
}
|
||||
$xsi_type = $prr->getAttributeNodeNS($XSI, $XSI_TYPE)->value;
|
||||
$xsi_type = explode(':', $xsi_type, 2);
|
||||
if (count($xsi_type) != 2) {
|
||||
throw new Exception('Missing namespace prefix in xsi:type value: ' . implode($xsi_type));
|
||||
}
|
||||
$xsi_type_ns_uri = $prr->lookupNamespaceURI($xsi_type[0]);
|
||||
if ($xsi_type_ns_uri != $BASIC || $xsi_type[1] != $BASIC_ATTRIBUTE_REQUESTER_STRING) {
|
||||
throw new Exception('xsi:type is not basic:AttributeRequesterString');
|
||||
}
|
||||
$entity_id = $prr->attributes->getNamedItem($VALUE);
|
||||
if (! $entity_id) {
|
||||
throw new Exception('PolicyRequirementRule missing a value attribute');
|
||||
}
|
||||
$entity_id = $entity_id->value;
|
||||
$attributes = array();
|
||||
$this->attributes[$entity_id] = $attributes;
|
||||
foreach (array_slice($subchildren, 1) as $subchild) {
|
||||
if (! SimpleSAML_Utilities::isDOMElementOfType($subchild,
|
||||
$AF_ATTRIBUTE_RULE, $AFP)) {
|
||||
throw new Exception('Unexpected attribute rule node: [' . $subchild->namespaceURI . ']:' .
|
||||
$subchild->localName);
|
||||
}
|
||||
$attribute_id = $subchild->attributes->getNamedItem($ATTRIBUTE_ID);
|
||||
if (! $attribute_id) {
|
||||
throw new Exception('Missing attributeID attribute on attribute rule node');
|
||||
}
|
||||
$attribute_id = $attribute_id->value;
|
||||
$subsubchildren = $this->getChildNodes($subchild);
|
||||
if (count($subsubchildren) != 1) {
|
||||
throw new Exception("Attribute rule node must have only one child");
|
||||
}
|
||||
$pvr = $subsubchildren[0];
|
||||
if (! SimpleSAML_Utilities::isDOMElementOfType($pvr,
|
||||
$AF_PERMIT_VALUE_RULE, $AFP)) {
|
||||
throw new Exception('Unexpected PermiteValueRule node: [' . $pvr->namespaceURI . ']:' .
|
||||
$pvr->localName);
|
||||
}
|
||||
if (! $pvr->hasAttributeNS($XSI, $XSI_TYPE)) {
|
||||
throw new Exception('Missing xsi:type attribute');
|
||||
}
|
||||
$xsi_type = $pvr->getAttributeNodeNS($XSI, $XSI_TYPE)->value;
|
||||
$xsi_type = explode(':', $xsi_type, 2);
|
||||
if (count($xsi_type) != 2) {
|
||||
throw new Exception('Missing namespace prefix in xsi:type value');
|
||||
}
|
||||
$xsi_type_ns_uri = $pvr->lookupNamespaceURI($xsi_type[0]);
|
||||
if ($xsi_type_ns_uri != $BASIC || $xsi_type[1] != $BASIC_ANY) {
|
||||
throw new Exception('xsi:type is not basic:ANY');
|
||||
}
|
||||
$renater_is_weird = array(
|
||||
'email' => 'mail',
|
||||
);
|
||||
if (isset($renater_is_weird[$attribute_id])) { # fix wrongly named attributes
|
||||
$attribute_id = $renater_is_weird[$attribute_id];
|
||||
}
|
||||
$this->attributes[$entity_id][] = $attribute_id;
|
||||
# echo $entity_id . ' ' . $attribute_id . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function processes a SAML metadata file.
|
||||
*
|
||||
* @param $source
|
||||
*/
|
||||
public function loadSource($source) {
|
||||
|
||||
if (preg_match('@^https?://@i', $source['src'])) {
|
||||
// Build new HTTP context
|
||||
$context = $this->createContext($source);
|
||||
|
||||
// GET!
|
||||
try {
|
||||
list($data, $responseHeaders) = SimpleSAML_Utilities::fetch($source['src'], $context, TRUE);
|
||||
} catch(Exception $e) {
|
||||
SimpleSAML_Logger::warning('metarefreshsupann: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
// We have response headers, so the request succeeded
|
||||
if(!isset($responseHeaders)) {
|
||||
// No response headers, this means the request failed in some way, so re-use old data
|
||||
SimpleSAML_Logger::debug('No response from ' . $source['src'] . ' - attempting to re-use cached metadata');
|
||||
$this->addCachedMetadata($source);
|
||||
return;
|
||||
} elseif(preg_match('@^HTTP/1\.[01]\s304\s@', $responseHeaders[0])) {
|
||||
// 304 response
|
||||
SimpleSAML_Logger::debug('Received HTTP 304 (Not Modified) - attempting to re-use cached metadata');
|
||||
$this->addCachedMetadata($source);
|
||||
return;
|
||||
} elseif(!preg_match('@^HTTP/1\.[01]\s200\s@', $responseHeaders[0])) {
|
||||
// Other error.
|
||||
SimpleSAML_Logger::debug('Error from ' . $source['src'] . ' - attempting to re-use cached metadata');
|
||||
$this->addCachedMetadata($source);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* Local file. */
|
||||
$data = file_get_contents($source['src']);
|
||||
$responseHeaders = NULL;
|
||||
}
|
||||
|
||||
/* Everything OK. Proceed. */
|
||||
if (isset($source['conditionalGET']) && $source['conditionalGET']) {
|
||||
// Stale or no metadata, so a fresh copy
|
||||
SimpleSAML_Logger::debug('Downloaded fresh copy');
|
||||
}
|
||||
|
||||
$entities = $this->loadXML($data, $source);
|
||||
|
||||
foreach($entities as $entity) {
|
||||
|
||||
if(isset($source['blacklist'])) {
|
||||
if(!empty($source['blacklist']) && in_array($entity->getEntityID(), $source['blacklist'])) {
|
||||
SimpleSAML_Logger::info('Skipping "' . $entity->getEntityID() . '" - blacklisted.' . "\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($source['whitelist'])) {
|
||||
if(!empty($source['whitelist']) && !in_array($entity->getEntityID(), $source['whitelist'])) {
|
||||
SimpleSAML_Logger::info('Skipping "' . $entity->getEntityID() . '" - not in the whitelist.' . "\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(array_key_exists('validateFingerprint', $source) && $source['validateFingerprint'] !== NULL) {
|
||||
if(!$entity->validateFingerprint($source['validateFingerprint'])) {
|
||||
SimpleSAML_Logger::info('Skipping "' . $entity->getEntityId() . '" - could not verify signature.' . "\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$template = NULL;
|
||||
if (array_key_exists('template', $source)) $template = $source['template'];
|
||||
|
||||
$this->addMetadata($source['src'], $entity->getMetadata1xSP(), 'shib13-sp-remote', $template);
|
||||
$this->addMetadata($source['src'], $entity->getMetadata1xIdP(), 'shib13-idp-remote', $template);
|
||||
$this->addMetadata($source['src'], $entity->getMetadata20SP(), 'saml20-sp-remote', $template);
|
||||
$this->addMetadata($source['src'], $entity->getMetadata20IdP(), 'saml20-idp-remote', $template);
|
||||
$attributeAuthorities = $entity->getAttributeAuthorities();
|
||||
if (!empty($attributeAuthorities)) {
|
||||
$this->addMetadata($source['src'], $attributeAuthorities[0], 'attributeauthority-remote', $template);
|
||||
}
|
||||
}
|
||||
|
||||
$this->saveState($source, $responseHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create HTTP context, with any available caches taken into account
|
||||
*/
|
||||
private function createContext($source) {
|
||||
|
||||
$context = NULL;
|
||||
|
||||
$config = SimpleSAML_Configuration::getInstance();
|
||||
$name = $config->getString('technicalcontact_name', NULL);
|
||||
$mail = $config->getString('technicalcontact_email', NULL);
|
||||
|
||||
$rawheader = "User-Agent: SimpleSAMLphp metarefreshsupann, run by $name <$mail>\r\n";
|
||||
|
||||
if (isset($source['conditionalGET']) && $source['conditionalGET']) {
|
||||
if(array_key_exists($source['src'], $this->state)) {
|
||||
|
||||
$sourceState = $this->state[$source['src']];
|
||||
|
||||
if(isset($sourceState['last-modified'])) {
|
||||
$rawheader .= 'If-Modified-Since: ' . $sourceState['last-modified'] . "\r\n";
|
||||
}
|
||||
|
||||
if(isset($sourceState['etag'])) {
|
||||
$rawheader .= 'If-None-Match: ' . $sourceState['etag'] . "\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array('http' => array('header' => $rawheader));
|
||||
}
|
||||
|
||||
|
||||
private function addCachedMetadata($source) {
|
||||
if(isset($this->oldMetadataSrc)) {
|
||||
foreach(self::$types as $type) {
|
||||
foreach($this->oldMetadataSrc->getMetadataSet($type) as $entity) {
|
||||
if(array_key_exists('metarefresh:src', $entity)) {
|
||||
if($entity['metarefresh:src'] == $source['src']) {
|
||||
//SimpleSAML_Logger::debug('Re-using cached metadata for ' . $entity['entityid']);
|
||||
$this->addMetadata($source['src'], $entity, $type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store caching state data for a source
|
||||
*/
|
||||
private function saveState($source, $responseHeaders) {
|
||||
|
||||
if (isset($source['conditionalGET']) && $source['conditionalGET']) {
|
||||
|
||||
// Headers section
|
||||
$candidates = array('last-modified', 'etag');
|
||||
|
||||
foreach($candidates as $candidate) {
|
||||
if(array_key_exists($candidate, $responseHeaders)) {
|
||||
$this->state[$source['src']][$candidate] = $responseHeaders[$candidate];
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($this->state[$source['src']])) {
|
||||
// Timestamp when this src was requested.
|
||||
$this->state[$source['src']]['requested_at'] = $this->getTime();
|
||||
|
||||
$this->changed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse XML metadata and return entities
|
||||
*/
|
||||
private function loadXML($data, $source) {
|
||||
$entities = array();
|
||||
try {
|
||||
$doc = new DOMDocument();
|
||||
$res = $doc->loadXML($data);
|
||||
if($res !== TRUE) {
|
||||
throw new Exception('Failed to read XML from ' . $source['src']);
|
||||
}
|
||||
if($doc->documentElement === NULL) throw new Exception('Opened file is not an XML document: ' . $source['src']);
|
||||
$entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsElement($doc->documentElement);
|
||||
} catch(Exception $e) {
|
||||
SimpleSAML_Logger::warning('metarefreshsupann: Failed to retrieve metadata. ' . $e->getMessage());
|
||||
}
|
||||
return $entities;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function writes the state array back to disk
|
||||
*/
|
||||
public function writeState() {
|
||||
if($this->changed) {
|
||||
SimpleSAML_Logger::debug('Writing: ' . $this->stateFile);
|
||||
SimpleSAML_Utilities::writeFile(
|
||||
$this->stateFile,
|
||||
"<?php\n/* This file was generated by the metarefreshsupann module at ".$this->getTime() . ".\n".
|
||||
" Do not update it manually as it will get overwritten. */\n".
|
||||
'$state = ' . var_export($this->state, TRUE) . ";\n?>\n",
|
||||
0644
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function writes the metadata to stdout.
|
||||
*/
|
||||
public function dumpMetadataStdOut() {
|
||||
|
||||
foreach($this->metadata as $category => $elements) {
|
||||
|
||||
echo('/* The following data should be added to metadata/' . $category . '.php. */' . "\n");
|
||||
|
||||
|
||||
foreach($elements as $m) {
|
||||
$filename = $m['filename'];
|
||||
$entityID = $m['metadata']['entityid'];
|
||||
|
||||
echo("\n");
|
||||
echo('/* The following metadata was generated from ' . $filename . ' on ' . $this->getTime() . '. */' . "\n");
|
||||
echo('$metadata[\'' . addslashes($entityID) . '\'] = ' . var_export($m['metadata'], TRUE) . ';' . "\n");
|
||||
}
|
||||
|
||||
|
||||
echo("\n");
|
||||
echo('/* End of data which should be added to metadata/' . $category . '.php. */' . "\n");
|
||||
echo("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function adds metadata from the specified file to the list of metadata.
|
||||
* This function will return without making any changes if $metadata is NULL.
|
||||
*
|
||||
* @param $filename The filename the metadata comes from.
|
||||
* @param $metadata The metadata.
|
||||
* @param $type The metadata type.
|
||||
*/
|
||||
private function addMetadata($filename, $metadata, $type, $template = NULL) {
|
||||
|
||||
if($metadata === NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($type == 'saml20-sp-remote' && isset($this->attributes)
|
||||
&& isset($this->attributes[$metadata['entityid']])) {
|
||||
$metadata['attributes'] = $this->attributes[$metadata['entityid']];
|
||||
}
|
||||
|
||||
if (isset($template)) {
|
||||
// foreach($metadata AS $mkey => $mentry) {
|
||||
// echo '<pre>'; print_r($metadata); exit;
|
||||
// $metadata[$mkey] = array_merge($mentry, $template);
|
||||
// }
|
||||
$metadata = array_merge($metadata, $template);
|
||||
}
|
||||
|
||||
$metadata['metarefresh:src'] = $filename;
|
||||
if(!array_key_exists($type, $this->metadata)) {
|
||||
$this->metadata[$type] = array();
|
||||
}
|
||||
|
||||
// If expire is defined in constructor...
|
||||
if (!empty($this->expire)) {
|
||||
|
||||
// If expire is already in metadata
|
||||
if (array_key_exists('expire', $metadata)) {
|
||||
|
||||
// Override metadata expire with more restrictive global config-
|
||||
if ($this->expire < $metadata['expire'])
|
||||
$metadata['expire'] = $this->expire;
|
||||
|
||||
// If expire is not already in metadata use global config
|
||||
} else {
|
||||
$metadata['expire'] = $this->expire;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$this->metadata[$type][] = array('filename' => $filename, 'metadata' => $metadata);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function writes the metadata to to separate files in the output directory.
|
||||
*/
|
||||
function writeMetadataFiles($outputDir) {
|
||||
|
||||
while(strlen($outputDir) > 0 && $outputDir[strlen($outputDir) - 1] === '/') {
|
||||
$outputDir = substr($outputDir, 0, strlen($outputDir) - 1);
|
||||
}
|
||||
|
||||
if(!file_exists($outputDir)) {
|
||||
SimpleSAML_Logger::info('Creating directory: ' . $outputDir . "\n");
|
||||
$res = @mkdir($outputDir, 0777, TRUE);
|
||||
if ($res === FALSE) {
|
||||
throw new Exception('Error creating directory: ' . $outputDir);
|
||||
}
|
||||
}
|
||||
|
||||
foreach(self::$types as $type) {
|
||||
|
||||
$filename = $outputDir . '/' . $type . '.php';
|
||||
|
||||
if(array_key_exists($type, $this->metadata)) {
|
||||
$elements = $this->metadata[$type];
|
||||
SimpleSAML_Logger::debug('Writing: ' . $filename);
|
||||
|
||||
$content = '<?php' . "\n" . '/* This file was generated by the metarefreshsupann module at '. $this->getTime() . "\n";
|
||||
$content .= ' Do not update it manually as it will get overwritten' . "\n" . '*/' . "\n";
|
||||
|
||||
foreach($elements as $m) {
|
||||
$entityID = $m['metadata']['entityid'];
|
||||
$content .= "\n";
|
||||
$content .= '$metadata[\'' . addslashes($entityID) . '\'] = ' . var_export($m['metadata'], TRUE) . ';' . "\n";
|
||||
}
|
||||
|
||||
$content .= "\n" . '?>';
|
||||
|
||||
SimpleSAML_Utilities::writeFile($filename, $content, 0644);
|
||||
} elseif(is_file($filename)) {
|
||||
if(unlink($filename)) {
|
||||
SimpleSAML_Logger::debug('Deleting stale metadata file: ' . $filename);
|
||||
} else {
|
||||
SimpleSAML_Logger::warning('Could not delete stale metadata file: ' . $filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save metadata for loading with the 'serialize' metadata loader.
|
||||
*
|
||||
* @param string $outputDir The directory we should save the metadata to.
|
||||
*/
|
||||
public function writeMetadataSerialize($outputDir) {
|
||||
assert('is_string($outputDir)');
|
||||
|
||||
$metaHandler = new SimpleSAML_Metadata_MetaDataStorageHandlerSerialize(array('directory' => $outputDir));
|
||||
|
||||
/* First we add all the metadata entries to the metadata handler. */
|
||||
foreach ($this->metadata as $set => $elements) {
|
||||
foreach ($elements as $m) {
|
||||
$entityId = $m['metadata']['entityid'];
|
||||
|
||||
SimpleSAML_Logger::debug('metarefreshsupann: Add metadata entry ' .
|
||||
var_export($entityId, TRUE) . ' in set ' . var_export($set, TRUE) . '.');
|
||||
$metaHandler->saveMetadata($entityId, $set, $m['metadata']);
|
||||
}
|
||||
}
|
||||
|
||||
/* Then we delete old entries which should no longer exist. */
|
||||
$ct = time();
|
||||
foreach ($metaHandler->getMetadataSets() as $set) {
|
||||
foreach ($metaHandler->getMetadataSet($set) as $entityId => $metadata) {
|
||||
if (!array_key_exists('expire', $metadata)) {
|
||||
SimpleSAML_Logger::warning('metarefreshsupann: Metadata entry without expire timestamp: ' . var_export($entityId, TRUE) .
|
||||
' in set ' . var_export($set, TRUE) . '.');
|
||||
continue;
|
||||
}
|
||||
if ($metadata['expire'] > $ct) {
|
||||
continue;
|
||||
}
|
||||
SimpleSAML_Logger::debug('metarefreshsupann: ' . $entityId . ' expired ' . date('l jS \of F Y h:i:s A', $metadata['expire']) );
|
||||
SimpleSAML_Logger::debug('metarefreshsupann: Delete expired metadata entry ' .
|
||||
var_export($entityId, TRUE) . ' in set ' . var_export($set, TRUE) . '. (' . ($ct - $metadata['expire']) . ' sec)');
|
||||
$metaHandler->deleteMetadata($entityId, $set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function getTime() {
|
||||
/* The current date, as a string. */
|
||||
date_default_timezone_set('UTC');
|
||||
$when = date('Y-m-d\\TH:i:s\\Z');
|
||||
return $when;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
$attributemap = array(
|
||||
'supannEtuAnneeInscription' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.25',
|
||||
'supannGroupeAdminDN' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.19',
|
||||
'supannParrainDN' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.17',
|
||||
'supannTypeEntite' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.16',
|
||||
'supannEtuTypeDiplome' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.33',
|
||||
'supannCodeINE' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.9',
|
||||
'supannOrganisme' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.3',
|
||||
'supannMailPerso' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.15',
|
||||
'supannGroupeDateFin' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.18',
|
||||
'supannEtuCursusAnnee' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.26',
|
||||
'supannActivite' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.2',
|
||||
'supannEmpId' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.11',
|
||||
'supannTypeEntiteAffectation' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.36',
|
||||
'supannEtuDiplome' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.27',
|
||||
'supannEtuId' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.10',
|
||||
'supannCivilite' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.4',
|
||||
'supannEtuRegimeInscription' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.31',
|
||||
'supannEtablissement' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.14',
|
||||
'supannCodeEntiteParent' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.7',
|
||||
'supannEntiteAffectationPrincipale' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.13',
|
||||
'supannEtuElementPedagogique' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.28',
|
||||
'supannAffectation' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.5',
|
||||
'supannAutreTelephone' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.12',
|
||||
'supannEmpCorps' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.35',
|
||||
'supannCodeEntite' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.6',
|
||||
'supannEtuInscription' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.30',
|
||||
'supannRefId' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.37',
|
||||
'supannListeRouge' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.1',
|
||||
'supannEtuSecteurDisciplinaire' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.32',
|
||||
'supannEntiteAffectation' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.8',
|
||||
'supannRoleEntite' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.24',
|
||||
'supannRole' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.21',
|
||||
'supannEtuEtape' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.29',
|
||||
'supannAutreMail' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.34',
|
||||
'supannRoleGenerique' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.23',
|
||||
'supannGroupeLecteurDN' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.22',
|
||||
'supannAliasLogin' => 'urn:oid:1.3.6.1.4.1.7135.1.2.1.20',
|
||||
);
|
||||
?>
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
$this->data['header'] = $this->t('{aggregator:aggregator:aggregator_header}');
|
||||
$this->includeAtTemplateBase('includes/header.php');
|
||||
|
||||
echo('<h1>Metarefresh fetch</h1>');
|
||||
|
||||
|
||||
if (!empty($this->data['logentries'])) {
|
||||
|
||||
echo '<pre style="border: 1px solid #aaa; padding: .5em; overflow: scroll">';
|
||||
foreach($this->data['logentries'] AS $l) {
|
||||
echo $l . "\n";
|
||||
}
|
||||
echo '</pre>';
|
||||
|
||||
} else {
|
||||
echo 'No output from metarefresh.';
|
||||
}
|
||||
|
||||
|
||||
|
||||
$this->includeAtTemplateBase('includes/footer.php');
|
||||
?>
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
$config = SimpleSAML_Configuration::getInstance();
|
||||
$mconfig = SimpleSAML_Configuration::getOptionalConfig('config-metarefresh.php');
|
||||
|
||||
SimpleSAML_Utilities::requireAdmin();
|
||||
|
||||
SimpleSAML_Logger::setCaptureLog(TRUE);
|
||||
|
||||
|
||||
$sets = $mconfig->getConfigList('sets', array());
|
||||
|
||||
foreach ($sets AS $setkey => $set) {
|
||||
|
||||
SimpleSAML_Logger::info('[metarefresh]: Executing set [' . $setkey . ']');
|
||||
|
||||
try {
|
||||
|
||||
|
||||
$expireAfter = $set->getInteger('expireAfter', NULL);
|
||||
if ($expireAfter !== NULL) {
|
||||
$expire = time() + $expireAfter;
|
||||
} else {
|
||||
$expire = NULL;
|
||||
}
|
||||
|
||||
$metaloader = new sspmod_metarefresh_MetaLoader($expire);
|
||||
|
||||
# Get global black/whitelists
|
||||
$blacklist = $mconfig->getArray('blacklist', array());
|
||||
$whitelist = $mconfig->getArray('whitelist', array());
|
||||
|
||||
foreach($set->getArray('afps') AS $afp) {
|
||||
$metaload->loadAfp($afp);
|
||||
}
|
||||
|
||||
foreach($set->getArray('sources') AS $source) {
|
||||
|
||||
# Merge global and src specific blacklists
|
||||
if(isset($source['blacklist'])) {
|
||||
$source['blacklist'] = array_unique(array_merge($source['blacklist'], $blacklist));
|
||||
} else {
|
||||
$source['blacklist'] = $blacklist;
|
||||
}
|
||||
|
||||
# Merge global and src specific whitelists
|
||||
if(isset($source['whitelist'])) {
|
||||
$source['whitelist'] = array_unique(array_merge($source['whitelist'], $whitelist));
|
||||
} else {
|
||||
$source['whitelist'] = $whitelist;
|
||||
}
|
||||
|
||||
SimpleSAML_Logger::debug('[metarefresh]: In set [' . $setkey . '] loading source [' . $source['src'] . ']');
|
||||
$metaloader->loadSource($source);
|
||||
}
|
||||
|
||||
$outputDir = $set->getString('outputDir');
|
||||
$outputDir = $config->resolvePath($outputDir);
|
||||
|
||||
$outputFormat = $set->getValueValidate('outputFormat', array('flatfile', 'serialize'), 'flatfile');
|
||||
switch ($outputFormat) {
|
||||
case 'flatfile':
|
||||
$metaloader->writeMetadataFiles($outputDir);
|
||||
break;
|
||||
case 'serialize':
|
||||
$metaloader->writeMetadataSerialize($outputDir);
|
||||
break;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$e = SimpleSAML_Error_Exception::fromException($e);
|
||||
$e->logWarning();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$logentries = SimpleSAML_Logger::getCapturedLog();
|
||||
|
||||
$t = new SimpleSAML_XHTML_Template($config, 'metarefresh:fetch.tpl.php');
|
||||
$t->data['logentries'] = $logentries;
|
||||
$t->show();
|
Reference in New Issue