File(s): conf/attribute-filter.xml
Format: Custom Schema
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. |
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.
<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."
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.
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
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:
urn:mace:shibboleth:2.0:afp:mf:basic
namespace, the schema for which can be located at http://shibboleth.net/schema/idp/shibboleth-afp-mf-basic.xsdurn:mace:shibboleth:2.0:afp:mf:saml
namespace, the schema for which can be located at http://shibboleth.net/schema/idp/shibboleth-afp-mf-saml.xsdUse 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.
The <AttributeFilterPolicyGroup>
element should have an id
attribute. This must be unique and is used for logging purposes.
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.
During attribute filtering, the engine:
<AttributeFilterPolicyGroup>
elements provided (for instance across multiple files) in an unspecified order.<AttributeFilterPolicy>
elements within each <AttributeFilterPolicyGroup>
, again in an unspecified order.<PolicyRequirementRule>
is true:<AttributeRule>
elements, such that:<PermitValueRule>
get added to a "permit list".<DenyValueRule>
get added to a "deny list".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:
<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:
<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?
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:
<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.<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:
attributeId
attribute is specified.<...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>
.
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.