11from __future__ import annotations
22
3+ import re
34import socket
45
56from pytest_mh import BackupTopologyController
@@ -58,6 +59,54 @@ def teardown(self) -> None:
5859
5960 super ().teardown ()
6061
62+ def join_domain (self , client : ClientHost , provider : IPAHost | ADHost | SambaHost ):
63+ """
64+ Helper method for joining domains
65+ """
66+ self .logger .info (f"Enrolling { client .hostname } into { provider .domain } " )
67+
68+ # Remove any existing Kerberos configuration and keytab
69+ client .fs .rm ("/etc/krb5.conf" )
70+ client .fs .rm ("/etc/krb5.keytab" )
71+
72+ # First check if joined. If so, leave.
73+ result = client .conn .exec (["realm" , "list" ])
74+ self .logger .info (f"REALM_LIST STDOUT: \n { result .stdout } " )
75+ self .logger .info (f"REALM_LIST STDERR: \n { result .stderr } " )
76+ pattern = rf"^{ re .escape (provider .domain )} $"
77+ if re .search (pattern , result .stdout , re .MULTILINE ):
78+ self .logger .info (f"Found { provider .domain } in realm list. Leaving." )
79+ result = client .conn .exec (
80+ ["realm" , "leave" , provider .domain ], input = provider .adminpw , raise_on_error = False
81+ )
82+ self .logger .info (f"Optional realm leave failed...continuing to join { provider .domain } ." )
83+
84+ if isinstance (provider , (IPAHost )):
85+ # Backup ipa-client-install files
86+ client .fs .backup ("/etc/ipa" )
87+ client .fs .backup ("/var/lib/ipa-client" )
88+
89+ # Configure realm to keep kerberos intact
90+ client .fs .backup ("/etc/realmd.conf" )
91+ client .fs .write (
92+ "/etc/realmd.conf" ,
93+ """
94+ [service]
95+ manage-krb5-conf = no
96+ """ ,
97+ )
98+
99+ # Join provider domain
100+ result = client .conn .exec (["realm" , "join" , provider .domain ], input = provider .adminpw , raise_on_error = False )
101+ if result .rc != 0 :
102+ self .logger .info (f"Running realm join failed with:\n { result .stdout } \n { result .stderr } " )
103+ self .logger .info ("Trying uninstall and join again." )
104+ if isinstance (provider , (IPAHost )):
105+ client .conn .exec (["ipa-client-install" , "--uninstall" , "-U" ])
106+ else :
107+ client .conn .exec (["realm" , "leave" , "--unattended" , provider .domain ], input = provider .adminpw )
108+ client .conn .exec (["realm" , "join" , provider .domain ], input = provider .adminpw )
109+
61110
62111class ClientTopologyController (ProvisionedBackupTopologyController ):
63112 """
@@ -86,18 +135,8 @@ def topology_setup(self, client: ClientHost, ipa: IPAHost) -> None:
86135 self .logger .info (f"Topology '{ self .name } ' is already provisioned" )
87136 return
88137
89- self .logger .info (f"Enrolling { client .hostname } into { ipa .domain } " )
90-
91- # Remove any existing Kerberos configuration and keytab
92- client .fs .rm ("/etc/krb5.conf" )
93- client .fs .rm ("/etc/krb5.keytab" )
94-
95- # Backup ipa-client-install files
96- client .fs .backup ("/etc/ipa" )
97- client .fs .backup ("/var/lib/ipa-client" )
98-
99- # Join ipa domain
100- client .conn .exec (["realm" , "join" , ipa .domain ], input = ipa .adminpw )
138+ # Join IPA domain
139+ self .join_domain (client , ipa )
101140
102141 # Backup so we can restore to this state after each test
103142 super ().topology_setup ()
@@ -114,14 +153,8 @@ def topology_setup(self, client: ClientHost, provider: ADHost | SambaHost) -> No
114153 self .logger .info (f"Topology '{ self .name } ' is already provisioned" )
115154 return
116155
117- self .logger .info (f"Enrolling { client .hostname } into { provider .domain } " )
118-
119- # Remove any existing Kerberos configuration and keytab
120- client .fs .rm ("/etc/krb5.conf" )
121- client .fs .rm ("/etc/krb5.keytab" )
122-
123- # Join AD domain
124- client .conn .exec (["realm" , "join" , provider .domain ], input = provider .adminpw )
156+ # Join AD/Samba domain
157+ self .join_domain (client , provider )
125158
126159 # Backup so we can restore to this state after each test
127160 super ().topology_setup ()
@@ -156,18 +189,8 @@ def topology_setup(self, client: ClientHost, ipa: IPAHost, trusted: ADHost | Sam
156189
157190 # Do not enroll client into IPA domain if it is already joined
158191 if "ipa" not in self .multihost .provisioned_topologies :
159- self .logger .info (f"Enrolling { client .hostname } into { ipa .domain } " )
160-
161- # Remove any existing Kerberos configuration and keytab
162- client .fs .rm ("/etc/krb5.conf" )
163- client .fs .rm ("/etc/krb5.keytab" )
164-
165- # Backup ipa-client-install files
166- client .fs .backup ("/etc/ipa" )
167- client .fs .backup ("/var/lib/ipa-client" )
168-
169- # Join IPA domain)
170- client .conn .exec (["realm" , "join" , ipa .domain ], input = ipa .adminpw )
192+ # Join IPA domain
193+ self .join_domain (client , ipa )
171194
172195 # Backup so we can restore to this state after each test
173196 super ().topology_setup ()
@@ -284,12 +307,19 @@ class GDMTopologyController(ProvisionedBackupTopologyController):
284307
285308 @BackupTopologyController .restore_vanilla_on_error
286309 def topology_setup (self , client : ClientHost , ipa : IPAHost , keycloak : KeycloakHost ) -> None :
310+ if "gdm" not in client .features or not client .features ["gdm" ]:
311+ self .logger .info (f"Topology '{ self .name } ' setup skipped because gdm feature not found on client" )
312+ return
313+
287314 if self .provisioned :
288315 self .logger .info (f"Topology '{ self .name } ' is already provisioned" )
289316 return
290317
291318 self .logger .info (f"Enrolling IPA server { ipa .hostname } into { keycloak .hostname } by creating an IdP client" )
292319
320+ # Join IPA domain
321+ self .join_domain (client , ipa )
322+
293323 # Create an IdP client
294324 keycloak .kclogin ()
295325 keycloak .conn .run (
@@ -311,13 +341,18 @@ def topology_setup(self, client: ClientHost, ipa: IPAHost, keycloak: KeycloakHos
311341 # Backup so we can restore to this state after each test
312342 super ().topology_setup ()
313343
314- def topology_teardown (self , ipa : IPAHost , keycloak : KeycloakHost ) -> None :
344+ def topology_teardown (self , client : ClientHost , ipa : IPAHost , keycloak : KeycloakHost ) -> None :
345+ if "gdm" not in client .features or not client .features ["gdm" ]:
346+ self .logger .info (f"Topology '{ self .name } ' teardown skipped because gdm feature not found on client" )
347+ return
348+
315349 self .logger .info (f"Un-enrolling IPA server { ipa .hostname } from { keycloak .hostname } by deleting the IdP client" )
316350 keycloak .kclogin ()
317351 keycloak .conn .run (
318352 "ID=$(/opt/keycloak/bin/kcadm.sh get clients -q clientId=ipa_oidc_client --fields=id|jq -r '.[0].id'); "
319353 "/opt/keycloak/bin/kcadm.sh delete clients/$ID"
320354 )
355+
321356 ipa .kinit ()
322357 ipa .conn .run ("ipa idp-del keycloak" )
323358 super ().topology_teardown ()
0 commit comments