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:
parent
330200b4d8
commit
239c755473
|
@ -14,6 +14,14 @@ Project Documentation:
|
|||
keystone
|
||||
--------
|
||||
|
||||
2024.1 approved specs:
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
|
||||
specs/keystone/2024.1/*
|
||||
|
||||
2023.1 approved specs:
|
||||
|
||||
.. toctree::
|
||||
|
|
|
@ -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/
|
|
@ -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.
|
Loading…
Reference in New Issue