1 <?xml version="1.0" encoding="UTF-8"?>
6 XSL stylesheet converting a Shibboleth 1.2 sites file into the equivalent for
7 Shibboleth 1.3, which is based on the SAML 1.1 profile of the SAML 2.0
8 metadata format. No attempt is made to incorporate the separate trust
9 data used by Shibboleth 1.2.
11 Author: Ian A. Young <ian@iay.org.uk>
15 <xsl:stylesheet version="1.0"
16 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
17 xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
18 xmlns:shib="urn:mace:shibboleth:1.0"
19 xmlns:shibmeta="urn:mace:shibboleth:metadata:1.0"
20 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21 xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
22 exclude-result-prefixes="shib">
25 Version information for this file. Remember to peel off the dollar signs
26 before dropping the text into another versioned file.
28 <xsl:param name="cvsId">$Id$</xsl:param>
31 Add a comment to the start of the output file.
33 <xsl:template match="/">
35 <xsl:text> 	***DO NOT EDIT THIS FILE*** </xsl:text>
36 <xsl:text>	Converted by: 	</xsl:text>
37 <xsl:value-of select="substring-before(substring-after($cvsId, ': '), '$')"/>
38 <xsl:text> </xsl:text>
40 <xsl:apply-templates/>
43 <!--Force UTF-8 encoding for the output.-->
44 <xsl:output omit-xml-declaration="no" method="xml" encoding="UTF-8" indent="yes"/>
47 SiteGroup is the root element for the sites file. The corresponding element in the new format file
48 is an EntitiesDescriptor.
50 <xsl:template match="shib:SiteGroup">
51 <EntitiesDescriptor Name="{@Name}">
52 <xsl:attribute name="xsi:schemaLocation">
53 <xsl:text>urn:oasis:names:tc:SAML:2.0:metadata sstc-saml-schema-metadata-2.0.xsd </xsl:text>
54 <xsl:text>urn:mace:shibboleth:metadata:1.0 shibboleth-metadata-1.0.xsd </xsl:text>
55 <xsl:text>http://www.w3.org/2000/09/xmldsig# xmldsig-core-schema.xsd</xsl:text>
58 Pass through text blocks and comments, and any shib elements.
59 These may be: OriginSite, DestinationSite or nested SiteGroup.
61 <xsl:apply-templates select="text()|comment()|shib:*"/>
66 Map OriginSite to an EntityDescriptor with a particular format.
68 <xsl:template match="shib:OriginSite">
69 <EntityDescriptor entityID="{@Name}">
71 Copy through comments and text blocks at the start of the output element.
72 This means we don't lose comments, but there is no way to guarantee they will
73 come out "in the right place".
75 <xsl:apply-templates select="text()|comment()"/>
77 Map HandleService and AttributeAuthority. We need to pass in the (possibly empty)
78 set of Domain elements as a parameter.
80 <xsl:apply-templates select="shib:HandleService|shib:AttributeAuthority">
81 <xsl:with-param name="Domain" select="shib:Domain"/>
82 </xsl:apply-templates>
83 <xsl:call-template name="Alias"/>
84 <xsl:apply-templates select="shib:Contact"/>
89 Map HandleService to IDPSSODescriptor.
91 <xsl:template match="shib:HandleService">
92 <xsl:param name="Domain"/>
93 <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:mace:shibboleth:1.0">
95 Extensions appears iff there is something to put in it.
97 <xsl:if test="boolean($Domain)">
99 <xsl:apply-templates select="$Domain"/>
102 <KeyDescriptor use="signing">
105 <xsl:value-of select="@Name"/>
109 <SingleSignOnService Binding="urn:mace:shibboleth:1.0:profiles:AuthnRequest"
110 Location="{@Location}"/>
115 Map AttributeAuthority to AttributeAuthorityDescriptor.
117 <xsl:template match="shib:AttributeAuthority">
118 <xsl:param name="Domain"/>
119 <AttributeAuthorityDescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol">
121 Extensions appears iff there is something to put in it.
123 <xsl:if test="boolean($Domain)">
125 <xsl:apply-templates select="$Domain"/>
128 <AttributeService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding"
129 Location="{@Location}"/>
130 </AttributeAuthorityDescriptor>
134 Map Domain to a Scope extension.
136 <xsl:template match="shib:Domain">
138 <xsl:apply-templates select="@regexp"/>
139 <xsl:value-of select="."/>
144 Map DestinationSite to an EntityDescriptor with a particular format.
146 <xsl:template match="shib:DestinationSite">
147 <EntityDescriptor entityID="{@Name}">
149 Copy through comments and text blocks at the start of the output element.
150 This means we don't lose comments, but there is no way to guarantee they will
151 come out "in the right place".
153 <xsl:apply-templates select="text()|comment()"/>
155 Generate IDPSSODescriptor.
157 <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol">
159 Map @ErrorURL (if present) to @errorURL
161 <xsl:apply-templates select="@ErrorURL"/>
163 Map AttributeRequester elements to KeyDescriptor elements.
165 <xsl:apply-templates select="shib:AttributeRequester"/>
167 Map the AssertionConsumerServiceURL elements to
168 AssertionConsumerService elements. The latter require unique
169 integer indices, so do this by looping over them and using
170 position in the loop to generate each index.
172 <xsl:for-each select="shib:AssertionConsumerServiceURL">
173 <xsl:apply-templates select=".">
174 <xsl:with-param name="index" select="position()-1"/>
175 </xsl:apply-templates>
178 <xsl:call-template name="Alias"/>
179 <xsl:apply-templates select="shib:Contact"/>
184 Map @ErrorURL to @errorURL
186 <xsl:template match="@ErrorURL">
187 <xsl:attribute name="errorURL"><xsl:value-of select="."/></xsl:attribute>
191 Map AttributeRequester to KeyDescriptor.
193 <xsl:template match="shib:AttributeRequester">
197 <xsl:value-of select="@Name"/>
204 Map AssertionConsumerServiceURL to AssertionConsumerService.
206 <xsl:template match="shib:AssertionConsumerServiceURL">
207 <xsl:param name="index"/>
208 <AssertionConsumerService index="{$index}"
209 Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="{@Location}"
214 Named template to map a set of Alias elements to a corresponding Organization.
216 <xsl:template name="Alias">
217 <xsl:if test="boolean(shib:Alias)">
219 <xsl:apply-templates select="shib:Alias" mode="OrganizationName"/>
220 <xsl:apply-templates select="shib:Alias" mode="OrganizationDisplayName"/>
221 <xsl:apply-templates select="shib:Alias" mode="OrganizationURL"/>
227 Map Alias to OrganizationName
229 <xsl:template match="shib:Alias" mode="OrganizationName">
231 <xsl:call-template name="copyXmlLang"/>
232 <xsl:value-of select="."/>
237 Map Alias to OrganizationDisplayName
239 <xsl:template match="shib:Alias" mode="OrganizationDisplayName">
240 <OrganizationDisplayName>
241 <xsl:call-template name="copyXmlLang"/>
242 <xsl:value-of select="."/>
243 </OrganizationDisplayName>
247 Map Alias to OrganizationURL
249 <xsl:template match="shib:Alias" mode="OrganizationURL">
251 <xsl:call-template name="copyXmlLang"/>
252 <!-- there is nothing to map, but the URL is mandatory -->
253 <xsl:text>http://www.example.com/</xsl:text>
258 Copy an xml:lang attribute, or default to "en" if none present.
260 <xsl:template name="copyXmlLang">
261 <xsl:if test="boolean(@xml:lang)">
262 <xsl:attribute name="xml:lang"><xsl:value-of select="@xml:lang"/></xsl:attribute>
264 <xsl:if test="not(boolean(@xml:lang))">
265 <xsl:attribute name="xml:lang">en</xsl:attribute>
270 Map Contact to ContactPerson
272 <xsl:template match="shib:Contact">
273 <ContactPerson contactType="{@Type}">
275 There is no real mapping for the Name attribute, so we rather arbitrarily
276 dump that into GivenName rather than trying to split it into a GivenName and
277 a SurName or something complicated like that.
280 <xsl:value-of select="@Name"/>
283 E-mail address, but only if it was present in the original.
285 <xsl:apply-templates select="@Email" mode="Contact"/>
290 E-mail address for Contact
292 <xsl:template match="@Email" mode="Contact">
294 <xsl:value-of select="."/>
299 By default, copy referenced attributes through unchanged.
301 <xsl:template match="@*">
302 <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
306 By default, copy comments through to the output unchanged, but strip extra text.
308 <xsl:template match="comment()">
311 <xsl:template match="text()"/>