Skip to content

Commit

Permalink
Add scope injection from members.xml to the aggregator version of the…
Browse files Browse the repository at this point in the history
… UK federation flows.

Requires a bump to the spring-extensions library snapshot.
  • Loading branch information
iay committed Jun 10, 2011
1 parent cb60225 commit 9520c38
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 12 deletions.
135 changes: 135 additions & 0 deletions mdx/uk/scopes.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
scopes.xsl
XSL stylesheet that handles the UK federation's approach to Shibboleth
scope extensions.
-->
<xsl:stylesheet version="1.0"
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:members="http://ukfederation.org.uk/2007/01/members"
xmlns:shibmeta="urn:mace:shibboleth:metadata:1.0"

xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="members">

<!--Force UTF-8 encoding for the output.-->
<xsl:output omit-xml-declaration="no" method="xml" encoding="UTF-8" indent="yes"/>

<!--
The "members" document is passed in as a parmeter; extract outsourced scope lists from it.
-->
<xsl:param name="membersDocument"/>
<xsl:variable name="outsourcedScopes"
select="$membersDocument//members:Member/members:Scopes[members:Entity]"/>

<!--
Extend the scope list contained within an IdP's entity-level Extensions element
with any outsourced scopes provided by the member list.
-->
<xsl:template match="md:EntityDescriptor[md:IDPSSODescriptor]/md:Extensions">
<xsl:copy>
<!-- copy everything from within the original element -->
<xsl:apply-templates select="node()"/>
<!-- copy scopes from member outsource records -->
<xsl:variable name="entityID" select="ancestor::md:EntityDescriptor/@entityID"/>
<xsl:for-each select="$outsourcedScopes[members:Entity = $entityID]/members:Scope">
<xsl:text> </xsl:text>
<xsl:element name="shibmeta:Scope">
<xsl:attribute name="regexp">false</xsl:attribute>
<xsl:value-of select="."/>
</xsl:element>
<xsl:text>&#10; </xsl:text>
</xsl:for-each>
</xsl:copy>
</xsl:template>

<!--
If an IdP's SSO or AA roles are missing Extensions (and Scope extensions in
particular) then manufacture them as a combination of the EntityDescriptor's
overall scope extensions and any outsourced scopes provided by the member list.
-->
<xsl:template match="md:IDPSSODescriptor[not(md:Extensions)] |
md:AttributeAuthorityDescriptor[not(md:Extensions)]">
<xsl:copy>
<xsl:variable name="entityID" select="ancestor::md:EntityDescriptor/@entityID"/>
<xsl:apply-templates select="@*"/>
<xsl:text>&#10; </xsl:text>
<xsl:element name="Extensions" namespace="urn:oasis:names:tc:SAML:2.0:metadata">
<!-- copy scopes from EntityDescriptor extensions -->
<xsl:for-each select="ancestor::md:EntityDescriptor/md:Extensions/shibmeta:Scope">
<xsl:text>&#10; </xsl:text>
<xsl:copy-of select="."/>
</xsl:for-each>
<!-- copy scopes from member outsource records -->
<xsl:for-each select="$outsourcedScopes[members:Entity = $entityID]/members:Scope">
<xsl:text>&#10; </xsl:text>
<xsl:element name="shibmeta:Scope">
<xsl:attribute name="regexp">false</xsl:attribute>
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
<xsl:text>&#10; </xsl:text>
</xsl:element>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>

<!--
If an IdP's SSO or AA roles already includes an Extensions element, this may
already contain extensions other than scopes. We need to make sure that
if it does not also contain scopes, then any scopes declared at the entity
level are copied down, and any outsourced scopes provided by the member
list are imported.
-->
<xsl:template match="md:IDPSSODescriptor/md:Extensions |
md:AttributeAuthorityDescriptor/md:Extensions">
<xsl:copy>
<xsl:variable name="entityID" select="ancestor::md:EntityDescriptor/@entityID"/>
<xsl:apply-templates select="node()"/>
<xsl:if test="not(shibmeta:Scope)">
<!-- copy scopes from EntityDescriptor extensions -->
<xsl:for-each select="ancestor::md:EntityDescriptor/md:Extensions/shibmeta:Scope">
<xsl:text> </xsl:text>
<xsl:copy-of select="."/>
<xsl:text>&#10; </xsl:text>
</xsl:for-each>
<!-- copy scopes from member outsource records -->
<xsl:for-each select="$outsourcedScopes[members:Entity = $entityID]/members:Scope">
<xsl:text> </xsl:text>
<xsl:element name="shibmeta:Scope">
<xsl:attribute name="regexp">false</xsl:attribute>
<xsl:value-of select="."/>
</xsl:element>
<xsl:text>&#10; </xsl:text>
</xsl:for-each>
</xsl:if>
</xsl:copy>
</xsl:template>

<!--
*********************************************
*** ***
*** D E F A U L T T E M P L A T E S ***
*** ***
*********************************************
-->


<!--By default, copy text blocks, comments and attributes unchanged.-->
<xsl:template match="text()|comment()|@*">
<xsl:copy/>
</xsl:template>

<!--By default, copy all elements from the input to the output, along with their attributes and contents.-->
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>
19 changes: 19 additions & 0 deletions mdx/uk/uk-beans.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

<!--
membersResource
A Resource referencing the members.xml document.
-->
<bean id="membersResource" class="org.opensaml.util.resource.FilesystemResource" lazy-init="true">
<constructor-arg value="#{ systemProperties['basedir'] }/xml/members.xml"/>
</bean>

<!--
membersDocument
This bean contains the contents of the members.xml file as a DOM Document.
-->
<bean id="membersDocument" class="net.shibboleth.ext.spring.factory.DomDocumentFactoryBean" lazy-init="true">
<property name="documentResource" ref="membersResource"/>
<property name="parserPool" ref="parserPool"/>
</bean>

<!--
members
Expand Down
75 changes: 63 additions & 12 deletions mdx/uk/uk-collect.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,15 @@
<import resource="uk-beans.xml"/>

<!--
filterDeletedEntities
fetchUkFragmentFiles
Remove entity items which have the ukfedlabel:DeletedEntity label on them.
This convention will be replaced at some point by the files not being available
for collection in the first place.
Collects all the UK metadata "fragment files" from the /entities directory.
Each fragment file contains a single EntityDescriptor. The name of each
eligible file matches a particular regular expression.
-->
<bean id="filterDeletedEntities" class="net.shibboleth.metadata.dom.XPathFilteringStage"
init-method="initialize" lazy-init="true">
<property name="id" value="filterDeletedEntities"/>
<constructor-arg name="expression" value="//ukfedlabel:DeletedEntity"/>
<constructor-arg name="prefixMappings" ref="commonNamespaces"/>
</bean>

<bean id="fetchUkFragmentFiles" class="net.shibboleth.metadata.dom.DomFilesystemSourceStage"
init-method="initialize" lazy-init="true">
init-method="initialize">
<property name="id" value="fetchUkFragmentFiles"/>
<property name="parserPool" ref="parserPool"/>
<property name="source">
Expand All @@ -49,6 +43,52 @@
</property>
</bean>

<!--
filterDeletedEntities
Remove entity items which have the ukfedlabel:DeletedEntity label on them.
This convention will be replaced at some point by the files not being available
for collection in the first place.
-->
<bean id="filterDeletedEntities" class="net.shibboleth.metadata.dom.XPathFilteringStage"
init-method="initialize">
<property name="id" value="filterDeletedEntities"/>
<constructor-arg name="expression" value="//ukfedlabel:DeletedEntity"/>
<constructor-arg name="prefixMappings" ref="commonNamespaces"/>
</bean>

<!--
processScopes
This stage normalises scope handling in two ways particular to the UK
federation:
* we make all three potential scope lists equivalent (on the entity, on
the IDPSSODescriptor and on the AttributeAuthority)
* we inject scopes "pushed" to entities from the members.xml file
This transform can be run on individual EntityDescriptors or on an
aggregate EntitiesDescriptor.
-->
<bean id="processScopes" class="net.shibboleth.metadata.dom.XSLTransformationStage"
init-method="initialize">
<property name="id" value="processScopes"/>
<property name="xslResource">
<bean class="org.opensaml.util.resource.FilesystemResource">
<constructor-arg value="#{ systemProperties['basedir'] }/mdx/uk/scopes.xsl"/>
</bean>
</property>
<property name="transformParameters">
<map>
<entry key="membersDocument" value-ref="membersDocument"/>
</map>
</property>
</bean>

<!--
pipeline
-->
<bean id="pipeline" class="net.shibboleth.metadata.pipeline.SimplePipeline">
<property name="id" value="pipeline"/>
<property name="stages">
Expand All @@ -59,6 +99,17 @@
<ref bean="CHECK.std"/>
<ref bean="errorAnnouncingFilter"/><!-- should be fatal -->
<ref bean="assemble"/>

<!--
Process scopes on the entities. Because the transform performs
a fairly heavyweight extraction operation on the members document
before applying the results, this is best done on the resulting
aggregate so that the extraction happens only once.
A better long-term alternative would be to build support for
this on a per-entity or per-owner basis into the Members bean.
-->
<ref bean="processScopes"/>

<!--
It's much faster to run this check on the EntitiesDescriptor because it
Expand Down

0 comments on commit 9520c38

Please sign in to comment.