Reviewed: https://review.opendev.org/687990 Committed: https://git.openstack.org/cgit/openstack/keystone/commit/?id=7597ecc1350eb6918c09585e4116911102acb54a Submitter: Zuul Branch: master
commit 7597ecc1350eb6918c09585e4116911102acb54a Author: Pedro Martins <php...@gmail.com> Date: Thu Oct 10 08:51:32 2019 -0300 Stop adding entry in local_user while updating ephemerals Problem description =================== Today we have a consistency problem when updating federated users via OpenStack. When I update a ephemeral user via OpenStack, a registry in the local_user table is created, making this user having entries in user, local_user and federated_user tables in the database. Furthermore, if I try to do some operations using this user (that has entries in all three tables), I get a "More than one user exists with the name ..." error from the OpenStack Keystone API. It happens because the user has an entry in both local_user and federated_user tables. I fix the persistence in the local_user table for ephemeral users when doing updates. Proposal ======== I fix the problem with creating an entry in the local_user table while updating an ephemeral user Closes-Bug: #1848342 Change-Id: I2ac6e90f24b94dc5c0d9c0758f008a388597036c ** Changed in: keystone Status: In Progress => Fix Released -- You received this bug notification because you are a member of Yahoo! Engineering Team, which is subscribed to OpenStack Identity (keystone). https://bugs.launchpad.net/bugs/1848342 Title: Duplicated entries in users API Status in OpenStack Identity (keystone): Fix Released Bug description: System version ============== Keystone: 14.0.1 (Rocky) The error happens when I try to show a federated user via the user name as the key instead of using the ID Reproducing the error: ====================== First of all, I created a user in my Identity Provider (Idp) that is configured my KeyStone instance. We use OpenID Connect protocol to create the federated environment. In this test, the user created is named as 'use_case'. At this moment, the user is not in the OpenStack database, just in the Idp (ephemeral user type). Authenticating with the ephemeral federated user: Let's see the database tables before the login process. Users already created in the Idp (before the login): select * from user; +----------------------------------+-------+---------+--------------------+---------------------+----------------+-----------+ | id | extra | enabled | default_project_id | created_at | last_active_at | domain_id | +----------------------------------+-------+---------+--------------------+---------------------+----------------+-----------+ | 1b0ed400ec974420a3574a8788acc795 | {} | 1 | NULL | 2019-09-16 20:06:39 | NULL | default | +----------------------------------+-------+---------+--------------------+---------------------+----------------+-----------+ select * from local_user; +-----+----------------------------------+-----------+-------+-------------------+----------------+ | id | user_id | domain_id | name | failed_auth_count | failed_auth_at | +-----+----------------------------------+-----------+-------+-------------------+----------------+ | 1 | 1b0ed400ec974420a3574a8788acc795 | default | admin | 0 | NULL | +-----+----------------------------------+-----------+-------+-------------------+----------------+ select * from federated_user; Empty set (0.00 sec) So far, we have only the local user admin Then, we execute the login using the ephemeral user that we created in the IdP. Let's the database state after the first login: select * from user; +----------------------------------+---------------------------------+---------+--------------------+---------------------+----------------+----------------------------------+ | id | extra | enabled | default_project_id | created_at | last_active_at | domain_id | +----------------------------------+---------------------------------+---------+--------------------+---------------------+----------------+----------------------------------+ | 1b0ed400ec974420a3574a8788acc795 | {} | 1 | NULL | 2019-09-16 20:06:39 | NULL | default | | f0327d98278f4b1881aec9c051b027d3 | {"email": "use_c...@gmail.com"} | 1 | NULL | 2019-10-15 18:08:17 | NULL | d28c2423e9b546deb37a034bb2134f4d | +----------------------------------+---------------------------------+---------+--------------------+---------------------+----------------+----------------------------------+ select * from local_user; +----+----------------------------------+-----------+-------+-------------------+----------------+ | id | user_id | domain_id | name | failed_auth_count | failed_auth_at | +----+----------------------------------+-----------+-------+-------------------+----------------+ | 1 | 1b0ed400ec974420a3574a8788acc795 | default | admin | 0 | NULL | +----+----------------------------------+-----------+-------+-------------------+----------------+ select * from federated_user; +----+----------------------------------+--------+-------------+-----------+--------------+ | id | user_id | idp_id | protocol_id | unique_id | display_name | +----+----------------------------------+--------+-------------+-----------+--------------+ | 1 | f0327d98278f4b1881aec9c051b027d3 | my_idp | openid | use_case | use_case | +----+----------------------------------+--------+-------------+-----------+--------------+ Here we can see that the user did not exist in OpenStack database before the first login; then, KeyStone receives the user attributes (during the authentication process) from the Idp and register the user in the OpenStack database as a federated user. (user and federated_user tables). Here is the OpenStack client output (when executing the show command after the first login): openstack user show use_case +---------------------+----------------------------------+ | Field | Value | +---------------------+----------------------------------+ | domain_id | d28c2423e9b546deb37a034bb2134f4d | | email | use_c...@gmail.com | | enabled | True | | id | f0327d98278f4b1881aec9c051b027d3 | | name | use_case | | options | {} | | password_expires_at | None | +---------------------+----------------------------------+ Afterwards, we logout and then we login again in Horizon via the IdP. Please invalidate your session, OpenStack has a bug, and it is not invalidating IdP sessions when the logout is called in Horizon): select * from user; +----------------------------------+---------------------------------+---------+--------------------+---------------------+----------------+----------------------------------+ | id | extra | enabled | default_project_id | created_at | last_active_at | domain_id | +----------------------------------+---------------------------------+---------+--------------------+---------------------+----------------+----------------------------------+ | 1b0ed400ec974420a3574a8788acc795 | {} | 1 | NULL | 2019-09-16 20:06:39 | NULL | default | | f0327d98278f4b1881aec9c051b027d3 | {"email": "use_c...@gmail.com"} | 1 | NULL | 2019-10-15 18:08:17 | NULL | d28c2423e9b546deb37a034bb2134f4d | +----------------------------------+---------------------------------+---------+--------------------+---------------------+----------------+----------------------------------+ select * from local_user; +----+----------------------------------+----------------------------------+----------+-------------------+----------------+ | id | user_id | domain_id | name | failed_auth_count | failed_auth_at | +----+----------------------------------+----------------------------------+----------+-------------------+----------------+ | 1 | 1b0ed400ec974420a3574a8788acc795 | default | admin | 0 | NULL | | 4 | f0327d98278f4b1881aec9c051b027d3 | d28c2423e9b546deb37a034bb2134f4d | use_case | 0 | NULL | +----+----------------------------------+----------------------------------+----------+-------------------+----------------+ select * from federated_user; +----+----------------------------------+--------+-------------+-----------+--------------+ | id | user_id | idp_id | protocol_id | unique_id | display_name | +----+----------------------------------+--------+-------------+-----------+--------------+ | 1 | f0327d98278f4b1881aec9c051b027d3 | my_idp | openid | use_case | use_case | +----+----------------------------------+--------+-------------+-----------+--------------+ Here is the bug, the user already existed in the OpenStack database, and during the second login, Keystone tried to update data with the attributes that come from the IdP. During the update process, Keystone will create an entry in the local_user table. The code that is generating this behavior can be found in https://github.com/openstack/keystone/blob/master/keystone/identity/core.py#L1421 After that, if I try to show the user via OpenStack client, I receive the following error openstack user show use_case More than one user exists with the name 'use_case'. Here is an excerpt of our Attribute Mapping JSON: [ { "local": [ { "user": { "name": "{0}", "email": "{1}", "domain": { "name": "{2}" } }, "domain": { "name": "{2}" }, "projects": [ { "name": "{3}", "roles": [ { "name": "member" }, { "name": "domadmin" }, { "name": "heat_stack_owner" }, { "name": "load-balancer_member" } ] } ] } ], "remote": [ { "type": "OIDC-preferred_username" }, { "type": "OIDC-email" }, { "type": "OIDC-openstack-user-domain" }, { "type": "OIDC-openstack-default-project" }, { "type": "OIDC-openstack-user-role", "any_one_of": [ "domain-admin" ] } ] }, { "local": [ { "user": { "name": "{0}", "email": "{1}", "type": "local", "domain": { "name": "{2}" } }, "domain": { "name": "{2}" }, "projects": [ { "name": "{3}", "roles": [ { "name": "member" }, { "name": "heat_stack_owner" }, { "name": "load-balancer_member" } ] } ] } ], "remote": [ { "type": "OIDC-preferred_username" }, { "type": "OIDC-email" }, { "type": "OIDC-openstack-user-domain" }, { "type": "OIDC-openstack-default-project" }, { "type": "OIDC-openstack-user-status", "any_one_of": [ "local" ] }, { "type": "OIDC-openstack-user-role", "any_one_of": [ "member" ] } ] } ] Here is a link to the PR that propose to fix that issue: https://review.opendev.org/#/c/687990 To manage notifications about this bug go to: https://bugs.launchpad.net/keystone/+bug/1848342/+subscriptions -- Mailing list: https://launchpad.net/~yahoo-eng-team Post to : yahoo-eng-team@lists.launchpad.net Unsubscribe : https://launchpad.net/~yahoo-eng-team More help : https://help.launchpad.net/ListHelp