diff --git a/app/Constants/EarcUtils.php b/app/Constants/EarcUtils.php new file mode 100644 index 0000000000000000000000000000000000000000..5eb70a931b8305d919557015e10d67d00f6ec4c5 --- /dev/null +++ b/app/Constants/EarcUtils.php @@ -0,0 +1,28 @@ +<?php + namespace App\Constants; + + abstract class EarcUtils + { + const COCO_GEANT_NET_URL = "http://www.geant.net/uri/dataprotection-code-of-conduct/v1"; + const RS_REFEDS_ORG_URL = "http://refeds.org/category/research-and-scholarship"; + const RS_SUPPORT_CATEGORY = "http://macedir.org/entity-category-support"; + const RS_CATEGORY = "http://macedir.org/entity-category"; + const RELEASE_CHECK_EDUGAIN = "https://release-check.edugain.org/results/"; + + const EARC_SP = [ + 'https://rns-ng.example.org/shibboleth', + 'https://coco.example.org/shibboleth', + 'https://noec.example.org/shibboleth', + // test + 'https://rns-ng-earc.aai-dev.grnet.gr/shibboleth', + 'https://coco-earc.aai-dev.grnet.gr/shibboleth', + 'https://noec-earc.aai-dev.grnet.gr/shibboleth', + ]; + + const EARC_REGIONAL_SP = [ + 'http://aai.grnet.gr/' => 'https://aai.grnet.gr', + 'http://rr.aai.switch.ch/' => 'https://attribute-viewer.aai.switch.ch/interfederation-test/', + 'http://taat.edu.ee' => 'https://eitja.taat.edu.ee/', + 'http://eduid.hu' => 'https://attributes.eduid.hu', + ]; + } \ No newline at end of file diff --git a/app/Http/Controllers/AttrReleaseTestController.php b/app/Http/Controllers/AttrReleaseTestController.php index b2a7ec1da965a05780cceab1752bdb63374d6b60..7bbdd2b7887a632bfdc6c0fdd8b391a87cf6a9bd 100755 --- a/app/Http/Controllers/AttrReleaseTestController.php +++ b/app/Http/Controllers/AttrReleaseTestController.php @@ -15,14 +15,18 @@ class AttrReleaseTestController extends Controller { $request->session()->put('test_allowed', true); - if ($request->has('sps')){ + if ($request->has('sps')) + { $sps = $request->input('sps'); $redirect_url = "https://".parse_url($sps[0], PHP_URL_HOST)."/sp"; + // Store the other SPs to checked in the session so that they can be retrieved later on - if (count(array_slice($sps,1)) > 0){ + if (count(array_slice($sps,1)) > 0) + { $request->session()->put('remaining_sps', array_slice($sps,1)); } + return redirect($redirect_url); } } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index dc4d3d377f044adc1c76da5856339bdc1baaef7a..33a96af0b6343d9faea210e94f345774d6b0f2f2 100755 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -5,7 +5,6 @@ namespace App\Http\Controllers; use App\IdpResult; use App\Libraries\EarcUtils; use App\Http\Controllers\Controller; -use \SimpleSAML_Configuration; class HomeController extends Controller { @@ -17,12 +16,16 @@ class HomeController extends Controller public function __invoke() { session(['test_allowed' => 'true']); + $sp_entities = EarcUtils::getSpMetadata(null); $attributemap = EarcUtils::getAttributeMap(); + //Get only the latest result for each IdP $idps = IdpResult::all()->unique('idp_entity_id'); - $historical_results = array(); - foreach ($idps as $idp){ + $historical_results = []; + + foreach ($idps as $idp) + { $historical_results[] = IdpResult::where('idp_entity_id', $idp['idp_entity_id']) ->orderBy('created_at', 'desc') ->first(); diff --git a/app/Http/Controllers/ResultsController.php b/app/Http/Controllers/ResultsController.php index 31ee41e629eb78f6654849a95e49a07189243067..02462b1138563f9c9b8c5dfdfb579d8d78bff392 100755 --- a/app/Http/Controllers/ResultsController.php +++ b/app/Http/Controllers/ResultsController.php @@ -8,6 +8,7 @@ use App\TestResult; use App\TestAttribute; use App\Libraries\EarcUtils; use Illuminate\Http\Request; +use App\Constants\EarcUtils AS EarcConstants; class ResultsController extends Controller { @@ -18,52 +19,82 @@ class ResultsController extends Controller { //Get only the latest result for each IdP $idps = IdpResult::all()->unique('idp_entity_id'); - foreach ($idps as $idp) { + + foreach ($idps as $idp) + { $historical_results[] = IdpResult::where('idp_entity_id', $idp['idp_entity_id'])->orderBy('created_at', 'desc')->first(); } + $idp_result = IdpResult::where('test_id', $test_id)->get(); - if (count($idp_result) > 0) { + + if (count($idp_result) > 0) + { $released_attributes = array(); $sp_entities = EarcUtils::getSpMetadata(null); $test_results = TestResult::where('test_id', $test_id)->get(); $test_attributes = TestAttribute::where('test_id', $test_id)->get(); - foreach ($test_results as $result) { + + foreach ($test_results as $result) + { $sp_entities[$result->sp_entityid]['tested'] = true; - if ($result->sp_entityid == env('APP_URL_NOEC') . "/shibboleth") { - if (strpos($result->test_mark, 'F') !== false) { + + if ($result->sp_entityid == env('APP_URL_NOEC') . "/shibboleth") + { + if (strpos($result->test_mark, 'F') !== false) + { $verdict[$result->sp_entityid]['comment'] = 'Good data privacy but bad usability.'; - } elseif (strpos($result->test_mark, 'A') !== false) { + } + elseif (strpos($result->test_mark, 'A') !== false) + { $verdict[$result->sp_entityid]['comment'] = 'Good usability but bad data privacy.'; - } else { + } + else + { $verdict[$result->sp_entityid]['comment'] = $result->test_comment; } + $verdict[$result->sp_entityid]['mark'] = ''; - } else { + } + else + { $verdict[$result->sp_entityid]['mark'] = $result->test_mark; $verdict[$result->sp_entityid]['comment'] = $result->test_comment; } - $released_attributes[$result->sp_entityid] = array(); + + $released_attributes[$result->sp_entityid] = []; } - foreach ($test_attributes as $attribute) { + + foreach ($test_attributes as $attribute) + { $released_attributes[$attribute->sp_entityid][$attribute->attr_name] = $attribute->attr_value_multiplicity; } - foreach ($sp_entities as $sp) { - if (array_key_exists('tested', $sp)) { - if (array_key_exists('attributeNamesRequired', $sp)) { - if (EarcUtils::isRnsIndicated($sp)) { - if (array_key_exists('eduPersonScopedAffiliation', $released_attributes[$sp['entityid']])) { + + foreach ($sp_entities as $sp) + { + if (array_key_exists('tested', $sp)) + { + if (array_key_exists('attributeNamesRequired', $sp)) + { + if (EarcUtils::isRnsIndicated($sp)) + { + if (array_key_exists('eduPersonScopedAffiliation', $released_attributes[$sp['entityid']])) + { $sp['attributeNamesRequired'][] = 'eduPersonScopedAffiliation'; } - if (array_key_exists('eduPersonTargetedID', $released_attributes[$sp['entityid']])) { + + if (array_key_exists('eduPersonTargetedID', $released_attributes[$sp['entityid']])) + { $sp['attributeNamesRequired'][] = 'eduPersonTargetedID'; } } + $sp_entities[$sp['entityid']]['superfluous_attributes'] = array_diff(array_keys($released_attributes[$sp['entityid']]), $sp['attributeNamesRequired']); } } } - $regional_earc = array_key_exists($idp_result[0]['registration_authority'], config('app.regional_earc')) - ? config('app.regional_earc')[$idp_result[0]['registration_authority']] + + $regional_earc = array_key_exists($idp_result[0]['registration_authority'], EarcConstants::EARC_REGIONAL_SP) + ? EarcConstants::EARC_REGIONAL_SP[$idp_result[0]['registration_authority']] : null; return view('results', ['historical_results' => $historical_results, @@ -72,38 +103,44 @@ class ResultsController extends Controller 'verdict' => $verdict, 'sp_entities' => $sp_entities, 'released_attributes' => $released_attributes, ]); - } else { - abort(404); - } + } + + abort(404); } public function getHistoricalResults() { $idps = IdpResult::all()->unique('idp_entity_id'); - foreach ($idps as $idp) { + foreach ($idps as $idp) + { $historical_results[] = IdpResult::where('idp_entity_id', $idp['idp_entity_id'])->orderBy('created_at', 'desc')->first(); } - foreach ($historical_results as $key => $result) { + foreach ($historical_results as $key => $result) + { $historical_results[$key]['test_result'] = TestResult::where('test_id', $result['test_id'])->get(); - $historical_results[$key]['result_page'] = 'https://release-check.edugain.org/results/' . $historical_results[$key]['test_id']; + $historical_results[$key]['result_page'] = EarcConstants::RELEASE_CHECK_EDUGAIN . $historical_results[$key]['test_id']; $historical_results[$key]['date'] = $historical_results[$key]['created_at']; - foreach ($historical_results[$key]['test_result'] as $tkey => $tvalue) { - if ($historical_results[$key]['test_result'][$tkey]['sp_entityid'] == env('APP_URL_NOEC') . "/shibboleth") { + + foreach ($historical_results[$key]['test_result'] as $tkey => $tvalue) + { + if ($historical_results[$key]['test_result'][$tkey]['sp_entityid'] == env('APP_URL_NOEC') . "/shibboleth") + { unset($historical_results[$key]['test_result'][$tkey]); continue; } + unset($historical_results[$key]['test_result'][$tkey]['test_comment']); unset($historical_results[$key]['test_result'][$tkey]['created_at']); unset($historical_results[$key]['test_result'][$tkey]['updated_at']); unset($historical_results[$key]['test_result'][$tkey]['id']); unset($historical_results[$key]['test_result'][$tkey]['test_id']); } + unset($historical_results[$key]['created_at']); unset($historical_results[$key]['updated_at']); unset($historical_results[$key]['id']); unset($historical_results[$key]['test_id']); - } return $historical_results; @@ -114,15 +151,15 @@ class ResultsController extends Controller $idp_entity_id = urldecode($idp_entity_id); $historical_result = IdpResult::where('idp_entity_id', $idp_entity_id)->orderBy('created_at', 'desc')->first(); - if (count($historical_result)>0) { + if (count($historical_result)>0) + { $historical_result['datetime'] = $historical_result['created_at']; - $historical_result['result_page'] = 'https://release-check.edugain.org/results/' . $historical_result['test_id']; + $historical_result['result_page'] = EarcConstants::RELEASE_CHECK_EDUGAIN . $historical_result['test_id']; unset($historical_result['test_comment']); unset($historical_result['created_at']); unset($historical_result['updated_at']); unset($historical_result['id']); unset($historical_result['test_id']); - } return $historical_result; diff --git a/app/Libraries/EarcUtils.php b/app/Libraries/EarcUtils.php index 1cf152a4c9f3bf1ad89c7e4ab4cb047576c8656a..a1536c6240366c749dd53260d582cee5daec56ed 100755 --- a/app/Libraries/EarcUtils.php +++ b/app/Libraries/EarcUtils.php @@ -3,32 +3,23 @@ namespace app\Libraries; use Illuminate\Support\Facades\Storage; -use app\Libraries\MetadataUtils; -use PSpell\Config; +use Illuminate\Support\Facades\Log; +use App\Constants\EarcUtils; class EarcUtils { - - /*private $utils; - - public function __construct() - { - $this->utils = new MetadataUtils(); - }*/ - public function getEncatName($value) { switch ($value) { - case 'http://www.geant.net/uri/dataprotection-code-of-conduct/v1': + case EarcUtils::COCO_GEANT_NET_URL: $ret = 'Code of Conduct'; break; - case 'http://refeds.org/category/research-and-scholarship': + case EarcUtils::RS_REFEDS_ORG_URL: $ret = 'Research & Scholarship'; break; default: $ret = 'None'; } - return $ret; } @@ -49,7 +40,7 @@ class EarcUtils } else { - $sps = config('app.earc_sps'); + $sps = EarcUtils::EARC_SP; } foreach ($sps as $key => $sp_entity_id ) @@ -68,18 +59,29 @@ class EarcUtils if (array_key_exists('attributes', $metadata[$sp_entity_id])) { - $sp_metadata[$sp_entity_id]['attributes'] = $metadata[$sp_entity_id]['attributes']; - $sp_metadata[$sp_entity_id]['attributesRequired'] = array_unique($metadata[$sp_entity_id]['attributes.required']); - - foreach ($metadata[$sp_entity_id]['attributes'] as $oid) + try { - $sp_metadata[$sp_entity_id]['attributeNames'][] = $attributemap[$oid]; + $sp_metadata[$sp_entity_id]['attributes'] = $metadata[$sp_entity_id]['attributes']; + $sp_metadata[$sp_entity_id]['attributesRequired'] = $metadata[$sp_entity_id]['attributes.required'] ? array_unique($metadata[$sp_entity_id]['attributes.required']) : []; + + foreach ($metadata[$sp_entity_id]['attributes'] as $oid) + { + $sp_metadata[$sp_entity_id]['attributeNames'][] = $attributemap[$oid]; + } + + foreach ($sp_metadata[$sp_entity_id]['attributesRequired'] as $oid) + { + $sp_metadata[$sp_entity_id]['attributeNamesRequired'][] = $attributemap[$oid]; + } } - - foreach ($sp_metadata[$sp_entity_id]['attributesRequired'] as $oid) + catch(\Exception $e) { - $sp_metadata[$sp_entity_id]['attributeNamesRequired'][] = $attributemap[$oid]; + Log::error("Failed to parse entity metadata:" . $e->getMessage()); + + $sp_metadata[$sp_entity_id]['attributeNames'] = []; + $sp_metadata[$sp_entity_id]['attributeNamesRequired'] = []; } + } elseif (self::isRnsIndicated($sp_metadata[$sp_entity_id])) { @@ -94,9 +96,12 @@ class EarcUtils } } - if (null != $sp_entity_id_input) { + if (null != $sp_entity_id_input) + { return $sp_metadata[$sp_entity_id_input]; - } else { + } + else + { return $sp_metadata; } } @@ -128,20 +133,26 @@ class EarcUtils public static function getRegistrationAuthority($idp_metadata) { $decoded = base64_decode($idp_metadata['entityDescriptor']); - if (preg_match('/registrationAuthority=\"(.*)\"/U', $decoded, $match)) { - return $match[1]; - } else { - return; - } + + if (preg_match('/registrationAuthority=\"(.*)\"/U', $decoded, $match)) + { + return $match[1] ?? 'Not found'; + } + + return 'Not found'; } public static function isRnsSupportIndicated($idp_metadata) { $ret = false; - if (array_key_exists('EntityAttributes', $idp_metadata) && array_key_exists('http://macedir.org/entity-category-support', $idp_metadata['EntityAttributes']) && is_array($idp_metadata['EntityAttributes']['http://macedir.org/entity-category-support'])) { - foreach ($idp_metadata['EntityAttributes']['http://macedir.org/entity-category-support'] as $encat) { - if ($encat === 'http://refeds.org/category/research-and-scholarship') { - $ret = true; + + if (array_key_exists('EntityAttributes', $idp_metadata) && array_key_exists(EarcUtils::RS_SUPPORT_CATEGORY, $idp_metadata['EntityAttributes']) && is_array($idp_metadata['EntityAttributes'][EarcUtils::RS_SUPPORT_CATEGORY])) + { + foreach ($idp_metadata['EntityAttributes'][EarcUtils::RS_SUPPORT_CATEGORY] as $encat) + { + if ($encat === EarcUtils::RS_REFEDS_ORG_URL) + { + $ret = true; } } } @@ -152,9 +163,12 @@ class EarcUtils public static function isRnsIndicated($sp_metadata) { $ret = false; - if (array_key_exists('EntityAttributes', $sp_metadata) && array_key_exists('http://macedir.org/entity-category', $sp_metadata['EntityAttributes']) && is_array($sp_metadata['EntityAttributes']['http://macedir.org/entity-category'])) { - foreach ($sp_metadata['EntityAttributes']['http://macedir.org/entity-category'] as $encat) { - if ($encat === 'http://refeds.org/category/research-and-scholarship') { + if (array_key_exists('EntityAttributes', $sp_metadata) && array_key_exists(EarcUtils::RS_CATEGORY, $sp_metadata['EntityAttributes']) && is_array($sp_metadata['EntityAttributes'][EarcUtils::RS_CATEGORY])) + { + foreach ($sp_metadata['EntityAttributes'][EarcUtils::RS_CATEGORY] as $encat) + { + if ($encat === EarcUtils::RS_REFEDS_ORG_URL) + { $ret = true; } } @@ -166,27 +180,37 @@ class EarcUtils public static function checkAttributeSyntax($attributeName, $attributeValue) { $failed = array(); - if (in_array($attributeName, array('eduPersonPrincipalName', 'mail', 'eduPersonScopedAffiliation'))) { - if (!filter_var($attributeValue, FILTER_VALIDATE_EMAIL)) { + + if (in_array($attributeName, array('eduPersonPrincipalName', 'mail', 'eduPersonScopedAffiliation'))) + { + if (!filter_var($attributeValue, FILTER_VALIDATE_EMAIL)) + { $failed[] = $attributeName; } - } elseif ($attributeName == 'schacHomeOrganizationType') { - if (!preg_match('/urn:schac:homeOrganizationType:/', $attributeValue)) { + } + elseif ($attributeName == 'schacHomeOrganizationType') + { + if (!preg_match('/urn:schac:homeOrganizationType:/', $attributeValue)) + { $failed[] = $attributeName; } } - if (!empty($failed)) { + + if (!empty($failed)) + { return implode(',', $failed); - } else { - return true; - } + } + + return true; } public static function isMinimalSubsetSent($released_attributes) { $minimalSubset = array('eduPersonPrincipalName', 'mail', 'displayName'); - foreach ($minimalSubset as $attributeName) { - if (!array_key_exists($attributeName, $released_attributes) && !self::canBeRedundant($attributeName, $released_attributes)) { + foreach ($minimalSubset as $attributeName) + { + if (!array_key_exists($attributeName, $released_attributes) && !self::canBeRedundant($attributeName, $released_attributes)) + { return false; } } @@ -197,8 +221,11 @@ class EarcUtils public static function isBasicSubsetSent($released_attributes) { $minimalSubset = array('eduPersonPrincipalName', 'eduPersonTargetedID', 'eduPersonUniqueId'); - foreach ($minimalSubset as $attributeName) { - if (array_key_exists($attributeName, $released_attributes)) { + + foreach ($minimalSubset as $attributeName) + { + if (array_key_exists($attributeName, $released_attributes)) + { return true; } } @@ -209,47 +236,53 @@ class EarcUtils public static function canBeRedundant($attributeName, $released_attributes) { if (($attributeName == 'schacHomeOrganization' && (array_key_exists('eduPersonPrincipalName', $released_attributes) || array_key_exists('eduPersonScopedAffiliation', $released_attributes))) || - ($attributeName == 'cn' && (array_key_exists('sn', $released_attributes) && array_key_exists('givenName', $released_attributes))) || ($attributeName == 'eduPersonAffiliation' && (array_key_exists('eduPersonScopedAffiliation', $released_attributes))) || - ($attributeName == 'cn' && array_key_exists('displayName', $released_attributes)) || - ($attributeName == 'sn' && array_key_exists('displayName', $released_attributes)) || - ($attributeName == 'sn' && array_key_exists('cn', $released_attributes)) || - ($attributeName == 'givenName' && array_key_exists('displayName', $released_attributes)) || - ($attributeName == 'givenName' && array_key_exists('cn', $released_attributes)) || - ($attributeName == 'displayName' && (array_key_exists('sn', $released_attributes) && array_key_exists('givenName', $released_attributes))) || - ($attributeName == 'displayName' && array_key_exists('cn', $released_attributes)) - ) { + ($attributeName == 'cn' && ((array_key_exists('sn', $released_attributes) && array_key_exists('givenName', $released_attributes)) || array_key_exists('displayName', $released_attributes))) || + ($attributeName == 'sn' && (array_key_exists('displayName', $released_attributes) || array_key_exists('cn', $released_attributes))) || + ($attributeName == 'givenName' && (array_key_exists('displayName', $released_attributes) || array_key_exists('cn', $released_attributes))) || + ($attributeName == 'displayName' && ((array_key_exists('sn', $released_attributes) && array_key_exists('givenName', $released_attributes)) || array_key_exists('cn', $released_attributes))) + ) + { return true; - } else { - return false; - } + } + + return false; } public static function getExtraPoints($mark, $sp, $released_attributes, $superfluous_attributes, $idp_metadata, $non_personal_attributes) { $ret = ''; - switch ($mark) { + switch ($mark) + { case 'A': - if (self::isRnsSupportIndicated($idp_metadata)) { + if (self::isRnsSupportIndicated($idp_metadata)) + { $ret = '+'; - } else { + } + else + { $ret = '-'; } break; default: // IdP sends superfluous non-personal information - if (count($superfluous_attributes) > 0) { - foreach ($superfluous_attributes as $attributeName) { - if (in_array($attributeName, $non_personal_attributes)) { + if (count($superfluous_attributes) > 0) + { + foreach ($superfluous_attributes as $attributeName) + { + if (in_array($attributeName, $non_personal_attributes)) + { $ret = '-'; break; } } } // Redundant attributes are missing, but information is available - foreach ($sp['attributeNames'] as $attributeName) { - if (!array_key_exists($attributeName, $released_attributes) && self::canBeRedundant($attributeName, $released_attributes)) { + foreach ($sp['attributeNames'] as $attributeName) + { + if (!array_key_exists($attributeName, $released_attributes) && self::canBeRedundant($attributeName, $released_attributes)) + { $ret = '-'; } } @@ -271,84 +304,123 @@ class EarcUtils { // The attribute is decoded as eduPersonTargetedID // The NameID value is decoded as persistent-id - if (array_key_exists('eduPersonTargetedID', $released_attributes) && array_key_exists('persistent-id', $released_attributes)) { - if ($released_attributes['eduPersonTargetedID'] == $released_attributes['persistent-id']) { + if (array_key_exists('eduPersonTargetedID', $released_attributes) && array_key_exists('persistent-id', $released_attributes)) + { + if ($released_attributes['eduPersonTargetedID'] == $released_attributes['persistent-id']) + { unset($released_attributes['persistent-id']); } return $released_attributes; - } elseif (!array_key_exists('eduPersonTargetedID', $released_attributes) && array_key_exists('persistent-id', $released_attributes)) { + } + elseif (!array_key_exists('eduPersonTargetedID', $released_attributes) && array_key_exists('persistent-id', $released_attributes)) + { $released_attributes['eduPersonTargetedID'] = $released_attributes['persistent-id']; unset($released_attributes['persistent-id']); return $released_attributes; - } elseif (array_key_exists('eduPersonTargetedID', $released_attributes) && !array_key_exists('persistent-id', $released_attributes)) { + } + elseif (array_key_exists('eduPersonTargetedID', $released_attributes) && !array_key_exists('persistent-id', $released_attributes)) + { //This should give an error ? return $released_attributes; - } else { - return $released_attributes; - } + } + + return $released_attributes; } public static function calculateVerdictForAnSP($sp_entity_id, $released_attributes, $idp_entityid) { - $additional_information = array(); - $single_valued_attributes = array('eduPersonTargetedID', 'eduPersonPrincipalName', 'sn', 'givenName', 'displayName', 'preferredLanguage', 'schacDateOfBirth', 'schacYearOfBirth', 'schacPersonalTitle', 'eduPersonNickName', 'eduPersonPrimaryOrgUnitDN'); - $non_personal_attributes = array('schacHomeOrganization', 'schacHomeOrganizationType', 'eduPersonAffiliation', 'eduPersonScopedAffiliation', 'o', 'swissEduPersonHomeOrganization', 'swissEduPersonHomeOrganizationType'); - $rns_attributes = array('eduPersonPrincipalName', 'mail', 'displayName', 'givenName', 'sn', 'eduPersonScopedAffiliation'); + $additional_information = []; + $single_valued_attributes = ['eduPersonTargetedID', 'eduPersonPrincipalName', 'sn', 'givenName', + 'displayName', 'preferredLanguage', 'schacDateOfBirth', 'schacYearOfBirth', + 'schacPersonalTitle', 'eduPersonNickName', 'eduPersonPrimaryOrgUnitDN']; + + $non_personal_attributes = ['schacHomeOrganization', 'schacHomeOrganizationType', 'eduPersonAffiliation', + 'eduPersonScopedAffiliation', 'o', 'swissEduPersonHomeOrganization', + 'swissEduPersonHomeOrganizationType']; + + $rns_attributes = ['eduPersonPrincipalName', 'mail', 'displayName', 'givenName', + 'sn', 'eduPersonScopedAffiliation']; $sp_metadata = self::getSpMetadata($sp_entity_id); - if (self::isRnsIndicated($sp_metadata)) { + if (self::isRnsIndicated($sp_metadata)) + { $superfluous_attributes = array_diff(array_keys($released_attributes), $sp_metadata['attributeNamesRequired']); $superfluous_attributes = array_diff($superfluous_attributes, $rns_attributes); - } else { + } + else + { $superfluous_attributes = array_diff(array_keys($released_attributes), $sp_metadata['attributeNamesRequired']); } + $idp_metadata = self::getIdpMetadata($idp_entityid); // F: No attributes received - if (count(array_keys($released_attributes)) == 0) { + if (count(array_keys($released_attributes)) == 0) + { return array('mark' => 'F', 'text' => 'No attributes received', 'additional_information' => $additional_information); } // F: R&S category support is indicated but its requirements are not satisfied - if (self::isRnsSupportIndicated($idp_metadata) && self::isRnsIndicated($sp_metadata) && !self::isMinimalSubsetSent($released_attributes)) { + if (self::isRnsSupportIndicated($idp_metadata) && self::isRnsIndicated($sp_metadata) && !self::isMinimalSubsetSent($released_attributes)) + { return array('mark' => 'F', 'text' => 'R&S category support is indicated but its requirements are not satisfied', 'additional_information' => $additional_information); } + // F: Incorrect value syntax (except for eptid) - foreach ($released_attributes as $attributeName => $attributeValues) { - if (in_array($attributeName, $single_valued_attributes) && count($attributeValues) > 1) { + foreach ($released_attributes as $attributeName => $attributeValues) + { + if (in_array($attributeName, $single_valued_attributes) && count($attributeValues) > 1) + { return array('mark' => 'F', 'text' => 'Incorrect value syntax, got multiple values for a single value attribute', 'additional_information' => $additional_information); } - if ($attributeName != 'eduPersonTargetedID') { - foreach ($attributeValues as $attributeValue) { + + if ($attributeName != 'eduPersonTargetedID') + { + foreach ($attributeValues as $attributeValue) + { $checkResult = self::checkAttributeSyntax($attributeName, $attributeValue); - if (!$checkResult) { + + if (!$checkResult) + { return array('mark' => 'F', 'text' => 'Incorrect value syntax: '.$checkResult, 'additional_information' => $additional_information); } } } } + // D: IdP does not release minimal and does not indicate RnS support - if (!self::isMinimalSubsetSent($released_attributes) && self::isRnsSupportIndicated($idp_metadata) && self::isRnsIndicated($sp_metadata)) { + if (!self::isMinimalSubsetSent($released_attributes) && self::isRnsSupportIndicated($idp_metadata) && self::isRnsIndicated($sp_metadata)) + { return array('mark' => 'D', 'text' => 'REFEDS R&S Entity Category is not supported. Consider enabling support, more information can be found in <a href="https://wiki.refeds.org/display/ENT/Research+and+Scholarship+FAQ">REFEDS wiki</a>', 'additional_information' => $additional_information); } + // D: IdP sends some subset of the requested information, but no persistent identifier as specified in basic information - if (!self::isBasicSubsetSent($released_attributes)) { + if (!self::isBasicSubsetSent($released_attributes)) + { return array('mark' => 'D', 'text' => 'IdP sends some subset of the requested information, but no persistent identifier as specified in basic information', 'additional_information' => $additional_information); } + // D: IdP sends superfluous _personal_ information - if (count($superfluous_attributes) > 0) { - foreach ($superfluous_attributes as $attributeName) { - if (!self::canBeRedundant($attributeName, $released_attributes)) { - if (!in_array($attributeName, $non_personal_attributes)) { - if ($attributeName == 'eduPersonEntitlement' && count($released_attributes['eduPersonEntitlement']) == 1 && $released_attributes['eduPersonEntitlement'][0] == 'urn:mace:dir:entitlement:common-lib-terms') { + if (count($superfluous_attributes) > 0) + { + foreach ($superfluous_attributes as $attributeName) + { + if (!self::canBeRedundant($attributeName, $released_attributes)) + { + if (!in_array($attributeName, $non_personal_attributes)) + { + if ($attributeName == 'eduPersonEntitlement' && count($released_attributes['eduPersonEntitlement']) == 1 && $released_attributes['eduPersonEntitlement'][0] == 'urn:mace:dir:entitlement:common-lib-terms') + { unset($superfluous_attributes[array_search('eduPersonEntitlement', $superfluous_attributes)]); $additional_information[] = 'eduPersonEntitlement attribute with "urn:mace:dir:entitlement:common-lib-terms" value has been sent, but it was not required.'; continue; } - if ($attributeName == 'eduPersonTargetedID') { + + if ($attributeName == 'eduPersonTargetedID') + { unset($superfluous_attributes[array_search('eduPersonTargetedID', $superfluous_attributes)]); $additional_information[] = 'eduPersonTargetedID has been sent, but it was not required.'; continue; @@ -361,19 +433,27 @@ class EarcUtils } // C: IdP sends eduPersonTargetedId with the wrong (legacy) syntax - if (array_key_exists('eduPersonTargetedID', $released_attributes)) { - if (filter_var($released_attributes['eduPersonTargetedID'], FILTER_VALIDATE_EMAIL)) { + if (array_key_exists('eduPersonTargetedID', $released_attributes)) + { + if (filter_var($released_attributes['eduPersonTargetedID'], FILTER_VALIDATE_EMAIL)) + { return array('mark' => 'C'.self::getExtraPoints('C', $sp_metadata, $released_attributes, $superfluous_attributes, $idp_metadata, $non_personal_attributes), 'text' => 'IdP sends eduPersonTargetedId with the wrong (legacy) syntax', 'additional_information' => $additional_information); } } // C: IdP sends basic information while some required information is missing - if (self::isBasicSubsetSent($released_attributes)) { - foreach ($sp_metadata['attributeNamesRequired'] as $attribute) { - if (!array_key_exists($attribute, $released_attributes) && !self::canBeRedundant($attribute, $released_attributes)) { - if (self::isRnsIndicated($sp_metadata) && $attribute == 'eduPersonTargetedId' && array_key_exists('eduPersonPrincipalName', $released_attributes)) { + if (self::isBasicSubsetSent($released_attributes)) + { + foreach ($sp_metadata['attributeNamesRequired'] as $attribute) + { + if (!array_key_exists($attribute, $released_attributes) && !self::canBeRedundant($attribute, $released_attributes)) + { + if (self::isRnsIndicated($sp_metadata) && $attribute == 'eduPersonTargetedId' && array_key_exists('eduPersonPrincipalName', $released_attributes)) + { $remark = true; - } else { + } + else + { return array('mark' => 'C'.self::getExtraPoints('C', $sp_metadata, $released_attributes, $superfluous_attributes, $idp_metadata, $non_personal_attributes), 'text' => 'IdP sends basic information while some required information is missing', 'additional_information' => $additional_information); } } @@ -381,23 +461,26 @@ class EarcUtils } // B: IdP sends minimal information - if (self::isMinimalSubsetSent(array_keys($released_attributes))) { - foreach ($sp_metadata['attributeNames'] as $attribute) { - if (!array_key_exists($attribute, $released_attributes) && !self::canBeRedundant($attribute, $released_attributes)) { + if (self::isMinimalSubsetSent(array_keys($released_attributes))) + { + foreach ($sp_metadata['attributeNames'] as $attribute) + { + if (!array_key_exists($attribute, $released_attributes) && !self::canBeRedundant($attribute, $released_attributes)) + { return array('mark' => 'B'.self::getExtraPoints('B', $sp_metadata, $released_attributes, $superfluous_attributes, $idp_metadata, $non_personal_attributes), 'text' => 'IdP sends minimal information', 'additional_information' => $additional_information); } } } // A-: IdP sends some non personal superfluous attributes - if (count($superfluous_attributes) > 0) { + if (count($superfluous_attributes) > 0) + { return array('mark' => 'A'.self::getExtraPoints('B', $sp_metadata, $released_attributes, $superfluous_attributes, $idp_metadata, $non_personal_attributes), 'text' => 'IdP sends all necessary information but sends some non-personal superfluous attributes ('.implode(',', $superfluous_attributes).') as well.', 'additional_information' => $additional_information); - } - // A: IdP sends all necessary information - if (count($superfluous_attributes) == 0) { + if (count($superfluous_attributes) == 0) + { return array('mark' => 'A'.self::getExtraPoints('A', $sp_metadata, $released_attributes, $superfluous_attributes, $idp_metadata, $non_personal_attributes), 'text' => 'Great! IdP sends all necessary information', 'additional_information' => $additional_information); } } diff --git a/config/app.php b/config/app.php index 6ce5feb4a1dacbc9939fd794c54b8cfd920dd845..25890980adb70f51b6619d64672a67b2b1630926 100755 --- a/config/app.php +++ b/config/app.php @@ -124,31 +124,6 @@ return [ 'log_level' => env('APP_LOG_LEVEL', 'debug'), - /* - |--------------------------------------------------------------------------- - |EARC specific Configuration - | - | - */ - - // XXX Updated using ansible - 'earc_sps' => [ - 'https://rns-ng.example.org/shibboleth', - 'https://coco.example.org/shibboleth', - 'https://noec.example.org/shibboleth', - ], - - - 'regional_earc' => [ - 'http://aai.grnet.gr/' => 'https://aai.grnet.gr', - 'http://rr.aai.switch.ch/' => 'https://attribute-viewer.aai.switch.ch/interfederation-test/', - 'http://taat.edu.ee' => 'https://eitja.taat.edu.ee/', - 'http://eduid.hu' => 'https://attributes.eduid.hu', - ], - - 'metadata_url' => env('METADATA_URL', ""), - - /* |-------------------------------------------------------------------------- | Autoloaded Service Providers diff --git a/config/metadata.php b/config/metadata.php index 2fa0fd502b1d0f513a771ed1b300b0680bb557a6..4727cd3ffb7c114d6555678f356d23bb6cbcef32 100644 --- a/config/metadata.php +++ b/config/metadata.php @@ -1,6 +1,8 @@ <?php return [ + 'metadata_url' => env('METADATA_URL', ""), + 'sp_remote_metadata_filename' => 'saml20-sp-remote.php', 'idp_remote_metadata_filename' => 'saml20-idp-remote.php',