def enroll_dl0_replica(installer, fstore, remote_api, debug=False): """ Do partial host enrollment in DL0: * add host entry to remote master * request host keytab from remote master * configure client-like /etc/krb5.conf to enable GSSAPI auth further down the replica installation """ logger.info("Enrolling host to IPA domain") config = installer._config hostname = config.host_name try: installer._enrollment_performed = True host_result = remote_api.Command.host_add( unicode(config.host_name), force=installer.no_host_dns )['result'] host_princ = unicode(host_result['krbcanonicalname'][0]) purge_host_keytab(config.realm_name) getkeytab_args = [ paths.IPA_GETKEYTAB, '-s', config.master_host_name, '-p', host_princ, '-D', unicode(ipaldap.DIRMAN_DN), '-w', config.dirman_password, '-k', paths.KRB5_KEYTAB, '--cacert', os.path.join(config.dir, 'ca.crt') ] ipautil.run(getkeytab_args, nolog=(config.dirman_password,)) _hostname, _sep, host_domain = hostname.partition('.') fstore.backup_file(paths.KRB5_CONF) configure_krb5_conf( config.realm_name, config.domain_name, [config.master_host_name], [config.master_host_name], False, paths.KRB5_CONF, host_domain, hostname, configure_sssd=False ) except CalledProcessError as e: raise RuntimeError("Failed to fetch host keytab: {}".format(e))
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), kdc=dict(required=True), kinit_attempts=dict(required=False, type='int', default=5), ), supports_check_mode=True, ) module._ansible_debug = True servers = module.params.get('servers') domain = module.params.get('domain') realm = module.params.get('realm') hostname = module.params.get('hostname') kdc = module.params.get('kdc') kinit_attempts = module.params.get('kinit_attempts') client_domain = hostname[hostname.find(".") + 1:] host_principal = 'host/%s@%s' % (hostname, realm) sssd = True # Remove IPA_DNS_CCACHE remain if it exists try: os.remove(paths.IPA_DNS_CCACHE) except OSError: pass krb5_keytab_ok = False krb5_conf_ok = False ipa_test_ok = False ca_crt_exists = os.path.exists(paths.IPA_CA_CRT) env = {'PATH': SECURE_PATH, 'KRB5CCNAME': paths.IPA_DNS_CCACHE} # First try: Validate krb5 keytab with system krb5 configuraiton try: kinit_keytab(host_principal, paths.KRB5_KEYTAB, paths.IPA_DNS_CCACHE, config=paths.KRB5_CONF, attempts=kinit_attempts) krb5_keytab_ok = True krb5_conf_ok = True # Test IPA try: result = run(["/usr/bin/ipa", "ping"], raiseonerr=False, env=env) if result.returncode == 0: ipa_test_ok = True except OSError: pass except gssapi.exceptions.GSSError as e: pass # Second try: Validate krb5 keytab with temporary krb5 # configuration if not krb5_conf_ok: try: (krb_fd, krb_name) = tempfile.mkstemp() os.close(krb_fd) configure_krb5_conf(cli_realm=realm, cli_domain=domain, cli_server=servers, cli_kdc=kdc, dnsok=False, filename=krb_name, client_domain=client_domain, client_hostname=hostname, configure_sssd=sssd, force=False) try: kinit_keytab(host_principal, paths.KRB5_KEYTAB, paths.IPA_DNS_CCACHE, config=krb_name, attempts=kinit_attempts) krb5_keytab_ok = True # Test IPA env['KRB5_CONFIG'] = krb_name try: result = run(["/usr/bin/ipa", "ping"], raiseonerr=False, env=env) if result.returncode == 0: ipa_test_ok = True except OSError: pass except gssapi.exceptions.GSSError as e: pass finally: try: os.remove(krb_name) except OSError: module.fail_json(msg="Could not remove %s" % krb_name) module.exit_json(changed=False, krb5_keytab_ok=krb5_keytab_ok, krb5_conf_ok=krb5_conf_ok, ca_crt_exists=ca_crt_exists, ipa_test_ok=ipa_test_ok)
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), kdc=dict(required=True), basedn=dict(required=True), principal=dict(required=False), password=dict(required=False, no_log=True), keytab=dict(required=False), ca_cert_file=dict(required=False), force_join=dict(required=False, type='bool'), kinit_attempts=dict(required=False, type='int', default=5), debug=dict(required=False, type='bool'), ), supports_check_mode = True, ) module._ansible_debug = True servers = module.params.get('servers') domain = module.params.get('domain') realm = module.params.get('realm') hostname = module.params.get('hostname') basedn = module.params.get('basedn') kdc = module.params.get('kdc') force_join = module.params.get('force_join') principal = module.params.get('principal') password = module.params.get('password') keytab = module.params.get('keytab') ca_cert_file = module.params.get('ca_cert_file') kinit_attempts = module.params.get('kinit_attempts') debug = module.params.get('debug') if password is not None and password != "" and \ keytab is not None and keytab != "": module.fail_json(msg="Password and keytab cannot be used together") client_domain = hostname[hostname.find(".")+1:] nolog = tuple() env = {'PATH': SECURE_PATH} fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) host_principal = 'host/%s@%s' % (hostname, realm) sssd = True options.ca_cert_file = ca_cert_file options.unattended = True options.principal = principal if principal != "" else None options.force = False options.password = password ccache_dir = None changed = False already_joined = False try: (krb_fd, krb_name) = tempfile.mkstemp() os.close(krb_fd) configure_krb5_conf( cli_realm=realm, cli_domain=domain, cli_server=servers, cli_kdc=kdc, dnsok=False, filename=krb_name, client_domain=client_domain, client_hostname=hostname, configure_sssd=sssd, force=False) env['KRB5_CONFIG'] = krb_name ccache_dir = tempfile.mkdtemp(prefix='krbcc') ccache_name = os.path.join(ccache_dir, 'ccache') join_args = [paths.SBIN_IPA_JOIN, "-s", servers[0], "-b", str(realm_to_suffix(realm)), "-h", hostname] if debug: join_args.append("-d") env['XMLRPC_TRACE_CURL'] = 'yes' if force_join: join_args.append("-f") if principal: if principal.find('@') == -1: principal = '%s@%s' % (principal, realm) try: kinit_password(principal, password, ccache_name, config=krb_name) except RuntimeError as e: module.fail_json( msg="Kerberos authentication failed: {}".format(e)) elif keytab: join_args.append("-f") if os.path.exists(keytab): try: kinit_keytab(host_principal, keytab, ccache_name, config=krb_name, attempts=kinit_attempts) except gssapi.exceptions.GSSError as e: module.fail_json( msg="Kerberos authentication failed: {}".format(e)) else: module.fail_json( msg="Keytab file could not be found: {}".format(keytab)) elif password: join_args.append("-w") join_args.append(password) nolog = (password,) env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = ccache_name # Get the CA certificate try: os.environ['KRB5_CONFIG'] = env['KRB5_CONFIG'] if NUM_VERSION < 40100: get_ca_cert(fstore, options, servers[0], basedn) else: get_ca_certs(fstore, options, servers[0], basedn, realm) del os.environ['KRB5_CONFIG'] except errors.FileError as e: module.fail_json(msg='%s' % e) except Exception as e: module.fail_json(msg="Cannot obtain CA certificate\n%s" % e) # Now join the domain result = run( join_args, raiseonerr=False, env=env, nolog=nolog, capture_error=True) stderr = result.error_output if result.returncode != 0: if result.returncode == 13: already_joined = True module.log("Host is already joined") else: if principal: run(["kdestroy"], raiseonerr=False, env=env) module.fail_json(msg="Joining realm failed: %s" % stderr) else: changed = True module.log("Enrolled in IPA realm %s" % realm) # Fail for missing krb5.keytab on already joined host if already_joined and not os.path.exists(paths.KRB5_KEYTAB): module.fail_json(msg="krb5.keytab missing! Retry with ipaclient_force_join=yes to generate a new one.") if principal: run(["kdestroy"], raiseonerr=False, env=env) # Obtain the TGT. We do it with the temporary krb5.conf, sot # tha only the KDC we're installing under is contacted. # Other KDCs might not have replicated the principal yet. # Once we have the TGT, it's usable on any server. try: kinit_keytab(host_principal, paths.KRB5_KEYTAB, paths.IPA_DNS_CCACHE, config=krb_name, attempts=kinit_attempts) env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE except gssapi.exceptions.GSSError as e: # failure to get ticket makes it impossible to login and # bind from sssd to LDAP, abort installation module.fail_json(msg="Failed to obtain host TGT: %s" % e) finally: try: os.remove(krb_name) except OSError: module.fail_json(msg="Could not remove %s" % krb_name) if ccache_dir is not None: try: os.rmdir(ccache_dir) except OSError: pass if os.path.exists(krb_name + ".ipabkp"): try: os.remove(krb_name + ".ipabkp") except OSError: module.fail_json(msg="Could not remove %s.ipabkp" % krb_name) module.exit_json(changed=changed, already_joined=already_joined)
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), kdc=dict(required=True), principal=dict(required=False), kinit_attempts=dict(required=False, type='int', default=5), ), supports_check_mode = True, ) module._ansible_debug = True servers = module.params.get('servers') domain = module.params.get('domain') realm = module.params.get('realm') hostname = module.params.get('hostname') kdc = module.params.get('kdc') principal = module.params.get('principal') kinit_attempts = module.params.get('kinit_attempts') client_domain = hostname[hostname.find(".")+1:] host_principal = 'host/%s@%s' % (hostname, realm) sssd = True krb5_keytab_ok = True try: (krb_fd, krb_name) = tempfile.mkstemp() os.close(krb_fd) configure_krb5_conf( cli_realm=realm, cli_domain=domain, cli_server=servers, cli_kdc=kdc, dnsok=False, filename=krb_name, client_domain=client_domain, client_hostname=hostname, configure_sssd=sssd, force=False) # Obtain the TGT. We do it with the temporary krb5.conf, so that # only the KDC we're installing under is contacted. # Other KDCs might not have replicated the principal yet. # Once we have the TGT, it's usable on any server. try: kinit_keytab(host_principal, paths.KRB5_KEYTAB, paths.IPA_DNS_CCACHE, config=krb_name, attempts=kinit_attempts) except gssapi.exceptions.GSSError as e: # failure to get ticket makes it impossible to login and bind # from sssd to LDAP, abort installation and rollback changes krb5_keytab_ok = False finally: try: os.remove(krb_name) except OSError: module.fail_json(msg="Could not remove %s" % krb_name) module.exit_json(changed=False, krb5_keytab_ok=krb5_keytab_ok)