create a user use ignore_password_expiry but still has expires_at to db

Bug #1871784 reported by kuangpeiling
10
This bug affects 2 people
Affects Status Importance Assigned to Milestone
OpenStack Identity (keystone)
Triaged
Low
Unassigned

Bug Description

-----------------
Updated bug description:

The password_expires_at field for a user resource and the ignore_password_expiry option for a user resource appear to be in conflict with one another. The resource options documentation[1] and the /v3/users API reference should clarify that when ignore_password_expiry is set for the user, the password_expires_at field may still contain a timestamp but can be ignored.

[1] https://docs.openstack.org/keystone/latest/admin/resource-options.html
[2] https://docs.openstack.org/api-ref/identity/v3/#users
-----------------

Original bug description:

when i create a user use ignore_password_expiry,i see the database password expires_at not null,
the code in create_user set password before resource_options_ref_to_mapper,so get_resource_option can not get the option i set
is this a bug?

Revision history for this message
kuangpeiling (kuangpeiling) wrote :

the same as ignore_change_password_upon_first_use,in code create_user,
    def create_user(self, user_id, user):
        with sql.session_for_write() as session:
            user_ref = model.User.from_dict(user)
            if self._change_password_required(user_ref):
                user_ref.password_ref.expires_at = datetime.datetime.utcnow()
            user_ref.created_at = datetime.datetime.utcnow()
            session.add(user_ref)
            # Set resource options passed on creation
            resource_options.resource_options_ref_to_mapper(
                user_ref, model.UserOption)
            return base.filter_user(user_ref.to_dict())

    def _change_password_required(self, user):
        if not CONF.security_compliance.change_password_upon_first_use:
            return False
        ignore_option = user.get_resource_option(
            options.IGNORE_CHANGE_PASSWORD_OPT.option_id)
        return not (ignore_option and ignore_option.option_value is True)

the IGNORE_CHANGE_PASSWORD_OPT is used in _change_password_required before resource_options_ref_to_mapper,so _change_password_required return wrong,expires_at is wrong either

Revision history for this message
Vishakha Agarwal (vishakha.agarwal) wrote :

Hi Kuangpieling,

What problem exactly are you facing here? I am sorry but I am not able to understand your query. Could you briefly explain it?

Changed in keystone:
status: New → Incomplete
Revision history for this message
kuangpeiling (kuangpeiling) wrote :

i want to create a user with ignore_password_expiry,but when i create it i find that i can see the expire_at not null,and i can use user filter password_expires_at to find it

Revision history for this message
Colleen Murphy (krinkle) wrote :

The expiry may be set in the database, but it is ignored in the code:

https://opendev.org/openstack/keystone/src/commit/07abf2fa4d5c2bc5dc1c77d700ac3589d1169d3f/keystone/identity/backends/sql_model.py#L181-L188

Why is it important whether it is set in the database? Are you experiencing an error or seeing incorrect behavior? Can you show exactly what behavior you are seeing and what behavior you're expecting? The underlying implementation in the database should not be important, you should only be interacting with the REST APIs.

Revision history for this message
kuangpeiling (kuangpeiling) wrote :

url /v3/users?password_expires_at=lt:2016-12-08T22:02:00Z can find this user while this user is not set to expire, why not set resource_options_ref_to_mapper before update password?

Revision history for this message
Colleen Murphy (krinkle) wrote :

Thanks for the example, that clarifies the problem for me. The password_expires_at field is also visible when you do a 'openstack user show', and I can see how that would be confusing if you've set ignore_password_expiry for the user.

The resource option ignore_password_expiry only applies to how authentication is handled. It cannot and should not change the data associated with the user, whether that's directly in the database or in the presentation when the user is queried in the API. If adding the resource option caused the expiry field to appear as null, reversing it would be dangerous and could cause the user to be locked out.

I think this could be resolved by adding documentation in the resource options page and the API reference to clarify this confusing behavior. I will update the bug description to note that this is a documentation bug.

tags: added: documentation
Changed in keystone:
status: Incomplete → Triaged
importance: Undecided → Low
description: updated
Revision history for this message
kuangpeiling (kuangpeiling) wrote :

i can't understand why not fix this bug,but add doc?I see it is easy to fix it by seting create_user function resource_options_ref_to_mapper before update password while update_user function is right
such as
    def create_user(self, user_id, user):
        with sql.session_for_write() as session:
            password = user.pop("password", None)
            user_ref = model.User.from_dict(user)
            # Set resource options passed on creation
            resource_options.resource_options_ref_to_mapper(
                user_ref, model.UserOption)
            if password:
                user_ref.password = password
                if self._change_password_required(user_ref):
                    user_ref.password_ref.expires_at = \
                        datetime.datetime.utcnow()
            user_ref.created_at = datetime.datetime.utcnow()
            session.add(user_ref)
            return base.filter_user(user_ref.to_dict())

Changed in keystone:
assignee: nobody → HanGuangyu (hanguangyu)
Changed in keystone:
assignee: HanGuangyu (hanguangyu) → nobody
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.