The Shibboleth IdP V3 software has reached its End of Life and is no longer supported. This documentation is available for historical purposes only. See the IDP4 wiki space for current documentation on the supported version.

AttributeFilterConfiguration

File(s): conf/attribute-filter.xml

Format: Custom Schema

Overview

Attribute Filtering occurs between Attribute Resolution and Attribute Encoding. It is about constraining the set of attributes and/or attribute values prior to them being passed over to a relying party. In this way, you can tailor the attributes seen by a specific relying party for a specific subject. The full range of environmental information (for instance about the relying party, about the specific request, and about the subject) is available to guide the filtering process.

You can exercise and debug the behavior of this process using the AACLI tool or the web interface it uses. This is particularly helpful if you're making changes, performing upgrades, etc., to validate the results match in any given case.

Constraining attribute resolution and encoding using ActivationConditions

The attributes which are released to a relying party can be influenced by adding ActivationConditions to DataConnectors and AttributeDefinitions. This can limit the attributes available at the start of the filtering process, and can thus act as a form of filtering. Typically these activation conditions are used to avoid expensive operations which serve no purpose in a given situation. For instance you might not connect to an LDAP directory for attributes if you knew that those attributes would never be used in assertions for a specific relying party (or if the subject was not visible in that directory).

Equally ActivationConditions can be attached to AttributeEncoders. These can be used to limit the encoding an attribute into SAML under certain circumstances. This is often useful to control the format used to render a particular attribute for a particular relying party. In V2, this could only be achieved by cumbersome duplication of attributes with specific filters.

In general activation conditions should not be viewed as an alternative form of filtering. Rather they should be viewed as a way of achieving something which in V2 could only be achieved in more cumbersome ways. In most cases, it's simpler to start with "resolving everything" and by encoding attributes consistently, and use this feature for special situations.

In a typical (and default) configuration, only one XML resource is configured to supply the attribute filtering configuration, a file called attribute-filter.xml. All resources contain a "root"  <AttributeFilterPolicyGroup> element in the urn:mace:shibboleth:2.0:afp namespace.

Simple Attribute-Filter.xml file (V3.2.0 and later)
<AttributeFilterPolicyGroup id="ShibbolethFilterPolicy"
        xmlns="urn:mace:shibboleth:2.0:afp"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:mace:shibboleth:2.0:afp http://shibboleth.net/schema/idp/shibboleth-afp.xsd">

	<!-- Release some attributes to an SP. -->
    <AttributeFilterPolicy id="example1">
        <PolicyRequirementRule xsi:type="Requester" value="https://sp.example.org" />
        <AttributeRule attributeID="eduPersonPrincipalName">
            <PermitValueRule xsi:type="ANY" />
        </AttributeRule>
        <AttributeRule attributeID="uid">
            <PermitValueRule xsi:type="ANY" />
        </AttributeRule>
        <AttributeRule attributeID="mail">
            <PermitValueRule xsi:type="ANY" />
        </AttributeRule>
    </AttributeFilterPolicy>

	<!-- Release eduPersonAffiliation to two specific SPs. -->
    <AttributeFilterPolicy id="example2">
        <PolicyRequirementRule xsi:type="OR">
            <Rule xsi:type="Requester" value="https://sp.example.org" />
            <Rule xsi:type="Requester" value="https://another.example.org/shibboleth" />
        </PolicyRequirementRule>
        <AttributeRule attributeID="eduPersonScopedAffiliation">
            <PermitValueRule xsi:type="ANY" />
        </AttributeRule>
    </AttributeFilterPolicy>
</AttributeFilterPolicyGroup>

The semantics of the attribute language can be deceptive. Informally it is easy to see what is going on (for instance the last case in the example could read "If the relying party has an ID of 'https://sp.example.org' or 'https://another.example.org/shibboleth' then release all values of eduPersonScopedAffiliation". However the detailed semantics can be extremely confusing and often downright counter intuitive. This is explained in detail below. A good rule of thumb is "If it seems like a cute trick and a good idea, it isn't. Do it the obvious way."

Configuration

Formally, this is the configuration of the "AttributeFilter" service. By default, one file, attribute-filter.xml, defines the attributes and values to be passed on. Multiple files can be specified by changing the bean referred to by the property idp.service.attribute.filter.resources (default value shibboleth.AttributeFilterResource) defined in the services.xml file.

Properties

While not all that common, the attribute-filter.xml file can leverage property replacement to externalize particular settings. By default, these properties are defined in the idp.properties file. Properties are referenced via a brace syntax (e.g., %{idp.home}).

The properties which affect the filtering process are names staring with idp.service.attribute.filter as described here

Schema Name

Elements described in this page and its children are defined by the urn:mace:shibboleth:2.0:afp namespace, the schema for which can be located at http://shibboleth.net/schema/idp/shibboleth-afp.xsd

In addition, IdP versions prior to 3.2.0 used the following additional namespaces:

Use of these additional namespaces remains supported in newer versions, but is not required or advised in newer deployments, and they will be removed from V4.0. Plugin types defined in these two namespaces have corresponding types with the same, or a truncated version of, the name. The tables of legacy to current name mappings are given here.

Attribute

The  <AttributeFilterPolicyGroup> element should have an id attribute. This must be unique and is used for logging purposes.

Child Elements

The  <AttributeFilterPolicyGroup> contains a series of zero or more <AttributeFilterPolicy> elements expressing the policies that may be applied.

In V2, it was possible for other "rule" elements to appear at the top level, but this referencing/reuse feature was inconsistently implemented and is no longer supported. It should be avoided.

Semantics

During attribute filtering, the engine:

  1. Examines all the <AttributeFilterPolicyGroup> elements provided (for instance across multiple files) in an unspecified order.
  2. Examines all the <AttributeFilterPolicy> elements within each <AttributeFilterPolicyGroup>, again in an unspecified order.
  3. For each policy, if the <PolicyRequirementRule> is true:
    1. Applies each of the child <AttributeRule> elements, such that:
      1. The attributes (and their values) returned by <PermitValueRule> get added to a "permit list".
      2. The attributes (and their values) returned by <DenyValueRule> get added to a "deny list".
  4. At the end of filtering, the final results are calculated by:
    1. Populating the result initially from the permit list.
    2. Removing all attribute values found in the deny list.
    3. Removing all attributes with no values.

In this way, it can be seen that a <DenyValueRule> 'trumps' the result of a <PermitValueRule> in the manner typically found in such policy languages.

This is relatively uncontroversial, although some of the side effects of a deny rule can be surprising. For instance, denying is not the same as not permitting.

The difficulty arises in that anything that can be used in an <AttributeRule> can be used in a <PermitValueRule> or <DenyValueRule>. The fist example below is relatively obvious:

Obvious Example
<AttributeFilterPolicy id="example1">
  <PolicyRequirementRule xsi:type="Requester" value="https://sp.example.org" />
  <AttributeRule attributeID="eduPersonPrincipalName">
    <PermitValueRule xsi:type="Value" value="jsmith" ignoreCase="true" />
  </AttributeRule>
</AttributeFilterPolicy>

"If the RP is named 'https://sp.example.org', then (only) release the 'eduPersonPrincipalName' attribute value of 'jsmith'."

But the rules can be swapped:

Non-obvious Example
<AttributeFilterPolicy id="example2">
  <PolicyRequirementRule  xsi:type="Value" value="jsmith" ignoreCase="true" />
  <AttributeRule attributeID="eduPersonPrincipalName">
    <PermitValueRule xsi:type="Requester" value="https://sp.example.org" />
  </AttributeRule>
</AttributeFilterPolicy>

This is valid and has a specific meaning. But what is the meaning?

PolicyRules and Matchers

In order to make this tractable, the implementation considers plugin types as being either 'PolicyRules' or 'Matchers'. PolicyRules can be expected to give a "yes/no" answer and are usually used within a <PolicyRequirementRule>. Matchers usually return sets of values when applied to an attribute and are usually used within an <AttributeRule>.

The rules used are as follows:

  • If a Matcher is specified inside a <PolicyRequirementRule>, then if the plugin returns a value when applied to any of the input attributes then it is taken as being true, otherwise it is taken as being false.
  • If a PolicyRule is specified inside an <AttributeRule>, then if the plugin returns true then all the values of the attribute concerned are returned (and added to the permit or deny list, as appropriate for the containing rule).

To confuse the issue further:

  • The logic rules (and, or, not), which are natural PolicyRules have specific semantics when they are being used inside Matcher rules
  • Some value-based rules change from being Matchers to being PolicyRules when the attributeId attribute is specified.
    So <...xsi:type="Value" value="jsmith" ignoreCase="true" /> is a Matcher (return all values which case-insensitively match "jsmith"), but <...xsi:type="Value" value="jsmith" ignoreCase="true" attributeId="uid" /> is a PolicyRule (true if and only if there is an attribute called "uid" with a value which case-insensitively matches jsmith).

So to answer the question above, the non-obvious second example means "If any value of any attribute matches 'jsmith' in a case-insensitive manner, then release all values of 'eduPersonPrincipalName' if the name of the SP is 'https://sp.example.org'". This is intelligible, but probably useless in practice. Most "swaps" of plugin types result in similar meaning.

Once compounded with NOT and deny rules, working out what is going on becomes incredibly non-intuitive. A good guiding rule is to only ever use PolicyRules inside <PolicyRequirementRule> and to only use Matchers inside <AttributeRule>.

Error handling

Because of the dangers of the NOT plugin, it becomes impossible for any particular rule to "do the right thing" if a failure occurs during processing. The filtering engine handles this by special-casing errors to the fail-safe (release nothing) case.