Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Expand
titleHow to add an ID attribute to the root EntitiesDescriptor element.

The following example adds an attribute 'ID' to the root element (e.g.< EntitiesDescriptor> element) of a SAML metadata file. Strictly speaking, such an ID is required to correctly identify the node whose signature shall be checked. The ID can be any any random identifier but one reasonable convention is to make it a speaking identifier that contains the federation name and a timestamp of the date where the metadata file was created. The example below implements this recommendation by adding for example an ID attribute of the form ID="SWITCHaai-20140116160314".

Example provided by SWITCH.

Step 1: Create a new file add-root-id-attribute.xsl in the etc directory of your MDA instance.

Code Block
languagehtml/xml
titleadd-root-id-attribute.xsl
firstline1
linenumberstrue
collapsetrue
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
    xmlns:date="http://exslt.org/dates-and-times"
    extension-element-prefixes="date">
<!--
    Add attribute 'ID' to root element (EntitiesDescriptor).
    The value of this attribute has the form ID="SWITCHaai-yyyymmddhhiiss"
    where the last component is a time stamp of the current time.
    
    This value is generated from a normalised version of the aggregation instant,
    transformed so that it can be used as an XML ID value.
    
    Strict conformance to the SAML 2.0 metadata specification (section 3.1.2) requires
    that the signature explicitly references an identifier attribute in the element
    being signed, in this case the document element.
-->
<xsl:param name="prefix">Interfederation</xsl:param>
<xsl:variable name="documentID" select="concat($prefix, '-', translate(substring-before(date:date-time(),'+'),'-T:',''))"/>

    <!-- Add the attribute 'ID' -->
    <xsl:template match="/md:EntitiesDescriptor">
        <xsl:copy>
            <xsl:attribute name="ID">
                <xsl:value-of select="$documentID"/>
            </xsl:attribute>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- Identity template for copying everything else -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" /> 
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Step 2: Add the following beans to the MDA configuration file that is used to process metadata.

  • Make sure to adapt the path to the file created in step 1. In this example the path is assumed to be '/opt/mda/etc/add-root-id-attribute.xsl'.
  • Adapt the value of the RootIDPrefix bean. The value in the current example will generate for example: ID="SWITCHaai-20140116160314"
  • Make sure to add the bean reference (<ref bean="addIDAttribute" />) as a stage to the metadata processing pipeline, as is shown in the example.
Code Block
languagehtml/xml
titleconfig.xml
firstline1
linenumberstrue
collapsetrue
<!-- Path to XSLT file -->
<bean id="xslTransformationAddRootIDAttribute" class="java.lang.String">
    <constructor-arg value="/opt/mda/etc/add-root-id-attribute.xsl" />
</bean>

<!-- Prefix string to add to the ID attribute value before the timestamp -->
<bean id="RootIDPrefix" class="java.lang.String">
   <constructor-arg value="SWITCHaai"/>
</bean>

<!--
    Pipeline which adds an 'ID' attribute to the root EntitiesDescriptor element.
    The attribute has the form "Interfederation-yymmddhhiiss" where the timestamp
    is the time when the metadata was aggregated and signed.
-->
<bean id="addIDAttribute" class="net.shibboleth.metadata.dom.XSLTransformationStage" p:id="addIDAttribute">
    <property name="xslResourceXSLResource">
        <bean class="net.shibboleth.utilities.java.support.resource.FilesystemResource">
            <constructor-arg ref="xslTransformationAddRootIDAttribute" />
        </bean>
    </property>
     <property name="transformParameters">
        <map>
            <entry key="prefix" value-ref="RootIDPrefix"/>
        </map>
    </property>
</bean>

<!-- Example of a pipeline with several processing stages -->
<bean id="outputAll" class="net.shibboleth.metadata.pipeline.SimplePipeline"
    p:id="outputAll" >
    <property name="stages">
        <util:list>
            <ref bean="buildEntitiesDecriptor" />
			
			<!-- Add the bean reference to the addIDAttribute bean as a stage -->
            <ref bean="addIDAttribute" />

            <ref bean="addValidUntil" />
            <ref bean="serializeAll" />
        </util:list>
    </property>
</bean>