PredicateMetadataFilter

Namespace: urn:mace:shibboleth:2.0:metadata
Schema: http://shibboleth.net/schema/idp/shibboleth-metadata.xsd

Overview

The Predicate metadata filter applies an include or exclude rule to each entity in the input if a supplied Predicate<EntityDescriptor> returns true. The predicate may be defined explicitly (via the conditionRef attribute) or implicitly from the child elements.

Filter order is important!

This filter changes the content of the metadata and so a filter of type Predicate should appear after any https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631654 in the overall sequence of filters.

Reference

Name

Type

Default

Description

Name

Type

Default

Description

direction

"include" or "exclude"



This attribute must be set to either "include" or "exclude".

If set to "include", then all entities that match the predicate are included in the result (all other entities are excluded).

If set to "exclude", then all entities that match the predicate are excluded from the result (all other entities are included).

conditionRef

Bean ID



If present, the value of this attribute is the Spring Bean ID of a Predicate<EntityDescriptor> to execute on each entity in the metadata being filtered.

If this attribute is not present, then the child elements are used to construct an implicit predicate as described below.

trim

Boolean



This attribute is required if a <Tag> element appears; it controls whether leading and trailing whitespace is to be stripped from the each <Tag> element's content

removeEmptyEntitiesDescriptors

Boolean

true

If the value of this attribute is true, then any <EntitiesDescriptor> element that becomes empty as a result of the filter is removed

If the conditionRef attribute is specified, then only it is used and any child elements are ignored. Otherwise the condition is constructed as one that returns true if:

  • The entityID of the candidate matches any of the supplied <Entity> elements OR

  • The Name of any ancestor <md:EntitiesDescriptor> element for the candidate matches any of the supplied <Group> child elements OR

  • Any <mdattr:EntityAttributes> extension elements associated with the candidate match the supplied <Tag> child elements OR

  • Any scripts designated by a <ConditionScript> element return true

 

Name

Cardinality

Description

Name

Cardinality

Description

<Entity>

0 or more

The content of this element is an entity ID. If the content matches a candidate entity's entityID, then the condition is true.

<Group>

0 or more

The content of this element is the Name of an <md:EntitiesDescriptor> element. If the content matches a candidate's surrounding group names, then the condition is true.

<Tag>

0 or more

The (required) attribute 'name' provides the <saml:Attribute> Name to match,
The (optional) attribute 'nameFormat' specifies the <saml:Attribute> NameFormat to match. If not specified (or set to urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified), then all formats match.

The content of this element is a series of one or more <Value> elements whose contents specify a specific <saml:AttributeValue> to match (which may be trimmed in accordance with the trim attribute mentioned above).

(See example below.)

<ConditionScript>

0 or more

The content of this element is an inline or local script resource that implements Predicate<EntityDescriptor>

Examples

Include a single entity

The following simple example includes at most one entity. This filter intentionally prevents new or unexpected entities from appearing in the metadata feed.

Include a single entity
1 2 3 <MetadataFilter xsi:type="Predicate" direction="include" removeEmptyEntitiesDescriptors="true"> <Entity>https://sp.example.org/trusted-sp</Entity> </MetadataFilter>

Exclude all entities containing a particular entity attribute

The next example excludes all entities containing a particular entity attribute, presumably because the IdP is the sole authority for this attribute.

Exclude all entities containing an unauthorized entity attribute
1 2 3 4 5 <MetadataFilter xsi:type="Predicate" direction="exclude" removeEmptyEntitiesDescriptors="true" trim="true"> <Tag name="http://macedir.org/entity-category" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <Value>http://idp.example.org/local-category</Value> </Tag> </MetadataFilter>

Note that implicit conditions may be combined in logical OR fashion. For instance, if any of the conditions in the following example are true, the entity is excluded:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 <MetadataFilter xsi:type="Predicate" direction="exclude" removeEmptyEntitiesDescriptors="true" trim="true"> <Entity>https://sp.example.org/untrusted-sp</Entity> <Tag name="http://macedir.org/entity-category" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <Value>http://idp.example.org/local-category-one</Value> <Value>http://idp.example.org/local-category-two</Value> </Tag> <Tag name="http://idp.example.org/entity-category" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <Value>http://idp.example.org/local-category-three</Value> </Tag> </MetadataFilter>

Reference

The name "http://macedir.org/entity-category" used in the above examples is a standard entity attribute name. For reference, consult the following specification: The Entity Category SAML Attribute Types

Include all entities based on a regexp applied to the entityID

The core of this is the RegexPredicate. However this takes a string, rather than an EntityID and so we need to navigate to it.  We could of course use jacascript, but the Spring EL Predicate provides a better shorthand.  One injects the RegexPredicate to do the work and use Spring EL to do the navigation.  The result is this Spring Segment

Regexp predicate
1 2 3 4 <bean id="the.Metadata.regexp.Pred" class="net.shibboleth.utilities.java.support.logic.RegexPredicate" c:_0="^.*sp1.*" /> <bean id="the.Metadata.Pred" class="net.shibboleth.ext.spring.util.SpringExpressionPredicate" p:customObject-ref="the.Metadata.regexp.Pred" c:expression="#custom.apply(#input.getEntityID())" />

Exclude "roleless" entity descriptors

Recall that the following EntityRoleWhiteList filter retains all <md:SPSSODescriptor> elements in the input:

Retain SP roles only
1 2 3 <MetadataFilter xsi:type="EntityRoleWhiteList" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"> <RetainedRole>md:SPSSODescriptor</RetainedRole> </MetadataFilter>

The previous filter essentially filters all non-SP role descriptors from the input. At the end of that process, if an empty entity descriptor remains (because all of its roles have been removed), the entity itself is removed.

Unfortunately the EntityRoleWhiteList filter may not handle affiliation descriptors as expected. Specifically, an <md:EntityDescriptor> element that contains an <md:AffiliationDescriptor> child element is handled in exactly the same way as an <md:EntityDescriptor> element that contains no role descriptors. That is, if removeRolelessEntityDescriptors is true (which it is by default), both are removed from the input.

A quick fix that preserves any affiliation descriptors in the input is to set removeRolelessEntityDescriptors to false on the EntityRoleWhiteList filter. However, this also prevents truly “roleless” entity descriptors from being removed, which may have a negative impact on memory utilization. A workaround is to use both an EntityRoleWhiteList filter and a Predicate filter, in sequence.

The following filter sequence is a complete replacement for the above EntityRoleWhiteList filter:

Retain SP roles while preserving affiliation descriptors
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <!-- retain SPs only but don’t remove “roleless” entity descriptors --> <MetadataFilter xsi:type="EntityRoleWhiteList" removeRolelessEntityDescriptors="false" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">     <RetainedRole>md:SPSSODescriptor</RetainedRole> </MetadataFilter> <!-- clean up the mess made by the EntityRoleWhiteList filter --> <MetadataFilter xsi:type="Predicate" direction="exclude" removeEmptyEntitiesDescriptors="true"> <ConditionScript> <Script> <![CDATA[ // an implementation of Predicate<EntityDescriptor> // // if the predicate function returns true, the entity descriptor // is excluded from the output (since direction="exclude"). // // the input argument is of type: // org.opensaml.saml.saml2.metadata.EntityDescriptor // (function (entity) { "use strict"; // check the parameter if (entity === null) { return false; } // preserve an affiliation descriptor if (entity.getAffiliationDescriptor() !== null) { return false; } // exclude a "roleless" entity descriptor return entity.getRoleDescriptors() === null; }(input)); ]]> </Script> </ConditionScript> </MetadataFilter>

Note that removeRolelessEntityDescriptors is set to false on the EntityRoleWhiteList filter, which runs first. The Predicate filter then removes the “roleless” entity descriptors from its input without disturbing the affiliation descriptors (if any).