AttributeFilter

The IdP's Attribute Filtering Engine is a policy engine that determines what information, expressed as attributes as described in the Attribute Resolver design document, is released by the IdP. This gives the author of the filtering policies the power to permit or deny the release of information regardless of what a requester may have asked for.

Anatomy of an Attribute Filter Policy

An attribute filter policy contains:

  1. an ID to identify the policy

  2. a policy requirement rule to determine if the policy applies to an attribute filter context

  3. attribute rules to permit or deny the release of attribute values

Anatomy of an Attribute Rule

An attribute rule contains:

  1. the ID of the attribute the rule applies to

  2. a matching function operating on the values

Rules may be for permitting values (releasing the values for which the matching function evaluates true) and denying values (blocking the values for which the matching function evaluates true).

The Filtering Process

The attribute filtering process is invoked with a given collection of attributes (probably having come from the attribute resolver) and proceeds as follows:

For every attribute filter policy loaded in to the engine:

  1. The policy requirement rule is evaluated. If the requirement rule is met, processing continues.

  2. For each attribute value filter within the policy

    1. the attribute referenced by the attribute value filter is looked up, if the attribute is present processing continues

    2. the value matching function is executed against the values of the attribute

    3. the matching attribute values are recorded as either values to be permitted or denied based on the value filter's flag

Once all of the filter policies have been processed then, for every attribute provided when the filtering engine was invoked

  1. All values which are not marked as permitted or which are specifically denied are removed.

  2. Any attributes which contain no values are removed from the collection

There are a couple things to note about this process. First, the value set of an attribute is not adjusted until the end of the filtering process is complete. This means that all policy requirement rules and attribute value filters operate on the full, unfiltered, set of values for attributes. Second, only those values that explicitly permitted and not denied are released by the filter engine. If a value is never matched by an attribute value filter it will never be released.

Separating <PolicyRequirementRule/> from <AttributeRule/>

When the filtering syntax was introduced, many different rules were implemented. Some were more applicable to policy rules (for instance AttributeRequesterString) and some were more applicable to attributes rules (for instance AttributeValueRegexp).

Nonetheless all sorts of rules were made (and documented to be) applicable in both roles. Somewhat arbitrary interpretations were imposed, for instance:

  • AttributeValueString inside a <PolicyRequirementRule/> was taken as "If any value of any attribute matches then this rule is true".

  • PrincipalNameString, when applied to be an <AttributeRule/> was taken as "if it is true then return all values of the selected attribute".

These interpretations were coded up in the implementation of each individual rule, and so were not necessarily consistent.

Representation

In the schema a <MatchFunctor/> can be placed either in a <PolicyRequirementRule/> or in a <PermitRule/> or a <DenyRule/>

The implementation explicitly separates these two types which are represented by two interfaces

PolicyRequirement:

This has a single method which takes a FilterContext and returns a tristate (yes/no/fail)

Matcher

This has a single method which takes a FilterContext and an attribute and returns a (potentially empty) Set of attribute values with null representing the “fail” condition.

Logical operators (and/or/not)

Each of these have two implementations one of which implements PolicyRequirementRule and the other of which implements Matcher. The parsing code inspects the provided element and instructs Spring to create a bean of the correct sort. We need to ensure that the setter/getters are the same in both cases. Job done.

All other operators

These implement only one of  PolicyRequirement or Matcher, whichever allows the more natural implementation.

Three bridging classes are available to convert between these two types:

  1. MatcherFromPolicy takes a PolicyRequirementRule (as a constructor parameter) and implements Matcher.

  2. PolicyFromMatcher takes a Matcher (as a constructor parameter) and implements PolicyRequirementRule

  3. PolicyFromMatcherId  takes a Matcher and an Attribute Id (as constructor parameters) and implements Policy Requirement. This class is aimed at attribute value matchers which have an attribute Id  specified.

Furnished with these three functions the parsers can “do the right thing” and the implementations can concentrate on implementing the natural functionality.

The parsers need to become slightly more complicated since they now have to detect what sort of interface need to be implemented and summon up the “bridging beans” – whilst ensuring that the Id generated make sense.  Note that it may become necessary to doubly next the bridging classes.

For instance:

1  <afp:PermitValueRule xmlns="urn:mace:shibboleth:2.0:afp:mf:basic" xsi:type="AttributeValueString" value="faculty" attributeId="affiliation"/>

Would be a

Programming Guide to Attribute Filtering

A web flow that wishes to invoke the Attribute Filtering subsystem must do the following.

  1. Create an AttributeFilterContext and populate it with appropriate parameters (where relevant)

    • The canonical Prinicipal name

    • The entityID of the IdP and the SP

    • The authentication method applied.

  2. Add a lookup strategy to allow relevant filters to navigate from the Attribute Filter Context to a SAMLMetadataContext via a call to setRequesterMetadataContextLookupStrategy

  3. Any requested attributed (converted into into internal names and IdPRequestedAttribute) should be populated via a call to setRequestedAttributes

  4. The attributes to be filteres should be populated via a call to setRequessetPrefilteredIdPAttributestedAttributes

  5. Locate an Attribute Filter. This would usually be done via a ReloadableSpringService.  See ReloadableConfiguration.

  6. Call the filter.  After filtering the result can be extracted via the  getFilteredIdPAttributes method.

  7. If using a ReloadableSpringService. do not forget to call unpinComponent.