diff --git a/doc/source/cli/command-objects/user.rst b/doc/source/cli/command-objects/user.rst
index 632d0e2566..d0fc3f8734 100644
--- a/doc/source/cli/command-objects/user.rst
+++ b/doc/source/cli/command-objects/user.rst
@@ -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)
diff --git a/openstackclient/identity/v3/user.py b/openstackclient/identity/v3/user.py
index ca85c5d8a8..cbc112a058 100644
--- a/openstackclient/identity/v3/user.py
+++ b/openstackclient/identity/v3/user.py
@@ -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)
 
 
diff --git a/openstackclient/tests/unit/identity/v3/fakes.py b/openstackclient/tests/unit/identity/v3/fakes.py
index eb3ce2a356..58d5d14d04 100644
--- a/openstackclient/tests/unit/identity/v3/fakes.py
+++ b/openstackclient/tests/unit/identity/v3/fakes.py
@@ -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'
diff --git a/openstackclient/tests/unit/identity/v3/test_user.py b/openstackclient/tests/unit/identity/v3/test_user.py
index 4b14bca05a..c71435bacf 100644
--- a/openstackclient/tests/unit/identity/v3/test_user.py
+++ b/openstackclient/tests/unit/identity/v3/test_user.py
@@ -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):
 
diff --git a/releasenotes/notes/add_options_to_user_create_and_set-302401520f36d153.yaml b/releasenotes/notes/add_options_to_user_create_and_set-302401520f36d153.yaml
new file mode 100644
index 0000000000..698a6f189d
--- /dev/null
+++ b/releasenotes/notes/add_options_to_user_create_and_set-302401520f36d153.yaml
@@ -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>