def __init__(self, service_name, service_desc=None, sstore=None, fstore=None, api=api, realm_name=None, service_user=None, service_prefix=None, keytab=None): self.service_name = service_name self.service_desc = service_desc self.service = services.service(service_name, api) self.steps = [] self.output_fd = sys.stdout self.fqdn = socket.gethostname() if sstore: self.sstore = sstore else: self.sstore = sysrestore.StateFile(paths.SYSRESTORE) if fstore: self.fstore = fstore else: self.fstore = sysrestore.FileStore(paths.SYSRESTORE) self.realm = realm_name self.suffix = DN() self.service_prefix = service_prefix self.keytab = keytab self.cert = None self.api = api self.service_user = service_user self.keytab_user = service_user self.dm_password = None # silence pylint self.promote = False
def is_ipa_configured(): """ Using the state and index install files determine if IPA is already configured. """ installed = False sstore = sysrestore.StateFile(paths.SYSRESTORE) fstore = sysrestore.FileStore(paths.SYSRESTORE) for module in IPA_MODULES: if sstore.has_state(module): logger.debug('%s is configured', module) installed = True else: logger.debug('%s is not configured', module) if fstore.has_files(): logger.debug('filestore has files') installed = True else: logger.debug('filestore is tracking no files') return installed
def uninstall_check(installer): options = installer tasks.check_selinux_status() installer._installation_cleanup = False if not is_ipa_configured(): print("WARNING:\nIPA server is not configured on this system. " "If you want to install the\nIPA server, please install " "it using 'ipa-server-install'.") fstore = sysrestore.FileStore(SYSRESTORE_DIR_PATH) sstore = sysrestore.StateFile(SYSRESTORE_DIR_PATH) # Configuration for ipalib, we will bootstrap and finalize later, after # we are sure we have the configuration file ready. cfg = dict( context='installer', confdir=paths.ETC_IPA, in_server=True, ) # We will need at least api.env, finalize api now. This system is # already installed, so the configuration file is there. api.bootstrap(**cfg) api.finalize() if installer.interactive: print( "\nThis is a NON REVERSIBLE operation and will delete all data " "and configuration!\nIt is highly recommended to take a backup of " "existing data and configuration using ipa-backup utility " "before proceeding.\n") if not user_input( "Are you sure you want to continue with the " "uninstall procedure?", False): raise ScriptError("Aborting uninstall operation.") try: api.Backend.ldap2.connect(autobind=True) domain_level = dsinstance.get_domain_level(api) except Exception: msg = ("\nWARNING: Failed to connect to Directory Server to find " "information about replication agreements. Uninstallation " "will continue despite the possible existing replication " "agreements.\n\n" "If this server is the last instance of CA, KRA, or DNSSEC " "master, uninstallation may result in data loss.\n\n") print(textwrap.fill(msg, width=80, replace_whitespace=False)) if (installer.interactive and not user_input( "Are you sure you want to continue with the uninstall " "procedure?", False)): raise ScriptError("Aborting uninstall operation.") else: dns.uninstall_check(options) if domain_level == DOMAIN_LEVEL_0: rm = replication.ReplicationManager(realm=api.env.realm, hostname=api.env.host, dirman_passwd=None, conn=api.Backend.ldap2) agreements = rm.find_ipa_replication_agreements() if agreements: other_masters = [a.get('cn')[0][4:] for a in agreements] msg = ( "\nReplication agreements with the following IPA masters " "found: %s. Removing any replication agreements before " "uninstalling the server is strongly recommended. You can " "remove replication agreements by running the following " "command on any other IPA master:\n" % ", ".join(other_masters)) cmd = "$ ipa-replica-manage del %s\n" % api.env.host print(textwrap.fill(msg, width=80, replace_whitespace=False)) print(cmd) if (installer.interactive and not user_input( "Are you sure you want to continue with" " the uninstall procedure?", False)): raise ScriptError("Aborting uninstall operation.") else: remove_master_from_managed_topology(api, options) api.Backend.ldap2.disconnect() installer._fstore = fstore installer._sstore = sstore
def install_check(installer): options = installer dirsrv_pkcs12_file = installer._dirsrv_pkcs12_file http_pkcs12_file = installer._http_pkcs12_file pkinit_pkcs12_file = installer._pkinit_pkcs12_file dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info http_pkcs12_info = installer._http_pkcs12_info pkinit_pkcs12_info = installer._pkinit_pkcs12_info external_cert_file = installer._external_cert_file external_ca_file = installer._external_ca_file http_ca_cert = installer._ca_cert tasks.check_ipv6_stack_enabled() tasks.check_selinux_status() if options.master_password: msg = ("WARNING:\noption '-P/--master-password' is deprecated. " "KDC master password of sufficient strength is autogenerated " "during IPA server installation and should not be set " "manually.") print(textwrap.fill(msg, width=79, replace_whitespace=False)) installer._installation_cleanup = True print("\nThe log file for this installation can be found in " "/var/log/ipaserver-install.log") if (not options.external_ca and not options.external_cert_files and is_ipa_configured()): installer._installation_cleanup = False raise ScriptError( "IPA server is already configured on this system.\n" "If you want to reinstall the IPA server, please uninstall " "it first using 'ipa-server-install --uninstall'.") client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if client_fstore.has_files(): installer._installation_cleanup = False raise ScriptError( "IPA client is already configured on this system.\n" "Please uninstall it before configuring the IPA server, " "using 'ipa-client-install --uninstall'") fstore = sysrestore.FileStore(SYSRESTORE_DIR_PATH) sstore = sysrestore.StateFile(SYSRESTORE_DIR_PATH) # This will override any settings passed in on the cmdline if ipautil.file_exists(paths.ROOT_IPA_CACHE): if options.dm_password is not None: dm_password = options.dm_password else: dm_password = read_password("Directory Manager", confirm=False) if dm_password is None: raise ScriptError("Directory Manager password required") try: cache_vars = read_cache(dm_password) options.__dict__.update(cache_vars) if cache_vars.get('external_ca', False): options.external_ca = False options.interactive = False except Exception as e: raise ScriptError("Cannot process the cache file: %s" % str(e)) # We only set up the CA if the PKCS#12 options are not given. if options.dirsrv_cert_files: setup_ca = False else: setup_ca = True options.setup_ca = setup_ca if not setup_ca and options.ca_subject: raise ScriptError( "--ca-subject cannot be used with CA-less installation") if not setup_ca and options.subject_base: raise ScriptError( "--subject-base cannot be used with CA-less installation") if not setup_ca and options.setup_kra: raise ScriptError( "--setup-kra cannot be used with CA-less installation") print("=======================================" "=======================================") print("This program will set up the FreeIPA Server.") print("") print("This includes:") if setup_ca: print(" * Configure a stand-alone CA (dogtag) for certificate " "management") if not options.no_ntp: print(" * Configure the Network Time Daemon (ntpd)") print(" * Create and configure an instance of Directory Server") print(" * Create and configure a Kerberos Key Distribution Center (KDC)") print(" * Configure Apache (httpd)") if options.setup_kra: print(" * Configure KRA (dogtag) for secret management") if options.setup_dns: print(" * Configure DNS (bind)") if options.setup_adtrust: print(" * Configure Samba (smb) and winbind for managing AD trusts") if not options.no_pkinit: print(" * Configure the KDC to enable PKINIT") if options.no_ntp: print("") print("Excluded by options:") print(" * Configure the Network Time Daemon (ntpd)") if installer.interactive: print("") print("To accept the default shown in brackets, press the Enter key.") print("") if not options.external_cert_files: # Make sure the 389-ds ports are available check_dirsrv(not installer.interactive) if not options.no_ntp: try: ipaclient.install.ntpconf.check_timedate_services() except ipaclient.install.ntpconf.NTPConflictingService as e: print( ("WARNING: conflicting time&date synchronization service '%s'" " will be disabled" % e.conflicting_service)) print("in favor of ntpd") print("") except ipaclient.install.ntpconf.NTPConfigurationError: pass # Check to see if httpd is already configured to listen on 443 if httpinstance.httpd_443_configured(): raise ScriptError("Aborting installation") if not options.setup_dns and installer.interactive: if ipautil.user_input( "Do you want to configure integrated DNS " "(BIND)?", False): options.setup_dns = True print("") # check bind packages are installed if options.setup_dns: # Don't require an external DNS to say who we are if we are # setting up a local DNS server. options.no_host_dns = True # check the hostname is correctly configured, it must be as the kldap # utilities just use the hostname as returned by getaddrinfo to set # up some of the standard entries if options.host_name: host_default = options.host_name else: host_default = get_fqdn() try: if not installer.interactive or options.host_name: verify_fqdn(host_default, options.no_host_dns) host_name = host_default else: host_name = read_host_name(host_default, options.no_host_dns) except BadHostError as e: raise ScriptError(e) host_name = host_name.lower() root_logger.debug("will use host_name: %s\n" % host_name) if not options.domain_name: domain_name = read_domain_name(host_name[host_name.find(".") + 1:], not installer.interactive) root_logger.debug("read domain_name: %s\n" % domain_name) try: validate_domain_name(domain_name) except ValueError as e: raise ScriptError("Invalid domain name: %s" % unicode(e)) else: domain_name = options.domain_name domain_name = domain_name.lower() if not options.realm_name: realm_name = read_realm_name(domain_name, not installer.interactive) root_logger.debug("read realm_name: %s\n" % realm_name) else: realm_name = options.realm_name.upper() if not options.subject_base: options.subject_base = installutils.default_subject_base(realm_name) if not options.ca_subject: options.ca_subject = \ installutils.default_ca_subject_dn(options.subject_base) if options.http_cert_files: if options.http_pin is None: options.http_pin = installutils.read_password( "Enter Apache Server private key unlock", confirm=False, validate=False, retry=False) if options.http_pin is None: raise ScriptError( "Apache Server private key unlock password required") http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12( cert_files=options.http_cert_files, key_password=options.http_pin, key_nickname=options.http_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) http_pkcs12_info = (http_pkcs12_file.name, http_pin) if options.dirsrv_cert_files: if options.dirsrv_pin is None: options.dirsrv_pin = read_password( "Enter Directory Server private key unlock", confirm=False, validate=False, retry=False) if options.dirsrv_pin is None: raise ScriptError( "Directory Server private key unlock password required") dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12( cert_files=options.dirsrv_cert_files, key_password=options.dirsrv_pin, key_nickname=options.dirsrv_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) if options.pkinit_cert_files: if options.pkinit_pin is None: options.pkinit_pin = read_password( "Enter Kerberos KDC private key unlock", confirm=False, validate=False, retry=False) if options.pkinit_pin is None: raise ScriptError( "Kerberos KDC private key unlock password required") pkinit_pkcs12_file, pkinit_pin, _pkinit_ca_cert = load_pkcs12( cert_files=options.pkinit_cert_files, key_password=options.pkinit_pin, key_nickname=options.pkinit_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin) if (options.http_cert_files and options.dirsrv_cert_files and http_ca_cert != dirsrv_ca_cert): raise ScriptError( "Apache Server SSL certificate and Directory Server SSL " "certificate are not signed by the same CA certificate") if not options.dm_password: dm_password = read_dm_password() if dm_password is None: raise ScriptError("Directory Manager password required") else: dm_password = options.dm_password if not options.master_password: master_password = ipa_generate_password() else: master_password = options.master_password if not options.admin_password: admin_password = read_admin_password() if admin_password is None: raise ScriptError("IPA admin password required") else: admin_password = options.admin_password # Configuration for ipalib, we will bootstrap and finalize later, after # we are sure we have the configuration file ready. cfg = dict( context='installer', confdir=paths.ETC_IPA, in_server=True, # make sure host name specified by user is used instead of default host=host_name, ) if setup_ca: # we have an IPA-integrated CA cfg['ca_host'] = host_name # Create the management framework config file and finalize api target_fname = paths.IPA_DEFAULT_CONF fd = open(target_fname, "w") fd.write("[global]\n") fd.write("host=%s\n" % host_name) fd.write("basedn=%s\n" % ipautil.realm_to_suffix(realm_name)) fd.write("realm=%s\n" % realm_name) fd.write("domain=%s\n" % domain_name) fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % format_netloc(host_name)) fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % installutils.realm_to_serverid(realm_name)) if setup_ca: fd.write("enable_ra=True\n") fd.write("ra_plugin=dogtag\n") fd.write("dogtag_version=10\n") else: fd.write("enable_ra=False\n") fd.write("ra_plugin=none\n") fd.write("mode=production\n") fd.close() # Must be readable for everyone os.chmod(target_fname, 0o644) api.bootstrap(**cfg) api.finalize() if setup_ca: ca.install_check(False, None, options) if options.setup_kra: kra.install_check(api, None, options) if options.setup_dns: dns.install_check(False, api, False, options, host_name) ip_addresses = dns.ip_addresses else: ip_addresses = get_server_ip_address(host_name, not installer.interactive, False, options.ip_addresses) # check addresses here, dns module is doing own check network_ip_address_warning(ip_addresses) broadcast_ip_address_warning(ip_addresses) if options.setup_adtrust: adtrust.install_check(False, options, api) # installer needs to update hosts file when DNS subsystem will be # installed or custom addresses are used if options.ip_addresses or options.setup_dns: installer._update_hosts_file = True print() print("The IPA Master Server will be configured with:") print("Hostname: %s" % host_name) print("IP address(es): %s" % ", ".join(str(ip) for ip in ip_addresses)) print("Domain name: %s" % domain_name) print("Realm name: %s" % realm_name) print() if options.setup_dns: print("BIND DNS server will be configured to serve IPA domain with:") print("Forwarders: %s" % ("No forwarders" if not options.forwarders else ", ".join( [str(ip) for ip in options.forwarders]))) print('Forward policy: %s' % options.forward_policy) print("Reverse zone(s): %s" % ("No reverse zone" if options.no_reverse or not dns.reverse_zones else ", ".join(str(rz) for rz in dns.reverse_zones))) print() if not options.setup_adtrust: # If domain name and realm does not match, IPA server will not be able # to estabilish trust with Active Directory. Print big fat warning. realm_not_matching_domain = (domain_name.upper() != realm_name) if realm_not_matching_domain: print("WARNING: Realm name does not match the domain name.\n" "You will not be able to estabilish trusts with Active " "Directory unless\nthe realm name of the IPA server matches " "its domain name.\n\n") if installer.interactive and not user_input( "Continue to configure the system with these values?", False): raise ScriptError("Installation aborted") options.realm_name = realm_name options.domain_name = domain_name options.dm_password = dm_password options.master_password = master_password options.admin_password = admin_password options._host_name_overridden = bool(options.host_name) options.host_name = host_name options.ip_addresses = ip_addresses installer._fstore = fstore installer._sstore = sstore installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file installer._http_pkcs12_file = http_pkcs12_file installer._pkinit_pkcs12_file = pkinit_pkcs12_file installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info installer._http_pkcs12_info = http_pkcs12_info installer._pkinit_pkcs12_info = pkinit_pkcs12_info installer._external_cert_file = external_cert_file installer._external_ca_file = external_ca_file installer._ca_cert = http_ca_cert
def configure_automount(): try: check_client_configuration() except ScriptError as e: print(e.msg) sys.exit(e.rval) fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE) options, _args = parse_options() standard_logging_setup( paths.IPACLIENT_INSTALL_LOG, verbose=False, debug=options.debug, filemode='a', console_format='%(message)s', ) cfg = dict( context='cli_installer', confdir=paths.ETC_IPA, in_server=False, debug=options.debug, verbose=0, ) # Bootstrap API early so that env object is available api.bootstrap(**cfg) if options.uninstall: return uninstall(fstore, statestore) ca_cert_path = None if os.path.exists(paths.IPA_CA_CRT): ca_cert_path = paths.IPA_CA_CRT if statestore.has_state('autofs'): print('An automount location is already configured') sys.exit(CLIENT_ALREADY_CONFIGURED) autodiscover = False ds = ipadiscovery.IPADiscovery() if not options.server: print("Searching for IPA server...") ret = ds.search(ca_cert_path=ca_cert_path) logger.debug('Executing DNS discovery') if ret == ipadiscovery.NO_LDAP_SERVER: logger.debug('Autodiscovery did not find LDAP server') s = urlsplit(api.env.xmlrpc_uri) server = [s.netloc] logger.debug('Setting server to %s', s.netloc) else: autodiscover = True if not ds.servers: sys.exit( 'Autodiscovery was successful but didn\'t return a server' ) logger.debug( 'Autodiscovery success, possible servers %s', ','.join(ds.servers), ) server = ds.servers[0] else: server = options.server logger.debug("Verifying that %s is an IPA server", server) ldapret = ds.ipacheckldap(server, api.env.realm, ca_cert_path) if ldapret[0] == ipadiscovery.NO_ACCESS_TO_LDAP: print("Anonymous access to the LDAP server is disabled.") print("Proceeding without strict verification.") print( "Note: This is not an error if anonymous access has been " "explicitly restricted." ) elif ldapret[0] == ipadiscovery.NO_TLS_LDAP: logger.warning("Unencrypted access to LDAP is not supported.") elif ldapret[0] != 0: sys.exit('Unable to confirm that %s is an IPA server' % server) if not autodiscover: print("IPA server: %s" % server) logger.debug('Using fixed server %s', server) else: print("IPA server: DNS discovery") logger.debug('Configuring to use DNS discovery') print("Location: %s" % options.location) logger.debug('Using automount location %s', options.location) ccache_dir = tempfile.mkdtemp() ccache_name = os.path.join(ccache_dir, 'ccache') try: try: host_princ = str('host/%s@%s' % (api.env.host, api.env.realm)) kinit_keytab(host_princ, paths.KRB5_KEYTAB, ccache_name) os.environ['KRB5CCNAME'] = ccache_name except gssapi.exceptions.GSSError as e: sys.exit("Failed to obtain host TGT: %s" % e) # Finalize API when TGT obtained using host keytab exists api.finalize() # Now we have a TGT, connect to IPA try: api.Backend.rpcclient.connect() except errors.KerberosError as e: sys.exit('Cannot connect to the server due to ' + str(e)) try: # Use the RPC directly so older servers are supported api.Backend.rpcclient.forward( 'automountlocation_show', ipautil.fsdecode(options.location), version=u'2.0', ) except errors.VersionError as e: sys.exit('This client is incompatible: ' + str(e)) except errors.NotFound: sys.exit( "Automount location '%s' does not exist" % options.location ) except errors.PublicError as e: sys.exit( "Cannot connect to the server due to generic error: %s" % str(e) ) finally: shutil.rmtree(ccache_dir) if not options.unattended and not ipautil.user_input( "Continue to configure the system with these values?", False ): sys.exit("Installation aborted") try: if not options.sssd: tasks.enable_ldap_automount(statestore) configure_nfs(fstore, statestore, options) if options.sssd: configure_autofs_sssd(fstore, statestore, autodiscover, options) else: configure_xml(fstore) configure_autofs( fstore, statestore, autodiscover, server, options ) configure_autofs_common(fstore, statestore, options) except Exception as e: logger.debug('Raised exception %s', e) print("Installation failed. Rolling back changes.") uninstall(fstore, statestore) return 1 return 0
def install_check(installer): options = installer dirsrv_pkcs12_file = installer._dirsrv_pkcs12_file http_pkcs12_file = installer._http_pkcs12_file pkinit_pkcs12_file = installer._pkinit_pkcs12_file dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info http_pkcs12_info = installer._http_pkcs12_info pkinit_pkcs12_info = installer._pkinit_pkcs12_info external_cert_file = installer._external_cert_file external_ca_file = installer._external_ca_file http_ca_cert = installer._ca_cert dirsrv_ca_cert = None pkinit_ca_cert = None tasks.check_ipv6_stack_enabled() tasks.check_selinux_status() check_ldap_conf() mask_str = validate_mask() if mask_str: print("Unexpected system mask: %s, expected 0022" % mask_str) if installer.interactive: if not user_input("Do you want to continue anyway?", True): raise ScriptError( "Unexpected system mask: %s" % mask_str) else: raise ScriptError("Unexpected system mask: %s" % mask_str) if options.master_password: msg = ("WARNING:\noption '-P/--master-password' is deprecated. " "KDC master password of sufficient strength is autogenerated " "during IPA server installation and should not be set " "manually.") print(textwrap.fill(msg, width=79, replace_whitespace=False)) installer._installation_cleanup = True print("\nThe log file for this installation can be found in " "/var/log/ipaserver-install.log") if (not options.external_ca and not options.external_cert_files and is_ipa_configured()): installer._installation_cleanup = False raise ScriptError( "IPA server is already configured on this system.\n" "If you want to reinstall the IPA server, please uninstall " "it first using 'ipa-server-install --uninstall'.") client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if client_fstore.has_files(): installer._installation_cleanup = False raise ScriptError( "IPA client is already configured on this system.\n" "Please uninstall it before configuring the IPA server, " "using 'ipa-client-install --uninstall'") fstore = sysrestore.FileStore(SYSRESTORE_DIR_PATH) sstore = sysrestore.StateFile(SYSRESTORE_DIR_PATH) # This will override any settings passed in on the cmdline if os.path.isfile(paths.ROOT_IPA_CACHE): if options.dm_password is not None: dm_password = options.dm_password else: dm_password = read_password("Directory Manager", confirm=False) if dm_password is None: raise ScriptError("Directory Manager password required") try: cache_vars = read_cache(dm_password) options.__dict__.update(cache_vars) if cache_vars.get('external_ca', False): options.external_ca = False options.interactive = False except Exception as e: raise ScriptError("Cannot process the cache file: %s" % str(e)) # We only set up the CA if the PKCS#12 options are not given. if options.dirsrv_cert_files: setup_ca = False else: setup_ca = True options.setup_ca = setup_ca if not setup_ca and options.ca_subject: raise ScriptError( "--ca-subject cannot be used with CA-less installation") if not setup_ca and options.subject_base: raise ScriptError( "--subject-base cannot be used with CA-less installation") if not setup_ca and options.setup_kra: raise ScriptError( "--setup-kra cannot be used with CA-less installation") print("=======================================" "=======================================") print("This program will set up the FreeIPA Server.") print("Version {}".format(version.VERSION)) print("") print("This includes:") if setup_ca: print(" * Configure a stand-alone CA (dogtag) for certificate " "management") if not options.no_ntp: print(" * Configure the NTP client (chronyd)") print(" * Create and configure an instance of Directory Server") print(" * Create and configure a Kerberos Key Distribution Center (KDC)") print(" * Configure Apache (httpd)") if options.setup_kra: print(" * Configure KRA (dogtag) for secret management") if options.setup_dns: print(" * Configure DNS (bind)") if options.setup_adtrust: print(" * Configure Samba (smb) and winbind for managing AD trusts") if not options.no_pkinit: print(" * Configure the KDC to enable PKINIT") if options.no_ntp: print("") print("Excluded by options:") print(" * Configure the NTP client (chronyd)") if installer.interactive: print("") print("To accept the default shown in brackets, press the Enter key.") print("") if not options.external_cert_files: # Make sure the 389-ds ports are available check_dirsrv(not installer.interactive) if not options.no_ntp: try: timeconf.check_timedate_services() except timeconf.NTPConflictingService as e: print( "WARNING: conflicting time&date synchronization service " "'{}' will be disabled in favor of chronyd\n".format( e.conflicting_service ) ) except timeconf.NTPConfigurationError: pass if not options.setup_dns and installer.interactive: if ipautil.user_input("Do you want to configure integrated DNS " "(BIND)?", False): options.setup_dns = True print("") # check bind packages are installed if options.setup_dns: # Don't require an external DNS to say who we are if we are # setting up a local DNS server. options.no_host_dns = True # check the hostname is correctly configured, it must be as the kldap # utilities just use the hostname as returned by getaddrinfo to set # up some of the standard entries if options.host_name: host_default = options.host_name else: host_default = get_fqdn() try: if not installer.interactive or options.host_name: verify_fqdn(host_default, options.no_host_dns) host_name = host_default else: host_name = read_host_name(host_default, options.no_host_dns) except BadHostError as e: raise ScriptError(e) host_name = host_name.lower() logger.debug("will use host_name: %s\n", host_name) if not options.domain_name: domain_name = read_domain_name(host_name[host_name.find(".")+1:], not installer.interactive) logger.debug("read domain_name: %s\n", domain_name) try: validate_domain_name(domain_name) except ValueError as e: raise ScriptError("Invalid domain name: %s" % unicode(e)) else: domain_name = options.domain_name domain_name = domain_name.lower() if not options.realm_name: realm_name = read_realm_name(domain_name, not installer.interactive) logger.debug("read realm_name: %s\n", realm_name) try: validate_domain_name(realm_name, entity="realm") except ValueError as e: raise ScriptError("Invalid realm name: {}".format(unicode(e))) else: realm_name = options.realm_name.upper() if not options.subject_base: options.subject_base = installutils.default_subject_base(realm_name) if not options.ca_subject: options.ca_subject = \ installutils.default_ca_subject_dn(options.subject_base) if options.http_cert_files: if options.http_pin is None: options.http_pin = installutils.read_password( "Enter Apache Server private key unlock", confirm=False, validate=False, retry=False) if options.http_pin is None: raise ScriptError( "Apache Server private key unlock password required") http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12( cert_files=options.http_cert_files, key_password=options.http_pin, key_nickname=options.http_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) http_pkcs12_info = (http_pkcs12_file.name, http_pin) if options.dirsrv_cert_files: if options.dirsrv_pin is None: options.dirsrv_pin = read_password( "Enter Directory Server private key unlock", confirm=False, validate=False, retry=False) if options.dirsrv_pin is None: raise ScriptError( "Directory Server private key unlock password required") dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12( cert_files=options.dirsrv_cert_files, key_password=options.dirsrv_pin, key_nickname=options.dirsrv_cert_name, ca_cert_files=options.ca_cert_files, host_name=host_name) dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) if options.pkinit_cert_files: if options.pkinit_pin is None: options.pkinit_pin = read_password( "Enter Kerberos KDC private key unlock", confirm=False, validate=False, retry=False) if options.pkinit_pin is None: raise ScriptError( "Kerberos KDC private key unlock password required") pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12( cert_files=options.pkinit_cert_files, key_password=options.pkinit_pin, key_nickname=options.pkinit_cert_name, ca_cert_files=options.ca_cert_files, realm_name=realm_name) pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin) if (options.http_cert_files and options.dirsrv_cert_files and http_ca_cert != dirsrv_ca_cert): raise ScriptError( "Apache Server SSL certificate and Directory Server SSL " "certificate are not signed by the same CA certificate") if (options.http_cert_files and options.pkinit_cert_files and http_ca_cert != pkinit_ca_cert): raise ScriptError( "Apache Server SSL certificate and PKINIT KDC " "certificate are not signed by the same CA certificate") if not options.dm_password: dm_password = read_dm_password() if dm_password is None: raise ScriptError("Directory Manager password required") else: dm_password = options.dm_password if not options.master_password: master_password = ipa_generate_password() else: master_password = options.master_password if not options.admin_password: admin_password = read_admin_password() if admin_password is None: raise ScriptError("IPA admin password required") else: admin_password = options.admin_password # Configuration for ipalib, we will bootstrap and finalize later, after # we are sure we have the configuration file ready. cfg = dict( context='installer', confdir=paths.ETC_IPA, in_server=True, # make sure host name specified by user is used instead of default host=host_name, ) if setup_ca: # we have an IPA-integrated CA cfg['ca_host'] = host_name # Create the management framework config file and finalize api target_fname = paths.IPA_DEFAULT_CONF ipaconf = IPAChangeConf("IPA Server Install") ipaconf.setOptionAssignment(" = ") ipaconf.setSectionNameDelimiters(("[", "]")) xmlrpc_uri = 'https://{0}/ipa/xml'.format( ipautil.format_netloc(host_name)) ldapi_uri = ipaldap.realm_to_ldapi_uri(realm_name) # [global] section gopts = [ ipaconf.setOption('host', host_name), ipaconf.setOption('basedn', ipautil.realm_to_suffix(realm_name)), ipaconf.setOption('realm', realm_name), ipaconf.setOption('domain', domain_name), ipaconf.setOption('xmlrpc_uri', xmlrpc_uri), ipaconf.setOption('ldap_uri', ldapi_uri), ipaconf.setOption('mode', 'production') ] if setup_ca: gopts.extend([ ipaconf.setOption('enable_ra', 'True'), ipaconf.setOption('ra_plugin', 'dogtag'), ipaconf.setOption('dogtag_version', '10') ]) else: gopts.extend([ ipaconf.setOption('enable_ra', 'False'), ipaconf.setOption('ra_plugin', 'None') ]) opts = [ ipaconf.setSection('global', gopts), {'name': 'empty', 'type': 'empty'} ] ipaconf.newConf(target_fname, opts) # Must be readable for everyone os.chmod(target_fname, 0o644) api.bootstrap(**cfg) api.finalize() if setup_ca: ca.install_check(False, None, options) if options.setup_kra: kra.install_check(api, None, options) if options.setup_dns: dns.install_check(False, api, False, options, host_name) ip_addresses = dns.ip_addresses else: ip_addresses = get_server_ip_address(host_name, not installer.interactive, False, options.ip_addresses) # check addresses here, dns module is doing own check no_matching_interface_for_ip_address_warning(ip_addresses) instance_name = "-".join(realm_name.split(".")) dirsrv = services.knownservices.dirsrv if (options.external_cert_files and dirsrv.is_installed(instance_name) and not dirsrv.is_running(instance_name)): logger.debug('Starting Directory Server') services.knownservices.dirsrv.start(instance_name) if options.setup_adtrust: adtrust.install_check(False, options, api) # installer needs to update hosts file when DNS subsystem will be # installed or custom addresses are used if options.ip_addresses or options.setup_dns: installer._update_hosts_file = True if not options.no_ntp and not options.unattended and not ( options.ntp_servers or options.ntp_pool): options.ntp_servers, options.ntp_pool = timeconf.get_time_source() print() print("The IPA Master Server will be configured with:") print("Hostname: %s" % host_name) print("IP address(es): %s" % ", ".join(str(ip) for ip in ip_addresses)) print("Domain name: %s" % domain_name) print("Realm name: %s" % realm_name) print() if setup_ca: ca.print_ca_configuration(options) print() if options.setup_dns: print("BIND DNS server will be configured to serve IPA domain with:") print("Forwarders: %s" % ( "No forwarders" if not options.forwarders else ", ".join([str(ip) for ip in options.forwarders]) )) print('Forward policy: %s' % options.forward_policy) print("Reverse zone(s): %s" % ( "No reverse zone" if options.no_reverse or not dns.reverse_zones else ", ".join(str(rz) for rz in dns.reverse_zones) )) print() if not options.setup_adtrust: # If domain name and realm does not match, IPA server will not be able # to establish trust with Active Directory. Print big fat warning. realm_not_matching_domain = (domain_name.upper() != realm_name) if realm_not_matching_domain: print("WARNING: Realm name does not match the domain name.\n" "You will not be able to establish trusts with Active " "Directory unless\nthe realm name of the IPA server matches " "its domain name.\n\n") if options.ntp_servers or options.ntp_pool: if options.ntp_servers: for server in options.ntp_servers: print("NTP server:\t{}".format(server)) if options.ntp_pool: print("NTP pool:\t{}".format(options.ntp_pool)) if installer.interactive and not user_input( "Continue to configure the system with these values?", False): raise ScriptError("Installation aborted") options.realm_name = realm_name options.domain_name = domain_name options.dm_password = dm_password options.master_password = master_password options.admin_password = admin_password options._host_name_overridden = bool(options.host_name) options.host_name = host_name options.ip_addresses = ip_addresses installer._fstore = fstore installer._sstore = sstore installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file installer._http_pkcs12_file = http_pkcs12_file installer._pkinit_pkcs12_file = pkinit_pkcs12_file installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info installer._http_pkcs12_info = http_pkcs12_info installer._pkinit_pkcs12_info = pkinit_pkcs12_info installer._external_cert_file = external_cert_file installer._external_ca_file = external_ca_file installer._ca_cert = http_ca_cert
def run(): try: check_client_configuration() except ScriptError as e: print(e.msg) return e.rval fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE) options, _args = parse_options() logfile = paths.IPACLIENTSAMBA_INSTALL_LOG if options.uninstall: logfile = paths.IPACLIENTSAMBA_UNINSTALL_LOG standard_logging_setup( logfile, verbose=False, debug=options.debug, filemode="a", console_format="%(message)s", ) cfg = dict( context="cli_installer", confdir=paths.ETC_IPA, in_server=False, debug=options.debug, verbose=0, ) # Bootstrap API early so that env object is available api.bootstrap(**cfg) local_config = dict( host_princ=str("host/%s@%s" % (api.env.host, api.env.realm)), smb_princ=str("cifs/%s@%s" % (api.env.host, api.env.realm)), ) # Until api.finalize() is called, we can add our own configuration api.env._merge(**local_config) if options.uninstall: if statestore.has_state("domain_member"): uninstall(fstore, statestore, options) try: keys = ("configured", "hardening", "groupmap", "tdb", "service.principal", "smb.conf") for key in keys: statestore.delete_state("domain_member", key) except Exception as e: print("Error: Failed to remove the domain_member statestores: " "%s" % e) return 1 else: print("Samba configuration is reverted. " "However, Samba databases were fully cleaned and " "old configuration file will not be usable anymore.") else: print("Samba domain member is not configured yet") return 0 ca_cert_path = None if os.path.exists(paths.IPA_CA_CRT): ca_cert_path = paths.IPA_CA_CRT if statestore.has_state("domain_member") and not options.force: print("Samba domain member is already configured") return CLIENT_ALREADY_CONFIGURED if not os.path.exists(paths.SMBD): print("Samba suite is not installed") return CLIENT_NOT_CONFIGURED autodiscover = False ds = discovery.IPADiscovery() if not options.server: print("Searching for IPA server...") ret = ds.search(ca_cert_path=ca_cert_path) logger.debug("Executing DNS discovery") if ret == discovery.NO_LDAP_SERVER: logger.debug("Autodiscovery did not find LDAP server") s = urlsplit(api.env.xmlrpc_uri) server = [s.netloc] logger.debug("Setting server to %s", s.netloc) else: autodiscover = True if not ds.servers: print( "Autodiscovery was successful but didn't return a server") return 1 logger.debug( "Autodiscovery success, possible servers %s", ",".join(ds.servers), ) server = ds.servers[0] else: server = options.server logger.debug("Verifying that %s is an IPA server", server) ldapret = ds.ipacheckldap(server, api.env.realm, ca_cert_path) if ldapret[0] == discovery.NO_ACCESS_TO_LDAP: print("Anonymous access to the LDAP server is disabled.") print("Proceeding without strict verification.") print("Note: This is not an error if anonymous access has been " "explicitly restricted.") elif ldapret[0] == discovery.NO_TLS_LDAP: logger.warning("Unencrypted access to LDAP is not supported.") elif ldapret[0] != 0: print("Unable to confirm that %s is an IPA server" % server) return 1 if not autodiscover: print("IPA server: %s" % server) logger.debug("Using fixed server %s", server) else: print("IPA server: DNS discovery") logger.info("Configured to use DNS discovery") if api.env.host == server: logger.error("Cannot run on IPA master. " "Cannot configure Samba as a domain member on a domain " "controller. Please use ipa-adtrust-install for that!") return 1 if not options.netbiosname: options.netbiosname = DNSName.from_text(api.env.host)[0].decode() options.netbiosname = options.netbiosname.upper() with use_api_as_principal(api.env.host_princ, paths.KRB5_KEYTAB): try: # Try to access 'service_add_smb' command, if it throws # AttributeError exception, the IPA server doesn't support # setting up Samba as a domain member. service_add_smb = api.Command.service_add_smb # Now try to see if SMB principal already exists api.Command.service_show(api.env.smb_princ) # If no exception was raised, the object exists. # We cannot continue because we would break existing configuration print("WARNING: SMB service principal %s already exists. " "Please remove it before proceeding." % (api.env.smb_princ)) if not options.force: return 1 # For --force, we should then delete cifs/.. service object api.Command.service_del(api.env.smb_princ) except AttributeError: logger.error( "Chosen IPA master %s does not have support to " "set up Samba domain members", server, ) return 1 except errors.VersionError as e: print("This client is incompatible: " + str(e)) return 1 except errors.NotFound: logger.debug("No SMB service principal exists, OK to proceed") except errors.PublicError as e: logger.error( "Cannot connect to the server due to " "a generic error: %s", e, ) return 1 # At this point we have proper setup: # - we connected to IPA API end-point as a host principal # - no cifs/... principal exists so we can create it print("Chosen IPA master: %s" % server) print("SMB principal to be created: %s" % api.env.smb_princ) print("NetBIOS name to be used: %s" % options.netbiosname) logger.info("Chosen IPA master: %s", server) logger.info("SMB principal to be created: %s", api.env.smb_princ) logger.info("NetBIOS name to be used: %s", options.netbiosname) # 1. Pull down ID range and other details of known domains domains = retrieve_domain_information(api) if len(domains) == 0: # logger.error() produces both log file and stderr output logger.error("No configured trust controller detected " "on IPA masters. Use ipa-adtrust-install on an IPA " "master to configure trust controller role.") return 1 str_info = pretty_print_domain_information(domains) logger.info("Discovered domains to use:\n%s", str_info) print("Discovered domains to use:\n%s" % str_info) if not options.unattended and not ipautil.user_input( "Continue to configure the system with these values?", False): print("Installation aborted") return 1 # 2. Create SMB service principal, if we are here, the command exists if (not statestore.get_state("domain_member", "service.principal") or options.force): service_add_smb(api.env.host, options.netbiosname) statestore.backup_state("domain_member", "service.principal", "configured") # 3. Generate machine account password for reuse password = generate_smb_machine_account(fstore, statestore, options, domains[0]) # 4. Now that we have all domains retrieved, we can generate smb.conf if (not statestore.get_state("domain_member", "smb.conf") or options.force): configure_smb_conf(fstore, statestore, options, domains) statestore.backup_state("domain_member", "smb.conf", "configured") # 5. Create SMB service if statestore.get_state("domain_member", "service.principal") == "configured": retrieve_service_principal(fstore, statestore, options, domains[0], api.env.smb_princ, password) statestore.backup_state("domain_member", "service.principal", "configured") # 6. Configure databases to contain proper details if not statestore.get_state("domain_member", "tdb") or options.force: populate_samba_databases(fstore, statestore, options, domains[0], password) statestore.backup_state("domain_member", "tdb", "configured") # 7. Configure default group mapping if (not statestore.get_state("domain_member", "groupmap") or options.force): configure_default_groupmap(fstore, statestore, options, domains[0]) statestore.backup_state("domain_member", "groupmap", "configured") # 8. Enable SELinux policies if (not statestore.get_state("domain_member", "hardening") or options.force): harden_configuration(fstore, statestore, options, domains[0]) statestore.backup_state("domain_member", "hardening", "configured") # 9. Finally, store the state of upgrade statestore.backup_state("domain_member", "configured", True) # Suggest service start only after validating smb.conf print("Samba domain member is configured. " "Please check configuration at %s and " "start smb and winbind services" % paths.SMB_CONF) logger.info( "Samba domain member is configured. " "Please check configuration at %s and " "start smb and winbind services", paths.SMB_CONF, ) return 0
def _load_sstore(): global _sstore if _sstore is None: _sstore = sysrestore.StateFile(paths.STATEFILE_DIR, STATEFILE_FILE)
def promote_check(installer): options = installer installer._enrollment_performed = False installer._top_dir = tempfile.mkdtemp("ipa") # check selinux status, http and DS ports, NTP conflicting services common_check(options.no_ntp) client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if not client_fstore.has_files(): ensure_enrolled(installer) else: if (options.domain_name or options.server or options.realm_name or options.host_name or options.password or options.keytab): print("IPA client is already configured on this system, ignoring " "the --domain, --server, --realm, --hostname, --password " "and --keytab options.") # The NTP configuration can not be touched on pre-installed client: if options.no_ntp or options.ntp_servers or options.ntp_pool: raise ScriptError( "NTP configuration cannot be updated during promotion") sstore = sysrestore.StateFile(paths.SYSRESTORE) fstore = sysrestore.FileStore(paths.SYSRESTORE) env = Env() env._bootstrap(context='installer', confdir=paths.ETC_IPA, log=None) env._finalize_core(**dict(constants.DEFAULT_CONFIG)) # pylint: disable=no-member xmlrpc_uri = 'https://{}/ipa/xml'.format(ipautil.format_netloc(env.host)) api.bootstrap(in_server=True, context='installer', confdir=paths.ETC_IPA, ldap_uri=installutils.realm_to_ldapi_uri(env.realm), xmlrpc_uri=xmlrpc_uri) # pylint: enable=no-member api.finalize() config = ReplicaConfig() config.realm_name = api.env.realm config.host_name = api.env.host config.domain_name = api.env.domain config.master_host_name = api.env.server config.ca_host_name = api.env.ca_host config.kra_host_name = config.ca_host_name config.ca_ds_port = 389 config.setup_ca = options.setup_ca config.setup_kra = options.setup_kra config.dir = installer._top_dir config.basedn = api.env.basedn http_pkcs12_file = None http_pkcs12_info = None http_ca_cert = None dirsrv_pkcs12_file = None dirsrv_pkcs12_info = None dirsrv_ca_cert = None pkinit_pkcs12_file = None pkinit_pkcs12_info = None pkinit_ca_cert = None if options.http_cert_files: if options.http_pin is None: options.http_pin = installutils.read_password( "Enter Apache Server private key unlock", confirm=False, validate=False, retry=False) if options.http_pin is None: raise ScriptError( "Apache Server private key unlock password required") http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12( cert_files=options.http_cert_files, key_password=options.http_pin, key_nickname=options.http_cert_name, ca_cert_files=options.ca_cert_files, host_name=config.host_name) http_pkcs12_info = (http_pkcs12_file.name, http_pin) if options.dirsrv_cert_files: if options.dirsrv_pin is None: options.dirsrv_pin = installutils.read_password( "Enter Directory Server private key unlock", confirm=False, validate=False, retry=False) if options.dirsrv_pin is None: raise ScriptError( "Directory Server private key unlock password required") dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12( cert_files=options.dirsrv_cert_files, key_password=options.dirsrv_pin, key_nickname=options.dirsrv_cert_name, ca_cert_files=options.ca_cert_files, host_name=config.host_name) dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) if options.pkinit_cert_files: if options.pkinit_pin is None: options.pkinit_pin = installutils.read_password( "Enter Kerberos KDC private key unlock", confirm=False, validate=False, retry=False) if options.pkinit_pin is None: raise ScriptError( "Kerberos KDC private key unlock password required") pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12( cert_files=options.pkinit_cert_files, key_password=options.pkinit_pin, key_nickname=options.pkinit_cert_name, ca_cert_files=options.ca_cert_files, realm_name=config.realm_name) pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin) if (options.http_cert_files and options.dirsrv_cert_files and http_ca_cert != dirsrv_ca_cert): raise RuntimeError("Apache Server SSL certificate and Directory " "Server SSL certificate are not signed by the same" " CA certificate") if (options.http_cert_files and options.pkinit_cert_files and http_ca_cert != pkinit_ca_cert): raise RuntimeError("Apache Server SSL certificate and PKINIT KDC " "certificate are not signed by the same CA " "certificate") installutils.verify_fqdn(config.host_name, options.no_host_dns) installutils.verify_fqdn(config.master_host_name, options.no_host_dns) ccache = os.environ['KRB5CCNAME'] kinit_keytab('host/{env.host}@{env.realm}'.format(env=api.env), paths.KRB5_KEYTAB, ccache) cafile = paths.IPA_CA_CRT if not os.path.isfile(cafile): raise RuntimeError("CA cert file is not available! Please reinstall" "the client and try again.") ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name) xmlrpc_uri = 'https://{}/ipa/xml'.format( ipautil.format_netloc(config.master_host_name)) remote_api = create_api(mode=None) remote_api.bootstrap(in_server=True, context='installer', confdir=paths.ETC_IPA, ldap_uri=ldapuri, xmlrpc_uri=xmlrpc_uri) remote_api.finalize() installer._remote_api = remote_api with rpc_client(remote_api) as client: check_remote_version(client, parse_version(api.env.version)) check_remote_fips_mode(client, api.env.fips_mode) conn = remote_api.Backend.ldap2 replman = None try: # Try out authentication conn.connect(ccache=ccache) replman = ReplicationManager(config.realm_name, config.master_host_name, None) promotion_check_ipa_domain(conn, remote_api.env.basedn) # Make sure that domain fulfills minimal domain level # requirement domain_level = current_domain_level(remote_api) check_domain_level_is_supported(domain_level) if domain_level < constants.MIN_DOMAIN_LEVEL: raise RuntimeError( "Cannot promote this client to a replica. The domain level " "must be raised to {mindomainlevel} before the replica can be " "installed".format(mindomainlevel=constants.MIN_DOMAIN_LEVEL)) # Check authorization result = remote_api.Command['hostgroup_find']( cn=u'ipaservers', host=[unicode(api.env.host)])['result'] add_to_ipaservers = not result if add_to_ipaservers: if options.password and not options.admin_password: raise errors.ACIError(info="Not authorized") if installer._ccache is None: del os.environ['KRB5CCNAME'] else: os.environ['KRB5CCNAME'] = installer._ccache try: installutils.check_creds(options, config.realm_name) installer._ccache = os.environ.get('KRB5CCNAME') finally: os.environ['KRB5CCNAME'] = ccache conn.disconnect() conn.connect(ccache=installer._ccache) try: result = remote_api.Command['hostgroup_show']( u'ipaservers', all=True, rights=True)['result'] if 'w' not in result['attributelevelrights']['member']: raise errors.ACIError(info="Not authorized") finally: conn.disconnect() conn.connect(ccache=ccache) # Check that we don't already have a replication agreement if replman.get_replication_agreement(config.host_name): msg = ("A replication agreement for this host already exists. " "It needs to be removed.\n" "Run this command:\n" " %% ipa-replica-manage del {host} --force".format( host=config.host_name)) raise ScriptError(msg, rval=3) # Detect if the other master can handle replication managers # cn=replication managers,cn=sysaccounts,cn=etc,$SUFFIX dn = DN(('cn', 'replication managers'), ('cn', 'sysaccounts'), ('cn', 'etc'), ipautil.realm_to_suffix(config.realm_name)) try: conn.get_entry(dn) except errors.NotFound: msg = ("The Replication Managers group is not available in " "the domain. Replica promotion requires the use of " "Replication Managers to be able to replicate data. " "Upgrade the peer master or use the ipa-replica-prepare " "command on the master and use a prep file to install " "this replica.") logger.error("%s", msg) raise ScriptError(rval=3) dns_masters = remote_api.Object['dnsrecord'].get_dns_masters() if dns_masters: if not options.no_host_dns: logger.debug('Check forward/reverse DNS resolution') resolution_ok = ( check_dns_resolution(config.master_host_name, dns_masters) and check_dns_resolution(config.host_name, dns_masters)) if not resolution_ok and installer.interactive: if not ipautil.user_input("Continue?", False): raise ScriptError(rval=0) else: logger.debug('No IPA DNS servers, ' 'skipping forward/reverse resolution check') entry_attrs = conn.get_ipa_config() subject_base = entry_attrs.get('ipacertificatesubjectbase', [None])[0] if subject_base is not None: config.subject_base = DN(subject_base) # Find if any server has a CA ca_host = service.find_providing_server('CA', conn, config.ca_host_name) if ca_host is not None: config.ca_host_name = ca_host ca_enabled = True if options.dirsrv_cert_files: logger.error("Certificates could not be provided when " "CA is present on some master.") raise ScriptError(rval=3) else: if options.setup_ca: logger.error("The remote master does not have a CA " "installed, can't set up CA") raise ScriptError(rval=3) ca_enabled = False if not options.dirsrv_cert_files: logger.error("Cannot issue certificates: a CA is not " "installed. Use the --http-cert-file, " "--dirsrv-cert-file options to provide " "custom certificates.") raise ScriptError(rval=3) kra_host = service.find_providing_server('KRA', conn, config.kra_host_name) if kra_host is not None: config.kra_host_name = kra_host kra_enabled = True else: if options.setup_kra: logger.error("There is no KRA server in the domain, " "can't setup a KRA clone") raise ScriptError(rval=3) kra_enabled = False if ca_enabled: options.realm_name = config.realm_name options.host_name = config.host_name ca.install_check(False, config, options) if kra_enabled: try: kra.install_check(remote_api, config, options) except RuntimeError as e: raise ScriptError(e) if options.setup_dns: dns.install_check(False, remote_api, True, options, config.host_name) config.ips = dns.ip_addresses else: config.ips = installutils.get_server_ip_address( config.host_name, not installer.interactive, False, options.ip_addresses) # check addresses here, dns module is doing own check no_matching_interface_for_ip_address_warning(config.ips) if options.setup_adtrust: adtrust.install_check(False, options, remote_api) except errors.ACIError: logger.debug("%s", traceback.format_exc()) raise ScriptError("\nInsufficient privileges to promote the server." "\nPossible issues:" "\n- A user has insufficient privileges" "\n- This client has insufficient privileges " "to become an IPA replica") except errors.LDAPError: logger.debug("%s", traceback.format_exc()) raise ScriptError("\nUnable to connect to LDAP server %s" % config.master_host_name) finally: if replman and replman.conn: replman.conn.unbind() if conn.isconnected(): conn.disconnect() # check connection if not options.skip_conncheck: if add_to_ipaservers: # use user's credentials when the server host is not ipaservers if installer._ccache is None: del os.environ['KRB5CCNAME'] else: os.environ['KRB5CCNAME'] = installer._ccache try: replica_conn_check(config.master_host_name, config.host_name, config.realm_name, options.setup_ca, 389, options.admin_password, principal=options.principal, ca_cert_file=cafile) finally: if add_to_ipaservers: os.environ['KRB5CCNAME'] = ccache installer._ca_enabled = ca_enabled installer._kra_enabled = kra_enabled installer._ca_file = cafile installer._fstore = fstore installer._sstore = sstore installer._config = config installer._add_to_ipaservers = add_to_ipaservers installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info installer._http_pkcs12_file = http_pkcs12_file installer._http_pkcs12_info = http_pkcs12_info installer._pkinit_pkcs12_file = pkinit_pkcs12_file installer._pkinit_pkcs12_info = pkinit_pkcs12_info
def main(): module = AnsibleModule( argument_spec=dict( servers=dict(required=True, type='list'), domain=dict(required=True), ntp=dict(required=False, type='bool', default='no'), force_ntpd=dict(required=False, type='bool', default='no'), ntp_servers=dict(required=False, type='list'), ssh=dict(required=False, type='bool', default='yes'), sssd=dict(required=False, type='bool', default='yes'), trust_sshfp=dict(required=False, type='bool', default='yes'), sshd=dict(required=False, type='bool', default='yes'), automount_location=dict(required=False), firefox=dict(required=False, type='bool', default='no'), firefox_dir=dict(required=False), no_nisdomain=dict(required=False, type='bool', default='no'), nisdomain=dict(required=False), on_master=dict(required=False, type='bool', default='no'), ), supports_check_mode=True, ) module._ansible_debug = True servers = module.params.get('servers') domain = module.params.get('domain') ntp = module.params.get('ntp') force_ntpd = module.params.get('force_ntpd') ntp_servers = module.params.get('ntp_servers') ssh = module.params.get('ssh') sssd = module.params.get('sssd') trust_sshfp = module.params.get('trust_sshfp') sshd = module.params.get('sshd') automount_location = module.params.get('automount_location') firefox = module.params.get('firefox') firefox_dir = module.params.get('firefox_dir') no_nisdomain = module.params.get('no_nisdomain') nisdomain = module.params.get('nisdomain') on_master = module.params.get('on_master') fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE) logger = logging.getLogger("ipa-client-install") os.environ['KRB5CCNAME'] = CCACHE_FILE class Object(object): pass options = Object() options.sssd = sssd options.trust_sshfp = trust_sshfp options.location = automount_location options.server = servers options.firefox_dir = firefox_dir options.nisdomain = nisdomain if ntp and not on_master: # disable other time&date services first if force_ntpd: ntpconf.force_ntpd(statestore) ntpconf.config_ntp(ntp_servers, fstore, statestore) module.log("NTP enabled") if ssh: configure_ssh_config(fstore, options) if sshd: configure_sshd_config(fstore, options) if automount_location: configure_automount(options) if firefox: configure_firefox(options, statestore, domain) if not no_nisdomain: configure_nisdomain(options=options, domain=domain, statestore=statestore) # Cleanup: Remove CCACHE_FILE try: os.remove(CCACHE_FILE) except Exception: pass module.exit_json(changed=True)
def main(): module = AnsibleModule( argument_spec = dict( servers=dict(required=True, type='list'), domain=dict(required=True), realm=dict(required=True), hostname=dict(required=True), basedn=dict(required=True), principal=dict(required=False), subject_base=dict(required=True), ca_enabled=dict(required=True, type='bool'), mkhomedir=dict(required=False, type='bool'), on_master=dict(required=False, type='bool'), ), supports_check_mode = True, ) module._ansible_debug = True servers = module.params.get('servers') realm = module.params.get('realm') hostname = module.params.get('hostname') basedn = module.params.get('basedn') domain = module.params.get('domain') principal = module.params.get('principal') subject_base = module.params.get('subject_base') ca_enabled = module.params.get('ca_enabled') mkhomedir = module.params.get('mkhomedir') on_master = module.params.get('on_master') fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE) ########################################################################### os.environ['KRB5CCNAME'] = CCACHE_FILE class Object(object): pass options = Object() options.dns_updates = False options.all_ip_addresses = False options.ip_addresses = None options.request_cert = False options.hostname = hostname options.preserve_sssd = False options.on_master = False options.conf_ssh = True options.conf_sshd = True options.conf_sudo = True options.primary = False options.permit = False options.krb5_offline_passwords = False options.create_sshfp = True ########################################################################## # Create IPA NSS database try: create_ipa_nssdb() except ipautil.CalledProcessError as e: module.fail_json(msg="Failed to create IPA NSS database: %s" % e) # Get CA certificates from the certificate store try: ca_certs = get_certs_from_ldap(servers[0], basedn, realm, ca_enabled) except errors.NoCertificateError: if ca_enabled: ca_subject = DN(('CN', 'Certificate Authority'), subject_base) else: ca_subject = None ca_certs = certstore.make_compat_ca_certs(ca_certs, realm, ca_subject) ca_certs_trust = [(c, n, certstore.key_policy_to_trust_flags(t, True, u)) for (c, n, t, u) in ca_certs] if hasattr(paths, "KDC_CA_BUNDLE_PEM"): x509.write_certificate_list( [c for c, n, t, u in ca_certs if t is not False], paths.KDC_CA_BUNDLE_PEM) if hasattr(paths, "CA_BUNDLE_PEM"): x509.write_certificate_list( [c for c, n, t, u in ca_certs if t is not False], paths.CA_BUNDLE_PEM) # Add the CA certificates to the IPA NSS database module.debug("Adding CA certificates to the IPA NSS database.") ipa_db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR) for cert, nickname, trust_flags in ca_certs_trust: try: ipa_db.add_cert(cert, nickname, trust_flags) except CalledProcessError as e: module.fail_json(msg="Failed to add %s to the IPA NSS database." % nickname) # Add the CA certificates to the platform-dependant systemwide CA store tasks.insert_ca_certs_into_systemwide_ca_store(ca_certs) if not on_master: client_dns(servers[0], hostname, options) configure_certmonger(fstore, subject_base, realm, hostname, options, ca_enabled) if hasattr(paths, "SSH_CONFIG_DIR"): ssh_config_dir = paths.SSH_CONFIG_DIR else: ssh_config_dir = services.knownservices.sshd.get_config_dir() update_ssh_keys(hostname, ssh_config_dir, options.create_sshfp) try: os.remove(CCACHE_FILE) except Exception: pass ########################################################################## # Name Server Caching Daemon. Disable for SSSD, use otherwise # (if installed) nscd = services.knownservices.nscd if nscd.is_installed(): save_state(nscd, statestore) try: nscd_service_action = 'stop' nscd.stop() except Exception: module.warn("Failed to %s the %s daemon" % (nscd_service_action, nscd.service_name)) try: nscd.disable() except Exception: module.warn("Failed to disable %s daemon. Disable it manually." % nscd.service_name) nslcd = services.knownservices.nslcd if nslcd.is_installed(): save_state(nslcd, statestore) retcode, conf = (0, None) ########################################################################## # Modify nsswitch/pam stack tasks.modify_nsswitch_pam_stack(sssd=True, mkhomedir=mkhomedir, statestore=statestore) module.log("SSSD enabled") argspec = inspect.getargspec(services.service) if len(argspec.args) > 1: sssd = services.service('sssd', api) else: sssd = services.service('sssd') try: sssd.restart() except CalledProcessError: module.warn("SSSD service restart was unsuccessful.") try: sssd.enable() except CalledProcessError as e: module.warn( "Failed to enable automatic startup of the SSSD daemon: " "%s", e) if configure_openldap_conf(fstore, basedn, servers): module.log("Configured /etc/openldap/ldap.conf") else: module.log("Failed to configure /etc/openldap/ldap.conf") # Check that nss is working properly if not on_master: user = principal if user is None or user == "": user = "******" % domain module.log("Principal is not set when enrolling with OTP" "; using principal '%s' for 'getent passwd'" % user) elif '@' not in user: user = "******" % (user, domain) n = 0 found = False # Loop for up to 10 seconds to see if nss is working properly. # It can sometimes take a few seconds to connect to the remote # provider. # Particulary, SSSD might take longer than 6-8 seconds. while n < 10 and not found: try: ipautil.run(["getent", "passwd", user]) found = True except Exception as e: time.sleep(1) n = n + 1 if not found: module.fail_json(msg="Unable to find '%s' user with 'getent " "passwd %s'!" % (user.split("@")[0], user)) if conf: module.log("Recognized configuration: %s" % conf) else: module.fail_json(msg= "Unable to reliably detect " "configuration. Check NSS setup manually.") try: hardcode_ldap_server(servers) except Exception as e: module.fail_json(msg="Adding hardcoded server name to " "/etc/ldap.conf failed: %s" % str(e)) ########################################################################## module.exit_json(changed=True, ca_enabled_ra=ca_enabled)
def main(): module = AnsibleModule( argument_spec = dict( servers=dict(required=True, type='list'), realm=dict(required=True), hostname=dict(required=True), debug=dict(required=False, type='bool', default="false") ), supports_check_mode = True, ) module._ansible_debug = True realm = module.params.get('realm') hostname = module.params.get('hostname') servers = module.params.get('servers') debug = module.params.get('debug') fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE) host_principal = 'host/%s@%s' % (hostname, realm) os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE ca_certs = x509.load_certificate_list_from_file(paths.IPA_CA_CRT) if NUM_VERSION >= 40500 and NUM_VERSION < 40590: ca_certs = [ cert.public_bytes(serialization.Encoding.DER) for cert in ca_certs ] elif NUM_VERSION < 40500: ca_certs = [ cert.der_data for cert in ca_certs ] with certdb.NSSDatabase() as tmp_db: api.bootstrap(context='cli_installer', confdir=paths.ETC_IPA, debug=debug, delegate=False, nss_dir=tmp_db.secdir) if 'config_loaded' not in api.env: module.fail_json(msg="Failed to initialize IPA API.") # Clear out any current session keyring information try: delete_persistent_client_session_data(host_principal) except ValueError: pass # Add CA certs to a temporary NSS database argspec = inspect.getargspec(tmp_db.create_db) try: if NUM_VERSION > 40404: tmp_db.create_db() for i, cert in enumerate(ca_certs): tmp_db.add_cert(cert, 'CA certificate %d' % (i + 1), certdb.EXTERNAL_CA_TRUST_FLAGS) else: pwd_file = write_tmp_file(ipa_generate_password()) tmp_db.create_db(pwd_file.name) for i, cert in enumerate(ca_certs): tmp_db.add_cert(cert, 'CA certificate %d' % (i + 1), 'C,,') except CalledProcessError as e: module.fail_json(msg="Failed to add CA to temporary NSS database.") api.finalize() # Now, let's try to connect to the server's RPC interface connected = False try: api.Backend.rpcclient.connect() connected = True module.debug("Try RPC connection") api.Backend.rpcclient.forward('ping') except errors.KerberosError as e: if connected: api.Backend.rpcclient.disconnect() module.log( "Cannot connect to the server due to Kerberos error: %s. " "Trying with delegate=True" % e) try: api.Backend.rpcclient.connect(delegate=True) module.debug("Try RPC connection") api.Backend.rpcclient.forward('ping') module.log("Connection with delegate=True successful") # The remote server is not capable of Kerberos S4U2Proxy # delegation. This features is implemented in IPA server # version 2.2 and higher module.warn( "Target IPA server has a lower version than the enrolled " "client") module.warn( "Some capabilities including the ipa command capability " "may not be available") except errors.PublicError as e2: module.fail_json( msg="Cannot connect to the IPA server RPC interface: %s" % e2) except errors.PublicError as e: module.fail_json( msg="Cannot connect to the server due to generic error: %s" % e) # Use the RPC directly so older servers are supported try: result = api.Backend.rpcclient.forward( 'ca_is_enabled', version=u'2.107', ) ca_enabled = result['result'] except (errors.CommandError, errors.NetworkError): result = api.Backend.rpcclient.forward( 'env', server=True, version=u'2.0', ) ca_enabled = result['result']['enable_ra'] if not ca_enabled: disable_ra() # Get subject base from ipa server try: config = api.Command['config_show']()['result'] subject_base = str(DN(config['ipacertificatesubjectbase'][0])) except errors.PublicError as e: module.fail_json(msg="Cannot get subject base from server: %s" % e) module.exit_json(changed=True, ca_enabled=ca_enabled, subject_base=subject_base)