Add ignore_user_inactivity user option
this option allows to override the [security_compliance]disable_user_account_days_inactive setting from config on per-user basis. Co-Authored-By: Vishakha Agarwal <agarwalvishakha18@gmail.com> Change-Id: Ida360e215426184195687bee2a800877af33af04 Closes-Bug: #1827431
This commit is contained in:
parent
e3bd1d747d
commit
c9c655a1e1
|
@ -1945,7 +1945,8 @@ response_user_options_body_required:
|
||||||
The resource options for the user. Available resource options are
|
The resource options for the user. Available resource options are
|
||||||
``ignore_change_password_upon_first_use``, ``ignore_password_expiry``,
|
``ignore_change_password_upon_first_use``, ``ignore_password_expiry``,
|
||||||
``ignore_lockout_failure_attempts``, ``lock_password``,
|
``ignore_lockout_failure_attempts``, ``lock_password``,
|
||||||
``multi_factor_auth_enabled``, and ``multi_factor_auth_rules``.
|
``multi_factor_auth_enabled``, and ``multi_factor_auth_rules``
|
||||||
|
``ignore_user_inactivity``.
|
||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
type: object
|
type: object
|
||||||
|
@ -2240,7 +2241,8 @@ user_options_request_body:
|
||||||
The resource options for the user. Available resource options are
|
The resource options for the user. Available resource options are
|
||||||
``ignore_change_password_upon_first_use``, ``ignore_password_expiry``,
|
``ignore_change_password_upon_first_use``, ``ignore_password_expiry``,
|
||||||
``ignore_lockout_failure_attempts``, ``lock_password``,
|
``ignore_lockout_failure_attempts``, ``lock_password``,
|
||||||
``multi_factor_auth_enabled``, and ``multi_factor_auth_rules``.
|
``multi_factor_auth_enabled``, and ``multi_factor_auth_rules``
|
||||||
|
``ignore_user_inactivity``.
|
||||||
in: body
|
in: body
|
||||||
required: false
|
required: false
|
||||||
type: object
|
type: object
|
||||||
|
|
|
@ -42,6 +42,36 @@ or by updating an existing user to include new options
|
||||||
``None``; if the option is set to ``None``, it is removed from the user's
|
``None``; if the option is set to ``None``, it is removed from the user's
|
||||||
data structure.
|
data structure.
|
||||||
|
|
||||||
|
.. _ignore_user_inactivity:
|
||||||
|
|
||||||
|
ignore_user_inactivity
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Type: ``Boolean``
|
||||||
|
|
||||||
|
Opt into ignoring global inactivity lock settings defined in
|
||||||
|
``keystone.conf [security_compliance]`` on a per-user basis. Setting this
|
||||||
|
option to ``True`` will make users not set as disabled even after the
|
||||||
|
globally configured inactivity period is reached.
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"user": {
|
||||||
|
"options": {
|
||||||
|
"ignore_user_inactivity": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Setting this option for users which are already disabled will not
|
||||||
|
make them automatically enabled. Such users must be enabled manually
|
||||||
|
after setting this option to True for them.
|
||||||
|
|
||||||
|
See the `security compliance documentation
|
||||||
|
<security-compliance.html>`_ for more details.
|
||||||
|
|
||||||
.. _ignore_change_password_upon_first_use:
|
.. _ignore_change_password_upon_first_use:
|
||||||
|
|
||||||
ignore_change_password_upon_first_use
|
ignore_change_password_upon_first_use
|
||||||
|
|
|
@ -80,6 +80,12 @@ LOCK_PASSWORD_OPT = (
|
||||||
option_name='lock_password',
|
option_name='lock_password',
|
||||||
validator=resource_options.boolean_validator,
|
validator=resource_options.boolean_validator,
|
||||||
json_schema_validation=parameter_types.boolean))
|
json_schema_validation=parameter_types.boolean))
|
||||||
|
IGNORE_USER_INACTIVITY_OPT = (
|
||||||
|
resource_options.ResourceOption(
|
||||||
|
option_id='1004',
|
||||||
|
option_name='ignore_user_inactivity',
|
||||||
|
validator=resource_options.boolean_validator,
|
||||||
|
json_schema_validation=parameter_types.boolean))
|
||||||
MFA_RULES_OPT = (
|
MFA_RULES_OPT = (
|
||||||
resource_options.ResourceOption(
|
resource_options.ResourceOption(
|
||||||
option_id='MFAR',
|
option_id='MFAR',
|
||||||
|
@ -117,6 +123,7 @@ def register_user_options():
|
||||||
IGNORE_PASSWORD_EXPIRY_OPT,
|
IGNORE_PASSWORD_EXPIRY_OPT,
|
||||||
IGNORE_LOCKOUT_ATTEMPT_OPT,
|
IGNORE_LOCKOUT_ATTEMPT_OPT,
|
||||||
LOCK_PASSWORD_OPT,
|
LOCK_PASSWORD_OPT,
|
||||||
|
IGNORE_USER_INACTIVITY_OPT,
|
||||||
MFA_RULES_OPT,
|
MFA_RULES_OPT,
|
||||||
MFA_ENABLED_OPT,
|
MFA_ENABLED_OPT,
|
||||||
]:
|
]:
|
||||||
|
|
|
@ -199,13 +199,18 @@ class User(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
if self._enabled:
|
if self._enabled:
|
||||||
max_days = (
|
max_days = (
|
||||||
CONF.security_compliance.disable_user_account_days_inactive)
|
CONF.security_compliance.disable_user_account_days_inactive)
|
||||||
|
inactivity_exempt = getattr(
|
||||||
|
self.get_resource_option(
|
||||||
|
iro.IGNORE_USER_INACTIVITY_OPT.option_id),
|
||||||
|
'option_value',
|
||||||
|
False)
|
||||||
last_active = self.last_active_at
|
last_active = self.last_active_at
|
||||||
if not last_active and self.created_at:
|
if not last_active and self.created_at:
|
||||||
last_active = self.created_at.date()
|
last_active = self.created_at.date()
|
||||||
if max_days and last_active:
|
if max_days and last_active:
|
||||||
now = datetime.datetime.utcnow().date()
|
now = datetime.datetime.utcnow().date()
|
||||||
days_inactive = (now - last_active).days
|
days_inactive = (now - last_active).days
|
||||||
if days_inactive >= max_days:
|
if days_inactive >= max_days and not inactivity_exempt:
|
||||||
self._enabled = False
|
self._enabled = False
|
||||||
return self._enabled
|
return self._enabled
|
||||||
|
|
||||||
|
|
|
@ -342,6 +342,43 @@ class DisableInactiveUserTests(test_backend_sql.SqlTests):
|
||||||
user_ref = self._get_user_ref(user['id'])
|
user_ref = self._get_user_ref(user['id'])
|
||||||
self.assertTrue(user_ref.enabled)
|
self.assertTrue(user_ref.enabled)
|
||||||
|
|
||||||
|
def test_ignore_user_inactivity(self):
|
||||||
|
self.user_dict['options'] = {'ignore_user_inactivity': True}
|
||||||
|
user = PROVIDERS.identity_api.create_user(
|
||||||
|
self.user_dict)
|
||||||
|
# set last_active_at just beyond the max
|
||||||
|
last_active_at = (
|
||||||
|
datetime.datetime.utcnow() -
|
||||||
|
datetime.timedelta(self.max_inactive_days + 1)).date()
|
||||||
|
self._update_user_last_active_at(user['id'], last_active_at)
|
||||||
|
# get user and verify that the user is not disabled
|
||||||
|
user = PROVIDERS.identity_api.get_user(user['id'])
|
||||||
|
self.assertTrue(user['enabled'])
|
||||||
|
|
||||||
|
def test_ignore_user_inactivity_with_user_disabled(self):
|
||||||
|
user = PROVIDERS.identity_api.create_user(
|
||||||
|
self.user_dict)
|
||||||
|
# set last_active_at just beyond the max
|
||||||
|
last_active_at = (
|
||||||
|
datetime.datetime.utcnow() -
|
||||||
|
datetime.timedelta(self.max_inactive_days + 1)).date()
|
||||||
|
self._update_user_last_active_at(user['id'], last_active_at)
|
||||||
|
# get user and verify that the user is disabled
|
||||||
|
user = PROVIDERS.identity_api.get_user(user['id'])
|
||||||
|
self.assertFalse(user['enabled'])
|
||||||
|
# update disabled user with ignore_user_inactivity to true
|
||||||
|
user['options'] = {'ignore_user_inactivity': True}
|
||||||
|
user = PROVIDERS.identity_api.update_user(
|
||||||
|
user['id'], user)
|
||||||
|
# user is not enabled
|
||||||
|
user = PROVIDERS.identity_api.get_user(user['id'])
|
||||||
|
self.assertFalse(user['enabled'])
|
||||||
|
# Manually set enabled and test
|
||||||
|
user['enabled'] = True
|
||||||
|
PROVIDERS.identity_api.update_user(user['id'], user)
|
||||||
|
user = PROVIDERS.identity_api.get_user(user['id'])
|
||||||
|
self.assertTrue(user['enabled'])
|
||||||
|
|
||||||
def _get_user_dict(self, password):
|
def _get_user_dict(self, password):
|
||||||
user = {
|
user = {
|
||||||
'name': uuid.uuid4().hex,
|
'name': uuid.uuid4().hex,
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
[`bug 1827431 <https://bugs.launchpad.net/keystone/+bug/1827431>`_]
|
||||||
|
Added a new user option 'ignore_user_inactivity' (defaults to False).
|
||||||
|
When set to True, it overrides disabling the user after being inactive
|
||||||
|
for certain time as set in
|
||||||
|
``[security_compliance]disable_user_account_days_inactive`` option
|
||||||
|
in Keystone configuration file.
|
Loading…
Reference in New Issue