ipatests: Add AD-integration related tasks

Part of: https://fedorahosted.org/freeipa/ticket/3834
This commit is contained in:
Tomas Babej
2013-09-04 16:29:06 +02:00
committed by Petr Viktorin
parent 70bf2f739b
commit 0e3a39e76c
3 changed files with 324 additions and 5 deletions

View File

@@ -27,6 +27,7 @@ import argparse
from ipapython.ipa_log_manager import log_mgr, standard_logging_setup
from ipatests.test_integration import config
from ipatests.test_integration import tasks
from ipatests.test_integration.host import Host
from ipatests.beakerlib_plugin import BeakerLibProcess
@@ -39,10 +40,10 @@ class TaskRunner(object):
def get_parser(self):
parser = argparse.ArgumentParser(
description="Perform an operation for integration testing."
"All operations are performed on configured hosts, see"
"http://www.freeipa.org/page/V3/Integration_testing"
"see for configuration details")
description="Perform an operation for integration testing. "
"All operations are performed on configured hosts, see "
"http://www.freeipa.org/page/V3/Integration_testing "
"for configuration details")
parser.add_argument('--with-beakerlib', action='store_true',
dest='with_beakerlib',
@@ -153,6 +154,65 @@ class TaskRunner(object):
(Default: all hosts from config)""")
subparser.set_defaults(func=self.cleanup)
subparser = subparsers.add_parser(
'install-adtrust',
help='Runs ipa-adtrust-install on the host')
subparser.add_argument('host', type=str,
help='Host to run ipa-adtrust-install on')
subparser.set_defaults(func=self.install_adtrust)
subparser = subparsers.add_parser(
'configure-dns-for-trust',
help='Sets DNS on the given host for trust with the given AD')
subparser.add_argument('host', type=str,
help='Host to change DNS configuration on')
subparser.add_argument('ad', type=str,
help='AD that trust will be established with')
subparser.set_defaults(func=self.configure_dns_for_trust)
subparser = subparsers.add_parser(
'establish-trust-with-ad',
help='Establishes trust between IPA host and AD')
subparser.add_argument('host', type=str,
help='IPA Host to establish AD trust on')
subparser.add_argument('ad', type=str,
help='AD to establish trust with')
subparser.set_defaults(func=self.establish_trust_with_ad)
subparser = subparsers.add_parser(
'remove-trust-with-ad',
help='Removes trust between IPA host and AD')
subparser.add_argument('host', type=str,
help='IPA Host to remove AD trust on')
subparser.add_argument('ad', type=str,
help='AD to remove trust with')
subparser.set_defaults(func=self.remove_trust_with_ad)
subparser = subparsers.add_parser(
'configure-auth-to-local-rule',
help='Configures auth_to_local rule on IPA host with respect to AD')
subparser.add_argument('host', type=str,
help='IPA Host to configure auth_to_local rule on')
subparser.add_argument('ad', type=str,
help='AD to configure the rule with')
subparser.set_defaults(func=self.configure_auth_to_local_rule)
subparser = subparsers.add_parser(
'clear-sssd-cache',
help='Clears SSSD cache on the IPA host.')
subparser.add_argument('host', type=str,
help='IPA Host to clear SSSD cache on')
subparser.set_defaults(func=self.clear_sssd_cache)
subparser = subparsers.add_parser(
'sync-time',
help='Synchronize time on host with respect to server')
subparser.add_argument('host', type=str,
help='IPA Host to set the time on')
subparser.add_argument('server', type=str,
help='Server that serves as a time source')
subparser.set_defaults(func=self.sync_time)
return parser
def main(self, argv):
@@ -180,6 +240,11 @@ class TaskRunner(object):
args.domain = self.config.domains[0]
if self.config.ad_domains:
args.ad_domain = self.config.ad_domains[0]
else:
args.ad_domain = None
import logging; logging.basicConfig()
try:
@@ -214,12 +279,17 @@ class TaskRunner(object):
return [self.prepare_host(h) for h in default]
def prepare_host(self, host):
if host not in self._prepared_hosts:
# Prepare only UNIX hosts
if host not in self._prepared_hosts and isinstance(host, Host):
host.add_log_collector(self.collect_log)
tasks.prepare_host(host)
self._prepared_hosts.add(host)
return host
def require_ad_domain(self, args):
if not args.ad_domain:
SystemExit("At least one AD domain is required for this task")
def install_master(self, args):
master = self.get_host(args.host, default=args.domain.master)
log.info('Installing master %s', master.hostname)
@@ -289,6 +359,43 @@ class TaskRunner(object):
tasks.install_topo(args.topo, master, replicas, clients,
skip_master=args.skip_master)
def install_adtrust(self, args):
master = self.get_host(args.host, default=args.domain.master)
log.info('Configuring AD trust support on %s', master.hostname)
tasks.install_adtrust(master)
def configure_dns_for_trust(self, args):
self.require_ad_domain(args)
host = self.get_host(args.host, default=args.domain.master)
ad = self.get_host(args.ad, default=args.ad_domain.ads[0])
tasks.configure_dns_for_trust(host, ad)
def establish_trust_with_ad(self, args):
self.require_ad_domain(args)
host = self.get_host(args.host, default=args.domain.master)
ad = self.get_host(args.ad, default=args.ad_domain.ads[0])
tasks.establish_trust_with_ad(host, ad)
def remove_trust_with_ad(self, args):
self.require_ad_domain(args)
host = self.get_host(args.host, default=args.domain.master)
ad = self.get_host(args.ad, default=args.ad_domain.ads[0])
tasks.remove_trust_with_ad(host, ad)
def configure_auth_to_local_rule(self, args):
self.require_ad_domain(args)
host = self.get_host(args.host, default=args.domain.master)
ad = self.get_host(args.ad, default=args.ad_domain.ads[0])
tasks.configure_auth_to_local_rule(host, ad)
def clear_sssd_cache(self, args):
host = self.get_host(args.host, default=args.domain.master)
tasks.clear_sssd_cache(host)
def sync_time(self, args):
host = self.get_host(args.host, default=args.domain.master)
server = self.get_host(args.server)
tasks.sync_time(host, server)
if __name__ == '__main__':
exit(TaskRunner().main(sys.argv[1:]))

View File

@@ -116,6 +116,38 @@ Servers used for client installation are selected in a round-robin fashion.
\fBipa\-test\-task list-topos\fR
List the topologies available for the install-topo subcommand.
.TP
\fBipa\-test\-task install\-adtrust HOST\fR
Run ipa-adtrust-install on the IPA and generate SIDs for the entries in IPA.
.TP
\fBipa\-test\-task configure\-dns\-for\-trust HOST AD\fR
Based on the relationship of the domains configures the IPA DNS for trust.
AD DNS needs to be setup manually.
.TP
\fBipa\-test\-task estabilish\-trust\-with\-ad HOST AD\fR
Estabilishes trust with Active Directory. Trust type is detected depending on
the presence of SfU (Services for Unix) support on the AD.
.TP
\fBipa\-test\-task remove\-trust\-with\-ad HOST AD\fR
Removes trust with Active Directory. Also removes the associated ID range.
.TP
\fBipa\-test\-task configure\-auth\-to\-local\-rule HOST AD\fR
Configures auth_to_local rule in /etc/krb5.conf
.TP
\fBipa\-test\-task clear\-sssd\-cache HOST\fR
Clears SSSD cache by removing the cache files. Restarts SSSD.
.TP
\fBipa\-test\-task sync\-time HOST SERVER\fR
Syncs the time with the remote server. Please note that this function leaves
ntpd stopped.
.SH "EXIT STATUS"
0 if the command was successful

View File

@@ -32,6 +32,7 @@ from ldif import LDIFWriter
from ipapython import ipautil
from ipapython.dn import DN
from ipapython.ipa_log_manager import log_mgr
from ipatests.test_integration import util
from ipatests.test_integration.config import env_to_script
log = log_mgr.get_logger(__name__)
@@ -197,6 +198,7 @@ def install_replica(master, replica, setup_ca=True):
kinit_admin(replica)
def install_client(master, client):
client.collect_log('/var/log/ipaclient-install.log')
@@ -212,6 +214,184 @@ def install_client(master, client):
kinit_admin(client)
def install_adtrust(host):
"""
Runs ipa-adtrust-install on the client and generates SIDs for the entries.
Configures the compat tree for the legacy clients.
"""
# ipa-adtrust-install appends to ipaserver-install.log
host.collect_log('/var/log/ipaserver-install.log')
inst = host.domain.realm.replace('.', '-')
host.collect_log('/var/log/dirsrv/slapd-%s/errors' % inst)
host.collect_log('/var/log/dirsrv/slapd-%s/access' % inst)
kinit_admin(host)
host.run_command(['ipa-adtrust-install', '-U',
'--enable-compat',
'--netbios-name', host.netbios,
'-a', host.config.admin_password,
'--add-sids'])
# Restart named because it lost connection to dirsrv
# (Directory server restarts during the ipa-adtrust-install)
host.run_command(['systemctl', 'restart', 'named'])
# Check that named is running and has loaded the information from LDAP
dig_command = ['dig', 'SRV', '+short', '@localhost',
'_ldap._tcp.%s' % host.domain.name]
dig_output = '0 100 389 %s.' % host.hostname
dig_test = lambda x: re.search(re.escape(dig_output), x)
util.run_repeatedly(host, dig_command, test=dig_test)
def configure_dns_for_trust(master, ad):
"""
This configures DNS on IPA master according to the relationship of the
IPA's and AD's domains.
"""
def is_subdomain(subdomain, domain):
subdomain_unpacked = subdomain.split('.')
domain_unpacked = domain.split('.')
subdomain_unpacked.reverse()
domain_unpacked.reverse()
subdomain = False
if len(subdomain_unpacked) > len(domain_unpacked):
subdomain = True
for subdomain_segment, domain_segment in zip(subdomain_unpacked,
domain_unpacked):
subdomain = subdomain and subdomain_segment == domain_segment
return subdomain
kinit_admin(master)
if is_subdomain(master.domain.name, ad.domain.name):
master.run_command(['ipa', 'dnszone-add', ad.domain.name,
'--name-server', ad.hostname,
'--admin-email', 'hostmaster@%s' % ad.domain.name,
'--forwarder', ad.ip,
'--forward-policy', 'only',
'--ip-address', ad.ip,
'--force'])
elif is_subdomain(ad.domain.name, master.domain.name):
master.run_command(['ipa', 'dnsrecord-add', master.domain.name,
'%s.%s' % (ad.shortname, ad.netbios),
'--a-ip-address', ad.ip])
master.run_command(['ipa', 'dnsrecord-add', master.domain.name,
ad.netbios,
'--ns-hostname',
'%s.%s' % (ad.shortname, ad.netbios)])
master.run_command(['ipa', 'dnszone-mod', master.domain.name,
'--allow-transfer', ad.ip])
else:
master.run_command(['ipa', 'dnszone-add', ad.domain.name,
'--name-server', ad.hostname,
'--admin-email', 'hostmaster@%s' % ad.domain.name,
'--forwarder', ad.ip,
'--forward-policy', 'only',
'--ip-address', ad.ip,
'--force'])
def establish_trust_with_ad(master, ad, extra_args=()):
"""
Establishes trust with Active Directory. Trust type is detected depending
on the presence of SfU (Services for Unix) support on the AD.
Use extra arguments to pass extra arguments to the trust-add command, such
as --range-type="ipa-ad-trust" to enfroce a particular range type.
"""
# Force KDC to reload MS-PAC info by trying to get TGT for HTTP
master.run_command(['kinit', '-kt', '/etc/httpd/conf/ipa.keytab',
'HTTP/%s' % master.hostname])
master.run_command(['systemctl', 'restart', 'krb5kdc.service'])
master.run_command(['kdestroy', '-A'])
kinit_admin(master)
master.run_command(['klist'])
master.run_command(['smbcontrol', 'all', 'debug', '100'])
util.run_repeatedly(master,
['ipa', 'trust-add',
'--type', 'ad', ad.domain.name,
'--admin', 'Administrator',
'--password'] + list(extra_args),
stdin_text=master.config.ad_admin_password)
master.run_command(['smbcontrol', 'all', 'debug', '1'])
clear_sssd_cache(master)
def remove_trust_with_ad(master, ad):
"""
Removes trust with Active Directory. Also removes the associated ID range.
"""
kinit_admin(master)
# Remove the trust
master.run_command(['ipa', 'trust-del', ad.domain.name])
# Remove the range
range_name = ad.domain.name.upper() + '_id_range'
master.run_command(['ipa', 'idrange-del', range_name])
def configure_auth_to_local_rule(master, ad):
"""
Configures auth_to_local rule in /etc/krb5.conf
"""
section_identifier = " %s = {" % master.domain.realm
line1 = (" auth_to_local = RULE:[1:$1@$0](^.*@%s$)s/@%s/@%s/"
% (ad.domain.realm, ad.domain.realm, ad.domain.name))
line2 = " auth_to_local = DEFAULT"
krb5_conf_content = master.get_file_contents('/etc/krb5.conf')
krb5_lines = [line.rstrip() for line in krb5_conf_content.split('\n')]
realm_section_index = krb5_lines.index(section_identifier)
krb5_lines.insert(realm_section_index + 1, line1)
krb5_lines.insert(realm_section_index + 2, line2)
krb5_conf_new_content = '\n'.join(krb5_lines)
master.put_file_contents('/etc/krb5.conf', krb5_conf_new_content)
master.run_command(['systemctl', 'restart', 'sssd'])
def clear_sssd_cache(host):
"""
Clears SSSD cache by removing the cache files. Restarts SSSD.
"""
host.run_command(['systemctl', 'stop', 'sssd'])
host.run_command(['rm', '-rfv', '/var/lib/sss/db/cache_%s.ldb'
% host.domain.name])
host.run_command(['rm', '-rfv', '/var/lib/sss/mc/group'])
host.run_command(['rm', '-rfv', '/var/lib/sss/mc/passwd'])
host.run_command(['systemctl', 'start', 'sssd'])
def sync_time(host, server):
"""
Syncs the time with the remote server. Please note that this function
leaves ntpd stopped.
"""
host.run_command(['sudo', 'systemctl', 'stop', 'ntpd'])
host.run_command(['sudo', 'ntpdate', server.hostname])
def connect_replica(master, replica):
kinit_admin(replica)
replica.run_command(['ipa-replica-manage', 'connect', master.hostname])