This software is not yet released and this is preliminary documentaton subject to significant change. It should not be used in production or to protect important resources at this stage.
AgentResolverService
This is a more complete treatment of this service; a more introductory page covering the most critical aspects can be found in AgentResolverBasics.
The IdP includes a number of core ReloadableServices, most of which are used for similar (or somewhat “inverted”) purposes within the Hub. The Hub supplements this by adding a new service called an Agent Resolver, which plays a role similar to the IdP’s RelyingPartyConfiguration resolver service and in fact extends it. (Note, the original IdP version of that service is not used by the Hub at all.)
The default configuration file for this service is conf/sp/agents.xml (the exact set of resources can be adjusted, control over service reload, etc. as with other IdP services, see TBD for reference details).
Notably, since this is a reloadable service (on demand or when changes are detected), the Hub can dynamically be adjusted to support new Agents or change existing Agent behavior easily. The service ID for this is shibboleth.sp.AgentResolver. The configuration can also be built up in a variety of ways via imported files to provide a lot of flexibility in operating the Hub to suit particular deployment needs. Additional techniques for scaling the management of many Agents are also under consideration.
This page provides an overview of the structure of the configuration and how it’s evaluated when processing requests to help in understanding how to use it. For a complete reference to the configuration options available on these objects, see the Advanced topics such as AgentSettingsReference, ApplicationSettingsReference, etc.
See also these more task-oriented sub-topics, though familiarity with this material is recommended first:
Configuration Structure
The AgentResolverBasics topic describes this service at a high level with a focus on only what is typically needed by most deployers.
Fully understanding this service requires understanding the logical structure of the Hub’s configuration, which consists of Agent, Application, RelyingPartyConfiguration, and ProfileConfiguration objects (the latter two playing a very similar role they play in the IdP’s RelyingPartyConfigurationlayer, as noted at the end of this page).
The linked Javadocs for those interfaces and (in the case of ProfileConfiguration, its many subinterfaces) collectively define almost all the settings that you can configure at various levels to control behavior.
The bean structure can be visualized as:
Agent, its Default Application, and its Default RelyingPartyConfiguration
Default ProfileConfigurations (typically auto-wired for you)
RelyingPartyConfiguration Override(s) (zero or more)
Overridden ProfileConfigurations (if overridden)
Application Override and its Default RelyingPartyConfiguration (zero or more)
Default ProfileConfigurations (typically auto-wired for you)
RelyingPartyConfiguration Override (zero or more)
Overridden ProfileConfigurations (if overridden)
Each Agent (of which there can be any number) is a container for a set of Applications along with some dedicated settings that apply to the Agent as a whole. The Agent bean acts as its default Application and can contain a number of Application Overrides that can customize behavior of the Agent when requested (though in practice it is not expected and indeed discouraged to make any use of this feature).
Each Application (default or override) is itself a container for a set of RelyingPartyConfiguration objects. It is itself a default one and optionally contains a list of overrides that may be triggered based on various criteria typically associated with the authenticating authority (i.e., IdP) that is in use. An Application directly exposes its default RelyingPartyConfiguration settings in the same way that an Agent directly exposes its default Application settings.
Another way of saying this: each Agent is an Application but can contain other Applications. Each Application is a default RelyingPartyConfiguration but can contain overrides.
Each RelyingPartyConfiguration provides various settings and is a container for one or more ProfileConfiguration objects.
In the simplest cases, then, defining a single Agent bean gets you:
the Agent’s settings
the default Application and its settings
the default RelyingPartyConfiguration and its settings
through auto-wiring or by reference, the incorporation of a set of default ProfileConfigurations and their settings
Because the actual set of ProfileConfigurations is typically supplied by one or more additional plugins (such as those for SAML or OpenID Connect), the system supports plugins reporting out what they supply to the runtime automatically so that installing a new protocol plugin automatically enables the profiles supplied by the plugin using their default settings across the system to all Agents and Applications. It is also possible to short-circuit this automation by defining lists of ProfileConfiguration objects that you want to use while excluding others you don’t want.
In this way, simple requirements are met in very simple ways and apart from learning what settings exist and when you’d need them, the Spring configuration can be pretty minimal. If you make things more complex, which is almost always avoidable, things get very hairy very quickly.
Defining New Configuration Objects
In accordance with the model described above, the typical objects you may need to define and the parent beans supplied to facilitate this are described here, along with a link to an introduction on how to do this at a high level as well as a link to more detailed reference documentation.
Object / Interface | Parent Bean(s) | Overview Topic | Reference Topic |
|---|---|---|---|
shibboleth.sp.Agent | |||
shibboleth.sp.Application | |||
RelyingPartyByName | RelyingPartySettingsReference (TBD) | ||
These are supplied by protocol plugins | SAMLSettingsReference |
In the delivered example configuration, there are other helpful beans defined for you (or commented out) in the agents.xml file:
shibboleth.sp.RelyingPartyOverrides
RelyingPartyConfiguration overrides applied by default for all Applications. Typically in doing so, specific ProfileConfigurations will also be defined, but if not done, the parent Application’s set of active profiles is used. In practice, the automatically registered profiles (or, if defined, the shibboleth.sp.DefaultProfileConfigurations bean list) is what generally provides this.
shibboleth.sp.DefaultProfileConfigurations
Profiles and settings active by default for all Application and RelyingPartyConfiguration instances except for the “unverified” case. This bean is commented by default and is only needed if you wish to change the set of defaults to something other than the full set supplied by any installed plugins, or explicitly alter particular profile settings by hand.
shibboleth.sp.UnverifiedProfileConfigurations
Profiles and settings active by default for all Applications in the “unverified” case. This bean is commented by default and is only needed if you wish to change the set of defaults to something other than the full set supplied by any installed plugins, or explicitly alter particular profile settings by hand.
These beans provide a single place in which you can override the default verified and unverified profile beans and settings to enable for all/most of your Applications, and a place to define RelyingPartyConfiguration overrides that will be defined for you across all Applications. You are not required to use these common definitions across all Agent and Application instances, but with many deployment scenarios, this will be common to do because RelyingPartyConfiguration and ProfileConfiguration settings are often more about the relying party (the IdP/OP) than about the SP. If you need a workaround for a particular IdP, chances are you might need it no matter which Agent or Application is involved, and the configuration is geared to making that as simple as possible.
You can when necessary override these bean properties on an Agent or Application if you have to in order to subvert the default behavior:
p:profileConfigurationsp:unverifiedConfigurationp:relyingPartyConfigurations
Finally, when things get very complex, there is an element of inheritance supported to further attempt to limit the amount of Spring configuration required. It can be complex to use, but in general the software attempts to follow the general rule that if a setting is absent/null/missing, the obvious “container” (parent Application, parent Agent) is used to supply the missing setting. This is not always true, but it is “mostly” true with the exception of settings defined on the individual ProfileConfiguration level. The linked topic discussed this in more detail.
Resolution Process
When an Agent (e.g., our Apache module) makes a request to the Hub to do work, in most cases the Hub’s Agent Resolver service evaluates the configuration hierarchy outlined above to map the request to the relevant objects in the configuration that will supply the settings to use in processing the request.
The request contains credentials that identify the Agent ID (and possible a secret to authenticate the request if the Agent is non-local). This ID is fed into the Agent Resolver service to return the matching Agent object (or a failure). This is a simple string match, not based on any customizable lookup criteria.
The Agent bean’s settings determine whether to authenticate the request, allowed client addresses, etc. and assuming the request passes muster, processing continues.
Most Agent requests will carry an “application” input parameter that identifies the Application within the Agent to associate with the request. This is again based on simple string matching. Application IDs are unique within an Agent, but not globally (each is essentially “qualified” by the relevant Agent).
Due to the Spring wiring used, each Agent is itself an Application, specifically the “default” Application for the Agent.
If the requested operation involves interacting with an authenticating authority (e.g., issuing a request to one, processing a response from one), then the identity of this system and additional information known about it (e.g., SAML metadata, OIDC client information) is fed into the Application to “resolve” the RelyingPartyConfiguration to apply to the request. (This will either be the “default” RelyingPartyConfiguration, provided by the Application bean itself, or an “override”.)
Finally, based on the applicable/resolved RelyingPartyConfiguration, a set of “active/enabled” ProfileConfigurations is retrieved and the request is evaluated to determine which profile applies and whether it is enabled or not. If so, the request continues to be processed, otherwise processing aborts, either in part or in full depending on the specific type of request.
Sometimes a single request to the Hub will attempt to execute various different profiles in sequence, while other times the request is inherently going to represent only one specific profile. Session initiation tends to work in the former manner (requests could be made via SAML or OpenID Connect seamlessly), while token consumer handling tends to be specific to one (SAML or OpenID Connect only).
Comparison to IdP’s RelyingPartyConfiguration Resolver
For those familiar with the IdP software, there are direct comparisons one can make to help understand the Hub’s processing. The concept of Agents and Applications are not part of the IdP; rather, you could think of the IdP as a single Agent and Application, the IdP itself.
Within that single system, the use of default and overridden RelyingPartyConfiguration beans mirrors the Hub’s use of them, as a basis for configuring behavior based on the SP/RP. And as in the Hub, those objects contain a collection of ProfileConfiguration beans to enable and customize specific profiles. One notable difference is the automatic enablement of those profiles by plugins, which the IdP does not (yet at least) support.
The additional complexity of the Hub’s configuration is due to the Hub’s ability to support many Agents at once (and for each Agent to support multiple Applications), whereas the IdP was not developed with such a virtualization model in mind. (It is not beyond the realm of possibility this could port back to the IdP someday, but that isn’t a current priority.)
The other major difference between the Hub and the IdP is that the IdP doesn’t really support much in the way of inheritance of settings because most of that support in the Hub revolves around how the Application construct enables that, and the IdP lacks that construct. However, we may consider backporting some of the newer inheritance features supported within the RelyingPartyConfiguration layer at some point.