389-ds-base/0055-Issue-7236-Fix-GSSAPI-tests-7237.patch
2026-04-07 06:30:11 -04:00

228 lines
10 KiB
Diff

From 26feecae026581e39a43f001faff59e81a92c03d Mon Sep 17 00:00:00 2001
From: Lenka Doudova <mirielka@users.noreply.github.com>
Date: Wed, 18 Feb 2026 14:33:49 +0100
Subject: [PATCH] Issue 7236 - Fix GSSAPI tests (#7237)
* Issue 7236 - Fix GSSAPI tests
Description:
Fix for failing GSSAPI tests
Add GSSAPI_ACK variable to pytest workflow for proper execution in
Github CI
Relates: #7236
Author: Lenka Doudova
Reviewer: Barbora Simonova, Viktor Ashirov
---
.github/workflows/lmdbpytest.yml | 2 +-
.github/workflows/pytest.yml | 2 +-
.../tests/suites/gssapi/simple_gssapi_test.py | 2 +
.../suites/gssapi_repl/gssapi_repl_test.py | 43 +++++---------
src/lib389/lib389/topologies.py | 57 +++++++++++++++++++
5 files changed, 76 insertions(+), 30 deletions(-)
diff --git a/.github/workflows/lmdbpytest.yml b/.github/workflows/lmdbpytest.yml
index 2d0a122bf..376090bf6 100644
--- a/.github/workflows/lmdbpytest.yml
+++ b/.github/workflows/lmdbpytest.yml
@@ -120,7 +120,7 @@ jobs:
sudo docker exec $CID sh -c "systemctl enable --now cockpit.socket"
sudo docker exec $CID sh -c "mkdir -p /workspace/assets/cores && chmod 777 /workspace{,/assets{,/cores}}"
sudo docker exec $CID sh -c "echo '/workspace/assets/cores/core.%e.%P' > /proc/sys/kernel/core_pattern"
- sudo docker exec -e WEBUI=1 -e NSSLAPD_DB_LIB=mdb -e DEBUG=pw:api -e PASSWD="${PASSWD}" $CID py.test --suppress-no-test-exit-code -m "not flaky" --junit-xml=pytest.xml --html=pytest.html --browser=firefox --browser=chromium -v dirsrvtests/tests/suites/${{ matrix.suite }}
+ sudo docker exec -e WEBUI=1 -e NSSLAPD_DB_LIB=mdb -e DEBUG=pw:api -e PASSWD="${PASSWD}" -e GSSAPI_ACK=1 $CID py.test --suppress-no-test-exit-code -m "not flaky" --junit-xml=pytest.xml --html=pytest.html --browser=firefox --browser=chromium -v dirsrvtests/tests/suites/${{ matrix.suite }}
- name: Make the results file readable by all
if: always()
diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml
index 8a543be85..a51553656 100644
--- a/.github/workflows/pytest.yml
+++ b/.github/workflows/pytest.yml
@@ -125,7 +125,7 @@ jobs:
echo "Tests skipped because read-only Berkeley Database is installed." > pytest.html
echo "<?xml version="1.0" encoding="utf-8"?>'Tests skipped because read-only Berkeley Database is installed.'" > pytest.xml
else
- sudo docker exec -e WEBUI=1 -e NSSLAPD_DB_LIB=bdb -e DEBUG=pw:api -e PASSWD="${PASSWD}" $CID py.test --suppress-no-test-exit-code -m "not flaky" --junit-xml=pytest.xml --html=pytest.html --browser=firefox --browser=chromium -v dirsrvtests/tests/suites/${{ matrix.suite }}
+ sudo docker exec -e WEBUI=1 -e NSSLAPD_DB_LIB=bdb -e DEBUG=pw:api -e PASSWD="${PASSWD}" -e GSSAPI_ACK=1 $CID py.test --suppress-no-test-exit-code -m "not flaky" --junit-xml=pytest.xml --html=pytest.html --browser=firefox --browser=chromium -v dirsrvtests/tests/suites/${{ matrix.suite }}
fi
- name: Make the results file readable by all
diff --git a/dirsrvtests/tests/suites/gssapi/simple_gssapi_test.py b/dirsrvtests/tests/suites/gssapi/simple_gssapi_test.py
index be6f68a9a..e48de3491 100644
--- a/dirsrvtests/tests/suites/gssapi/simple_gssapi_test.py
+++ b/dirsrvtests/tests/suites/gssapi/simple_gssapi_test.py
@@ -34,6 +34,8 @@ def testuser(topology_st_gssapi):
})
# Give them a krb princ
user.create_keytab()
+ # Make krb5 config readable by everyone for the tests to work
+ os.chmod(user._instance.realm.krb5confrealm, 0o644)
return user
@gssapi_ack
diff --git a/dirsrvtests/tests/suites/gssapi_repl/gssapi_repl_test.py b/dirsrvtests/tests/suites/gssapi_repl/gssapi_repl_test.py
index 402684aab..fa7fc9c24 100644
--- a/dirsrvtests/tests/suites/gssapi_repl/gssapi_repl_test.py
+++ b/dirsrvtests/tests/suites/gssapi_repl/gssapi_repl_test.py
@@ -10,7 +10,7 @@ import pytest
from lib389.tasks import *
from lib389.utils import *
from lib389.agreement import *
-from lib389.topologies import topology_m2
+from lib389.topologies import topology_m2_gssapi, gssapi_ack
pytestmark = pytest.mark.tier2
@@ -69,25 +69,8 @@ def _allow_machine_account(inst, name):
(ldap.MOD_REPLACE, 'nsDS5ReplicaBindDN', f"uid={name},ou=Machines,{DEFAULT_SUFFIX}".encode('utf-8'))
])
-def _verify_etc_hosts():
- #Check if /etc/hosts is compatible with the test
- NEEDED_HOSTS = ( ('ldapkdc.example.com', '127.0.0.1'),
- ('ldapkdc1.example.com', '127.0.1.1'),
- ('ldapkdc2.example.com', '127.0.2.1'))
- found_hosts = {}
- with open('/etc/hosts','r') as f:
- for l in f:
- s = l.split()
- if len(s) < 2:
- continue
- for nh in NEEDED_HOSTS:
- if (s[0] == nh[1] and s[1] == nh[0]):
- found_hosts[s[1]] = True
- return len(found_hosts) == len(NEEDED_HOSTS)
-
-@pytest.mark.skipif(not _verify_etc_hosts(), reason="/etc/hosts does not contains the needed hosts.")
-@pytest.mark.skipif(True, reason="Test disabled because it requires specific kerberos requirement (server principal, keytab, etc ...")
-def test_gssapi_repl(topology_m2):
+@gssapi_ack
+def test_gssapi_repl(topology_m2_gssapi):
"""Test gssapi authenticated replication agreement of two suppliers using KDC
:id: 552850aa-afc3-473e-9c39-aae802b46f11
@@ -112,8 +95,8 @@ def test_gssapi_repl(topology_m2):
6. Test User should be created on M1 and M2 both
7. Test User should be created on M1 and M2 both
"""
- supplier1 = topology_m2.ms["supplier1"]
- supplier2 = topology_m2.ms["supplier2"]
+ supplier1 = topology_m2_gssapi.ms["supplier1"]
+ supplier2 = topology_m2_gssapi.ms["supplier2"]
# Create the locations on each supplier for the other to bind to.
_create_machine_ou(supplier1)
@@ -134,10 +117,9 @@ def test_gssapi_repl(topology_m2):
# Creating agreement from supplier 1 to supplier 2
# Set the replica bind method to sasl gssapi
- properties = {RA_NAME: r'meTo_$host:$port',
+ properties = {RA_NAME: 'meTo_' + supplier2.host + ':' + str(supplier2.port),
RA_METHOD: 'SASL/GSSAPI',
RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
- supplier1.agreement.delete(suffix=SUFFIX, consumer_host=supplier2.host, consumer_port=supplier2.port)
m1_m2_agmt = supplier1.agreement.create(suffix=SUFFIX, host=supplier2.host, port=supplier2.port, properties=properties)
if not m1_m2_agmt:
log.fatal("Fail to create a supplier -> supplier replica agreement")
@@ -147,10 +129,9 @@ def test_gssapi_repl(topology_m2):
# Creating agreement from supplier 2 to supplier 1
# Set the replica bind method to sasl gssapi
- properties = {RA_NAME: r'meTo_$host:$port',
+ properties = {RA_NAME: 'meTo_' + supplier1.host + ':' + str(supplier1.port),
RA_METHOD: 'SASL/GSSAPI',
RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
- supplier2.agreement.delete(suffix=SUFFIX, consumer_host=supplier1.host, consumer_port=supplier1.port)
m2_m1_agmt = supplier2.agreement.create(suffix=SUFFIX, host=supplier1.host, port=supplier1.port, properties=properties)
if not m2_m1_agmt:
log.fatal("Fail to create a supplier -> supplier replica agreement")
@@ -169,9 +150,15 @@ def test_gssapi_repl(topology_m2):
# Check replication is working...
if supplier1.testReplication(DEFAULT_SUFFIX, supplier2):
- log.info('Replication is working.')
+ log.info('Replication is working: supplier1 -> supplier2')
else:
- log.fatal('Replication is not working.')
+ log.fatal('Replication is not working: supplier1 -> supplier2')
+ assert False
+
+ if supplier2.testReplication(DEFAULT_SUFFIX, supplier1):
+ log.info('Replication is working: supplier2 -> supplier1')
+ else:
+ log.fatal('Replication is not working: supplier2 -> supplier1')
assert False
# Add a user to supplier 1
diff --git a/src/lib389/lib389/topologies.py b/src/lib389/lib389/topologies.py
index 33341f669..84e620cb3 100644
--- a/src/lib389/lib389/topologies.py
+++ b/src/lib389/lib389/topologies.py
@@ -499,6 +499,63 @@ def topology_m2(request):
topology.logcap = LogCapture()
return topology
+@pytest.fixture(scope="module")
+def topology_m2_gssapi(request):
+ """Create Replication Deployment with two suppliers with GSSAPI enabled.
+
+ Similar to topology_st_gssapi but for two suppliers. Configures Kerberos
+ realm, principals and keytabs for ldap/ldapkdc1.<domain> and ldap/ldapkdc2.<domain>,
+ SASL mappings, and disables SSL port on both instances so GSSAPI can be used.
+ """
+ hostname = socket.gethostname().split('.', 1)
+ assert len(hostname) == 2
+ domain = hostname[1]
+ REALM = domain.upper()
+ host_supplier_1 = 'ldapkdc1.' + domain
+ host_supplier_2 = 'ldapkdc2.' + domain
+
+ topology = create_topology({ReplicaRole.SUPPLIER: 2}, request=request,
+ cleanup_cb=lambda x: krb.destroy_realm())
+
+ supplier1 = topology.ms["supplier1"]
+ supplier2 = topology.ms["supplier2"]
+ supplier1.host = host_supplier_1
+ supplier2.host = host_supplier_2
+
+ krb = MitKrb5(realm=REALM, debug=DEBUGGING)
+ if krb.check_realm():
+ krb.destroy_realm()
+ krb.create_realm()
+
+ krb.create_principal(principal=f'ldap/{host_supplier_1}')
+ krb.create_principal(principal=f'ldap/{host_supplier_2}')
+ krb.create_keytab(principal=f'ldap/{host_supplier_1}', keytab='/etc/krb5.keytab')
+ krb.create_keytab(principal=f'ldap/{host_supplier_2}', keytab='/etc/krb5.keytab')
+
+ os.chown('/etc/krb5.keytab', supplier1.get_user_uid(), supplier1.get_group_gid())
+
+ for inst, host in [(supplier1, host_supplier_1), (supplier2, host_supplier_2)]:
+ saslmappings = SaslMappings(inst)
+ for m in saslmappings.list():
+ m.delete()
+ saslmappings.create(properties={
+ 'cn': 'suffix map',
+ 'nsSaslMapRegexString': '\\(.*\\)',
+ 'nsSaslMapBaseDNTemplate': inst.creation_suffix,
+ 'nsSaslMapFilterTemplate': '(uid=\\1)'
+ })
+ inst.realm = krb
+ inst.config.set('nsslapd-localhost', host)
+ inst.sslport = None
+
+ supplier1.restart()
+ supplier2.restart()
+ supplier1.clearTmpDir(__file__)
+ supplier2.clearTmpDir(__file__)
+
+ topology.logcap = LogCapture()
+ return topology
+
@pytest.fixture(scope="module")
def topology_m3(request):
--
2.52.0