From 1c15447e1345a3c93932e70dea1177f6a42fb2d4 Mon Sep 17 00:00:00 2001 From: Sergey Orlov Date: Feb 03 2021 16:41:31 +0000 Subject: ipatests: use pexpect to invoke ktutil `ktutil` is a REPL-style utility that can be controlled only interactively. The common approach of sending commands to stdin does not work with it on systems where `readline` library has version less then 8.0 due to a bug in that version. With `pexpect` we avoid this bug because it emulates the terminal when interacting with spawned process instead of simply sending all input to stdin. Related to: https://pagure.io/freeipa/issue/8690 Reviewed-By: Alexander Bokovoy --- diff --git a/ipatests/pytest_ipa/integration/tasks.py b/ipatests/pytest_ipa/integration/tasks.py index 70ec1a3..b918598 100755 --- a/ipatests/pytest_ipa/integration/tasks.py +++ b/ipatests/pytest_ipa/integration/tasks.py @@ -2184,19 +2184,6 @@ class KerberosKeyCopier: return keys_to_sync def copy_key(self, keytab, keyentry): - # keyentry.key is a hex value of the actual key - # prefixed with 0x, as produced by klist -K -k. - # However, ktutil accepts hex value without 0x, so - # we should strip first two characters. - stdin = textwrap.dedent("""\ - rkt {keytab} - addent -key -p {principal} -k {kvno} -e {etype} - {key} - wkt {keytab} - """).format(keytab=keytab, principal=keyentry.principal, - kvno=keyentry.kvno, etype=keyentry.etype, - key=keyentry.key[2:]) - def get_keytab_mtime(): """Get keytab file mtime. @@ -2211,8 +2198,25 @@ class KerberosKeyCopier: mtime_before = get_keytab_mtime() - self.host.run_command([paths.KTUTIL], stdin_text=stdin, - log_stdout=False) + with self.host.spawn_expect(paths.KTUTIL, default_timeout=5) as e: + e.expect_exact('ktutil:') + e.sendline('rkt {}'.format(keytab)) + e.expect_exact('ktutil:') + e.sendline( + 'addent -key -p {principal} -k {kvno} -e {etype}' + .format(principal=keyentry.principal, kvno=keyentry.kvno, + etype=keyentry.etype,)) + e.expect('Key for.+:') + # keyentry.key is a hex value of the actual key + # prefixed with 0x, as produced by klist -K -k. + # However, ktutil accepts hex value without 0x, so + # we should strip first two characters. + e.sendline(keyentry.key[2:]) + e.expect_exact('ktutil:') + e.sendline('wkt {}'.format(keytab)) + e.expect_exact('ktutil:') + e.sendline('q') + if mtime_before == get_keytab_mtime(): raise Exception('{} did not update keytab file "{}"'.format( paths.KTUTIL, keytab))