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.
An attribute filter policy contains:
An attribute rule contains:
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 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:
Once all of the filter policies have been processed then, for every attribute provided when the filtering engine was invoked
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.
<PolicyRequirementRule/>
from <AttributeRule/>
In V2 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.
In the schema a <MatchFunctor/>
can be placed either in a <PolicyRequirementRule/>
or in a <PermitRule/>
or a <DenyRule/>
In all IdP implementations to date this bimodality has been handled by having an interface with methods to support both types of operation. This implementation explicitly separates these two types which are now represented by two interfaces
This has a single method which takes a FilterContext
and returns a tristate (yes/no/fail)
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.
Each of these have two implementations one of which implements PolicyRequirement
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.
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:
MatcherFromPolicy
takes a PolicyRequirement
(as a constructor parameter) and implements Matcher
.PolicyFromMatcher
takes a Matcher
(as a constructor parameter) and implements PolicyRequirement
PolicyFromMatcherId
(or some such name) 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:
<afp:PermitValueRule xmlns="urn:mace:shibboleth:2.0:afp:mf:basic" xsi:type="AttributeValueString" value="faculty" attributeId="affiliation"/>
Would be a
AttributeValueString
implementing Matcher
PolicyFromMatcherId
implementing PolicyRequirement
MatcherFromPolicy
implementing Matcher
AttributeInMetadata
filter.AttributeInMetadata will be implemented to be compatible with the V2.4 and later implementations.
The work will be done by comparing native IdP IdPAttribute and IdPAttributeValue objects. This means that we need to have a mechanism to convert from SAML2 <RequestedAttributes/>
into native IdP IdPRequestedAttribute which extends IdPAttribute with appropriate values.
Doing this requires a reverse mapping (decoding). We will use (most of) the urn:mace:shibboleth:2.0:attribute-map
schema to define this mapping.
The decoding will be done by a stage prior to attribute filtering and the results inserted into the AttributeFilterContext as a multi map (from AttributeId to requested attribute).
The decoding need to take account of the types of the attribute values. The following types will be supported
The behavior of the filter is different between the case where the (SAML) RequestedAttribute had no values (if match by attribute name and format then pass all values) is very distinct from the case where the (SAML) RequestedAttribute had but they could not be decoded (if match by name and format then pass no values). Therefore if such a situation arises the multimap will have a null RequestedAttribute inserted for the given attribute. |
As a final note, correct operation of this filter will require that the attribute values can be compared. All AttributeValue implementations explictly implement #equals(), but XMLObjectAttributeValue delegates to OpenSAML which tends to not implement #equals(), so we may seek to issue warnings in this case.
Filter rules have optional identifiers. In V3 we want to provide logging information based on these identifiers. The paradigm we will use is to general an identifier for anonymous rules when the filter is inititialized. We will log (at info level) the (random, run time) name given to the filter and a self-generated description. For instance:
Attribute Filter: Anonymous filter given name 'AB567F': Description "And filterRule of filters ["59C0F", "89034"].
Parameters to the Attribute Filter operation are provided by the AttributeFilterContext. In addtion, the AttributeFilterWorkContext is used as work space for the attribute filtering process; this context is entirely private to the specific implementation of attribute filtering.
A web flow that wishes to invoke the Attribute Filtering subsystem must do the following.