Skip to content

Instantly share code, notes, and snippets.

@trscavo
Last active November 12, 2017 23:12
Show Gist options
  • Save trscavo/a269860955c7f024c3a709fa998db6fa to your computer and use it in GitHub Desktop.
Save trscavo/a269860955c7f024c3a709fa998db6fa to your computer and use it in GitHub Desktop.
Flatten entity endpoints in a SAML metadata aggregate
<?xml version="1.0" encoding="UTF-8"?>
<!--
list_all_entity_endpoints_txt.xsl
This XSL transform takes a SAML V2.0 metadata file as input.
The script matches on every md:EntityDescriptor element in the
input. It then flattens all endpoints in metadata by returning lines
of output consisting of the following space-separated fields:
roleDescriptor endpointType binding location entityID registrarID
where roleDescriptor is one of the following:
IDPSSODescriptor
SPSSODescriptor
AttributeAuthorityDescriptor
and endpointType indicates the type of endpoint:
SingleSignOnService
SingleLogoutService
ArtifactResolutionService
AssertionConsumerService
DiscoveryResponse
RequestInitiator
AttributeService
For example, the roleDescriptor and the endpointType might be
'IDPSSODescriptor' and 'SingleSignOnService', respectively, in
which case the endpoint is a so-called IdP SSO endpoint.
Among other things, this script may be used to produce a list of
entityIDs of entities containing non-unique bindings in non-indexed
endpoints. For example, here's how to check the SingleSignOnService
endpoints in IdP metadata:
$ cat $MD_PATH \
| xsltproc /path/to/list_all_entity_endpoints_txt.xsl - \
| grep '^IDPSSODescriptor SingleSignOnService' \
| cut -f3,5 -d" " \
| uniq -d
Other non-indexed endpoints may be similarly checked.
Note that this script lists both indexed and non-indexed endpoints.
To list indexed endpoints only, and to include the index value in
the output, use: list_all_entity_endpoints_indexed_txt.xsl
-->
<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:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi"
xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol"
xmlns:init="urn:oasis:names:tc:SAML:profiles:SSO:request-init">
<!-- output is plain text -->
<xsl:output method="text"/>
<xsl:template match="//md:EntityDescriptor">
<xsl:variable name="entityID" select="./@entityID"/>
<xsl:variable name="registrarID" select="./md:Extensions/mdrpi:RegistrationInfo/@registrationAuthority"/>
<xsl:for-each select="./md:IDPSSODescriptor">
<xsl:for-each select="./md:SingleSignOnService">
<xsl:text>IDPSSODescriptor SingleSignOnService </xsl:text>
<xsl:value-of select="./@Binding"/>
<xsl:text> </xsl:text>
<xsl:value-of select="./@Location"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$entityID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$registrarID"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
<xsl:for-each select="./md:SingleLogoutService">
<xsl:text>IDPSSODescriptor SingleLogoutService </xsl:text>
<xsl:value-of select="./@Binding"/>
<xsl:text> </xsl:text>
<xsl:value-of select="./@Location"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$entityID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$registrarID"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
<xsl:for-each select="./md:ArtifactResolutionService">
<xsl:text>IDPSSODescriptor ArtifactResolutionService </xsl:text>
<xsl:value-of select="./@Binding"/>
<xsl:text> </xsl:text>
<xsl:value-of select="./@Location"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$entityID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$registrarID"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
</xsl:for-each>
<xsl:for-each select="./md:SPSSODescriptor">
<xsl:for-each select="./md:AssertionConsumerService">
<xsl:text>SPSSODescriptor AssertionConsumerService </xsl:text>
<xsl:value-of select="./@Binding"/>
<xsl:text> </xsl:text>
<xsl:value-of select="./@Location"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$entityID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$registrarID"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
<xsl:for-each select="./md:SingleLogoutService">
<xsl:text>SPSSODescriptor SingleLogoutService </xsl:text>
<xsl:value-of select="./@Binding"/>
<xsl:text> </xsl:text>
<xsl:value-of select="./@Location"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$entityID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$registrarID"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
<xsl:for-each select="./md:ArtifactResolutionService">
<xsl:text>SPSSODescriptor ArtifactResolutionService </xsl:text>
<xsl:value-of select="./@Binding"/>
<xsl:text> </xsl:text>
<xsl:value-of select="./@Location"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$entityID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$registrarID"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
<xsl:for-each select="./md:Extensions/idpdisc:DiscoveryResponse">
<xsl:text>SPSSODescriptor DiscoveryResponse </xsl:text>
<xsl:value-of select="./@Binding"/>
<xsl:text> </xsl:text>
<xsl:value-of select="./@Location"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$entityID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$registrarID"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
<xsl:for-each select="./md:Extensions/init:RequestInitiator">
<xsl:text>SPSSODescriptor RequestInitiator </xsl:text>
<xsl:value-of select="./@Binding"/>
<xsl:text> </xsl:text>
<xsl:value-of select="./@Location"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$entityID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$registrarID"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
</xsl:for-each>
<xsl:for-each select="./md:AttributeAuthorityDescriptor">
<xsl:for-each select="./md:AttributeService">
<xsl:text>AttributeAuthorityDescriptor AttributeService </xsl:text>
<xsl:value-of select="./@Binding"/>
<xsl:text> </xsl:text>
<xsl:value-of select="./@Location"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$entityID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$registrarID"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()">
<!-- do nothing -->
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment