Standardizing the federation process¶
We propose that the federated authentication process be reengineered so that a user_id is returned alongside the identity attributes. In addition, the saml2.py authentication module should be renamed as mapped.py to denote that it applies to all authentication methods which require the asserted identity attributes to be mapped into local attributes.
The existing federation logic uses saml2 auth plugin to establish a local Keystone identity, by mapping trusted external identity attributes to local identity attributes. Now that other federation protocols will be supported by Keystone, it makes no sense to apply mapping via a saml2 plugin. Some federation authentication protocols already determine the ID of the user, this should be leveraged by the protocol specific sub modules and not the mapping engine.
In order to resolve the problem the following changes should be made:
The saml2.py file should be renamed as mapped.py.
The method name “saml2” should be removed from mapped.py.
The renamed plugin Saml2 -> Mapped should have the logic for attribute mapping and attribute extraction split.
The function for extracting attributes should return a user_id among the asserted attributes.
Splitting the logic of the Mapped plugin will allow subclassing of the plugin to handle protocols which provide attributes in a different way to mod_shib, while still enabling reuse of the mapping filter implementation. We can then use the correct method name according to the protocol used so that clients can easily determine their behaviour.
For instance, a configuration for a SAML2 and an Open ID Connect enabled Keystone might look like:
[auth] methods = username, password, saml2, openidc saml2 = keystone.auth.plugins.mapped.Mapped openidc = keystone.auth.plugins.mapped.Mapped
This assumes that both protocols manage attributes in the same way so that extraction is identical. If this is not the case, the configuration might look like:
[auth] methods = username, password, saml2, openidc saml2 = keystone.auth.plugins.mapped.Mapped openidc = keystone.auth.plugins.mapped.OpenIDCMapped
Where OpenIDCMapped is a subclass of Mapped which handles its specific extraction of assertion data, then calls the mapping layer handling of the Mapped class.
Alternatively no changes could be made but this is undesirable as it makes no sense for non SAML assertion data to be processed by a module named saml2.py.
Other End User Impact¶
Other Deployer Impact¶
This would force developers to implement new federated protocols in a standardized way by requiring the attribute extraction / retrieval process to return a user_id among the asserted attributes.
Reengineer the current federation process to ensure that a user_id is guaranteed to be returned with the assertion attributes.
Modify handling of assertion data extraction to work across multiple protocols.
Rename saml2.py to mapped.py and remove the method name “saml2” from this.
Split the mapping and attribute assertion logic to allow protocol specific subclassing.
Current federation tests should still provide coverage.
Development docs should specify that functions to extract asserted attributes received from external identity providers should always return a user_id as part of the assertion data.