GET /v3/users?name=NAME returns duplicate

Bug #2040299 reported by Valery Tschopp
14
This bug affects 2 people
Affects Status Importance Assigned to Milestone
OpenStack Identity (keystone)
New
Undecided
Unassigned

Bug Description

GET /v3/users?name=<USER_NAME> will return duplicates if the user have federated data

I have a federated local user in the default domain:

REQ: GET https://identity/v3/users/91665ebad88b497cb90eaf4f856357ec
RESP: 200: OK
{
  "user": {
    "description": "Local federated user",
    "email": "<email address hidden>",
    "id": "91665ebad88b497cb90eaf4f856357ec",
    "name": "federated-user",
    "domain_id": "default",
    "enabled": true,
    "password_expires_at": null,
    "options": {},
    "federated": [
      {
        "idp_id": "eduid",
        "protocols": [
          {
            "protocol_id": "openid",
            "unique_id": "<email address hidden>"
          }
        ]
      }
    ],
    "links": {
      "self": "https://identity/v3/users/91665ebad88b497cb90eaf4f856357ec"
    }
  }
}

But when I try to get the user by name, it is returned twice:

REQ: GET https://identity/v3/users?name=federated-user
RESP: 200: OK
{
  "users": [
    {
      "description": "Local federated user",
      "email": "<email address hidden>",
      "id": "91665ebad88b497cb90eaf4f856357ec",
      "name": "federated-user",
      "domain_id": "default",
      "enabled": true,
      "password_expires_at": null,
      "options": {},
      "links": {
        "self": "https://identity/v3/users/91665ebad88b497cb90eaf4f856357ec"
      }
    },
    {
      "description": "Local federated user",
      "email": "<email address hidden>",
      "id": "91665ebad88b497cb90eaf4f856357ec",
      "name": "federated-user",
      "domain_id": "default",
      "enabled": true,
      "password_expires_at": null,
      "options": {},
      "links": {
        "self": "https://identity/v3/users/91665ebad88b497cb90eaf4f856357ec"
      }
    }
  ],
  "links": {
    "next": null,
    "self": "https://identity/v3/users?name=federated-user",
    "previous": null
  }
}

The same problem with the openstack CLI:

$ openstack user show federated-user
More than one user exists with the name 'federated-user'.

Why does this append?
Why is the user by name returned twice?

This is breaking a lot of python code, based on OpenstackSDK, typically the code:

api = openstack.connect()
user = api.identity.find_user('federated-user')

will throw an exception!

description: updated
description: updated
description: updated
description: updated
Revision history for this message
Jay Rhine (fredomlover23) wrote :

So I am seeing something similar in our setup. If a federated user gets created by logging in via the OpenStack web interface (via OIDC), the user does NOT have a local_user entry created. Such a user will NOT show a duplicate user warning.

However, if I create a user with federated identity data such a user will get entries in both the local_user database table, and in the federated_users database table.

My original thinking was that in the keystone/identity/core.py (https://github.com/openstack/keystone/blob/master/keystone/identity/core.py#L960C1-L976C24), there is a bug because this creation code will create both of these entries (see code snippet below)

A simple fix for this would be to add `del user['name']` right after `del user['federated']`. This will result in the same behavior for federated user creation via the Keystone API (POST /v3/users). The reason, this works is that in the SQL backend, the "create_user" interface will automatically create a local_user entry when setting the 'name' attribute IF there is no federated data. Since the federated data does not get added until after the user is created, there is a chicken and egg scenario.

However, your question makes me wonder if creating of a local_user entry is correct, but the the "GET /v3/users" behavior is wrong, and it shouldn't report the presense of both the local_user and federated_user as a duplicate. In this case, I would also ask the question of whether a user that gets added as a result of authenticationg via the OIDC, etc. should end up with the same database entries as a user that is added via the Keystone API with federated info.

```
    def _create_user_with_federated_objects(self, user, driver):
        # If the user did not pass a federated object along inside the user
        # object then we simply create the user as normal.
        if not user.get('federated'):
            if 'federated' in user:
                del user['federated']
            user = driver.create_user(user['id'], user)
            return user
        # Otherwise, validate the federated object and create the user.
        else:
            user_ref = user.copy()
            del user['federated']
            self._validate_federated_objects(user_ref['federated'])
            user = driver.create_user(user['id'], user)
            self._create_federated_objects(user_ref, user_ref['federated'])
            user['federated'] = user_ref['federated']
            return user
```

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.