Add pytest OpenSSH transport with password

The pytest_multihost transport does not provide password-based
authentication for OpenSSH transport. The OpenSSH command line tool has
no API to pass in a password securely.

The patch implements a custom transport that uses sshpass hack. It is
not recommended for production but good enough for testing.

Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
Christian Heimes 2020-01-24 14:03:00 +01:00 committed by Alexander Bokovoy
parent 9e47799cc7
commit e8602b1586
3 changed files with 54 additions and 0 deletions

View File

@ -750,6 +750,8 @@ Requires: python3-pytest-sourceorder
Requires: python3-sssdconfig >= %{sssd_version} Requires: python3-sssdconfig >= %{sssd_version}
Requires: tar Requires: tar
Requires: xz Requires: xz
Requires: openssh-clients
Requires: sshpass
%description -n python3-ipatests %description -n python3-ipatests
IPA is an integrated solution to provide centrally managed Identity (users, IPA is an integrated solution to provide centrally managed Identity (users,

View File

@ -31,6 +31,7 @@ from ipapython import ipaldap
from .fips import ( from .fips import (
is_fips_enabled, enable_userspace_fips, disable_userspace_fips is_fips_enabled, enable_userspace_fips, disable_userspace_fips
) )
from .transport import IPAOpenSSHTransport
FIPS_NOISE_RE = re.compile(br"FIPS mode initialized\r?\n?") FIPS_NOISE_RE = re.compile(br"FIPS mode initialized\r?\n?")
@ -65,6 +66,8 @@ class LDAPClientWithoutCertCheck(ipaldap.LDAPClient):
class Host(pytest_multihost.host.Host): class Host(pytest_multihost.host.Host):
"""Representation of a remote IPA host""" """Representation of a remote IPA host"""
transport_class = IPAOpenSSHTransport
def __init__(self, domain, hostname, role, ip=None, def __init__(self, domain, hostname, role, ip=None,
external_hostname=None, username=None, password=None, external_hostname=None, username=None, password=None,
test_dir=None, host_type=None): test_dir=None, host_type=None):
@ -203,3 +206,4 @@ class WinHost(pytest_multihost.host.WinHost):
This serves as a sketch class once we move from manual preparation of This serves as a sketch class once we move from manual preparation of
Active Directory to the automated setup. Active Directory to the automated setup.
""" """
transport_class = IPAOpenSSHTransport

View File

@ -0,0 +1,48 @@
#
# Copyright (C) 2020 FreeIPA Contributors see COPYING for license
#
"""Enhanced SSH transport for pytest multihost
Provides SSH password login for OpenSSH transport
"""
import os
from pytest_multihost.transport import OpenSSHTransport
class IPAOpenSSHTransport(OpenSSHTransport):
def _get_ssh_argv(self):
"""Return the path to SSH and options needed for every call"""
control_file = os.path.join(self.control_dir.path, "control")
known_hosts_file = os.path.join(self.control_dir.path, "known_hosts")
argv = [
"ssh",
"-l",
self.host.ssh_username,
"-o",
"ControlPath=%s" % control_file,
"-o",
"StrictHostKeyChecking=no",
"-o",
"UserKnownHostsFile=%s" % known_hosts_file,
]
if self.host.ssh_key_filename:
key_filename = os.path.expanduser(self.host.ssh_key_filename)
argv.extend(["-i", key_filename])
elif self.host.ssh_password:
password_file = os.path.join(self.control_dir.path, "password")
with open(password_file, "w") as f:
os.fchmod(f.fileno(), 600)
f.write(self.host.ssh_password)
f.write("\n")
argv = ["sshpass", f"-f{password_file}"] + argv
else:
self.log.critical("No SSH credentials configured")
raise RuntimeError("No SSH credentials configured")
argv.append(self.host.external_hostname)
self.log.debug("SSH invocation: %s", argv)
return argv