mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
389-ds OTP lasttoken plugin: Add unit test
Add a xmlrpc test checking that a user cannot delete his last OTP token. Related to https://pagure.io/freeipa/issue/7012 Reviewed-By: Nathaniel McCallum <npmccallum@redhat.com> Reviewed-By: Alexey Slaykovsky <alexey@slaykovsky.com>
This commit is contained in:
committed by
Christian Heimes
parent
8b6506a5f1
commit
c701cd21d3
173
ipatests/test_xmlrpc/test_otptoken_plugin.py
Normal file
173
ipatests/test_xmlrpc/test_otptoken_plugin.py
Normal file
@@ -0,0 +1,173 @@
|
||||
#
|
||||
# Copyright (C) 2018 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
|
||||
"""
|
||||
Test the otptoken plugin.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import pytest
|
||||
|
||||
from ipalib import api, errors
|
||||
from ipatests.util import change_principal, unlock_principal_password
|
||||
from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test
|
||||
from ipatests.test_xmlrpc.tracker.user_plugin import UserTracker
|
||||
|
||||
|
||||
user_password = u'userSecretPassword123'
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user(request):
|
||||
tracker = UserTracker(name=u'user_for_otp_test',
|
||||
givenname=u'Test', sn=u'User for OTP')
|
||||
return tracker.make_fixture(request)
|
||||
|
||||
|
||||
def id_function(arg):
|
||||
"""
|
||||
Return a label for the test parameters.
|
||||
|
||||
The params can be:
|
||||
- the global config (list containing ipauserauthtypes)
|
||||
in this case we need to extract the 'disabled' auth type to evaluate
|
||||
whether user setting override is allowed
|
||||
Example: [u'disabled', u'otp'] will return a label noOverride-otp
|
||||
[u'otp', u'password'] otp+password
|
||||
- the user config (list containing ipauserauthtypes)
|
||||
- the expected outcome (boolean True if delete should be allowed)
|
||||
"""
|
||||
|
||||
if isinstance(arg, list):
|
||||
# The arg is a list, need to extract the override flag
|
||||
labels = list()
|
||||
if u'disabled' in arg:
|
||||
labels.append('noOverride')
|
||||
|
||||
label = 'default'
|
||||
if arg:
|
||||
without_override = [item for item in arg if item != u'disabled']
|
||||
if without_override:
|
||||
label = '+'.join(without_override)
|
||||
labels.append(label)
|
||||
|
||||
return "-".join(labels)
|
||||
|
||||
if isinstance(arg, bool):
|
||||
return "allowed" if arg else "forbidden"
|
||||
|
||||
return 'default'
|
||||
|
||||
|
||||
class TestDeleteLastOtpToken(XMLRPC_test):
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"globalCfg,userCfg,allowDelLast", [
|
||||
# When Global config is not set and prevents user override,
|
||||
# it is possible to delete last token
|
||||
([u'disabled'], None, True),
|
||||
([u'disabled'], [u'otp'], True),
|
||||
([u'disabled'], [u'password'], True),
|
||||
([u'disabled'], [u'password', u'otp'], True),
|
||||
# When Global config is not set and allows user override,
|
||||
# the userCfg applies
|
||||
# Deletion is forbidden only when usercfg = otp only
|
||||
(None, None, True),
|
||||
(None, [u'otp'], False),
|
||||
(None, [u'password'], True),
|
||||
(None, [u'password', u'otp'], True),
|
||||
# When Global config is set to otp and prevents user override,
|
||||
# it is forbidden to delete last token
|
||||
([u'disabled', u'otp'], None, False),
|
||||
([u'disabled', u'otp'], [u'otp'], False),
|
||||
([u'disabled', u'otp'], [u'password'], False),
|
||||
([u'disabled', u'otp'], [u'password', u'otp'], False),
|
||||
# When Global config is set to otp and allows user override,
|
||||
# the userCfg applies
|
||||
# Deletion is forbidden when usercfg = otp only or usercfg not set
|
||||
([u'otp'], None, False),
|
||||
([u'otp'], [u'otp'], False),
|
||||
([u'otp'], [u'password'], True),
|
||||
([u'otp'], [u'password', u'otp'], True),
|
||||
# When Global config is set to password and prevents user override,
|
||||
# it is possible to delete last token
|
||||
([u'disabled', u'password'], None, True),
|
||||
([u'disabled', u'password'], [u'otp'], True),
|
||||
([u'disabled', u'password'], [u'password'], True),
|
||||
([u'disabled', u'password'], [u'password', u'otp'], True),
|
||||
# When Global config is set to password and allows user override,
|
||||
# the userCfg applies
|
||||
# Deletion is forbidden when usercfg = otp only
|
||||
([u'password'], None, True),
|
||||
([u'password'], [u'otp'], False),
|
||||
([u'password'], [u'password'], True),
|
||||
([u'password'], [u'password', u'otp'], True),
|
||||
# When Global config is set to password+otp and prevents user
|
||||
# override, it is possible to delete last token
|
||||
([u'disabled', u'password', u'otp'], None, True),
|
||||
([u'disabled', u'password', u'otp'], [u'otp'], True),
|
||||
([u'disabled', u'password', u'otp'], [u'password'], True),
|
||||
([u'disabled', u'password', u'otp'], [u'password', u'otp'], True),
|
||||
# When Global config is set to password+otp and allows user
|
||||
# override, the userCfg applies
|
||||
# Deletion is forbidden when usercfg = otp only
|
||||
([u'password', u'otp'], None, True),
|
||||
([u'password', u'otp'], [u'otp'], False),
|
||||
([u'password', u'otp'], [u'password'], True),
|
||||
([u'password', u'otp'], [u'password', u'otp'], True),
|
||||
],
|
||||
ids=id_function)
|
||||
def test_delete(self, globalCfg, userCfg, allowDelLast, user):
|
||||
"""
|
||||
Test the deletion of the last otp token
|
||||
|
||||
The user auth type can be defined at a global level, or
|
||||
per-user if the override is not disabled.
|
||||
Depending on the resulting setting, the deletion of last token
|
||||
is allowed or forbidden.
|
||||
"""
|
||||
# Save current global config
|
||||
result = api.Command.config_show()
|
||||
current_globalCfg = result.get('ipauserauthtype', None)
|
||||
|
||||
try:
|
||||
# Set the global config for the test
|
||||
api.Command.config_mod(ipauserauthtype=globalCfg)
|
||||
except errors.EmptyModlist:
|
||||
pass
|
||||
|
||||
try:
|
||||
user.ensure_exists()
|
||||
api.Command.user_mod(user.name, userpassword=user_password)
|
||||
unlock_principal_password(user.name,
|
||||
user_password, user_password)
|
||||
# Set the user config for the test
|
||||
api.Command.user_mod(user.name, ipauserauthtype=userCfg)
|
||||
|
||||
# Connect as user, create and delete the token
|
||||
with change_principal(user.name, user_password):
|
||||
api.Command.otptoken_add(u'lastotp', description=u'last otp',
|
||||
ipatokenowner=user.name)
|
||||
if allowDelLast:
|
||||
# We are expecting the del command to succeed
|
||||
api.Command.otptoken_del(u'lastotp')
|
||||
else:
|
||||
# We are expecting the del command to fail
|
||||
with pytest.raises(errors.DatabaseError):
|
||||
api.Command.otptoken_del(u'lastotp')
|
||||
|
||||
finally:
|
||||
# Make sure the token is removed
|
||||
try:
|
||||
api.Command.otptoken_del(u'lastotp',)
|
||||
except errors.NotFound:
|
||||
pass
|
||||
|
||||
# Restore the previous ipauserauthtype
|
||||
try:
|
||||
api.Command.config_mod(ipauserauthtype=current_globalCfg)
|
||||
except errors.EmptyModlist:
|
||||
pass
|
Reference in New Issue
Block a user