mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
ipatests: Add AD-integration related tasks
Part of: https://fedorahosted.org/freeipa/ticket/3834
This commit is contained in:
committed by
Petr Viktorin
parent
70bf2f739b
commit
0e3a39e76c
@@ -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:]))
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
Reference in New Issue
Block a user