Add schema version and support to "domain" attribute in mapping rules

As discussed in the Keystone meeting [1], I am proposing this spec, so
we can review and discuss the implementation proposed in [2].

[1] http://eavesdrop.openstack.org/meetings/keystone/2020/keystone.2020-08-25-16.59.log.txt
[2] https://review.opendev.org/#/c/739966/

Change-Id: I84426119a60c595eaf462662c6a24a990914c516
Implements: blueprint versioning-for-attribute-mapping-schema
RFE: https://bugs.launchpad.net/keystone/+bug/1887515
This commit is contained in:
Rafael Weingärtner 2020-08-25 19:22:07 -03:00
parent 330200b4d8
commit 239c755473
3 changed files with 296 additions and 144 deletions

View File

@ -14,6 +14,14 @@ Project Documentation:
keystone
--------
2024.1 approved specs:
.. toctree::
:glob:
:maxdepth: 1
specs/keystone/2024.1/*
2023.1 approved specs:
.. toctree::

View File

@ -0,0 +1,288 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=========================================================================
Add schema version and add support to "domain" attribute in mapping rules
=========================================================================
This spec makes Keystone to honor the "domain" attribute mapping rules,
and adds a versioning method to the attribute mapping schema used by identity
federation deployments.
`bug #1887515 <https://bugs.launchpad.net/keystone/+bug/1887515>`_
This specification implements an alternative solution for the versioned
mappings that were proposed in [1]_.
Problem Description
===================
Currently, Keystone identity provider (IdP) attribute mapping schema only
uses the "domain" attribute mapping as a default configuration for the domain
of groups being mapped; groups can override the default attribute mapping
domain by setting their specific domain. However, there are other "elements"
such as user and project that can also have a domain to define their location
in OpenStack.
An operator when reading the attribute mapping section and seeing the schema
for the attribute mapping definition, can be led to think that the domain
defined in the mapping will also apply to users and projects. However, that is
not what happens.
The examples in the documentation [2]_ do not cover all use cases, which is
fine. Therefore, some people might do what I did when I started working with
identity federation in Keystone. I went directly to the code, and checked the
schema to understand what I could define as the mapping. Then, I saw that at
the root of the `local` rules, we had a domain definition [3]_. I also saw a
domain options for the `user` and `group` properties. Therefore, I thought
that those could be used as an override, and this one ([3]_) was the default
for the mapping rule. I only discovered that this was not the case when I
started testing, and then I checked how the mapping was being processed.
This patch is not changing the feature, all we had working before will keep
working as it was. We are merely adding to it. Adding a method to define
a "default" domain for the rules, which can then be overridden in the user,
projects, or groups definitions.
Proposed Change
===============
First of all, to facilitate the development and extension concerning attribute
mappings for IdPs, we changed the way the attribute mapping schema is handled.
We introduced a new option called `schema_version`, which defaults to "1.0".
This attribute mapping schema version will then be used to control the
validation of the attribute mapping, and also the rule processors used to
process the attributes that come from the IdP. So far, with this patch, we
introduce support to the attribute mapping schema "2.0", which enables
operators to also define a domain for the projects they want to assign users.
If no domain is defined either in the project or in the global domain
definition for the attribute mapping, we take the IdP domain as the default.
Thus we extended Keystone identity provider (IdP) attribute mapping
schema to make Keystone honor the `domain` configuration that we have on it.
Currently, that configuration is only used to define a default domain for
groups (and then each group there, could override it). It is interesting to
expand this configuration (as long as it is in the root of the attribute
mapping) to be also applied for users and projects.
Attribute mapping schema
------------------------
The current schema defined at `keystone/federation/utils.py` does not have
a property to hold the schema version for the rules being defined. Therefore,
we will also introduce a new property there, called `schema_version`. This
new property will be a String that holds the mapping rule schema version.
The mapping rule schema version is then used to define the processor that we
take to process the attribute mapping rules JSON.
Before the proposed changes, one could create a mapping as follows (the
following mapping is only a sample; there are many other possibilities):
.. code-block:: python
{
"mapping": {
"rules": [
{
"remote": [
{
"type": "OIDC-preferred_username"
},
{
"type": "OIDC-email"
},
{
"type": "OIDC-openstack-user-domain"
},
{
"type": "OIDC-openstack-project-name"
}
],
"local": [
{
"domain": {
"name": "{2}"
},
"user": {
"domain": {
"name": "{2}"
},
"type": "ephemeral",
"email": "{1}",
"name": "{0}"
},
"projects": [
{
"domain": {
"name": "{2}"
},
"name": "{3}",
"roles": [
{
"name": "member"
}
]
}
]
}
]
}
],
"links": {
"self": "http://<keystone_server>/v3/OS-FEDERATION/mappings/<attribute_mapping_id>"
},
"id": "<attribute_mapping_id>",
}
}
With the proposed changes, one can for instance, use the following attribute
mapping. We are now able to only declare the domain at the root of the
mapping, and then it is re-used in all other elements that have it. Moreover,
it is possible to override it for specific objects.
.. code-block:: python
{
"mapping": {
"rules": [
{
"remote": [
{
"type": "OIDC-preferred_username"
},
{
"type": "OIDC-email"
},
{
"type": "OIDC-openstack-user-domain"
},
{
"type": "OIDC-openstack-extra-project-domain"
},
{
"type": "OIDC-openstack-project-name"
},
{
"type": "OIDC-openstack-extra-project-name"
}
],
"local": [
{
"domain": {
"name": "{2}"
},
"user": {
"type": "ephemeral",
"email": "{1}",
"name": "{0}"
},
"projects": [
{
"name": "{4}",
"roles": [
{
"name": "member"
}
]
},
{
"domain": {
"name": "{3}"
},
"name": "{5}",
"roles": [
{
"name": "member"
}
]
}
]
}
]
}
],
"links": {
"self": "http://<keystone_server>/v3/OS-FEDERATION/mappings/<attribute_mapping_id>"
},
"id": "<attribute_mapping_id>",
"schema_version": "2.0"
}
}
Validations
-----------
We will validate the `schema_version` against all existing/possible versions
of the field. Therefore, if it is not within the already defined version, an
error is thrown.
If no `schema_version` is presented, then the version used is `1.0`
Database table changes
----------------------
Currently, the table "mapping" is defined as:
.. code-block:: bash
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | varchar(64) | NO | PRI | NULL | |
| rules | text | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
We would add a newfield to it. Therefore, it would look like:
.. code-block:: bash
+----------------+-------------+------+-----+----------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+----------+-------+
| id | varchar(64) | NO | PRI | NULL | |
| rules | text | NO | | NULL | |
| schema_version | varchar(5) | NO | | '1.0' | |
+----------------+-------------+------+-----+----------+-------+
API impacts
-----------
- a new attribute will be available `schema_version`. It defaults to `1.0`.
- Properties `groups`, `projects`, and `user`, all accept the definition of a
`domain` that overrides the optional `domain` that is defined in the root of
the mapping rule. If thoese objects do not define a domain, we take the one
specified in the root of the mapping rule. If no domain is also defined in
the root of the mapping rule, the IdP domain is used.
Assignee(s)
-----------
Primary assignees:
- Rafael <rafael@apache.org>
Other contributors:
Work Items
----------
1) Implement proposed changes in Keystone [4]_
- Create a new mapping schema
- Create new processors for the proposed changes
- Implement validations and unit tests
- Update documentation
Dependencies
============
None
References
==========
.. [1] https://github.com/openstack/keystone-specs/blob/dfc7931a7f8975a98fc49fc3134cb923e31a5a76/specs/keystone/backlog/versioned-mappings.rst
.. [2] https://docs.openstack.org/keystone/latest/admin/federation/mapping_combinations.html
.. [3] https://github.com/openstack/keystone/blob/b0b93c03986f3bb40c5a2ec31ee37c83014e197a/keystone/federation/utils.py#L118
.. [4] https://review.opendev.org/#/c/739966/

View File

@ -1,144 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
================================================
Add Multi-Version Support To Federation Mappings
================================================
`bp versioned-mappings <https://blueprints.launchpad.net/keystone/+spec/versioned-mappings>`_
Our current mapping implementation was designed to take data out of a SAML2
assertion and provide a very crude way to use that data to define the user and
groups. We should have a proper way to extend the mapping syntax and not have
to worry about breaking existing mappings. Adding a version to the mapping will
allow us to make changes that are not backward compatible as needed.
Problem Description
===================
Currently there is no way to make changes that are not backward compatible. For
example, it would be nice to fix some of our mapping warts such as:
1. Not all remote rules provided an entry in the data that is used by the local
rules. This causes confusion for new users and forces a bit of duplication
in the remote rules.
In many different conversations with many different people, I've heard the need
to extend mapping. Sometimes the new feature would be backward compatible and
sometimes not. Here is an idea of what I have heard (these things are not going
to be implemented by this spec):
1. Direct mapping from a remote rule into the assertion data. Currently you add
an entry in the remote section to match something our of the environment and
make it available via index in the local rule. Why not just have the local
rule grab the data directly?
2. Allow transformation using something like `Jinja filters`_ to make it
possible to do some basic changes to the data. For example, (un)urlencoding,
lower/upper casing, etc.
There are lots more and I could probably talk about it for quite a while. I'm
not going to because I don't know how many of those cases have real customer
use cases and who/when they would be worked on. They are really just evidence
that there are potential changes coming that will only be possible if the
mappings have a version.
.. _Jinja filters: http://jinja.pocoo.org/docs/dev/templates/#filters
Proposed Change
===============
1. Change the federation backend interface for mapping to allow an optional
version.
2. Change the API to allow an optional version for the mapping.
3. (Optional in this cycle) Provide the code architecture for dispatching to
different implementations of the mapper based on the version.
Any time a version is not specified we'll use "1" as the version.
Alternatives
------------
1. Add the mapping to the mapping rules themselves. This would no longer need
any database changes. The caveat is that since our top level JSON rule
structure is an array we'd either have to make significant changes to make
it an object or we would have to put version information in every rule in
the array. Putting a version in every rule in the array means that a single
rule document could have multiple versions of rules.
2. Do nothing. Do not allow any significant change to the mapping syntax and
let it die on the vine.
Security Impact
---------------
None. At this point we are not changing the mapping in any way that would cause
changes to how the mappings generate users or groups.
Notifications Impact
--------------------
None.
Other End User Impact
---------------------
None.
Performance Impact
------------------
None.
Other Deployer Impact
---------------------
None. We are just enabling future changes that will expand what a deployer
can do with mappings.
Developer Impact
----------------
None.
Implementation
==============
Assignee(s)
-----------
Primary assignee:
dstanek
Work Items
----------
See the `Proposed Change`_ for a detailed list of work items.
Dependencies
============
None.
Documentation Impact
====================
The change won't require anything specific for the docs team. Though, a
"nice to have" change would be to direct people to start explicitly
specifying the version.
Future changes to the mapping engine will require documentation changes, but
those will also have their own specifications.
References
==========
None.