Skip to content

Commit

Permalink
Issue 6446 - on replica consumer, account policy plugin fails to mana…
Browse files Browse the repository at this point in the history
…ge the last login history (#6448)

Bug description:
	An internal update needs the flag SLAPI_OP_FLAG_BYPASS_REFERRALS
	on a RO consumer. Else the server does not select the backend
	and returns LDAP_REFERRAL to the internal operation.
	In acct_update_login_history the flag is missing.

Fix description:
	Use the same flags in acct_update_login_history as it is
	used in acct_record_login

fixes: #6446

Reviewed by: Mark Reynolds (Thanks!)
  • Loading branch information
tbordaz committed Dec 12, 2024
1 parent df43b93 commit 027015f
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 2 deletions.
123 changes: 122 additions & 1 deletion dirsrvtests/tests/suites/plugins/accpol_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import subprocess
from lib389.tasks import *
from lib389.utils import *
from lib389.topologies import topology_st
from lib389.topologies import topology_st, topology_m1c1
from lib389.idm.user import (UserAccount, UserAccounts)
from lib389.plugins import (AccountPolicyPlugin, AccountPolicyConfig, AccountPolicyConfigs)
from lib389.cos import (CosTemplate, CosPointerDefinition)
Expand Down Expand Up @@ -1298,6 +1298,127 @@ def test_locact_modrdn(topology_st, accpol_local):
account_status(topology_st, suffix, subtree, userid, 1, 0, "Enabled")
del_users(topology_st, suffix, subtree, userid, nousrs)

def test_acct_policy_consumer(topology_m1c1, request):
"""Test the lastLoginHistory is updated on consumer without
referral error
:id: 53a9a2c7-6b10-41c9-b9f9-bde412d04acb
:setup: Supplier Instance, Consumer Instance
:steps:
1. Create a test entry on the supplier
2. Configure lastLoginTime on supplier and consumer
3. On supplier 3 binds of the test entry
4. On supplier check there is 3 lastLoginHistory values
5. On supplier check there is no error in error logs
6. On consumer 3 binds of the test entry
7. On consumer check there is 3 lastLoginHistory values
8. On consumer check there is no error in error logs
:expectedresults:
1. Success
2. Success
3. Success
4. Success
5. Success
6. Success
7. Success
8. Success
"""

supplier = topology_m1c1.ms['supplier1']
consumer = topology_m1c1.cs['consumer1']
USER_PW = 'password'

# Add on the supplier a test user entry and wait it is on the consumer
users_supplier = UserAccounts(supplier, DEFAULT_SUFFIX, rdn=None)
user_supplier = users_supplier.create_test_user(uid=1000, gid=2000)
user_supplier.replace('userPassword', USER_PW)

users_consumer = UserAccounts(consumer, DEFAULT_SUFFIX, rdn=None)
for i in range(0, 10):
try:
user_consumer = users_consumer.get("test_user_1000")
break
except ldap.NO_SUCH_OBJECT:
time.sleep(1)

# Configure lastLoginTime on supplier and consumer
plugin = AccountPolicyPlugin(supplier)
plugin.enable()
ACCPOL_DN = "cn={},{}".format(PLUGIN_ACCT_POLICY, DN_PLUGIN)
ACCP_CONF = "{},{}".format(DN_CONFIG, ACCPOL_DN)
plugin.set('nsslapd-pluginarg0', ACCP_CONF)
accp = AccountPolicyConfig(supplier, dn=ACCP_CONF)
accp.set('alwaysrecordlogin', 'yes')
accp.set('stateattrname', 'lastLoginTime')
supplier.restart(timeout=10)

plugin = AccountPolicyPlugin(consumer)
plugin.enable()
ACCPOL_DN = "cn={},{}".format(PLUGIN_ACCT_POLICY, DN_PLUGIN)
ACCP_CONF = "{},{}".format(DN_CONFIG, ACCPOL_DN)
plugin.set('nsslapd-pluginarg0', ACCP_CONF)
accp = AccountPolicyConfig(consumer, dn=ACCP_CONF)
accp.set('alwaysrecordlogin', 'yes')
accp.set('stateattrname', 'lastLoginTime')
consumer.restart(timeout=10)

# On supplier
# Do 3 binds with a delay to
# allow several values lastLoginHistory
user_supplier.bind(USER_PW)
time.sleep(2)
user_supplier = users_supplier.get("test_user_1000")
user_supplier.bind(USER_PW)
time.sleep(2)
user_supplier = users_supplier.get("test_user_1000")
user_supplier.bind(USER_PW)

# Verify there is no referral error
results = supplier.ds_error_log.match('.*.acct_update_login_history - Modify error 10 on entry*')
assert not results

# Verify that we got 3 values for lastLoginHistory
assert len(user_supplier.get_attr_vals_utf8_l('lastLoginHistory')) == 3

# On Consumer
# Do 3 binds with a delay to
# allow several values lastLoginHistory
user_supplier.bind(USER_PW)
user_consumer.bind(USER_PW)
time.sleep(2)
user_consumer = users_supplier.get("test_user_1000")
user_consumer.bind(USER_PW)
time.sleep(2)
user_consumer = users_supplier.get("test_user_1000")
user_consumer.bind(USER_PW)

# Verify there is no referral error
results = consumer.ds_error_log.match('.*.acct_update_login_history - Modify error 10 on entry*')
assert not results

# Verify that we got at least 3 values for lastLoginHistory
assert len(user_consumer.get_attr_vals_utf8_l('lastLoginHistory')) >= 3


def fin():
user_supplier.delete()
log.info('Disabling Global accpolicy plugin and removing pwpolicy attrs')
try:
plugin = AccountPolicyPlugin(supplier)
plugin.disable()
except ldap.LDAPError as e:
log.error('Failed to disable Global accpolicy plugin, {}'.format(e.message['desc']))
assert False
supplier.restart(timeout=10)
try:
plugin = AccountPolicyPlugin(consumer)
plugin.disable()
except ldap.LDAPError as e:
log.error('Failed to disable Global accpolicy plugin, {}'.format(e.message['desc']))
assert False
consumer.restart(timeout=10)

request.addfinalizer(fin)

if __name__ == '__main__':
# Run isolated
Expand Down
3 changes: 2 additions & 1 deletion ldap/servers/plugins/acctpolicy/acct_plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,8 @@ acct_update_login_history(const char *dn, char *timestr)
list_of_mods[1] = NULL;

mod_pb = slapi_pblock_new();
slapi_modify_internal_set_pb(mod_pb, dn, list_of_mods, NULL, NULL, plugin_id, 0);
slapi_modify_internal_set_pb(mod_pb, dn, list_of_mods, NULL, NULL, plugin_id,
SLAPI_OP_FLAG_NO_ACCESS_CHECK |SLAPI_OP_FLAG_BYPASS_REFERRALS);
slapi_modify_internal_pb(mod_pb);
slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
if (rc != LDAP_SUCCESS) {
Expand Down

0 comments on commit 027015f

Please sign in to comment.