Password Rotation and Credential Lifecycle

Registered by Fabio Giannetti

Problem Statement

In the current Keystone implementation Users only have the ability of expressing one password. This eliminates the possibility of storing more than one password associated with the user as well as have a record of the last N passwords used. The rotation mechanism and history can simplify access without service interruption as well as make the system more secure preventing users to always use the same password which will never expire.

Supported Scenarios

1) Password Expiration
In this case, when a password is created, the system can specify the duration/validity of the password. For instance it could be valid for 1 day or 1 year.

2) Password rotation with no service interruption
A user can define at least two passwords allowing access to services using both the old and the new. Once all the services have migrated to use the new passwords the old one will be revoked and/or expired.

3) Prevent Usage of previous N passwords
The previous N passwords can be stored as indicated as "expired" or "disabled". When a user refreshes or create a new password it can be verified that it is not one of the N previously created and expired passwords.

Blueprint information

Status:
Complete
Approver:
None
Priority:
Not
Drafter:
Fabio Giannetti
Direction:
Needs approval
Assignee:
David Stanek
Definition:
Obsolete
Series goal:
None
Implementation:
Good progress
Milestone target:
None
Started by
Dolph Mathews
Completed by
Morgan Fainberg

Related branches

Sprints

Whiteboard

Narrow the scope of this blueprint to just item #2. Use cases 1 and 3 can be solved in subsequent blueprints rather trivially. As discussed in #openstack-dev, none of this requires API modifications and can piggy back on dstanek's self-service change password call. With the above, I'd be happy to target this to m3 or sooner. -dolph

Solution

The solution is achieved changing the Users and Credential entities in this way:

1) The password field is removed from Users
2) A "password" type is defined for the Credentials entity
3) The password field content is placed in the blob field of the Credentials type="password"
4) A default_credential_id is introduced in Users to default to the main username/password combination
5) The Credentials entity has a new status field with the following possible values: active, revoked, expired
6) The Credentials entity has a new expires_at field containing the timestamp (ISO 8601) when that credential will expire.

Credential Examples

Active Credential
{
    "credential": {
        "blob": "secrete",
        "id": "80239a",
        "expires_at": "2014-01-01T00:00:00Z",
        "links": {
            "self": "http://identity:35357/v3/credentials/80239a"
        },
        "project_id": "263fd9",
        "status": "active"
        "type": "password",
        "user_id": "0ca8f6"
    }
}

Expired Credential
{
    "credential": {
        "blob": "segreto",
        "id": "80238a",
        "expires_at": "2013-01-01T00:00:00Z",
        "links": {
            "self": "http://identity:35357/v3/credentials/80238a"
        },
        "project_id": "263fd9",
        "status": "expired"
        "type": "password",
        "user_id": "0ca8f6"
    }
}

User Examples
{
    "user": {
        "default_credential_id": "80239a",
        "default_project_id": "263fd9",
        "domain_id": "1789d1",
        "email": "<email address hidden>",
        "enabled": true,
        "id": "0ca8f6",
        "links": {
            "self": "http://identity:35357/v3/users/0ca8f6"
        },
        "name": "Joe"
    }
}

Supported Authentication Variants

User ID and Password:
If the user passes the request just the user id and password:

{
    "auth": {
        "identity": {
            "methods": [
                "password"
            ],
            "password": {
                "user": {
                    "id": "0ca8f6",
                    "password": "secrete"
                }
            }
        }
    }
}
Keystone will access the User using the user ID and the corresponding Credential using the default_credential_id.

User Name, Domain ID and Password:
If the user passes in the request the user name, password and domain id:

{
    "auth": {
        "identity": {
            "methods": [
                "password"
            ],
            "password": {
                "user": {
                    "domain": {
                        "id": "1789d1"
                    },
                    "name": "Joe",
                    "password": "secrete"
                }
            }
        }
    }
}
Keystone will identify the Domain. Scan all the users until finds the user with the corresponding name and then use the default_credential_id to identify the corresponding password.

Credential ID and Password:
If the user passes the credential id and the password:

{
    "auth": {
        "identity": {
            "methods": [
                "password"
            ],
            "password": {
                "user": {
                    "credential_id": "80239a",
                    "password": "secrete"
                }
            }
        }
    }
}
Keystone will immediately point to the Credential specified by the credential_id and to identify the corresponding password.

As discussed / designed at the keystone hackathon (dolphm, morganfainberg, dstanek, stevemar): https://gist.github.com/dolph/7665011

Gerrit topic: https://review.openstack.org/#q,topic:bp/password-rotation,n,z

Addressed by: https://review.openstack.org/72781 (merged)
    Changing testcase name to match our terminology

Addressed by: https://review.openstack.org/72782 (merged)
    Move identity logic from controller to manager

Addressed by: https://review.openstack.org/73368
    Adds table and model for storing rotated passwords

Addressed by: https://review.openstack.org/73304
    Adds model mixin for {to,from}_dict functionality

Addressed by: https://review.openstack.org/74447
    Identity authentication now uses rotated passwords

Addressed by: https://review.openstack.org/74623
    password rotation extension WIP

Addressed by: https://review.openstack.org/85651
    Moves test database setup/teardown into a fixture

There doesn't seem to be a push for this functionality. I'm marking this as 'Not' being implemented at this time and if there isn't any push back I'll mark it as closed next week.

(?)

Work Items

This blueprint contains Public information 
Everyone can see this information.