diff --git a/lib/baseline_report.xsl b/lib/baseline_report.xsl new file mode 100644 index 0000000..d27e703 --- /dev/null +++ b/lib/baseline_report.xsl @@ -0,0 +1,474 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2018 Internet2 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<!-- + baseline_report_csv.xsl + + This XSL transform takes a SAML metadata aggregate and produces a list of + IdP and SP baseline compliance factors (documented at [1]) for entities registered by 'https://incommon.org', containing the following fields: + +IdPs: + 1. entityID + 2. timestamp + 3. Organization Display Name + 4. "IdP" string literal + 5. IdP Display Name: mdui:DisplayName + 6. IdP Privacy URL or NONE + 7. IdP Logo present TRUE/FALSE + 8. IdP Tech contact or NONE + 9. IdP Admin contact or NONE + 10. IdP Security contact or NONE + 11. IdP complies with baseline expectations "Y" or "N" + + The IdP Display Name field is set to "NONE" if neither mdui:DisplayName nor + md:OrganizationDisplayName exist in the entity descriptor. + + BUG: Incorrectly processes an entity with multiple IDPSSODescriptor elements + +SPs: + 1. entityID + 2. timestamp + 3. Organization Display Name + 4. "SP" string literal + 5. SP Display Name: mdui:DisplayName + 6. SP Privacy URL or NONE + 7. SP Logo present TRUE/FALSE + 8. SP Tech contact or NONE + 9. SP Admin contact or NONE + 10. SP Security contact or NONE + 11. SP complies with baseline expectations "Y" or "N" + + The SP Display Name field is set to "NONE" if neither mdui:DisplayName nor + md:OrganizationDisplayName exist in the entity descriptor. + + BUG: Incorrectly processes an entity with multiple SPSSODescriptor elements + +[1] https://spaces.internet2.edu/x/4RL9Bg + +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" + xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute" + xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi" + xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui" + xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" + xmlns:remd="http://refeds.org/metadata" + xmlns:icmd="http://id.incommon.org/metadata" + xmlns:date="http://exslt.org/dates-and-times"> + + <!-- search-and-replace constants --> + <xsl:variable name="double_quote" select="'"'"/> + <xsl:variable name="double_double_quote" select="'""'"/> + <xsl:variable name="timestamp" select="date:date-time()"/> + <!-- line feed --> + <xsl:variable name="lf" select="' '" /> + + <!-- output is plain text --> + <xsl:output method="text"/> + + <!-- output the heading line --> + <xsl:template match="/" name="baseline_report"> + <!-- Set field_sep to "','" (comma) for CSV (default), + or "'	'" (tab) for Tab-delimited text --> + <xsl:param name="field_sep" select="','"/> + + <xsl:text>#entityID</xsl:text> + <xsl:value-of select="$field_sep" disable-output-escaping="yes" /> + <xsl:text>timestamp</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Organization Display Name</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Entity Type</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Entity Display Name</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Privacy URL</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Logo Present</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Tech Contact</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Admin Contact</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Security Contact</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Complies</xsl:text> + <xsl:value-of select="$lf" /> + <xsl:apply-templates> + <xsl:with-param name="field_sep" select="$field_sep" /> + </xsl:apply-templates> + </xsl:template> + + <!-- match all entity descriptors with an IdP role --> + <xsl:template match="//md:EntityDescriptor[md:Extensions/mdrpi:RegistrationInfo/@registrationAuthority='https://incommon.org'][md:IDPSSODescriptor]"> + + <xsl:param name="field_sep" select="','"/> + + <!-- compute the normalized values of mdui:DisplayName and md:OrganizationDisplayName --> + <xsl:variable name="displayName" select="normalize-space(md:IDPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:DisplayName[@xml:lang='en'])"/> + <xsl:variable name="orgDisplayName" select="normalize-space(md:Organization/md:OrganizationDisplayName[@xml:lang='en'])"/> + <xsl:variable name="privacyURL" select="normalize-space(md:IDPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:PrivacyStatementURL[@xml:lang='en'])"/> + <xsl:variable name="logo" select="normalize-space(md:IDPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:Logo)"/> + <xsl:variable name="techContact" select="normalize-space(md:ContactPerson[@contactType='technical']/md:EmailAddress)"/> + <xsl:variable name="adminContact" select="normalize-space(md:ContactPerson[@contactType='administrative']/md:EmailAddress)"/> + <xsl:variable name="rEFEDSSecurityContact" select="normalize-space(md:ContactPerson[@remd:contactType='http://refeds.org/metadata/contactType/security']/md:EmailAddress)"/> + <xsl:variable name="inCommonSecurityContact" select="normalize-space(md:ContactPerson[@icmd:contactType='http://id.incommon.org/metadata/contactType/security']/md:EmailAddress)"/> + + <!-- output the IdP entityID --> + <xsl:value-of select="@entityID"/> + + <!-- output the current timestamp --> + <xsl:value-of select="$field_sep" /> + <xsl:value-of select="$timestamp"/> + + <!-- output md:OrganizationDisplayName or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$orgDisplayName != ''"> + <!-- escape literal double quotes in md:OrganizationDisplayName --> + <xsl:variable name="escapedOrgDisplayName"> + <xsl:call-template name="string-replace-all"> + <xsl:with-param name="string" select="$orgDisplayName"/> + <xsl:with-param name="search" select="$double_quote"/> + <xsl:with-param name="replace" select="$double_double_quote"/> + </xsl:call-template> + </xsl:variable> + <xsl:text>"</xsl:text> + <xsl:value-of select="$escapedOrgDisplayName"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output that this is an IdP entity descriptor --> + <xsl:value-of select="$field_sep" /> + <xsl:text>IdP</xsl:text> + + <!-- output either mdui:DisplayName or md:OrganizationDisplayName or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$displayName != ''"> + <!-- escape literal double quotes in mdui:DisplayName --> + <xsl:variable name="escapedDisplayName"> + <xsl:call-template name="string-replace-all"> + <xsl:with-param name="string" select="$displayName"/> + <xsl:with-param name="search" select="$double_quote"/> + <xsl:with-param name="replace" select="$double_double_quote"/> + </xsl:call-template> + </xsl:variable> + <xsl:text>"</xsl:text> + <xsl:value-of select="$escapedDisplayName"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output either mdui:privacyURL or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$privacyURL != ''"> + <xsl:text>"</xsl:text> + <xsl:value-of select="$privacyURL"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output Logo Present "TRUE" or "FALSE" --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$logo != ''"> + <xsl:text>TRUE</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>FALSE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output either tech contact or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$techContact != ''"> + <xsl:text>"</xsl:text> + <xsl:value-of select="$techContact"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output either admin contact or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$adminContact != ''"> + <xsl:text>"</xsl:text> + <xsl:value-of select="$adminContact"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output either REFEDS security contact, InCommon security contact or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$rEFEDSSecurityContact != ''"> + <xsl:text>"</xsl:text> + <xsl:value-of select="$rEFEDSSecurityContact"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:when test="$inCommonSecurityContact != ''"> + <xsl:text>"</xsl:text> + <xsl:value-of select="$inCommonSecurityContact"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output "Y" (complies) or "N" (does not comply) with baseline expectations --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$privacyURL != '' and $logo != '' and $techContact != '' and $adminContact != '' and ($rEFEDSSecurityContact != '' or $inCommonSecurityContact != '')"> + <xsl:text>Y</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>N</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output "hide" or "show" depending on the hide-from-discovery entity attribute --> +<!-- + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="md:Extensions/mdattr:EntityAttributes/saml:Attribute[@Name='http://macedir.org/entity-category']/saml:AttributeValue[text()='http://refeds.org/category/hide-from-discovery']"> + <xsl:text>hide</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>show</xsl:text> + </xsl:otherwise> + </xsl:choose> +--> + + <!-- output the registrar ID --> +<!-- + <xsl:value-of select="$field_sep" /> + <xsl:value-of select="md:Extensions/mdrpi:RegistrationInfo/@registrationAuthority"/> +--> + + <xsl:text>
</xsl:text> + </xsl:template> + + <!-- match all entity descriptors with an SP role --> + <xsl:template match="//md:EntityDescriptor[md:Extensions/mdrpi:RegistrationInfo/@registrationAuthority='https://incommon.org'][md:SPSSODescriptor]"> + + <xsl:param name="field_sep" select="','"/> + + <!-- compute the normalized values of mdui:DisplayName and md:OrganizationDisplayName --> + <xsl:variable name="displayName" select="normalize-space(md:SPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:DisplayName[@xml:lang='en'])"/> + <xsl:variable name="orgDisplayName" select="normalize-space(md:Organization/md:OrganizationDisplayName[@xml:lang='en'])"/> + <xsl:variable name="privacyURL" select="normalize-space(md:SPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:PrivacyStatementURL[@xml:lang='en'])"/> + <xsl:variable name="logo" select="normalize-space(md:SPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:Logo)"/> + <xsl:variable name="techContact" select="normalize-space(md:ContactPerson[@contactType='technical']/md:EmailAddress)"/> + <xsl:variable name="adminContact" select="normalize-space(md:ContactPerson[@contactType='administrative']/md:EmailAddress)"/> + <xsl:variable name="rEFEDSSecurityContact" select="normalize-space(md:ContactPerson[@remd:contactType='http://refeds.org/metadata/contactType/security']/md:EmailAddress)"/> + <xsl:variable name="inCommonSecurityContact" select="normalize-space(md:ContactPerson[@icmd:contactType='http://id.incommon.org/metadata/contactType/security']/md:EmailAddress)"/> + + <!-- output the SP entityID --> + <xsl:value-of select="@entityID"/> + + <!-- output the current timestamp --> + <xsl:value-of select="$field_sep" /> + <xsl:value-of select="$timestamp"/> + + <!-- output md:OrganizationDisplayName or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$orgDisplayName != ''"> + <!-- escape literal double quotes in md:OrganizationDisplayName --> + <xsl:variable name="escapedOrgDisplayName"> + <xsl:call-template name="string-replace-all"> + <xsl:with-param name="string" select="$orgDisplayName"/> + <xsl:with-param name="search" select="$double_quote"/> + <xsl:with-param name="replace" select="$double_double_quote"/> + </xsl:call-template> + </xsl:variable> + <xsl:text>"</xsl:text> + <xsl:value-of select="$escapedOrgDisplayName"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + + <!-- output that this is an SP entity descriptor --> + <xsl:value-of select="$field_sep" /> + <xsl:text>SP</xsl:text> + + <!-- output either mdui:DisplayName or md:OrganizationDisplayName or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$displayName != ''"> + <!-- escape literal double quotes in mdui:DisplayName --> + <xsl:variable name="escapedDisplayName"> + <xsl:call-template name="string-replace-all"> + <xsl:with-param name="string" select="$displayName"/> + <xsl:with-param name="search" select="$double_quote"/> + <xsl:with-param name="replace" select="$double_double_quote"/> + </xsl:call-template> + </xsl:variable> + <xsl:text>"</xsl:text> + <xsl:value-of select="$escapedDisplayName"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output either mdui:privacyURL or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$privacyURL != ''"> + <xsl:text>"</xsl:text> + <xsl:value-of select="$privacyURL"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output Logo Present "TRUE" or "FALSE" --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$logo != ''"> + <xsl:text>TRUE</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>FALSE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output either tech contact or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$techContact != ''"> + <xsl:text>"</xsl:text> + <xsl:value-of select="$techContact"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output either admin contact or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$adminContact != ''"> + <xsl:text>"</xsl:text> + <xsl:value-of select="$adminContact"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output either REFEDS security contact, InCommon security contact or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$rEFEDSSecurityContact != ''"> + <xsl:text>"</xsl:text> + <xsl:value-of select="$rEFEDSSecurityContact"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:when test="$inCommonSecurityContact != ''"> + <xsl:text>"</xsl:text> + <xsl:value-of select="$inCommonSecurityContact"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output "Y" (complies) or "N" (does not comply) with baseline expectations --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$privacyURL != '' and $logo != '' and $techContact != '' and $adminContact != '' and ($rEFEDSSecurityContact != '' or $inCommonSecurityContact != '')"> + <xsl:text>Y</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>N</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output the registrar ID --> +<!-- + <xsl:value-of select="$field_sep" /> + <xsl:value-of select="md:Extensions/mdrpi:RegistrationInfo/@registrationAuthority"/> +--> + + <xsl:text>
</xsl:text> + </xsl:template> + + <!-- + A named template that performs global (recursive) search-and-replace on a string + (similar to fn:replace(string, pattern, replace) in XSLT 2.0). + See: http://stackoverflow.com/questions/3067113/xslt-string-replace/3067130#3067130 + --> + <xsl:template name="string-replace-all"> + <xsl:param name="string"/> + <xsl:param name="search"/> + <xsl:param name="replace"/> + <xsl:choose> + <xsl:when test="$string = '' or $search = '' or not($search)"> + <!-- Prevent this routine from hanging --> + <xsl:value-of select="$string"/> + </xsl:when> + <xsl:when test="contains($string, $search)"> + <xsl:value-of select="substring-before($string, $search)"/> + <xsl:value-of select="$replace"/> + <xsl:call-template name="string-replace-all"> + <xsl:with-param name="string" select="substring-after($string, $search)"/> + <xsl:with-param name="search" select="$search"/> + <xsl:with-param name="replace" select="$replace"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$string"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="text()"> + <!-- do nothing --> + </xsl:template> +</xsl:stylesheet> diff --git a/lib/baseline_report_csv.xsl b/lib/baseline_report_csv.xsl index 8005510..87c4de8 100644 --- a/lib/baseline_report_csv.xsl +++ b/lib/baseline_report_csv.xsl @@ -13,430 +13,16 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ---> -<!-- - baseline_report_csv.xsl - - This XSL transform takes a SAML metadata aggregate and produces a list of - IdP and SP baseline compliance factors (documented at [1]) for entities registered by 'https://incommon.org', containing the following fields: - -IdPs: - 1. entityID - 2. timestamp - 3. Organization Display Name - 4. "IdP" string literal - 5. IdP Display Name: mdui:DisplayName - 6. IdP Privacy URL or NONE - 7. IdP Logo present TRUE/FALSE - 8. IdP Tech contact or NONE - 9. IdP Admin contact or NONE - 10. IdP Security contact or NONE - 11. IdP complies with baseline expectations "Y" or "N" - - The IdP Display Name field is set to "NONE" if neither mdui:DisplayName nor - md:OrganizationDisplayName exist in the entity descriptor. - - BUG: Incorrectly processes an entity with multiple IDPSSODescriptor elements - -SPs: - 1. entityID - 2. timestamp - 3. Organization Display Name - 4. "SP" string literal - 5. SP Display Name: mdui:DisplayName - 6. SP Privacy URL or NONE - 7. SP Logo present TRUE/FALSE - 8. SP Tech contact or NONE - 9. SP Admin contact or NONE - 10. SP Security contact or NONE - 11. SP complies with baseline expectations "Y" or "N" - - The SP Display Name field is set to "NONE" if neither mdui:DisplayName nor - md:OrganizationDisplayName exist in the entity descriptor. - - BUG: Incorrectly processes an entity with multiple SPSSODescriptor elements - -[1] https://spaces.internet2.edu/x/4RL9Bg - --> <xsl:stylesheet version="1.0" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" - xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute" - xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi" - xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui" - xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" - xmlns:remd="http://refeds.org/metadata" - xmlns:icmd="http://id.incommon.org/metadata" - xmlns:date="http://exslt.org/dates-and-times"> - - <!-- search-and-replace constants --> - <xsl:variable name="double_quote" select="'"'"/> - <xsl:variable name="double_double_quote" select="'""'"/> - <xsl:variable name="timestamp" select="date:date-time()"/> + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> - <!-- output is plain text --> - <xsl:output method="text"/> + <xsl:include href="baseline_report.xsl" /> - <!-- output the heading line --> <xsl:template match="/"> - <xsl:text>entityID,timestamp,Organization Display Name,Entity Type,Entity Display Name,Privacy URL,Logo Present,Tech Contact,Admin Contact,Security Contact,Complies</xsl:text> - <xsl:text>
</xsl:text> - <xsl:apply-templates/> - </xsl:template> - - <!-- match all entity descriptors with an IdP role --> - <xsl:template match="//md:EntityDescriptor[md:Extensions/mdrpi:RegistrationInfo/@registrationAuthority='https://incommon.org'][md:IDPSSODescriptor]"> - - <!-- compute the normalized values of mdui:DisplayName and md:OrganizationDisplayName --> - <xsl:variable name="displayName" select="normalize-space(md:IDPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:DisplayName[@xml:lang='en'])"/> - <xsl:variable name="orgDisplayName" select="normalize-space(md:Organization/md:OrganizationDisplayName[@xml:lang='en'])"/> - <xsl:variable name="privacyURL" select="normalize-space(md:IDPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:PrivacyStatementURL[@xml:lang='en'])"/> - <xsl:variable name="logo" select="normalize-space(md:IDPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:Logo)"/> - <xsl:variable name="techContact" select="normalize-space(md:ContactPerson[@contactType='technical']/md:EmailAddress)"/> - <xsl:variable name="adminContact" select="normalize-space(md:ContactPerson[@contactType='administrative']/md:EmailAddress)"/> - <xsl:variable name="rEFEDSSecurityContact" select="normalize-space(md:ContactPerson[@remd:contactType='http://refeds.org/metadata/contactType/security']/md:EmailAddress)"/> - <xsl:variable name="inCommonSecurityContact" select="normalize-space(md:ContactPerson[@icmd:contactType='http://id.incommon.org/metadata/contactType/security']/md:EmailAddress)"/> - - <!-- output the IdP entityID --> - <xsl:value-of select="@entityID"/> - - <!-- output the current timestamp --> - <xsl:text>,</xsl:text> - <xsl:value-of select="$timestamp"/> - - <!-- output md:OrganizationDisplayName or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$orgDisplayName != ''"> - <!-- escape literal double quotes in md:OrganizationDisplayName --> - <xsl:variable name="escapedOrgDisplayName"> - <xsl:call-template name="string-replace-all"> - <xsl:with-param name="string" select="$orgDisplayName"/> - <xsl:with-param name="search" select="$double_quote"/> - <xsl:with-param name="replace" select="$double_double_quote"/> - </xsl:call-template> - </xsl:variable> - <xsl:text>"</xsl:text> - <xsl:value-of select="$escapedOrgDisplayName"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output that this is an IdP entity descriptor --> - <xsl:text>,</xsl:text> - <xsl:text>IdP</xsl:text> - - <!-- output either mdui:DisplayName or md:OrganizationDisplayName or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$displayName != ''"> - <!-- escape literal double quotes in mdui:DisplayName --> - <xsl:variable name="escapedDisplayName"> - <xsl:call-template name="string-replace-all"> - <xsl:with-param name="string" select="$displayName"/> - <xsl:with-param name="search" select="$double_quote"/> - <xsl:with-param name="replace" select="$double_double_quote"/> - </xsl:call-template> - </xsl:variable> - <xsl:text>"</xsl:text> - <xsl:value-of select="$escapedDisplayName"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output either mdui:privacyURL or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$privacyURL != ''"> - <xsl:text>"</xsl:text> - <xsl:value-of select="$privacyURL"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output Logo Present "TRUE" or "FALSE" --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$logo != ''"> - <xsl:text>TRUE</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>FALSE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output either tech contact or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$techContact != ''"> - <xsl:text>"</xsl:text> - <xsl:value-of select="$techContact"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output either admin contact or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$adminContact != ''"> - <xsl:text>"</xsl:text> - <xsl:value-of select="$adminContact"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output either REFEDS security contact, InCommon security contact or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$rEFEDSSecurityContact != ''"> - <xsl:text>"</xsl:text> - <xsl:value-of select="$rEFEDSSecurityContact"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:when test="$inCommonSecurityContact != ''"> - <xsl:text>"</xsl:text> - <xsl:value-of select="$inCommonSecurityContact"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output "Y" (complies) or "N" (does not comply) with baseline expectations --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$privacyURL != '' and $logo != '' and $techContact != '' and $adminContact != '' and ($rEFEDSSecurityContact != '' or $inCommonSecurityContact != '')"> - <xsl:text>Y</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>N</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output "hide" or "show" depending on the hide-from-discovery entity attribute --> -<!-- - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="md:Extensions/mdattr:EntityAttributes/saml:Attribute[@Name='http://macedir.org/entity-category']/saml:AttributeValue[text()='http://refeds.org/category/hide-from-discovery']"> - <xsl:text>hide</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>show</xsl:text> - </xsl:otherwise> - </xsl:choose> ---> - - <!-- output the registrar ID --> -<!-- - <xsl:text>,</xsl:text> - <xsl:value-of select="md:Extensions/mdrpi:RegistrationInfo/@registrationAuthority"/> ---> - - <xsl:text>
</xsl:text> + <xsl:call-template name="baseline_report"> + <xsl:with-param name="field_sep" select="','" /> + </xsl:call-template> </xsl:template> - - <!-- match all entity descriptors with an SP role --> - <xsl:template match="//md:EntityDescriptor[md:Extensions/mdrpi:RegistrationInfo/@registrationAuthority='https://incommon.org'][md:SPSSODescriptor]"> - <!-- compute the normalized values of mdui:DisplayName and md:OrganizationDisplayName --> - <xsl:variable name="displayName" select="normalize-space(md:SPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:DisplayName[@xml:lang='en'])"/> - <xsl:variable name="orgDisplayName" select="normalize-space(md:Organization/md:OrganizationDisplayName[@xml:lang='en'])"/> - <xsl:variable name="privacyURL" select="normalize-space(md:SPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:PrivacyStatementURL[@xml:lang='en'])"/> - <xsl:variable name="logo" select="normalize-space(md:SPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:Logo)"/> - <xsl:variable name="techContact" select="normalize-space(md:ContactPerson[@contactType='technical']/md:EmailAddress)"/> - <xsl:variable name="adminContact" select="normalize-space(md:ContactPerson[@contactType='administrative']/md:EmailAddress)"/> - <xsl:variable name="rEFEDSSecurityContact" select="normalize-space(md:ContactPerson[@remd:contactType='http://refeds.org/metadata/contactType/security']/md:EmailAddress)"/> - <xsl:variable name="inCommonSecurityContact" select="normalize-space(md:ContactPerson[@icmd:contactType='http://id.incommon.org/metadata/contactType/security']/md:EmailAddress)"/> - - <!-- output the SP entityID --> - <xsl:value-of select="@entityID"/> - - <!-- output the current timestamp --> - <xsl:text>,</xsl:text> - <xsl:value-of select="$timestamp"/> - - <!-- output md:OrganizationDisplayName or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$orgDisplayName != ''"> - <!-- escape literal double quotes in md:OrganizationDisplayName --> - <xsl:variable name="escapedOrgDisplayName"> - <xsl:call-template name="string-replace-all"> - <xsl:with-param name="string" select="$orgDisplayName"/> - <xsl:with-param name="search" select="$double_quote"/> - <xsl:with-param name="replace" select="$double_double_quote"/> - </xsl:call-template> - </xsl:variable> - <xsl:text>"</xsl:text> - <xsl:value-of select="$escapedOrgDisplayName"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - - <!-- output that this is an SP entity descriptor --> - <xsl:text>,</xsl:text> - <xsl:text>SP</xsl:text> - - <!-- output either mdui:DisplayName or md:OrganizationDisplayName or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$displayName != ''"> - <!-- escape literal double quotes in mdui:DisplayName --> - <xsl:variable name="escapedDisplayName"> - <xsl:call-template name="string-replace-all"> - <xsl:with-param name="string" select="$displayName"/> - <xsl:with-param name="search" select="$double_quote"/> - <xsl:with-param name="replace" select="$double_double_quote"/> - </xsl:call-template> - </xsl:variable> - <xsl:text>"</xsl:text> - <xsl:value-of select="$escapedDisplayName"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output either mdui:privacyURL or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$privacyURL != ''"> - <xsl:text>"</xsl:text> - <xsl:value-of select="$privacyURL"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output Logo Present "TRUE" or "FALSE" --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$logo != ''"> - <xsl:text>TRUE</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>FALSE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output either tech contact or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$techContact != ''"> - <xsl:text>"</xsl:text> - <xsl:value-of select="$techContact"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output either admin contact or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$adminContact != ''"> - <xsl:text>"</xsl:text> - <xsl:value-of select="$adminContact"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output either REFEDS security contact, InCommon security contact or "NONE" (in that order) --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$rEFEDSSecurityContact != ''"> - <xsl:text>"</xsl:text> - <xsl:value-of select="$rEFEDSSecurityContact"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:when test="$inCommonSecurityContact != ''"> - <xsl:text>"</xsl:text> - <xsl:value-of select="$inCommonSecurityContact"/> - <xsl:text>"</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>NONE</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output "Y" (complies) or "N" (does not comply) with baseline expectations --> - <xsl:text>,</xsl:text> - <xsl:choose> - <xsl:when test="$privacyURL != '' and $logo != '' and $techContact != '' and $adminContact != '' and ($rEFEDSSecurityContact != '' or $inCommonSecurityContact != '')"> - <xsl:text>Y</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>N</xsl:text> - </xsl:otherwise> - </xsl:choose> - - <!-- output the registrar ID --> -<!-- - <xsl:text>,</xsl:text> - <xsl:value-of select="md:Extensions/mdrpi:RegistrationInfo/@registrationAuthority"/> ---> - - <xsl:text>
</xsl:text> - </xsl:template> - - <!-- - A named template that performs global (recursive) search-and-replace on a string - (similar to fn:replace(string, pattern, replace) in XSLT 2.0). - See: http://stackoverflow.com/questions/3067113/xslt-string-replace/3067130#3067130 - --> - <xsl:template name="string-replace-all"> - <xsl:param name="string"/> - <xsl:param name="search"/> - <xsl:param name="replace"/> - <xsl:choose> - <xsl:when test="$string = '' or $search = '' or not($search)"> - <!-- Prevent this routine from hanging --> - <xsl:value-of select="$string"/> - </xsl:when> - <xsl:when test="contains($string, $search)"> - <xsl:value-of select="substring-before($string, $search)"/> - <xsl:value-of select="$replace"/> - <xsl:call-template name="string-replace-all"> - <xsl:with-param name="string" select="substring-after($string, $search)"/> - <xsl:with-param name="search" select="$search"/> - <xsl:with-param name="replace" select="$replace"/> - </xsl:call-template> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="$string"/> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - - <xsl:template match="text()"> - <!-- do nothing --> - </xsl:template> </xsl:stylesheet> diff --git a/lib/baseline_report_tsv.xsl b/lib/baseline_report_tsv.xsl new file mode 100644 index 0000000..09fcf60 --- /dev/null +++ b/lib/baseline_report_tsv.xsl @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2018 Internet2 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + + <xsl:include href="baseline_report.xsl" /> + + <xsl:template match="/"> + <xsl:call-template name="baseline_report"> + <xsl:with-param name="field_sep" select="'	'" /> + </xsl:call-template> + </xsl:template> + +</xsl:stylesheet> diff --git a/lib/baseline_report_web.xsl b/lib/baseline_report_web.xsl new file mode 100644 index 0000000..0411861 --- /dev/null +++ b/lib/baseline_report_web.xsl @@ -0,0 +1,409 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2018 Internet2 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<!-- + baseline_report_csv.xsl + + This XSL transform takes a SAML metadata aggregate and produces a list of + IdP and SP baseline compliance factors (documented at [1]) for entities registered by 'https://incommon.org', containing the following fields: + +IdPs: + 1. entityID + 2. timestamp + 3. Organization Display Name + 4. "IdP" string literal + 5. IdP Display Name: mdui:DisplayName + 6. IdP Privacy URL or NONE + 7. IdP Logo present TRUE/FALSE + 8. IdP Tech contact or NONE + 9. IdP Admin contact or NONE + 10. IdP Security contact or NONE + 11. IdP complies with baseline expectations "Y" or "N" + + The IdP Display Name field is set to "NONE" if neither mdui:DisplayName nor + md:OrganizationDisplayName exist in the entity descriptor. + + BUG: Incorrectly processes an entity with multiple IDPSSODescriptor elements + +SPs: + 1. entityID + 2. timestamp + 3. Organization Display Name + 4. "SP" string literal + 5. SP Display Name: mdui:DisplayName + 6. SP Privacy URL or NONE + 7. SP Logo present TRUE/FALSE + 8. SP Tech contact or NONE + 9. SP Admin contact or NONE + 10. SP Security contact or NONE + 11. SP complies with baseline expectations "Y" or "N" + + The SP Display Name field is set to "NONE" if neither mdui:DisplayName nor + md:OrganizationDisplayName exist in the entity descriptor. + + BUG: Incorrectly processes an entity with multiple SPSSODescriptor elements + +[1] https://spaces.internet2.edu/x/4RL9Bg + +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" + xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute" + xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi" + xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui" + xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" + xmlns:remd="http://refeds.org/metadata" + xmlns:icmd="http://id.incommon.org/metadata" + xmlns:date="http://exslt.org/dates-and-times"> + + <!-- search-and-replace constants --> + <xsl:variable name="double_quote" select="'"'"/> + <xsl:variable name="double_double_quote" select="'""'"/> + <xsl:variable name="timestamp" select="date:date-time()"/> + <!-- line feed --> + <xsl:variable name="lf" select="' '" /> + + <!-- output is plain text --> + <xsl:output method="text"/> + + <!-- output the heading line --> + <xsl:template match="/" name="baseline_report"> + <!-- Set field_sep to "','" (comma) for CSV (default), + or "'	'" (tab) for Tab-delimited text --> + <xsl:param name="field_sep" select="','"/> + + <xsl:text>Organization Display Name</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Entity Display Name</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Entity ID</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Entity Type</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Severity</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Has Privacy Statement</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Has Logo</xsl:text> + <xsl:value-of select="$field_sep" /> + <xsl:text>Has All Contacts</xsl:text> + <xsl:value-of select="$lf" /> + <xsl:apply-templates> + <xsl:with-param name="field_sep" select="$field_sep" /> + </xsl:apply-templates> + </xsl:template> + + <!-- match all entity descriptors with an IdP role --> + <xsl:template match="//md:EntityDescriptor[md:Extensions/mdrpi:RegistrationInfo/@registrationAuthority='https://incommon.org'][md:IDPSSODescriptor]"> + + <xsl:param name="field_sep" select="','"/> + + <!-- compute the normalized values of mdui:DisplayName and md:OrganizationDisplayName --> + <xsl:variable name="displayName" select="normalize-space(md:IDPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:DisplayName[@xml:lang='en'])"/> + <xsl:variable name="orgDisplayName" select="normalize-space(md:Organization/md:OrganizationDisplayName[@xml:lang='en'])"/> + <xsl:variable name="privacyURL" select="normalize-space(md:IDPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:PrivacyStatementURL[@xml:lang='en'])"/> + <xsl:variable name="logo" select="normalize-space(md:IDPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:Logo)"/> + <xsl:variable name="techContact" select="normalize-space(md:ContactPerson[@contactType='technical']/md:EmailAddress)"/> + <xsl:variable name="adminContact" select="normalize-space(md:ContactPerson[@contactType='administrative']/md:EmailAddress)"/> + <xsl:variable name="rEFEDSSecurityContact" select="normalize-space(md:ContactPerson[@remd:contactType='http://refeds.org/metadata/contactType/security']/md:EmailAddress)"/> + <xsl:variable name="inCommonSecurityContact" select="normalize-space(md:ContactPerson[@icmd:contactType='http://id.incommon.org/metadata/contactType/security']/md:EmailAddress)"/> + + + <!-- Only output if BE not met --> + <xsl:choose> + <xsl:when test="$privacyURL = '' or $logo = '' or $techContact = '' or $adminContact = '' or ($rEFEDSSecurityContact = '' and $inCommonSecurityContact = '')"> + + <xsl:choose> + <xsl:when test="$orgDisplayName != ''"> + <!-- escape literal double quotes in md:OrganizationDisplayName --> + <xsl:variable name="escapedOrgDisplayName"> + <xsl:call-template name="string-replace-all"> + <xsl:with-param name="string" select="$orgDisplayName"/> + <xsl:with-param name="search" select="$double_quote"/> + <xsl:with-param name="replace" select="$double_double_quote"/> + </xsl:call-template> + </xsl:variable> + <xsl:text>"</xsl:text> + <xsl:value-of select="$escapedOrgDisplayName"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + + <!-- output either mdui:DisplayName or md:OrganizationDisplayName or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$displayName != ''"> + <!-- escape literal double quotes in mdui:DisplayName --> + <xsl:variable name="escapedDisplayName"> + <xsl:call-template name="string-replace-all"> + <xsl:with-param name="string" select="$displayName"/> + <xsl:with-param name="search" select="$double_quote"/> + <xsl:with-param name="replace" select="$double_double_quote"/> + </xsl:call-template> + </xsl:variable> + <xsl:text>"</xsl:text> + <xsl:value-of select="$escapedDisplayName"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output the IdP entityID --> + <xsl:value-of select="$field_sep" /> + <xsl:value-of select="@entityID"/> + + + <!-- output that this is an IdP entity descriptor --> + <xsl:value-of select="$field_sep" /> + <xsl:text>IdP</xsl:text> + + + <!-- Severity Logic: + Serious = missing privacy statement and at least one contact + Moderate = missing either privacy statement or at least one contact + Minor = missing only the logo + --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$privacyURL = '' and ($techContact = '' or $adminContact = '' or ($rEFEDSSecurityContact = '' and $inCommonSecurityContact = ''))"> + <xsl:text>Significant</xsl:text> + </xsl:when> + <xsl:when test="$privacyURL = '' or ($techContact = '' or $adminContact = '' or ($rEFEDSSecurityContact = '' and $inCommonSecurityContact = ''))"> + <xsl:text>Moderate</xsl:text> + </xsl:when> + <xsl:when test="$logo = ''"> + <xsl:text>Minor</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>Unknown</xsl:text> + </xsl:otherwise> + </xsl:choose> + + + <!-- output either mdui:privacyURL (Yes) or (No) (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$privacyURL != ''"> + <xsl:text>YES</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NO</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output Logo Present "TRUE" or "FALSE" --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$logo != ''"> + <xsl:text>YES</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NO</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output "Y" (complies) or "N" (does not comply) with whether all contacts are there or not --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$techContact != '' and $adminContact != '' and ($rEFEDSSecurityContact != '' or $inCommonSecurityContact != '')"> + <xsl:text>YES</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NO</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <xsl:text>
</xsl:text> + + </xsl:when> + <!-- <xsl:otherwise>-IdP-</xsl:otherwise> --> + </xsl:choose> + + </xsl:template> + + <!-- match all entity descriptors with an SP role --> + <xsl:template match="//md:EntityDescriptor[md:Extensions/mdrpi:RegistrationInfo/@registrationAuthority='https://incommon.org'][md:SPSSODescriptor]"> + + <xsl:param name="field_sep" select="','"/> + + <!-- compute the normalized values of mdui:DisplayName and md:OrganizationDisplayName --> + <xsl:variable name="displayName" select="normalize-space(md:SPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:DisplayName[@xml:lang='en'])"/> + <xsl:variable name="orgDisplayName" select="normalize-space(md:Organization/md:OrganizationDisplayName[@xml:lang='en'])"/> + <xsl:variable name="privacyURL" select="normalize-space(md:SPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:PrivacyStatementURL[@xml:lang='en'])"/> + <xsl:variable name="logo" select="normalize-space(md:SPSSODescriptor/md:Extensions/mdui:UIInfo/mdui:Logo)"/> + <xsl:variable name="techContact" select="normalize-space(md:ContactPerson[@contactType='technical']/md:EmailAddress)"/> + <xsl:variable name="adminContact" select="normalize-space(md:ContactPerson[@contactType='administrative']/md:EmailAddress)"/> + <xsl:variable name="rEFEDSSecurityContact" select="normalize-space(md:ContactPerson[@remd:contactType='http://refeds.org/metadata/contactType/security']/md:EmailAddress)"/> + <xsl:variable name="inCommonSecurityContact" select="normalize-space(md:ContactPerson[@icmd:contactType='http://id.incommon.org/metadata/contactType/security']/md:EmailAddress)"/> + + <!-- Only output if BE not met --> + <xsl:choose> + <xsl:when test="$privacyURL = '' or $logo = '' or $techContact = '' or $adminContact = '' or ($rEFEDSSecurityContact = '' and $inCommonSecurityContact = '')"> + + <xsl:choose> + <xsl:when test="$orgDisplayName != ''"> + <!-- escape literal double quotes in md:OrganizationDisplayName --> + <xsl:variable name="escapedOrgDisplayName"> + <xsl:call-template name="string-replace-all"> + <xsl:with-param name="string" select="$orgDisplayName"/> + <xsl:with-param name="search" select="$double_quote"/> + <xsl:with-param name="replace" select="$double_double_quote"/> + </xsl:call-template> + </xsl:variable> + <xsl:text>"</xsl:text> + <xsl:value-of select="$escapedOrgDisplayName"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + + <!-- output either mdui:DisplayName or md:OrganizationDisplayName or "NONE" (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$displayName != ''"> + <!-- escape literal double quotes in mdui:DisplayName --> + <xsl:variable name="escapedDisplayName"> + <xsl:call-template name="string-replace-all"> + <xsl:with-param name="string" select="$displayName"/> + <xsl:with-param name="search" select="$double_quote"/> + <xsl:with-param name="replace" select="$double_double_quote"/> + </xsl:call-template> + </xsl:variable> + <xsl:text>"</xsl:text> + <xsl:value-of select="$escapedDisplayName"/> + <xsl:text>"</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NONE</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output the IdP entityID --> + <xsl:value-of select="$field_sep" /> + <xsl:value-of select="@entityID"/> + + + <!-- output that this is an IdP entity descriptor --> + <xsl:value-of select="$field_sep" /> + <xsl:text>SP</xsl:text> + + + <!-- Severity Logic: + Serious = missing privacy statement and at least one contact + Moderate = missing either privacy statement or at least one contact + Minor = missing only the logo + --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$privacyURL = '' and ($techContact = '' or $adminContact = '' or ($rEFEDSSecurityContact = '' and $inCommonSecurityContact = ''))"> + <xsl:text>Significant</xsl:text> + </xsl:when> + <xsl:when test="$privacyURL = '' or ($techContact = '' or $adminContact = '' or ($rEFEDSSecurityContact = '' and $inCommonSecurityContact = ''))"> + <xsl:text>Moderate</xsl:text> + </xsl:when> + <xsl:when test="$logo = ''"> + <xsl:text>Minor</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>Unknown</xsl:text> + </xsl:otherwise> + </xsl:choose> + + + <!-- output either mdui:privacyURL (Yes) or (No) (in that order) --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$privacyURL != ''"> + <xsl:text>YES</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NO</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output Logo Present "TRUE" or "FALSE" --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$logo != ''"> + <xsl:text>YES</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NO</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <!-- output "Y" (complies) or "N" (does not comply) with whether all contacts are there or not --> + <xsl:value-of select="$field_sep" /> + <xsl:choose> + <xsl:when test="$techContact != '' and $adminContact != '' and ($rEFEDSSecurityContact != '' or $inCommonSecurityContact != '')"> + <xsl:text>YES</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>NO</xsl:text> + </xsl:otherwise> + </xsl:choose> + + <xsl:text>
</xsl:text> + + </xsl:when> + <!-- <xsl:otherwise>-SP-</xsl:otherwise> --> + </xsl:choose> + + </xsl:template> + + <!-- + A named template that performs global (recursive) search-and-replace on a string + (similar to fn:replace(string, pattern, replace) in XSLT 2.0). + See: http://stackoverflow.com/questions/3067113/xslt-string-replace/3067130#3067130 + --> + <xsl:template name="string-replace-all"> + <xsl:param name="string"/> + <xsl:param name="search"/> + <xsl:param name="replace"/> + <xsl:choose> + <xsl:when test="$string = '' or $search = '' or not($search)"> + <!-- Prevent this routine from hanging --> + <xsl:value-of select="$string"/> + </xsl:when> + <xsl:when test="contains($string, $search)"> + <xsl:value-of select="substring-before($string, $search)"/> + <xsl:value-of select="$replace"/> + <xsl:call-template name="string-replace-all"> + <xsl:with-param name="string" select="substring-after($string, $search)"/> + <xsl:with-param name="search" select="$search"/> + <xsl:with-param name="replace" select="$replace"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$string"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="text()"> + <!-- do nothing --> + </xsl:template> +</xsl:stylesheet>