#!/usr/bin/python3 # # Authors: Sumit Bose # Based on ipa-server-install by Karl MacMillan # and ipa-dns-install by Martin Nagy # # Copyright (C) 2011 Red Hat # see file 'COPYING' for use and warranty information # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # from __future__ import print_function import logging import os import sys import six from optparse import SUPPRESS_HELP # pylint: disable=deprecated-module from ipalib.install import sysrestore from ipaserver.install import adtrust, service from ipaserver.install.installutils import ( read_password, check_server_configuration, run_script) from ipapython.admintool import ScriptError from ipapython import version from ipapython import ipautil from ipalib import api, errors, krb_utils from ipapython.config import IPAOptionParser from ipaplatform.paths import paths from ipapython.ipa_log_manager import standard_logging_setup if six.PY3: unicode = str logger = logging.getLogger(os.path.basename(__file__)) log_file_name = paths.IPASERVER_ADTRUST_INSTALL_LOG def parse_options(): parser = IPAOptionParser(version=version.VERSION) parser.add_option("-d", "--debug", dest="debug", action="store_true", default=False, help="print debugging information") parser.add_option("--netbios-name", dest="netbios_name", help="NetBIOS name of the IPA domain") # no-msdcs has not effect, option is here just for backward compatibility parser.add_option("--no-msdcs", dest="no_msdcs", action="store_true", default=False, help=SUPPRESS_HELP) parser.add_option("--rid-base", dest="rid_base", type=int, default=1000, help="Start value for mapping UIDs and GIDs to RIDs") parser.add_option("--secondary-rid-base", dest="secondary_rid_base", type=int, default=100000000, help="Start value of the secondary range for mapping " "UIDs and GIDs to RIDs") parser.add_option("-U", "--unattended", dest="unattended", action="store_true", default=False, help="unattended installation never prompts the user") parser.add_option("-a", "--admin-password", sensitive=True, dest="admin_password", help="admin user kerberos password") parser.add_option("-A", "--admin-name", sensitive=True, dest="admin_name", default='admin', help="admin user principal") parser.add_option("--add-sids", dest="add_sids", action="store_true", default=False, help="Add SIDs for existing users and" " groups as the final step") parser.add_option("--add-agents", dest="add_agents", action="store_true", default=False, help="Add IPA masters to a list of hosts allowed to " "serve information about users from trusted forests") parser.add_option("--enable-compat", dest="enable_compat", default=False, action="store_true", help="Enable support for trusted domains for old " "clients") options, _args = parser.parse_args() safe_options = parser.get_safe_opts(options) return safe_options, options def read_admin_password(admin_name): print("Configuring cross-realm trusts for IPA server requires password " "for user '%s'." % (admin_name)) print("This user is a regular system account used for IPA server " "administration.") print("") admin_password = read_password(admin_name, confirm=False, validate=None) return admin_password def ensure_admin_kinit(admin_name, admin_password): try: ipautil.run([paths.KINIT, admin_name], stdin=admin_password+'\n') except ipautil.CalledProcessError: print("There was error to automatically re-kinit your admin user " "ticket.") return False return True def main(): safe_options, options = parse_options() if os.getegid() != 0: raise ScriptError("Must be root to setup AD trusts on server") standard_logging_setup(log_file_name, debug=options.debug, filemode='a') print("\nThe log file for this installation can be found in %s" % log_file_name) logger.debug('%s was invoked with options: %s', sys.argv[0], safe_options) logger.debug( "missing options might be asked for interactively later\n") logger.debug('IPA version %s', version.VENDOR_VERSION) check_server_configuration() fstore = sysrestore.FileStore(paths.SYSRESTORE) print("================================================================" "==============") print("This program will setup components needed to establish trust to " "AD domains for") print("the IPA Server.") print("") print("This includes:") print(" * Configure Samba") print(" * Add trust related objects to IPA LDAP server") # TODO: # print " * Add a SID to all users and Posix groups" print("") print("To accept the default shown in brackets, press the Enter key.") print("") # Check if samba packages are installed # the same check is in the adtrust module but we must fail first if the # package is missing adtrust.check_for_installed_deps() # Initialize the ipalib api api.bootstrap( in_server=True, debug=options.debug, context='installer', confdir=paths.ETC_IPA ) api.finalize() admin_password = options.admin_password if not (options.unattended or admin_password): admin_password = read_admin_password(options.admin_name) admin_kinited = None if admin_password: admin_kinited = ensure_admin_kinit(options.admin_name, admin_password) if not admin_kinited: print("Proceeding with credentials that existed before") try: principal = krb_utils.get_principal() except errors.CCacheError as e: raise ScriptError( "Must have Kerberos credentials to setup AD trusts on server: " "{err}".format(err=e)) try: api.Backend.ldap2.connect() except errors.ACIError: raise ScriptError( "Outdated Kerberos credentials. " "Use kdestroy and kinit to update your ticket") except errors.DatabaseError: raise ScriptError( "Cannot connect to the LDAP database. Please check if IPA " "is running") try: user = api.Command.user_show( principal.partition('@')[0].partition('/')[0])['result'] group = api.Command.group_show(u'admins')['result'] if not (user['uid'][0] in group['member_user'] and group['cn'][0] in user['memberof_group']): raise errors.RequirementError(name='admins group membership') except errors.RequirementError as e: raise ScriptError( "Must have administrative privileges to setup AD trusts on server" ) except Exception as e: raise ScriptError( "Unrecognized error during check of admin rights: %s" % e) adtrust.install_check(True, options, api) adtrust.install(True, options, fstore, api) # Enable configured services and update DNS SRV records service.sync_services_state(api.env.host) dns_help = adtrust.generate_dns_service_records_help(api) if dns_help: for line in dns_help: service.print_msg(line, sys.stdout) else: api.Command.dns_update_system_records() print(""" ============================================================================= Setup complete You must make sure these network ports are open: \tTCP Ports: \t * 135: epmap \t * 138: netbios-dgm \t * 139: netbios-ssn \t * 445: microsoft-ds \t * 1024..1300: epmap listener range \t * 3268: msft-gc \tUDP Ports: \t * 138: netbios-dgm \t * 139: netbios-ssn \t * 389: (C)LDAP \t * 445: microsoft-ds See the ipa-adtrust-install(1) man page for more details ============================================================================= """) if admin_password: admin_kinited = ensure_admin_kinit(options.admin_name, admin_password) if not admin_kinited: print(""" WARNING: you MUST re-kinit admin user before using 'ipa trust-*' commands family in order to re-generate Kerberos tickets to include AD-specific information""") api.Backend.ldap2.disconnect() return 0 if __name__ == '__main__': run_script( main, log_file_name=log_file_name, operation_name='ipa-adtrust-install')