Commit 808ba25aa2b2dbb3aa21f0360a2d2e4c559127df

Authored by Esmeralda Pires
0 parents
Exists in master

1ªVersão

bin/checkMergedMetadata.php
... ... @@ -0,0 +1,52 @@
  1 +#!/usr/bin/env php
  2 +<?php
  3 +
  4 +define('SIMPLESAMLPATH', dirname(dirname(dirname(dirname(__FILE__)))));
  5 +define('MODULEPATH', (dirname(dirname(__FILE__))));
  6 +ini_set('error_level', E_ALL & E_STRICT);
  7 +ini_set('display_errors', true);
  8 +
  9 +require(MODULEPATH.'/config/config.php');
  10 +
  11 +
  12 +if(!($gen = @file_get_contents(SIMPLESAMLPATH.'/'.$destinationgenerated.'/saml20-sp-merged.php'))) {
  13 + echo("failed to get generated file's contents\n");
  14 + exit(2);
  15 +}
  16 +
  17 +$gen = preg_replace('/<\?php/', '', $gen);
  18 +$gen = preg_replace('/\?>/', '', $gen);
  19 +
  20 +if(($ret = @eval($gen) === false)) {
  21 + echo("parse error in generated code\n");
  22 + exit(2);
  23 +}
  24 +
  25 +function _raise_error($msg) {
  26 + echo($msg."\n");
  27 + exit(3);
  28 +}
  29 +
  30 +if(!isset($metadata))
  31 + _raise_error('metadata variable not set');
  32 +
  33 +if(!is_array($metadata))
  34 + _raise_error('metadata variable is not an array');
  35 +
  36 +if(sizeof($metadata) < 10)
  37 + _raise_error('metadata array holds less than 10 items');
  38 +
  39 +foreach($metadata as $k => $m) {
  40 + if(!is_array($m))
  41 + _raise_error('metadata item '.((string)$k).' is not an array');
  42 + if(empty($m['entityid']) || !is_string($m['entityid']))
  43 + _raise_error('metadata item '.((string)$k).' has empty or non-string \'entityid\' member');
  44 + if(empty($m['authproc']) || !is_array($m['authproc']))
  45 + _raise_error('metadata item '.((string)$k).' has empty or non-array \'authproc\' member');
  46 + if(empty($m['attributes']) || !is_array($m['attributes']))
  47 + _raise_error('metadata item '.((string)$k).' has empty or non-array \'attributes\' member');
  48 +}
  49 +
  50 +exit(0);
  51 +
  52 +?>
... ...
bin/fetchFederationMetadata.php
... ... @@ -0,0 +1,31 @@
  1 +#!/usr/bin/env php
  2 +<?php
  3 +
  4 +define('SCRIPTPATH', (dirname(__FILE__)));
  5 +define('BASEPATH', dirname(dirname(dirname(dirname(__FILE__)))));
  6 +
  7 +require(SCRIPTPATH.'/../config/config.php');
  8 +
  9 +$command = BASEPATH.'/modules/metarefresh/bin/metarefresh.php -o='.$destinationgenerated.' --validate-fingerprint=' . $fingerprint . ' ' . $metadatasource . ' >'.BASEPATH.'/log/'.$logdestination;
  10 +exec($command, $output, $exitCode);
  11 +if ($exitCode != 0) {
  12 + echo($output[0]);
  13 + exit($exitCode);
  14 +}
  15 +
  16 +exec(SCRIPTPATH.'/mergeMetadata.php', $output, $exitCode);
  17 +if ($exitCode != 0) {
  18 + echo($output[0]);
  19 + exit($exitCode);
  20 +}
  21 +
  22 +exec(SCRIPTPATH.'/checkMergedMetadata.php', $output, $exitCode);
  23 +if ($exitCode != 0) {
  24 + echo($output[0]);
  25 + exit($exitCode);
  26 +}
  27 +
  28 +rename(BASEPATH.'/'.$destinationgenerated.'/saml20-sp-merged.php', BASEPATH.'/metadata/'.$destination);
  29 +exit(0);
  30 +
  31 +?>
... ...
bin/mergeMetadata.php
... ... @@ -0,0 +1,93 @@
  1 +#!/usr/bin/env php
  2 +<?php
  3 +
  4 +define('SIMPLESAMLPATH', dirname(dirname(dirname(dirname(__FILE__)))));
  5 +define('MODULEPATH', (dirname(dirname(__FILE__))));
  6 +ini_set('error_level', E_ALL & E_STRICT);
  7 +ini_set('display_errors', true);
  8 +
  9 +/*
  10 + Merge metadata-generated/saml20-sp-remote.php with ../config/saml20-sp-mixin.php
  11 + and drop superfluous fields.
  12 + Templates may be specified by entityID or by category (http://macedir.org/entity-category).
  13 + If specified by entity-category fields in the metadata dominate otherwise the template
  14 + fields overwrite fields in the imported metadata.
  15 + Merged metadata are written to metadata-generated/saml20-sp-merged.php.
  16 + */
  17 +
  18 +require(MODULEPATH.'/config/config.php');
  19 +
  20 +require_once(SIMPLESAMLPATH.'/lib/_autoload.php');
  21 +require(SIMPLESAMLPATH.'/'.$destinationgenerated.'/saml20-sp-remote.php');
  22 +require(MODULEPATH.'/config/saml20-sp-mixin.php');
  23 +
  24 +foreach($template as $url => $mdata) {
  25 + if(!isset($metadata[$url])) {
  26 + passthru("logger -t IDP-METADATA-DIFF 'INFO: template url not found in metadata array: $url'");
  27 + }
  28 +}
  29 +
  30 +if(!($fh = @fopen(SIMPLESAMLPATH.'/'.$destinationgenerated.'/saml20-sp-merged.php', 'w'))) {
  31 + echo("cannot open/create output file\n");
  32 + exit(1);
  33 +}
  34 +@fwrite($fh, "<?php\n");
  35 +
  36 +foreach($metadata as $url => $mdata) {
  37 + foreach($fieldsToStrip as $field) unset($mdata[$field]);
  38 +
  39 +// map "attributes" and "attributes.required" from OIDs to friendly names
  40 + $mapper = new sspmod_core_Auth_Process_AttributeMap(array('oid2name'), NULL);
  41 + foreach(['attributes', 'attributes.required'] as $field) {
  42 + if(isset($mdata[$field])) {
  43 + $tmp = array('Attributes' => array_fill_keys($mdata[$field], 0));
  44 + $mapper->process($tmp);
  45 + $mdata[$field] = array_keys($tmp['Attributes']);
  46 + }
  47 + }
  48 +
  49 + $templateWins = true;
  50 + if(isset($template[$url])) $currentTemplate = $template[$url];
  51 + else $currentTemplate = NULL;
  52 +
  53 + if($currentTemplate == NULL && isset($mdata['EntityAttributes']['http://macedir.org/entity-category'])) {
  54 + foreach($mdata['EntityAttributes']['http://macedir.org/entity-category'] as $category) {
  55 + if(isset($template[$category])) {
  56 + $currentTemplate = $template[$category];
  57 + $templateWins = false;
  58 + }
  59 + }
  60 + }
  61 + if($currentTemplate == NULL) $currentTemplate = $defaultTemplate;
  62 +
  63 + foreach($currentTemplate as $field => $value) {
  64 + if($templateWins || !isset($mdata[$field])) $mdata[$field] = $value;
  65 + }
  66 +
  67 + if(isset($mdata['attributes.allowed'])) {
  68 + $mdata['attributes'] = array_intersect($mdata['attributes'], $mdata['attributes.allowed']);
  69 + unset($mdata['attributes.allowed']);
  70 + }
  71 + if(isset($mdata['attributes.required']) && isset($mdata['attributes.allowed.ifRequired'])) {
  72 + $allowed = array_intersect($mdata['attributes.required'], $mdata['attributes.allowed.ifRequired']);
  73 + $mdata['attributes'] = $mdata['attributes'] + $allowed;
  74 + }
  75 + unset($mdata['attributes.allowed.ifRequired']);
  76 + unset($mdata['attributes.required']);
  77 +
  78 + // output
  79 + if(!@fwrite($fh, "\n\$metadata['$url'] = ".var_export($mdata, true).";\n")) {
  80 + echo("cannot write to output file\n");
  81 + exit(1);
  82 + }
  83 +}
  84 +
  85 +@fwrite($fh, "\n?>");
  86 +if(!@fclose($fh)) {
  87 + echo("cannot close output file\n");
  88 + exit(1);
  89 +}
  90 +
  91 +exit(0);
  92 +
  93 +?>
... ...
config/config.php
... ... @@ -0,0 +1,24 @@
  1 +<?php
  2 +
  3 +
  4 +// IDPs and SPs from eduGAIN, downloaded from RCTSaai infrastrucuture.
  5 +
  6 +/* Metadata signer certificate SHA1 fingerprint obtained using the following command
  7 + # openssl x509 -in rctsaai-metadatasigner.pem -noout -fingerprint -sha1
  8 +*/
  9 +
  10 +// URL Metadados Antigos
  11 +//$fingerprint = 'aea789f491a4abdc7202ff18c6900623d3181ac2';
  12 +//$metadatasource = 'https://rctsaai-rr.fccn.pt/rr/signedmetadata/federation/RURVR0FJTg~~/metadata.xml';
  13 +
  14 +$fingerprint = '6C:C4:38:7D:8A:5B:FB:91:4A:60:9C:12:3C:AA:8C:EA:67:24:79:DE';
  15 +$metadatasource = 'https://registry.rctsaai.pt/metadata/interfederation-sp-metadata.xml';
  16 +
  17 +// NOTE: You need to create <simpleSAMLphp path>/metadata/metarefresh-services/metamerge-edugain with privileges for
  18 +// the cronjob to create saml20-sp-remote.php inside that directory
  19 +
  20 +$destination = 'metarefresh-services/metamerge-edugain/saml20-sp-remote.php';
  21 +$destinationgenerated = 'metadata-generated-edugain';
  22 +$logdestination = 'metadataimport-edugain.log';
  23 +
  24 +?>
... ...
config/saml20-sp-mixin.php
... ... @@ -0,0 +1,243 @@
  1 +<?php
  2 +
  3 +$fieldsToStrip = array('entityDescriptor');
  4 +
  5 +// NB: The examples assume that the authsource delivers attributes using friendly names
  6 +// and that the following global attribute filters are configured:
  7 +// 50 => 'core:AttributeLimit',
  8 +// 90 => array( 'class' => 'consent:Consent', ...),
  9 +// 95 => array('class' => 'core:AttributeMap', 'name2oid'),
  10 +
  11 +
  12 +
  13 +// ---( default Service Provider configuration template )---
  14 +
  15 +$defaultTemplate = array (
  16 + 'AttributeNameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
  17 +
  18 + /*
  19 + * NameID format to use (default is transient)
  20 + */
  21 + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
  22 +
  23 + 'attributes' => array(
  24 + 'eduPersonPrincipalName',
  25 + 'schacHomeOrganization',
  26 + 'eduPersonScopedAffiliation',
  27 + 'mail',
  28 + ),
  29 + 'attributes.allowed.ifrequired' => array(
  30 + 'displayName',
  31 + 'givenName',
  32 + 'sn',
  33 + 'o',
  34 + 'ou',
  35 + 'eduPersonPrimaryAffiliation',
  36 + 'eduPersonPrincipalName',
  37 + 'eduPersonScopedAffiliation',
  38 + 'eduPersonTargetedID',
  39 + 'schacHomeOrganization',
  40 + 'cn',
  41 + 'mail'
  42 + ),
  43 + 'authproc' => array(
  44 + 3 => array(
  45 + 'class' => 'core:TargetedID',
  46 + 'nameId' => TRUE,
  47 + ),
  48 + 50 => array(
  49 + 'class' => 'core:AttributeLimit',
  50 + ),
  51 + 90 => array(
  52 + 'class' => 'core:AttributeMap',
  53 + 'name2oid'
  54 + ),
  55 + ),
  56 +);
  57 +
  58 +// ---( Attribute release configuration template for services that comply with service categories/profiles )---
  59 +
  60 +/*
  61 + * REFEDS Research and Scholarship service category
  62 + */
  63 +$template['http://refeds.org/category/research-and-scholarship'] = array (
  64 + 'AttributeNameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
  65 +
  66 + /*
  67 + * NameID format to use (default is transient)
  68 + */
  69 + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
  70 +
  71 + // following attributes are default values
  72 + 'attributes' => array(
  73 + 'mail',
  74 + 'displayName',
  75 + 'eduPersonPrincipalName',
  76 + 'eduPersonScopedAffiliation',
  77 + 'eduPersonTargetedID'
  78 + ),
  79 + 'attributes.allowed.ifrequired' => array(
  80 + 'mail',
  81 + 'displayName',
  82 + 'givenName',
  83 + 'cn',
  84 + 'sn',
  85 + 'o',
  86 + 'ou',
  87 + 'eduPersonPrincipalName',
  88 + 'eduPersonTargetedID',
  89 + 'eduPersonPrimaryAffiliation',
  90 + 'eduPersonScopedAffiliation',
  91 + 'schacHomeOrganization',
  92 + ),
  93 + 'authproc' => array(
  94 + 3 => array(
  95 + 'class' => 'core:TargetedID',
  96 + 'nameId' => TRUE,
  97 + ),
  98 + 50 => array(
  99 + 'class' => 'core:AttributeLimit',
  100 + ),
  101 + 90 => array(
  102 + 'class' => 'core:AttributeMap',
  103 + 'name2oid'
  104 + ),
  105 + ),
  106 +);
  107 +
  108 +/*
  109 + * GÉANT Data Protection Code of Conduct service category
  110 + */
  111 +$template['http://www.geant.net/uri/dataprotection-code-of-conduct/v1'] = array (
  112 + 'AttributeNameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
  113 +
  114 + /*
  115 + * NameID format to use (default is transient)
  116 + */
  117 + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
  118 +
  119 + 'attributes' => array(
  120 + 'mail',
  121 + 'eduPersonPrincipalName',
  122 + 'schacHomeOrganization',
  123 + 'eduPersonScopedAffiliation',
  124 + ),
  125 + 'attributes.allowed.ifrequired' => array(
  126 + 'mail',
  127 + 'displayName',
  128 + 'givenName',
  129 + 'cn',
  130 + 'sn',
  131 + 'o',
  132 + 'ou',
  133 + 'eduPersonPrincipalName',
  134 + 'eduPersonTargetedID',
  135 + 'eduPersonPrimaryAffiliation',
  136 + 'eduPersonScopedAffiliation',
  137 + 'schacHomeOrganization',
  138 + ),
  139 + 'authproc' => array(
  140 + 3 => array(
  141 + 'class' => 'core:TargetedID',
  142 + 'nameId' => TRUE,
  143 + ),
  144 + 50 => array(
  145 + 'class' => 'core:AttributeLimit',
  146 + ),
  147 + 90 => array(
  148 + 'class' => 'core:AttributeMap',
  149 + 'name2oid'
  150 + ),
  151 + ),
  152 +);
  153 +
  154 +
  155 +// ---( Service Provider specific configuration templates )---
  156 +
  157 +
  158 +// SP EntityID "https://login.elixir-czech.org/proxy/" specifif configuration
  159 +// Even though this service belongs to R&S and Coco categories,
  160 +// its metadata also defines a list of required attributes that seem to exclude
  161 +// "mail" and "displayName" attribute. [Jorge Matias] (2018-02-05)
  162 +$template['https://login.elixir-czech.org/proxy/'] = array (
  163 + 'AttributeNameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
  164 +
  165 + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
  166 +
  167 + 'attributes' => array(
  168 + 'mail',
  169 + 'displayName',
  170 + 'eduPersonPrincipalName',
  171 + 'eduPersonAffiliation',
  172 + 'eduPersonScopedAffiliation',
  173 + 'eduPersonTargetedID',
  174 + 'schacHomeOrganization'
  175 + ),
  176 + 'authproc' => array(
  177 + 3 => array(
  178 + 'class' => 'core:TargetedID',
  179 + 'nameId' => TRUE,
  180 + ),
  181 + 50 => array(
  182 + 'class' => 'core:AttributeLimit',
  183 + ),
  184 + 90 => array(
  185 + 'class' => 'core:AttributeMap',
  186 + 'name2oid'
  187 + ),
  188 + ),
  189 + 'attributeencodings' => array('urn:oid:1.3.6.1.4.1.5923.1.1.1.10' => 'raw'),
  190 +);
  191 +
  192 +
  193 +// SP EntityID "https://www.digicert.com/sso" specific configuration
  194 +// This service requires an "eduPersonEntitlement" with a list of possible predefined values
  195 +// - urn:mace:terena.org:tcs:escience-user
  196 +// - urn:mace:terena.org:tcs:personal-user
  197 +// [Jorge Matias] (2018-02-09)
  198 +$template['https://www.digicert.com/sso'] = array (
  199 + 'AttributeNameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
  200 +
  201 + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
  202 +
  203 + 'attributes' => array(
  204 + 'mail',
  205 + 'displayName',
  206 + 'eduPersonPrincipalName',
  207 + 'eduPersonEntitlement',
  208 + 'schacHomeOrganization',
  209 + 'eduPersonTargetedID',
  210 + ),
  211 + 'authproc' => array(
  212 + 3 => array(
  213 + 'class' => 'core:TargetedID',
  214 + 'nameId' => TRUE,
  215 + ),
  216 + 39 => array(
  217 + 'class' => 'core:PHP',
  218 + 'code' => '
  219 + $attributes["eduPersonEntitlement"] = array();
  220 +
  221 + if (in_array("faculty", $attributes["eduPersonAffiliation"])) {
  222 + array_push($attributes["eduPersonEntitlement"], "urn:mace:terena.org:tcs:escience-user");
  223 + }
  224 + if (in_array("member", $attributes["eduPersonAffiliation"])) {
  225 + array_push($attributes["eduPersonEntitlement"], "urn:mace:terena.org:tcs:personal-user");
  226 + }
  227 + ',
  228 + ),
  229 +
  230 + 50 => array(
  231 + 'class' => 'core:AttributeLimit',
  232 + ),
  233 + 90 => array(
  234 + 'class' => 'core:AttributeMap',
  235 + 'name2oid'
  236 + ),
  237 + ),
  238 + 'attributeencodings' => array('urn:oid:1.3.6.1.4.1.5923.1.1.1.10' => 'raw'),
  239 +);
  240 +
  241 +
  242 +
  243 +?>
... ...
default-disable
docs/MetaMerge.txt
... ... @@ -0,0 +1,23 @@
  1 +MetaMerge
  2 +=========
  3 +
  4 +This module augments SAML20-SP matadata that have been fetched by MetaRefresh. Elements are added either based on entityId or on entity category (http://macedir.org/entity-category). If specified by entity category fields in the metadata dominate otherwise the template fields overwrite fields in the imported metadata.
  5 +
  6 +Superfluous metadata elements can be stripped to save space.
  7 +
  8 +Merged metadata are written to metadata-generated/saml20-sp-merged.php. After a plausibility check they are moved to the destination specified in the configuration.
  9 +
  10 +Configuration files are located in the metamerge/config directory.
  11 +
  12 +config.php specifies the metadata source, its fingerprint and the path of the merged data relative to the metadata directory.
  13 +
  14 +saml20-sp-mixin.php specifies the transformation process:
  15 +
  16 +$fieldsToStrip is an array of element names to remove.
  17 +$defaultTemplate is used for entities that have no match in the template array.
  18 +$template is an array of templates indexed by entityId or category.
  19 +
  20 +'attributes.allowed' restricts the set of attributes that may be released. For use in category templates to avoid unwanted attribute releases.
  21 +'attributes.allowed.ifRequired' lists attributes that may only be released if they are marked as required. For use in category templates to avoid unwanted attribute releases.
  22 +
  23 +Usage: Enable the MetaRefresh module and call metamerge/bin/fetchFederationMetadata.php in a cron job.
0 24 \ No newline at end of file
... ...
enable