def main(): module = AnsibleModule( argument_spec=dict( # basic domain=dict(required=False, default=None), servers=dict(required=False, type='list', default=None), realm=dict(required=False, default=None), hostname=dict(required=False, default=None), ntp_servers=dict(required=False, type='list', default=None), ntp_pool=dict(required=False, default=None), no_ntp=dict(required=False, type='bool', default=False), force_ntpd=dict(required=False, type='bool', default=False), nisdomain=dict(required=False, default=None), no_nisdomain=dict(required=False, type='bool', default='no'), kinit_attempts=dict(required=False, type='int'), ca_cert_files=dict(required=False, type='list', default=None), configure_firefox=dict(required=False, type='bool', default=False), firefox_dir=dict(required=False), ip_addresses=dict(required=False, type='list', default=None), all_ip_addresses=dict(required=False, type='bool', default=False), on_master=dict(required=False, type='bool', default=False), # sssd enable_dns_updates=dict(required=False, type='bool', default=False), ), supports_check_mode=True, ) # module._ansible_debug = True setup_logging() options.domain_name = module.params.get('domain') options.servers = module.params.get('servers') options.realm_name = module.params.get('realm') options.host_name = module.params.get('hostname') options.ntp_servers = module.params.get('ntp_servers') options.ntp_pool = module.params.get('ntp_pool') options.no_ntp = module.params.get('no_ntp') options.force_ntpd = module.params.get('force_ntpd') options.nisdomain = module.params.get('nisdomain') options.no_nisdomain = module.params.get('no_nisdomain') options.kinit_attempts = module.params.get('kinit_attempts') options.ca_cert_files = module.params.get('ca_cert_files') options.configure_firefox = module.params.get('configure_firefox') options.firefox_dir = module.params.get('firefox_dir') options.ip_addresses = module.params.get('ip_addresses') options.all_ip_addresses = module.params.get('all_ip_addresses') options.on_master = module.params.get('on_master') options.enable_dns_updates = module.params.get('enable_dns_updates') # Get domain from first server if domain is not set, but if there are # servers if options.domain_name is None and options.servers is not None: if len(options.servers) > 0: options.domain_name = options.servers[0][options.servers[0]. find(".") + 1:] try: self = options # HostNameInstallInterface if options.ip_addresses is not None: for value in options.ip_addresses: try: CheckedIPAddress(value) except Exception as e: raise ValueError("invalid IP address {0}: {1}".format( value, e)) # ServiceInstallInterface if options.domain_name: validate_domain_name(options.domain_name) if options.realm_name: argspec = inspect.getargspec(validate_domain_name) if "entity" in argspec.args: # NUM_VERSION >= 40690: validate_domain_name(options.realm_name, entity="realm") # ClientInstallInterface if options.kinit_attempts < 1: raise ValueError("expects an integer greater than 0.") # ClientInstallInterface.__init__ if self.servers and not self.domain_name: raise RuntimeError( "--server cannot be used without providing --domain") if self.force_ntpd: logger.warning("Option --force-ntpd has been deprecated") if self.ntp_servers and self.no_ntp: raise RuntimeError( "--ntp-server cannot be used together with --no-ntp") if self.ntp_pool and self.no_ntp: raise RuntimeError( "--ntp-pool cannot be used together with --no-ntp") if self.no_nisdomain and self.nisdomain: raise RuntimeError( "--no-nisdomain cannot be used together with --nisdomain") if self.ip_addresses: if self.enable_dns_updates: raise RuntimeError("--ip-address cannot be used together with" " --enable-dns-updates") if self.all_ip_addresses: raise RuntimeError("--ip-address cannot be used together with" "--all-ip-addresses") # SSSDInstallInterface self.no_sssd = False # ClientInstall if options.ca_cert_files is not None: for value in options.ca_cert_files: if not isinstance(value, list): raise ValueError("Expected list, got {!r}".format(value)) # this is what init() does value = value[-1] if not os.path.exists(value): raise ValueError("'%s' does not exist" % value) if not os.path.isfile(value): raise ValueError("'%s' is not a file" % value) if not os.path.isabs(value): raise ValueError("'%s' is not an absolute file path" % value) try: x509.load_certificate_from_file(value) except Exception: raise ValueError("'%s' is not a valid certificate file" % value) # self.prompt_password = self.interactive self.no_ac = False # ClientInstall.__init__ if self.firefox_dir and not self.configure_firefox: raise RuntimeError( "--firefox-dir cannot be used without --configure-firefox " "option") except (RuntimeError, ValueError) as e: module.fail_json(msg=str(e)) # ipaclient.install.client.init # root_logger options.debug = False if options.domain_name: options.domain = normalize_hostname(installer.domain_name) else: options.domain = None options.server = options.servers options.realm = options.realm_name # installer.primary = installer.fixed_primary # if installer.principal: # installer.password = installer.admin_password # else: # installer.password = installer.host_password installer.hostname = installer.host_name options.conf_ntp = not options.no_ntp # installer.trust_sshfp = installer.ssh_trust_dns # installer.conf_ssh = not installer.no_ssh # installer.conf_sshd = not installer.no_sshd # installer.conf_sudo = not installer.no_sudo # installer.create_sshfp = not installer.no_dns_sshfp if installer.ca_cert_files: installer.ca_cert_file = installer.ca_cert_files[-1] else: installer.ca_cert_file = None # installer.location = installer.automount_location installer.dns_updates = installer.enable_dns_updates # installer.krb5_offline_passwords = \ # not installer.no_krb5_offline_passwords installer.sssd = not installer.no_sssd try: # client # global variables hostname = None hostname_source = None nosssd_files = None dnsok = False cli_domain = None cli_server = None # subject_base = None cli_realm = None cli_kdc = None client_domain = None cli_basedn = None # end of global variables # client.install_check logger.info("This program will set up FreeIPA client.") logger.info("Version %s", version.VERSION) logger.info("") cli_domain_source = 'Unknown source' cli_server_source = 'Unknown source' # fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if not os.getegid() == 0: raise ScriptError("You must be root to run ipa-client-install.", rval=CLIENT_INSTALL_ERROR) tasks.check_selinux_status() # if is_ipa_client_installed(fstore, on_master=options.on_master): # logger.error("IPA client is already configured on this system.") # logger.info( # "If you want to reinstall the IPA client, uninstall it first " # "using 'ipa-client-install --uninstall'.") # raise ScriptError( # "IPA client is already configured on this system.", # rval=CLIENT_ALREADY_CONFIGURED) if check_ldap_conf is not None: check_ldap_conf() if options.conf_ntp: try: timeconf.check_timedate_services() except timeconf.NTPConflictingService as e: logger.info( "WARNING: conflicting time&date synchronization service " "'%s' will be disabled in favor of chronyd", e.conflicting_service) logger.info("") except timeconf.NTPConfigurationError: pass # password, principal and keytab are checked in tasks/install.yml # if options.unattended and ( # options.password is None and # options.principal is None and # options.keytab is None and # options.prompt_password is False and # not options.on_master # ): # raise ScriptError( # "One of password / principal / keytab is required.", # rval=CLIENT_INSTALL_ERROR) if options.hostname: hostname = options.hostname hostname_source = 'Provided as option' else: hostname = socket.getfqdn() hostname_source = "Machine's FQDN" if hostname != hostname.lower(): raise ScriptError( "Invalid hostname '{}', must be lower-case.".format(hostname), rval=CLIENT_INSTALL_ERROR) if hostname in ('localhost', 'localhost.localdomain'): raise ScriptError( "Invalid hostname, '{}' must not be used.".format(hostname), rval=CLIENT_INSTALL_ERROR) if hasattr(constants, "MAXHOSTNAMELEN"): try: validate_hostname(hostname, maxlen=constants.MAXHOSTNAMELEN) except ValueError as e: raise ScriptError('invalid hostname: {}'.format(e), rval=CLIENT_INSTALL_ERROR) if hasattr(tasks, "is_nosssd_supported"): # --no-sssd is not supported any more for rhel-based distros if not tasks.is_nosssd_supported() and not options.sssd: raise ScriptError( "Option '--no-sssd' is incompatible with the 'authselect' " "tool provided by this distribution for configuring " "system authentication resources", rval=CLIENT_INSTALL_ERROR) # --noac is not supported any more for rhel-based distros if not tasks.is_nosssd_supported() and options.no_ac: raise ScriptError( "Option '--noac' is incompatible with the 'authselect' " "tool provided by this distribution for configuring " "system authentication resources", rval=CLIENT_INSTALL_ERROR) # when installing with '--no-sssd' option, check whether nss-ldap is # installed if not options.sssd: if not os.path.exists(paths.PAM_KRB5_SO): raise ScriptError("The pam_krb5 package must be installed", rval=CLIENT_INSTALL_ERROR) (nssldap_installed, nosssd_files) = nssldap_exists() (nssldap_installed, __temp) = nssldap_exists() if not nssldap_installed: raise ScriptError( "One of these packages must be installed: nss_ldap or " "nss-pam-ldapd", rval=CLIENT_INSTALL_ERROR) # principal and keytab are checked in tasks/install.yml # if options.keytab and options.principal: # raise ScriptError( # "Options 'principal' and 'keytab' cannot be used together.", # rval=CLIENT_INSTALL_ERROR) # keytab and force_join are checked in tasks/install.yml # if options.keytab and options.force_join: # logger.warning("Option 'force-join' has no additional effect " # "when used with together with option 'keytab'.") # Added with freeipa-4.7.1 >>> # Remove invalid keytab file try: gssapi.Credentials( store={'keytab': paths.KRB5_KEYTAB}, usage='accept', ) except gssapi.exceptions.GSSError: logger.debug("Deleting invalid keytab: '%s'.", paths.KRB5_KEYTAB) remove_file(paths.KRB5_KEYTAB) # Added with freeipa-4.7.1 <<< # Check if old certificate exist and show warning if (not options.ca_cert_file and get_cert_path(options.ca_cert_file) == paths.IPA_CA_CRT): logger.warning("Using existing certificate '%s'.", paths.IPA_CA_CRT) if not check_ip_addresses(options): raise ScriptError( "Failed to check ip addresses, check installation log", rval=CLIENT_INSTALL_ERROR) # Create the discovery instance ds = ipadiscovery.IPADiscovery() ret = ds.search(domain=options.domain, servers=options.server, realm=options.realm_name, hostname=hostname, ca_cert_path=get_cert_path(options.ca_cert_file)) if options.server and ret != 0: # There is no point to continue with installation as server list # was passed as a fixed list of server and thus we cannot discover # any better result logger.error("Failed to verify that %s is an IPA Server.", ', '.join(options.server)) logger.error( "This may mean that the remote server is not up " "or is not reachable due to network or firewall settings.") print_port_conf_info() raise ScriptError("Failed to verify that %s is an IPA Server." % ', '.join(options.server), rval=CLIENT_INSTALL_ERROR) if ret == ipadiscovery.BAD_HOST_CONFIG: logger.error("Can't get the fully qualified name of this host") logger.info("Check that the client is properly configured") raise ScriptError( "Can't get the fully qualified name of this host", rval=CLIENT_INSTALL_ERROR) if ret == ipadiscovery.NOT_FQDN: raise ScriptError( "{} is not a fully-qualified hostname".format(hostname), rval=CLIENT_INSTALL_ERROR) if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \ or not ds.domain: if ret == ipadiscovery.NO_LDAP_SERVER: if ds.server: logger.debug("%s is not an LDAP server", ds.server) else: logger.debug("No LDAP server found") elif ret == ipadiscovery.NOT_IPA_SERVER: if ds.server: logger.debug("%s is not an IPA server", ds.server) else: logger.debug("No IPA server found") else: logger.debug("Domain not found") if options.domain: cli_domain = options.domain cli_domain_source = 'Provided as option' elif options.unattended: raise ScriptError( "Unable to discover domain, not provided on command line", rval=CLIENT_INSTALL_ERROR) else: raise ScriptError("No interactive installation") # logger.info( # "DNS discovery failed to determine your DNS domain") # cli_domain = user_input( # "Provide the domain name of your IPA server " # "(ex: example.com)", # allow_empty=False) # cli_domain_source = 'Provided interactively' # logger.debug( # "will use interactively provided domain: %s", cli_domain) ret = ds.search(domain=cli_domain, servers=options.server, hostname=hostname, ca_cert_path=get_cert_path(options.ca_cert_file)) if not cli_domain: if ds.domain: cli_domain = ds.domain cli_domain_source = ds.domain_source logger.debug("will use discovered domain: %s", cli_domain) client_domain = hostname[hostname.find(".") + 1:] if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \ or not ds.server: logger.debug("IPA Server not found") if options.server: cli_server = options.server cli_server_source = 'Provided as option' elif options.unattended: raise ScriptError("Unable to find IPA Server to join", rval=CLIENT_INSTALL_ERROR) else: raise ScriptError("No interactive installation") # logger.debug("DNS discovery failed to find the IPA Server") # cli_server = [ # user_input( # "Provide your IPA server name (ex: ipa.example.com)", # allow_empty=False) # ] # cli_server_source = 'Provided interactively' # logger.debug( # "will use interactively provided server: %s", cli_server[0]) ret = ds.search(domain=cli_domain, servers=cli_server, hostname=hostname, ca_cert_path=get_cert_path(options.ca_cert_file)) else: # Only set dnsok to True if we were not passed in one or more # servers and if DNS discovery actually worked. if not options.server: (server, domain) = ds.check_domain(ds.domain, set(), "Validating DNS Discovery") if server and domain: logger.debug("DNS validated, enabling discovery") dnsok = True else: logger.debug("DNS discovery failed, disabling discovery") else: logger.debug( "Using servers from command line, disabling DNS discovery") if not cli_server: if options.server: cli_server = ds.servers cli_server_source = 'Provided as option' logger.debug("will use provided server: %s", ', '.join(options.server)) elif ds.server: cli_server = ds.servers cli_server_source = ds.server_source logger.debug("will use discovered server: %s", cli_server[0]) if ret == ipadiscovery.NOT_IPA_SERVER: logger.error("%s is not an IPA v2 Server.", cli_server[0]) print_port_conf_info() logger.debug("(%s: %s)", cli_server[0], cli_server_source) raise ScriptError("%s is not an IPA v2 Server." % cli_server[0], rval=CLIENT_INSTALL_ERROR) if ret == ipadiscovery.NO_ACCESS_TO_LDAP: logger.warning("Anonymous access to the LDAP server is disabled.") logger.info("Proceeding without strict verification.") logger.info("Note: This is not an error if anonymous access " "has been explicitly restricted.") ret = 0 if ret == ipadiscovery.NO_TLS_LDAP: logger.warning( "The LDAP server requires TLS is but we do not have the CA.") logger.info("Proceeding without strict verification.") ret = 0 if ret != 0: logger.error("Failed to verify that %s is an IPA Server.", cli_server[0]) logger.error( "This may mean that the remote server is not up " "or is not reachable due to network or firewall settings.") print_port_conf_info() logger.debug("(%s: %s)", cli_server[0], cli_server_source) raise ScriptError("Failed to verify that %s is an IPA Server." % cli_server[0], rval=CLIENT_INSTALL_ERROR) cli_kdc = ds.kdc if dnsok and not cli_kdc: logger.error( "DNS domain '%s' is not configured for automatic " "KDC address lookup.", ds.realm.lower()) logger.debug("(%s: %s)", ds.realm, ds.realm_source) logger.error("KDC address will be set to fixed value.") if dnsok: logger.info("Discovery was successful!") elif not options.unattended: raise ScriptError("No interactive installation") # if not options.server: # logger.warning( # "The failure to use DNS to find your IPA " # "server indicates that your resolv.conf file is not properly " # "configured.") # logger.info( # "Autodiscovery of servers for failover cannot work " # "with this configuration.") # logger.info( # "If you proceed with the installation, services " # "will be configured to always access the discovered server for " # "all operations and will not fail over to other servers in case " # "of failure.") # if not user_input( # "Proceed with fixed values and no DNS discovery?", False): # raise ScriptError(rval=CLIENT_INSTALL_ERROR) # Do not ask for time source # if options.conf_ntp: # if not options.on_master and not options.unattended and not ( # options.ntp_servers or options.ntp_pool): # options.ntp_servers, options.ntp_pool = \ # timeconf.get_time_source() cli_realm = ds.realm cli_realm_source = ds.realm_source logger.debug("will use discovered realm: %s", cli_realm) if options.realm_name and options.realm_name != cli_realm: logger.error( "The provided realm name [%s] does not match discovered " "one [%s]", options.realm_name, cli_realm) logger.debug("(%s: %s)", cli_realm, cli_realm_source) raise ScriptError( "The provided realm name [%s] does not match discovered " "one [%s]" % (options.realm_name, cli_realm), rval=CLIENT_INSTALL_ERROR) cli_basedn = ds.basedn cli_basedn_source = ds.basedn_source logger.debug("will use discovered basedn: %s", cli_basedn) # subject_base = DN(('O', cli_realm)) logger.info("Client hostname: %s", hostname) logger.debug("Hostname source: %s", hostname_source) logger.info("Realm: %s", cli_realm) logger.debug("Realm source: %s", cli_realm_source) logger.info("DNS Domain: %s", cli_domain) logger.debug("DNS Domain source: %s", cli_domain_source) logger.info("IPA Server: %s", ', '.join(cli_server)) logger.debug("IPA Server source: %s", cli_server_source) logger.info("BaseDN: %s", cli_basedn) logger.debug("BaseDN source: %s", cli_basedn_source) if not options.on_master: if options.ntp_servers: for server in options.ntp_servers: logger.info("NTP server: %s", server) if options.ntp_pool: logger.info("NTP pool: %s", options.ntp_pool) # ipa-join would fail with IP address instead of a FQDN for srv in cli_server: try: socket.inet_pton(socket.AF_INET, srv) is_ipaddr = True except socket.error: try: socket.inet_pton(socket.AF_INET6, srv) is_ipaddr = True except socket.error: is_ipaddr = False if is_ipaddr: logger.info() logger.warning( "It seems that you are using an IP address " "instead of FQDN as an argument to --server. The " "installation may fail.") break # logger.info() # if not options.unattended and not user_input( # "Continue to configure the system with these values?", False): # raise ScriptError(rval=CLIENT_INSTALL_ERROR) except ScriptError as e: module.fail_json(msg=str(e)) ######################################################################### # client._install # May not happen in here at this time # if not options.on_master: # # Try removing old principals from the keytab # purge_host_keytab(cli_realm) # Check if ipa client is already configured if is_client_configured(): client_already_configured = True # Check that realm and domain match current_config = get_ipa_conf() if cli_domain != current_config.get('domain'): module.fail_json(msg="IPA client already installed " "with a conflicting domain") if cli_realm != current_config.get('realm'): module.fail_json(msg="IPA client already installed " "with a conflicting realm") else: client_already_configured = False # Done module.exit_json(changed=False, servers=cli_server, domain=cli_domain, realm=cli_realm, kdc=cli_kdc, basedn=str(cli_basedn), hostname=hostname, client_domain=client_domain, dnsok=dnsok, sssd=options.sssd, ntp_servers=options.ntp_servers, ntp_pool=options.ntp_pool, client_already_configured=client_already_configured, ipa_python_version=IPA_PYTHON_VERSION)
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'), dnsok=dict(required=False, type='bool', default=False), enable_dns_updates=dict(required=False, type='bool'), all_ip_addresses=dict(required=False, type='bool', default=False), ip_addresses=dict(required=False, type='list', default=None), request_cert=dict(required=False, type='bool', default=False), preserve_sssd=dict(required=False, type='bool'), no_ssh=dict(required=False, type='bool'), no_sshd=dict(required=False, type='bool'), no_sudo=dict(required=False, type='bool'), fixed_primary=dict(required=False, type='bool'), permit=dict(required=False, type='bool'), no_krb5_offline_passwords=dict(required=False, type='bool'), no_dns_sshfp=dict(required=False, type='bool', default=False), ), supports_check_mode=True, ) module._ansible_debug = True cli_server = module.params.get('servers') cli_realm = module.params.get('realm') hostname = module.params.get('hostname') cli_basedn = module.params.get('basedn') cli_domain = module.params.get('domain') options.principal = module.params.get('principal') subject_base = module.params.get('subject_base') ca_enabled = module.params.get('ca_enabled') options.mkhomedir = module.params.get('mkhomedir') options.on_master = module.params.get('on_master') dnsok = module.params.get('dnsok') fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE) os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE options.dns_updates = module.params.get('enable_dns_updates') options.all_ip_addresses = module.params.get('all_ip_addresses') options.ip_addresses = ansible_module_get_parsed_ip_addresses(module) options.request_cert = module.params.get('request_cert') options.hostname = hostname options.host_name = hostname options.preserve_sssd = module.params.get('preserve_sssd') options.no_ssh = module.params.get('no_ssh') options.conf_ssh = not options.no_ssh options.no_sshd = module.params.get('no_sshd') options.conf_sshd = not options.no_sshd options.no_sudo = module.params.get('no_sudo') options.conf_sudo = not options.no_sudo options.primary = module.params.get('fixed_primary') options.permit = module.params.get('permit') options.no_krb5_offline_passwords = module.params.get( 'no_krb5_offline_passwords') options.krb5_offline_passwords = not options.no_krb5_offline_passwords options.no_dns_sshfp = module.params.get('no_dns_sshfp') options.create_sshfp = not options.no_dns_sshfp options.no_sssd = False options.sssd = not options.no_sssd options.no_ac = False CCACHE_FILE = paths.IPA_DNS_CCACHE api.bootstrap(context='cli_installer', confdir=paths.ETC_IPA, debug=False, delegate=False) api.finalize() api.Backend.rpcclient.connect() try: api.Backend.rpcclient.forward('ping') except errors.KerberosError: # Cannot connect to the server due to Kerberos error, trying with # delegate=True api.Backend.rpcclient.disconnect() api.Backend.rpcclient.connect(delegate=True) api.Backend.rpcclient.forward('ping') ########################################################################## try: # Create IPA NSS database try: create_ipa_nssdb() except ipautil.CalledProcessError as e: raise ScriptError("Failed to create IPA NSS database: %s" % e, rval=CLIENT_INSTALL_ERROR) # Get CA certificates from the certificate store try: ca_certs = get_certs_from_ldap(cli_server[0], cli_basedn, cli_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, cli_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, # mode=0o644 ) 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, # mode=0o644 ) # Add the CA certificates to the IPA NSS database logger.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: raise ScriptError("Failed to add %s to the IPA NSS database." % nickname, rval=CLIENT_INSTALL_ERROR) # Add the CA certificates to the platform-dependant systemwide CA # store tasks.insert_ca_certs_into_systemwide_ca_store(ca_certs) if not options.on_master: client_dns(cli_server[0], hostname, options) configure_certmonger(fstore, subject_base, cli_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 argspec_save_state = inspect.getargspec(save_state) # Name Server Caching Daemon. Disable for SSSD, use otherwise # (if installed) nscd = services.knownservices.nscd if nscd.is_installed(): if "statestore" in argspec_save_state.args: save_state(nscd, statestore) else: save_state(nscd) nscd_service_action = None try: if options.sssd: nscd_service_action = 'stop' nscd.stop() else: nscd_service_action = 'restart' nscd.restart() except Exception: logger.warning("Failed to %s the %s daemon", nscd_service_action, nscd.service_name) if not options.sssd: logger.warning( "Caching of users/groups will not be available") try: if options.sssd: nscd.disable() else: nscd.enable() except Exception: if not options.sssd: logger.warning( "Failed to configure automatic startup of the %s " "daemon", nscd.service_name) logger.info("Caching of users/groups will not be " "available after reboot") else: logger.warning( "Failed to disable %s daemon. Disable it manually.", nscd.service_name) else: # this is optional service, just log if not options.sssd: logger.info("%s daemon is not installed, skip configuration", nscd.service_name) nslcd = services.knownservices.nslcd if nslcd.is_installed(): if "statestore" in argspec_save_state.args: save_state(nslcd, statestore) else: save_state(nslcd) retcode, conf = (0, None) if not options.no_ac: # Modify nsswitch/pam stack argspec = inspect.getargspec(tasks.modify_nsswitch_pam_stack) if "sudo" in argspec.args: tasks.modify_nsswitch_pam_stack(sssd=options.sssd, mkhomedir=options.mkhomedir, statestore=statestore, sudo=options.conf_sudo) else: tasks.modify_nsswitch_pam_stack(sssd=options.sssd, mkhomedir=options.mkhomedir, statestore=statestore) if hasattr(paths, "AUTHSELECT") and paths.AUTHSELECT is not None: # authselect is used # if mkhomedir, make sure oddjobd is enabled and started if options.mkhomedir: oddjobd = services.service('oddjobd', api) running = oddjobd.is_running() enabled = oddjobd.is_enabled() statestore.backup_state('oddjobd', 'running', running) statestore.backup_state('oddjobd', 'enabled', enabled) try: if not enabled: oddjobd.enable() if not running: oddjobd.start() except Exception as e: logger.critical("Unable to start oddjobd: %s", str(e)) logger.info("%s enabled", "SSSD" if options.sssd else "LDAP") if options.sssd: sssd = services.service('sssd', api) try: sssd.restart() except CalledProcessError: logger.warning("SSSD service restart was unsuccessful.") try: sssd.enable() except CalledProcessError as e: logger.warning( "Failed to enable automatic startup of the SSSD " "daemon: %s", e) if not options.sssd: tasks.modify_pam_to_use_krb5(statestore) logger.info("Kerberos 5 enabled") # Update non-SSSD LDAP configuration after authconfig calls as it # would change its configuration otherways if not options.sssd: for configurer in [configure_ldap_conf, configure_nslcd_conf]: (retcode, conf, filenames) = configurer( fstore, cli_basedn, cli_realm, cli_domain, cli_server, dnsok, options, nosssd_files[configurer.__name__]) if retcode: raise ScriptError(rval=CLIENT_INSTALL_ERROR) if conf: logger.info( "%s configured using configuration file(s) %s", conf, filenames) if configure_openldap_conf(fstore, cli_basedn, cli_server): logger.info("Configured /etc/openldap/ldap.conf") else: logger.info("Failed to configure /etc/openldap/ldap.conf") # Check that nss is working properly if not options.on_master: user = options.principal if user is None: user = "******" % cli_domain logger.info( "Principal is not set when enrolling with OTP" "; using principal '%s' for 'getent passwd'", user) elif '@' not in user: user = "******" % (user, cli_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. if hasattr(paths, "GETENT"): getent_cmd = paths.GETENT else: getent_cmd = '/usr/bin/getent' while n < 10 and not found: try: ipautil.run([getent_cmd, "passwd", user]) found = True except Exception: time.sleep(1) n = n + 1 if not found: logger.error( "Unable to find '%s' user with 'getent " "passwd %s'!", user.split("@")[0], user) if conf: logger.info("Recognized configuration: %s", conf) else: logger.error( "Unable to reliably detect " "configuration. Check NSS setup manually.") try: hardcode_ldap_server(cli_server) except Exception as e: logger.error( "Adding hardcoded server name to " "/etc/ldap.conf failed: %s", str(e)) except ScriptError as e: module.fail_json(msg=str(e)) ########################################################################## module.exit_json(changed=True, ca_enabled_ra=ca_enabled)