← Back to team overview

yahoo-eng-team team mailing list archive

[Bug 1848342] [NEW] Duplicated entries in users API

 

Public bug reported:

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_case@xxxxxxxxx"} |       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_case@xxxxxxxxx               |

        | 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_case@xxxxxxxxx"} |       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

** Affects: keystone
     Importance: Undecided
         Status: New

-- 
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):
  New

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_case@xxxxxxxxx"} |       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_case@xxxxxxxxx               |

          | 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_case@xxxxxxxxx"} |       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


Follow ups