Comment 1 for bug 2040299

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
```