Adding options to user cli
User options [1] can be set by making POST and PATCH request for /v3/users API calls but cannot by openstack CLI because of no user options defined in create and update user CLI [2]. This patch adds the user options [1] in create user and update user CLI. [1] https://docs.openstack.org/keystone/latest/admin/resource-options.html#multi-factor-auth-rules [2] https://docs.openstack.org/api-ref/identity/v3/#create-user Change-Id: I4e41bae2e8cfbe92d52b14d856991bedcd44164f
This commit is contained in:
parent
c5719a12b5
commit
05da145eae
@ -19,6 +19,12 @@ Create new user
|
||||
[--password-prompt]
|
||||
[--email <email-address>]
|
||||
[--description <description>]
|
||||
[--multi-factor-auth-rule <rule>]
|
||||
[--ignore-lockout-failure-attempts| --no-ignore-lockout-failure-attempts]
|
||||
[--ignore-password-expiry| --no-ignore-password-expiry]
|
||||
[--ignore-change-password-upon-first-use| --no-ignore-change-password-upon-first-use]
|
||||
[--enable-lock-password| --disable-lock-password]
|
||||
[--enable-multi-factor-auth| --disable-multi-factor-auth]
|
||||
[--enable | --disable]
|
||||
[--or-show]
|
||||
<user-name>
|
||||
@ -56,6 +62,63 @@ Create new user
|
||||
|
||||
.. versionadded:: 3
|
||||
|
||||
.. option:: --ignore-lockout-failure-attempts
|
||||
|
||||
Opt into ignoring the number of times a user has authenticated and
|
||||
locking out the user as a result
|
||||
|
||||
.. option:: --no-ignore-lockout-failure-attempts
|
||||
|
||||
Opt out of ignoring the number of times a user has authenticated
|
||||
and locking out the user as a result
|
||||
|
||||
.. option:: --ignore-change-password-upon-first-use
|
||||
|
||||
Control if a user should be forced to change their password immediately
|
||||
after they log into keystone for the first time. Opt into ignoring
|
||||
the user to change their password during first time login in keystone.
|
||||
|
||||
.. option:: --no-ignore-change-password-upon-first-use
|
||||
|
||||
Control if a user should be forced to change their password immediately
|
||||
after they log into keystone for the first time. Opt out of ignoring
|
||||
the user to change their password during first time login in keystone.
|
||||
|
||||
.. option:: --ignore-password-expiry
|
||||
|
||||
Opt into allowing user to continue using passwords that may be
|
||||
expired
|
||||
|
||||
.. option:: --no-ignore-password-expiry
|
||||
|
||||
Opt out of allowing user to continue using passwords that may be
|
||||
expired
|
||||
|
||||
.. option:: --enable-lock-password
|
||||
|
||||
Disables the ability for a user to change its password through
|
||||
self-service APIs
|
||||
|
||||
.. option:: --disable-lock-password
|
||||
|
||||
Enables the ability for a user to change its password through
|
||||
self-service APIs
|
||||
|
||||
.. option:: --enable-multi-factor-auth
|
||||
|
||||
Enables the MFA (Multi Factor Auth)
|
||||
|
||||
.. option:: --disable-multi-factor-auth
|
||||
|
||||
Disables the MFA (Multi Factor Auth)
|
||||
|
||||
.. option:: --multi-factor-auth-rule <rule>
|
||||
|
||||
Set multi-factor auth rules. For example, to set a rule requiring the
|
||||
"password" and "totp" auth methods to be provided,
|
||||
use: "--multi-factor-auth-rule password,totp".
|
||||
May be provided multiple times to set different rule combinations.
|
||||
|
||||
.. option:: --enable
|
||||
|
||||
Enable user (default)
|
||||
@ -146,6 +209,12 @@ Set user properties
|
||||
[--password-prompt]
|
||||
[--email <email-address>]
|
||||
[--description <description>]
|
||||
[--multi-factor-auth-rule <rule>]
|
||||
[--ignore-lockout-failure-attempts| --no-ignore-lockout-failure-attempts]
|
||||
[--ignore-password-expiry| --no-ignore-password-expiry]
|
||||
[--ignore-change-password-upon-first-use| --no-ignore-change-password-upon-first-use]
|
||||
[--enable-lock-password| --disable-lock-password]
|
||||
[--enable-multi-factor-auth| --disable-multi-factor-auth]
|
||||
[--enable|--disable]
|
||||
<user>
|
||||
|
||||
@ -187,6 +256,63 @@ Set user properties
|
||||
|
||||
.. versionadded:: 3
|
||||
|
||||
.. option:: --ignore-lockout-failure-attempts
|
||||
|
||||
Opt into ignoring the number of times a user has authenticated and
|
||||
locking out the user as a result
|
||||
|
||||
.. option:: --no-ignore-lockout-failure-attempts
|
||||
|
||||
Opt out of ignoring the number of times a user has authenticated
|
||||
and locking out the user as a result
|
||||
|
||||
.. option:: --ignore-change-password-upon-first-use
|
||||
|
||||
Control if a user should be forced to change their password immediately
|
||||
after they log into keystone for the first time. Opt into ignoring
|
||||
the user to change their password during first time login in keystone.
|
||||
|
||||
.. option:: --no-ignore-change-password-upon-first-use
|
||||
|
||||
Control if a user should be forced to change their password immediately
|
||||
after they log into keystone for the first time. Opt out of ignoring
|
||||
the user to change their password during first time login in keystone.
|
||||
|
||||
.. option:: --ignore-password-expiry
|
||||
|
||||
Opt into allowing user to continue using passwords that may be
|
||||
expired
|
||||
|
||||
.. option:: --no-ignore-password-expiry
|
||||
|
||||
Opt out of allowing user to continue using passwords that may be
|
||||
expired
|
||||
|
||||
.. option:: --enable-lock-password
|
||||
|
||||
Disables the ability for a user to change its password through
|
||||
self-service APIs
|
||||
|
||||
.. option:: --disable-lock-password
|
||||
|
||||
Enables the ability for a user to change its password through
|
||||
self-service APIs
|
||||
|
||||
.. option:: --enable-multi-factor-auth
|
||||
|
||||
Enables the MFA (Multi Factor Auth)
|
||||
|
||||
.. option:: --disable-multi-factor-auth
|
||||
|
||||
Disables the MFA (Multi Factor Auth)
|
||||
|
||||
.. option:: --multi-factor-auth-rule <rule>
|
||||
|
||||
Set multi-factor auth rules. For example, to set a rule requiring the
|
||||
"password" and "totp" auth methods to be provided,
|
||||
use: "--multi-factor-auth-rule password,totp".
|
||||
May be provided multiple times to set different rule combinations.
|
||||
|
||||
.. option:: --enable
|
||||
|
||||
Enable user (default)
|
||||
|
@ -30,6 +30,114 @@ from openstackclient.identity import common
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _get_options_for_user(identity_client, parsed_args):
|
||||
options = {}
|
||||
if parsed_args.ignore_lockout_failure_attempts:
|
||||
options['ignore_lockout_failure_attempts'] = True
|
||||
if parsed_args.no_ignore_lockout_failure_attempts:
|
||||
options['ignore_lockout_failure_attempts'] = False
|
||||
if parsed_args.ignore_password_expiry:
|
||||
options['ignore_password_expiry'] = True
|
||||
if parsed_args.no_ignore_password_expiry:
|
||||
options['ignore_password_expiry'] = False
|
||||
if parsed_args.ignore_change_password_upon_first_use:
|
||||
options['ignore_change_password_upon_first_use'] = True
|
||||
if parsed_args.no_ignore_change_password_upon_first_use:
|
||||
options['ignore_change_password_upon_first_use'] = False
|
||||
if parsed_args.enable_lock_password:
|
||||
options['lock_password'] = True
|
||||
if parsed_args.disable_lock_password:
|
||||
options['lock_password'] = False
|
||||
if parsed_args.enable_multi_factor_auth:
|
||||
options['multi_factor_auth_enabled'] = True
|
||||
if parsed_args.disable_multi_factor_auth:
|
||||
options['multi_factor_auth_enabled'] = False
|
||||
if parsed_args.multi_factor_auth_rule:
|
||||
auth_rules = [rule.split(",") for rule in
|
||||
parsed_args.multi_factor_auth_rule]
|
||||
if auth_rules:
|
||||
options['multi_factor_auth_rules'] = auth_rules
|
||||
return options
|
||||
|
||||
|
||||
def _add_user_options(parser):
|
||||
# Add additional user options
|
||||
|
||||
parser.add_argument(
|
||||
'--ignore-lockout-failure-attempts',
|
||||
action="store_true",
|
||||
help=_('Opt into ignoring the number of times a user has '
|
||||
'authenticated and locking out the user as a result'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--no-ignore-lockout-failure-attempts',
|
||||
action="store_true",
|
||||
help=_('Opt out of ignoring the number of times a user has '
|
||||
'authenticated and locking out the user as a result'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--ignore-password-expiry',
|
||||
action="store_true",
|
||||
help=_('Opt into allowing user to continue using passwords that '
|
||||
'may be expired'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--no-ignore-password-expiry',
|
||||
action="store_true",
|
||||
help=_('Opt out of allowing user to continue using passwords '
|
||||
'that may be expired'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--ignore-change-password-upon-first-use',
|
||||
action="store_true",
|
||||
help=_('Control if a user should be forced to change their password '
|
||||
'immediately after they log into keystone for the first time. '
|
||||
'Opt into ignoring the user to change their password during '
|
||||
'first time login in keystone'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--no-ignore-change-password-upon-first-use',
|
||||
action="store_true",
|
||||
help=_('Control if a user should be forced to change their password '
|
||||
'immediately after they log into keystone for the first time. '
|
||||
'Opt out of ignoring the user to change their password during '
|
||||
'first time login in keystone'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--enable-lock-password',
|
||||
action="store_true",
|
||||
help=_('Disables the ability for a user to change its password '
|
||||
'through self-service APIs'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--disable-lock-password',
|
||||
action="store_true",
|
||||
help=_('Enables the ability for a user to change its password '
|
||||
'through self-service APIs'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--enable-multi-factor-auth',
|
||||
action="store_true",
|
||||
help=_('Enables the MFA (Multi Factor Auth)'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--disable-multi-factor-auth',
|
||||
action="store_true",
|
||||
help=_('Disables the MFA (Multi Factor Auth)'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--multi-factor-auth-rule',
|
||||
metavar='<rule>',
|
||||
action="append",
|
||||
default=[],
|
||||
help=_('Set multi-factor auth rules. For example, to set a rule '
|
||||
'requiring the "password" and "totp" auth methods to be '
|
||||
'provided, use: "--multi-factor-auth-rule password,totp". '
|
||||
'May be provided multiple times to set different rule '
|
||||
'combinations.')
|
||||
)
|
||||
|
||||
|
||||
class CreateUser(command.ShowOne):
|
||||
_description = _("Create new user")
|
||||
|
||||
@ -72,6 +180,8 @@ class CreateUser(command.ShowOne):
|
||||
metavar='<description>',
|
||||
help=_('User description'),
|
||||
)
|
||||
_add_user_options(parser)
|
||||
|
||||
enable_group = parser.add_mutually_exclusive_group()
|
||||
enable_group.add_argument(
|
||||
'--enable',
|
||||
@ -113,6 +223,7 @@ class CreateUser(command.ShowOne):
|
||||
if not parsed_args.password:
|
||||
LOG.warning(_("No password was supplied, authentication will fail "
|
||||
"when a user does not have a password."))
|
||||
options = _get_options_for_user(identity_client, parsed_args)
|
||||
|
||||
try:
|
||||
user = identity_client.users.create(
|
||||
@ -122,7 +233,8 @@ class CreateUser(command.ShowOne):
|
||||
password=parsed_args.password,
|
||||
email=parsed_args.email,
|
||||
description=parsed_args.description,
|
||||
enabled=enabled
|
||||
enabled=enabled,
|
||||
options=options,
|
||||
)
|
||||
except ks_exc.Conflict:
|
||||
if parsed_args.or_show:
|
||||
@ -333,6 +445,8 @@ class SetUser(command.Command):
|
||||
metavar='<description>',
|
||||
help=_('Set user description'),
|
||||
)
|
||||
_add_user_options(parser)
|
||||
|
||||
enable_group = parser.add_mutually_exclusive_group()
|
||||
enable_group.add_argument(
|
||||
'--enable',
|
||||
@ -390,6 +504,10 @@ class SetUser(command.Command):
|
||||
if parsed_args.disable:
|
||||
kwargs['enabled'] = False
|
||||
|
||||
options = _get_options_for_user(identity_client, parsed_args)
|
||||
if options:
|
||||
kwargs['options'] = options
|
||||
|
||||
identity_client.users.update(user.id, **kwargs)
|
||||
|
||||
|
||||
|
@ -108,6 +108,9 @@ MAPPING_RESPONSE_2 = {
|
||||
"rules": MAPPING_RULES_2
|
||||
}
|
||||
|
||||
mfa_opt1 = 'password,totp'
|
||||
mfa_opt2 = 'password'
|
||||
|
||||
project_id = '8-9-64'
|
||||
project_name = 'beatles'
|
||||
project_description = 'Fab Four'
|
||||
|
@ -111,6 +111,7 @@ class TestUserCreate(TestUser):
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'options': {},
|
||||
'enabled': True,
|
||||
'password': None,
|
||||
}
|
||||
@ -150,6 +151,7 @@ class TestUserCreate(TestUser):
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'options': {},
|
||||
'enabled': True,
|
||||
'password': 'secret',
|
||||
}
|
||||
@ -190,6 +192,7 @@ class TestUserCreate(TestUser):
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'options': {},
|
||||
'enabled': True,
|
||||
'password': 'abc123',
|
||||
}
|
||||
@ -228,6 +231,7 @@ class TestUserCreate(TestUser):
|
||||
'domain': None,
|
||||
'email': 'barney@example.com',
|
||||
'enabled': True,
|
||||
'options': {},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
@ -265,6 +269,7 @@ class TestUserCreate(TestUser):
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
@ -311,6 +316,7 @@ class TestUserCreate(TestUser):
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'options': {},
|
||||
'enabled': True,
|
||||
'password': None,
|
||||
}
|
||||
@ -356,6 +362,7 @@ class TestUserCreate(TestUser):
|
||||
'description': None,
|
||||
'domain': self.domain.id,
|
||||
'email': None,
|
||||
'options': {},
|
||||
'enabled': True,
|
||||
'password': None,
|
||||
}
|
||||
@ -392,6 +399,7 @@ class TestUserCreate(TestUser):
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'options': {},
|
||||
'enabled': True,
|
||||
'password': None,
|
||||
}
|
||||
@ -428,6 +436,7 @@ class TestUserCreate(TestUser):
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'options': {},
|
||||
'enabled': False,
|
||||
'password': None,
|
||||
}
|
||||
@ -438,6 +447,471 @@ class TestUserCreate(TestUser):
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_ignore_lockout_failure_attempts(self):
|
||||
arglist = [
|
||||
'--ignore-lockout-failure-attempts',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('ignore_lockout_failure_attempts', True),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'ignore_lockout_failure_attempts': True},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_no_ignore_lockout_failure_attempts(self):
|
||||
arglist = [
|
||||
'--no-ignore-lockout-failure-attempts',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('no_ignore_lockout_failure_attempts', True),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'ignore_lockout_failure_attempts': False},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_ignore_password_expiry(self):
|
||||
arglist = [
|
||||
'--ignore-password-expiry',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('ignore_password_expiry', True),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'ignore_password_expiry': True},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_no_ignore_password_expiry(self):
|
||||
arglist = [
|
||||
'--no-ignore-password-expiry',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('no_ignore_password_expiry', True),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'ignore_password_expiry': False},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_ignore_change_password_upon_first_use(self):
|
||||
arglist = [
|
||||
'--ignore-change-password-upon-first-use',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('ignore_change_password_upon_first_use', True),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'ignore_change_password_upon_first_use': True},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_no_ignore_change_password_upon_first_use(self):
|
||||
arglist = [
|
||||
'--no-ignore-change-password-upon-first-use',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('no_ignore_change_password_upon_first_use', True),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'ignore_change_password_upon_first_use': False},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_enables_lock_password(self):
|
||||
arglist = [
|
||||
'--enable-lock-password',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('enable_lock_password', True),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'lock_password': True},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_disables_lock_password(self):
|
||||
arglist = [
|
||||
'--disable-lock-password',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('disable_lock_password', True),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'lock_password': False},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_enable_multi_factor_auth(self):
|
||||
arglist = [
|
||||
'--enable-multi-factor-auth',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('enable_multi_factor_auth', True),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'multi_factor_auth_enabled': True},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_disable_multi_factor_auth(self):
|
||||
arglist = [
|
||||
'--disable-multi-factor-auth',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('disable_multi_factor_auth', True),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'multi_factor_auth_enabled': False},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_option_with_multi_factor_auth_rule(self):
|
||||
arglist = [
|
||||
'--multi-factor-auth-rule', identity_fakes.mfa_opt1,
|
||||
'--multi-factor-auth-rule', identity_fakes.mfa_opt2,
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('multi_factor_auth_rule', [identity_fakes.mfa_opt1,
|
||||
identity_fakes.mfa_opt2]),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'multi_factor_auth_rules': [["password", "totp"],
|
||||
["password"]]},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
def test_user_create_with_multiple_options(self):
|
||||
arglist = [
|
||||
'--ignore-password-expiry',
|
||||
'--disable-multi-factor-auth',
|
||||
'--multi-factor-auth-rule', identity_fakes.mfa_opt1,
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('ignore_password_expiry', True),
|
||||
('disable_multi_factor_auth', True),
|
||||
('multi_factor_auth_rule', [identity_fakes.mfa_opt1]),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('name', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# In base command class ShowOne in cliff, abstract method take_action()
|
||||
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||
# data to be shown.
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'name': self.user.name,
|
||||
'default_project': None,
|
||||
'description': None,
|
||||
'domain': None,
|
||||
'email': None,
|
||||
'enabled': True,
|
||||
'options': {'ignore_password_expiry': True,
|
||||
'multi_factor_auth_enabled': False,
|
||||
'multi_factor_auth_rules': [["password", "totp"]]},
|
||||
'password': None,
|
||||
}
|
||||
# UserManager.create(name=, domain=, project=, password=, email=,
|
||||
# description=, enabled=, default_project=)
|
||||
self.users_mock.create.assert_called_with(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.datalist, data)
|
||||
|
||||
|
||||
class TestUserDelete(TestUser):
|
||||
|
||||
@ -1007,6 +1481,384 @@ class TestUserSet(TestUser):
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_ignore_lockout_failure_attempts(self):
|
||||
arglist = [
|
||||
'--ignore-lockout-failure-attempts',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('ignore_lockout_failure_attempts', True),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'ignore_lockout_failure_attempts': True},
|
||||
}
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_no_ignore_lockout_failure_attempts(self):
|
||||
arglist = [
|
||||
'--no-ignore-lockout-failure-attempts',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('no_ignore_lockout_failure_attempts', True),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'ignore_lockout_failure_attempts': False},
|
||||
}
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_ignore_password_expiry(self):
|
||||
arglist = [
|
||||
'--ignore-password-expiry',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('ignore_password_expiry', True),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'ignore_password_expiry': True},
|
||||
}
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_no_ignore_password_expiry(self):
|
||||
arglist = [
|
||||
'--no-ignore-password-expiry',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('no_ignore_password_expiry', True),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'ignore_password_expiry': False},
|
||||
}
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_ignore_change_password_upon_first_use(self):
|
||||
arglist = [
|
||||
'--ignore-change-password-upon-first-use',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('ignore_change_password_upon_first_use', True),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'ignore_change_password_upon_first_use': True},
|
||||
}
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_no_ignore_change_password_upon_first_use(self):
|
||||
arglist = [
|
||||
'--no-ignore-change-password-upon-first-use',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('no_ignore_change_password_upon_first_use', True),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'ignore_change_password_upon_first_use': False},
|
||||
}
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_enable_lock_password(self):
|
||||
arglist = [
|
||||
'--enable-lock-password',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('enable_lock_password', True),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'lock_password': True},
|
||||
}
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_disable_lock_password(self):
|
||||
arglist = [
|
||||
'--disable-lock-password',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('disable_lock_password', True),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'lock_password': False},
|
||||
}
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_enable_multi_factor_auth(self):
|
||||
arglist = [
|
||||
'--enable-multi-factor-auth',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('enable_multi_factor_auth', True),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'multi_factor_auth_enabled': True},
|
||||
}
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_disable_multi_factor_auth(self):
|
||||
arglist = [
|
||||
'--disable-multi-factor-auth',
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('disable_multi_factor_auth', True),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'multi_factor_auth_enabled': False},
|
||||
}
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_option_multi_factor_auth_rule(self):
|
||||
arglist = [
|
||||
'--multi-factor-auth-rule', identity_fakes.mfa_opt1,
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('multi_factor_auth_rule', [identity_fakes.mfa_opt1]),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'multi_factor_auth_rules': [["password", "totp"]]}}
|
||||
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_user_set_with_multiple_options(self):
|
||||
arglist = [
|
||||
'--ignore-password-expiry',
|
||||
'--enable-multi-factor-auth',
|
||||
'--multi-factor-auth-rule', identity_fakes.mfa_opt1,
|
||||
self.user.name,
|
||||
]
|
||||
verifylist = [
|
||||
('name', None),
|
||||
('password', None),
|
||||
('email', None),
|
||||
('ignore_password_expiry', True),
|
||||
('enable_multi_factor_auth', True),
|
||||
('multi_factor_auth_rule', [identity_fakes.mfa_opt1]),
|
||||
('project', None),
|
||||
('enable', False),
|
||||
('disable', False),
|
||||
('user', self.user.name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'enabled': True,
|
||||
'options': {'ignore_password_expiry': True,
|
||||
'multi_factor_auth_enabled': True,
|
||||
'multi_factor_auth_rules': [["password", "totp"]]}}
|
||||
|
||||
# UserManager.update(user, name=, domain=, project=, password=,
|
||||
# email=, description=, enabled=, default_project=)
|
||||
self.users_mock.update.assert_called_with(
|
||||
self.user.id,
|
||||
**kwargs
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
|
||||
class TestUserSetPassword(TestUser):
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added the below mentioned parameters to the user create and set commands.
|
||||
|
||||
* --ignore-lockout-failure-attempts
|
||||
* --no-ignore-lockout-failure-attempts
|
||||
* --ignore-password-expiry
|
||||
* --no-ignore-password-expiry
|
||||
* --ignore-change-password-upon-first-use
|
||||
* --no-ignore-change-password-upon-first-use
|
||||
* --enable-lock-password
|
||||
* --disable-lock-password
|
||||
* --enable-multi-factor-auth
|
||||
* --disable-multi-factor-auth
|
||||
* --multi-factor-auth-rule
|
||||
|
||||
This will now allow users to set user options via CLI.
|
||||
<https://docs.openstack.org/keystone/latest/admin/resource-options.html#user-options>
|
Loading…
Reference in New Issue
Block a user