228 lines
10 KiB
Diff
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
|
|
|