def add_instance_specific_data(self): ''' Add instance-specific files and directories. NOTE: this adds some things that may not get backed up. ''' serverid = ipaldap.realm_to_serverid(api.env.realm) for dir in [ paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % serverid, paths.VAR_LIB_DIRSRV_INSTANCE_SCRIPTS_TEMPLATE % serverid, paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE % serverid ]: if os.path.exists(dir): self.dirs.append(dir) for file in ( paths.SYSCONFIG_DIRSRV_INSTANCE % serverid, paths.ETC_TMPFILESD_DIRSRV % serverid, paths.SLAPD_INSTANCE_SYSTEMD_IPA_ENV_TEMPLATE % serverid, ): if os.path.exists(file): self.files.append(file) self.files.append( paths.HTTPD_PASSWD_FILE_FMT.format(host=api.env.host)) self.logs.append(paths.VAR_LOG_DIRSRV_INSTANCE_TEMPLATE % serverid)
def __setup_default_attributes(self): """ This method setups default attributes that are either constants, or based on api.env attributes, such as realm, hostname or domain name. """ # Constants self.smb_conf = paths.SMB_CONF self.cifs_hosts = [] # Values obtained from API.env self.fqdn = self.fqdn or api.env.host self.host_netbios_name = make_netbios_name(self.fqdn) self.realm = self.realm or api.env.realm self.suffix = ipautil.realm_to_suffix(self.realm) self.ldapi_socket = "%%2fvar%%2frun%%2fslapd-%s.socket" % \ ipaldap.realm_to_serverid(self.realm) # DN definitions self.trust_dn = DN(api.env.container_trusts, self.suffix) self.smb_dn = DN(('cn', 'adtrust agents'), ('cn', 'sysaccounts'), ('cn', 'etc'), self.suffix) self.smb_dom_dn = DN(('cn', api.env.domain), api.env.container_cifsdomains, self.suffix) self.cifs_agent = DN(('krbprincipalname', self.principal.lower()), api.env.container_service, self.suffix) self.host_princ = DN(('fqdn', self.fqdn), api.env.container_host, self.suffix)
def _setup_sub_dict(self): if paths.NAMED_CRYPTO_POLICY_FILE is not None: crypto_policy = 'include "{}";'.format( paths.NAMED_CRYPTO_POLICY_FILE ) else: crypto_policy = "// not available" self.sub_dict = dict( FQDN=self.fqdn, SERVER_ID=ipaldap.realm_to_serverid(self.realm), SUFFIX=self.suffix, MANAGED_KEYS_DIR=paths.NAMED_MANAGED_KEYS_DIR, ROOT_KEY=paths.NAMED_ROOT_KEY, NAMED_KEYTAB=self.keytab, RFC1912_ZONES=paths.NAMED_RFC1912_ZONES, NAMED_PID=paths.NAMED_PID, NAMED_VAR_DIR=paths.NAMED_VAR_DIR, BIND_LDAP_SO=paths.BIND_LDAP_SO, INCLUDE_CRYPTO_POLICY=crypto_policy, NAMED_CONF=paths.NAMED_CONF, NAMED_CUSTOM_CONF=paths.NAMED_CUSTOM_CONF, NAMED_CUSTOM_OPTIONS_CONF=paths.NAMED_CUSTOM_OPTIONS_CONF, NAMED_LOGGING_OPTIONS_CONF=paths.NAMED_LOGGING_OPTIONS_CONF, NAMED_DATA_DIR=constants.NAMED_DATA_DIR, NAMED_ZONE_COMMENT=constants.NAMED_ZONE_COMMENT, NAMED_DNSSEC_VALIDATION=self._get_dnssec_validation(), )
def realm_to_serverid(realm_name): warnings.warn( "Use 'ipapython.ipaldap.realm_to_serverid'", DeprecationWarning, stacklevel=2 ) return ipaldap.realm_to_serverid(realm_name)
def add_instance_specific_data(self): ''' Add instance-specific files and directories. NOTE: this adds some things that may not get backed up. ''' serverid = ipaldap.realm_to_serverid(api.env.realm) for dir in [paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % serverid, paths.VAR_LIB_DIRSRV_INSTANCE_SCRIPTS_TEMPLATE % serverid, paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE % serverid]: if os.path.exists(dir): self.dirs.append(dir) for file in ( paths.SYSCONFIG_DIRSRV_INSTANCE % serverid, paths.ETC_TMPFILESD_DIRSRV % serverid, paths.SLAPD_INSTANCE_SYSTEMD_IPA_ENV_TEMPLATE % serverid, ): if os.path.exists(file): self.files.append(file) self.files.append( paths.HTTPD_PASSWD_FILE_FMT.format(host=api.env.host) ) self.logs.append(paths.VAR_LOG_DIRSRV_INSTANCE_TEMPLATE % serverid)
def expired_ipa_certs(now): """ Determine which IPA certs are expired, or close to expiry. Return a list of (IPACertType, cert) pairs. """ certs = [] # IPA RA cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM) if cert.not_valid_after <= now: certs.append((IPACertType.IPARA, cert)) # Apache HTTPD cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE) if cert.not_valid_after <= now: certs.append((IPACertType.HTTPS, cert)) # LDAPS ds_dbdir = dsinstance.config_dirname(realm_to_serverid(api.env.realm)) db = NSSDatabase(nssdir=ds_dbdir) cert = db.get_cert('Server-Cert') if cert.not_valid_after <= now: certs.append((IPACertType.LDAPS, cert)) # KDC cert = x509.load_certificate_from_file(paths.KDC_CERT) if cert.not_valid_after <= now: certs.append((IPACertType.KDC, cert)) return certs
def test_source_ipahealthcheck_ipa_host_check_ipahostkeytab(self): """ Testcase checks behaviour of check IPAHostKeytab in source ipahealthcheck.ipa.host when dirsrv service is stopped and running on IPA master """ msg = ("Failed to obtain host TGT: Major (851968): " "Unspecified GSS failure. " "Minor code may provide more information, " "Minor (2529638972): Generic error (see e-text)") dirsrv_ipactl_status = 'Directory Service: STOPPED' api.env.realm = self.master.domain.name serverid = (realm_to_serverid(api.env.realm)).upper() dirsrv_service = "dirsrv@%s.service" % serverid self.master.run_command(["systemctl", "stop", dirsrv_service]) result = self.master.run_command(["ipactl", "status"]) returncode, data = run_healthcheck( self.master, "ipahealthcheck.ipa.host", "IPAHostKeytab", ) assert returncode == 1 if dirsrv_ipactl_status in result.stdout_text: assert data[0]["result"] == "ERROR" assert data[0]["kw"]["msg"] == msg else: assert data[0]["result"] == "SUCCESS" self.master.run_command(["systemctl", "start", dirsrv_service])
def __init__(self, reg): super().__init__(reg) self.ca = cainstance.CAInstance(api.env.realm, host_name=api.env.host) self.http = httpinstance.HTTPInstance() self.ds = dsinstance.DsInstance() self.serverid = realm_to_serverid(api.env.realm) self.conn = api.Backend.ldap2
def test_full_backup_and_restore(self): """backup, uninstall, restore""" with restore_checker(self.master): backup_path = tasks.get_backup_dir(self.master) self.master.run_command(['ipa-server-install', '--uninstall', '-U']) assert not self.master.transport.file_exists( paths.IPA_CUSTODIA_KEYS) assert not self.master.transport.file_exists( paths.IPA_CUSTODIA_CONF) dirman_password = self.master.config.dirman_password self.master.run_command(['ipa-restore', backup_path], stdin_text=dirman_password + '\nyes') # check the file permssion and ownership is set to 770 and # dirsrv:dirsrv after restore on /var/log/dirsrv/slapd-<instance> # related ticket : https://pagure.io/freeipa/issue/7725 instance = realm_to_serverid(self.master.domain.realm) log_path = paths.VAR_LOG_DIRSRV_INSTANCE_TEMPLATE % instance cmd = self.master.run_command(['stat', '-c', '"%a %G:%U"', log_path]) assert "770 dirsrv:dirsrv" in cmd.stdout_text
def test_failed_uninstall(self): self.master.run_command(['ipactl', 'stop']) serverid = realm_to_serverid(self.master.domain.realm) instance_name = ''.join([DS_INSTANCE_PREFIX, serverid]) try: # Moving the DS instance out of the way will cause the # uninstaller to raise an exception and return with a # non-zero return code. self.master.run_command([ '/bin/mv', '%s/%s' % (paths.ETC_DIRSRV, instance_name), '%s/%s.test' % (paths.ETC_DIRSRV, instance_name) ]) cmd = self.master.run_command([ 'ipa-server-install', '--uninstall', '-U'], raiseonerr=False ) assert cmd.returncode == 1 finally: # Be paranoid. If something really went wrong then DS may # be marked as uninstalled so server cert will still be # tracked and the instances may remain. This can cause # subsequent installations to fail so be thorough. dashed_domain = self.master.domain.realm.replace(".", '-') dirsrv_service = "dirsrv@%s.service" % dashed_domain self.master.run_command(['systemctl', 'stop', dirsrv_service]) # Moving it back should allow the uninstall to finish # successfully. self.master.run_command([ '/bin/mv', '%s/%s.test' % (paths.ETC_DIRSRV, instance_name), '%s/%s' % (paths.ETC_DIRSRV, instance_name) ]) cmd = self.master.run_command([ 'ipa-server-install', '--uninstall', '-U'], raiseonerr=False ) assert cmd.returncode == 0 self.master.run_command([ paths.IPA_GETCERT, 'stop-tracking', '-d', '%s/%s' % (paths.ETC_DIRSRV, instance_name), '-n', 'Server-Cert', ]) self.master.run_command([ paths.DSCTL, serverid, 'remove', '--do-it' ])
def test_failed_uninstall(self): self.master.run_command(['ipactl', 'stop']) serverid = realm_to_serverid(self.master.domain.realm) instance_name = ''.join([dsinstance.DS_INSTANCE_PREFIX, serverid]) try: # Moving the DS instance out of the way will cause the # uninstaller to raise an exception and return with a # non-zero return code. self.master.run_command([ '/bin/mv', '%s/%s' % (paths.ETC_DIRSRV, instance_name), '%s/%s.test' % (paths.ETC_DIRSRV, instance_name) ]) cmd = self.master.run_command([ 'ipa-server-install', '--uninstall', '-U'], raiseonerr=False ) assert cmd.returncode == 1 finally: # Be paranoid. If something really went wrong then DS may # be marked as uninstalled so server cert will still be # tracked and the instances may remain. This can cause # subsequent installations to fail so be thorough. dashed_domain = self.master.domain.realm.replace(".", '-') dirsrv_service = "dirsrv@%s.service" % dashed_domain self.master.run_command(['systemctl', 'stop', dirsrv_service]) # Moving it back should allow the uninstall to finish # successfully. self.master.run_command([ '/bin/mv', '%s/%s.test' % (paths.ETC_DIRSRV, instance_name), '%s/%s' % (paths.ETC_DIRSRV, instance_name) ]) cmd = self.master.run_command([ 'ipa-server-install', '--uninstall', '-U'], raiseonerr=False ) assert cmd.returncode == 0 self.master.run_command([ paths.IPA_GETCERT, 'stop-tracking', '-d', '%s/%s' % (paths.ETC_DIRSRV, instance_name), '-n', 'Server-Cert', ]) self.master.run_command([ paths.DSCTL, serverid, 'remove', '--do-it' ])
def check(self): if not self.registry.trust_controller: logger.debug('Not a trust controller, skipping') return ldapi_socket = "ipasam:ldapi://%%2fvar%%2frun%%2fslapd-%s.socket" % \ realm_to_serverid(api.env.realm) try: result = ipautil.run(['net', 'conf', 'list'], capture_output=True) except Exception as e: yield Result(self, constants.ERROR, key='net conf list', error=str(e), msg='Execution of {key} failed: {error}') return conf = result.output.replace('\t', '') config = configparser.ConfigParser(delimiters=('='), interpolation=None) try: config.read_string(conf) except Exception as e: yield Result(self, constants.ERROR, key='net conf list', error=str(e), msg='Unable to parse {key} output: {error}') return try: net_ldapi = config.get('global', 'passdb backend') except Exception as e: yield Result(self, constants.ERROR, key='net conf list', error=str(e), section='global', option='passdb backend', msg='Unable to read \'{option}\' in section ' '{section} in {key} output: {error}') return if net_ldapi != ldapi_socket: yield Result(self, constants.ERROR, key='net conf list', got=net_ldapi, expected=ldapi_socket, option='passdb backend', msg='{key} option {option} value {got} ' 'doesn\'t match expected value {expected}') else: yield Result(self, constants.SUCCESS, key='net conf list')
def __setup_sub_dict(self): if os.path.exists(paths.COMMON_KRB5_CONF_DIR): includes = 'includedir {}'.format(paths.COMMON_KRB5_CONF_DIR) else: includes = '' self.sub_dict = dict(FQDN=self.fqdn, IP=self.ip, PASSWORD=self.kdc_password, SUFFIX=self.suffix, DOMAIN=self.domain, HOST=self.host, SERVER_ID=ipaldap.realm_to_serverid(self.realm), REALM=self.realm, KRB5KDC_KADM5_ACL=paths.KRB5KDC_KADM5_ACL, DICT_WORDS=paths.DICT_WORDS, KRB5KDC_KADM5_KEYTAB=paths.KRB5KDC_KADM5_KEYTAB, KDC_CERT=paths.KDC_CERT, KDC_KEY=paths.KDC_KEY, CACERT_PEM=paths.CACERT_PEM, KDC_CA_BUNDLE_PEM=paths.KDC_CA_BUNDLE_PEM, CA_BUNDLE_PEM=paths.CA_BUNDLE_PEM, INCLUDES=includes, FIPS='#' if tasks.is_fips_enabled() else '') # IPA server/KDC is not a subdomain of default domain # Proper domain-realm mapping needs to be specified domain = dns.name.from_text(self.domain) fqdn = dns.name.from_text(self.fqdn) if not fqdn.is_subdomain(domain): logger.debug("IPA FQDN '%s' is not located in default domain '%s'", fqdn, domain) server_domain = fqdn.parent().to_unicode(omit_final_dot=True) logger.debug("Domain '%s' needs additional mapping in krb5.conf", server_domain) dr_map = " .%(domain)s = %(realm)s\n %(domain)s = %(realm)s\n" \ % dict(domain=server_domain, realm=self.realm) else: dr_map = "" self.sub_dict['OTHER_DOMAIN_REALM_MAPS'] = dr_map # Configure KEYRING CCACHE if supported if kernel_keyring.is_persistent_keyring_supported(): logger.debug("Enabling persistent keyring CCACHE") self.sub_dict['OTHER_LIBDEFAULTS'] = \ " default_ccache_name = KEYRING:persistent:%{uid}\n" else: logger.debug("Persistent keyring CCACHE is not enabled") self.sub_dict['OTHER_LIBDEFAULTS'] = '' # Create kadm5.acl if it doesn't exist if not os.path.exists(paths.KRB5KDC_KADM5_ACL): open(paths.KRB5KDC_KADM5_ACL, 'a').close() os.chmod(paths.KRB5KDC_KADM5_ACL, 0o600)
def __setup_sub_dict(self): if os.path.exists(paths.COMMON_KRB5_CONF_DIR): includes = 'includedir {}'.format(paths.COMMON_KRB5_CONF_DIR) else: includes = '' self.sub_dict = dict(FQDN=self.fqdn, IP=self.ip, PASSWORD=self.kdc_password, SUFFIX=self.suffix, DOMAIN=self.domain, HOST=self.host, SERVER_ID=ipaldap.realm_to_serverid(self.realm), REALM=self.realm, KRB5KDC_KADM5_ACL=paths.KRB5KDC_KADM5_ACL, DICT_WORDS=paths.DICT_WORDS, KRB5KDC_KADM5_KEYTAB=paths.KRB5KDC_KADM5_KEYTAB, KDC_CERT=paths.KDC_CERT, KDC_KEY=paths.KDC_KEY, CACERT_PEM=paths.CACERT_PEM, KDC_CA_BUNDLE_PEM=paths.KDC_CA_BUNDLE_PEM, CA_BUNDLE_PEM=paths.CA_BUNDLE_PEM, INCLUDES=includes) # IPA server/KDC is not a subdomain of default domain # Proper domain-realm mapping needs to be specified domain = dns.name.from_text(self.domain) fqdn = dns.name.from_text(self.fqdn) if not fqdn.is_subdomain(domain): logger.debug("IPA FQDN '%s' is not located in default domain '%s'", fqdn, domain) server_domain = fqdn.parent().to_unicode(omit_final_dot=True) logger.debug("Domain '%s' needs additional mapping in krb5.conf", server_domain) dr_map = " .%(domain)s = %(realm)s\n %(domain)s = %(realm)s\n" \ % dict(domain=server_domain, realm=self.realm) else: dr_map = "" self.sub_dict['OTHER_DOMAIN_REALM_MAPS'] = dr_map # Configure KEYRING CCACHE if supported if kernel_keyring.is_persistent_keyring_supported(): logger.debug("Enabling persistent keyring CCACHE") self.sub_dict['OTHER_LIBDEFAULTS'] = \ " default_ccache_name = KEYRING:persistent:%{uid}\n" else: logger.debug("Persistent keyring CCACHE is not enabled") self.sub_dict['OTHER_LIBDEFAULTS'] = '' # Create kadm5.acl if it doesn't exist if not os.path.exists(paths.KRB5KDC_KADM5_ACL): open(paths.KRB5KDC_KADM5_ACL, 'a').close() os.chmod(paths.KRB5KDC_KADM5_ACL, 0o600)
def expired_ipa_certs(now): """ Determine which IPA certs are expired, or close to expiry. Return a list of (IPACertType, cert) pairs. """ certs = [] non_renewed = [] # IPA RA cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM) if cert.not_valid_after <= now: certs.append((IPACertType.IPARA, cert)) # Apache HTTPD cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE) if cert.not_valid_after <= now: if not is_ipa_issued_cert(api, cert): non_renewed.append((IPACertType.HTTPS, cert)) else: certs.append((IPACertType.HTTPS, cert)) # LDAPS serverid = realm_to_serverid(api.env.realm) ds = dsinstance.DsInstance(realm_name=api.env.realm) ds_dbdir = dsinstance.config_dirname(serverid) ds_nickname = ds.get_server_cert_nickname(serverid) db = NSSDatabase(nssdir=ds_dbdir) cert = db.get_cert(ds_nickname) if cert.not_valid_after <= now: if not is_ipa_issued_cert(api, cert): non_renewed.append((IPACertType.LDAPS, cert)) else: certs.append((IPACertType.LDAPS, cert)) # KDC cert = x509.load_certificate_from_file(paths.KDC_CERT) if cert.not_valid_after <= now: if not is_ipa_issued_cert(api, cert): non_renewed.append((IPACertType.HTTPS, cert)) else: certs.append((IPACertType.KDC, cert)) return certs, non_renewed
def __init__(self, realm_name, files=[], schema_files=[]): """ realm_name: kerberos realm name, used to determine DS instance dir files: list of update files to process. If none use UPDATEDIR """ ext = '' rand = random.Random() for _i in range(8): h = "%02x" % rand.randint(0,255) ext += h super(IPAUpgrade, self).__init__("dirsrv", realm_name=realm_name) serverid = ipaldap.realm_to_serverid(realm_name) self.filename = '%s/%s' % (paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % serverid, DSE) self.savefilename = '%s/%s.ipa.%s' % (paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % serverid, DSE, ext) self.files = files self.modified = False self.serverid = serverid self.schema_files = schema_files
def install_dirsrv_cert(self): serverid = ipaldap.realm_to_serverid(api.env.realm) dirname = dsinstance.config_dirname(serverid) conn = api.Backend.ldap2 entry = conn.get_entry(DN(('cn', 'RSA'), ('cn', 'encryption'), ('cn', 'config')), ['nssslpersonalityssl']) old_cert = entry.single_value['nssslpersonalityssl'] server_cert = self.import_cert(dirname, self.options.pin, old_cert, 'ldap/%s' % api.env.host, 'restart_dirsrv %s' % serverid) entry['nssslpersonalityssl'] = [server_cert] try: conn.update_entry(entry) except errors.EmptyModlist: pass
def install_dirsrv_cert(self): serverid = ipaldap.realm_to_serverid(api.env.realm) dirname = dsinstance.config_dirname(serverid) conn = api.Backend.ldap2 entry = conn.get_entry( DN(('cn', 'RSA'), ('cn', 'encryption'), ('cn', 'config')), ['nssslpersonalityssl']) old_cert = entry.single_value['nssslpersonalityssl'] server_cert = self.import_cert(dirname, self.options.pin, old_cert, 'ldap/%s' % api.env.host, 'restart_dirsrv %s' % serverid) entry['nssslpersonalityssl'] = [server_cert] try: conn.update_entry(entry) except errors.EmptyModlist: pass
def cert_restore_prepare(self): cainstance.CAInstance().stop_tracking_certificates() httpinstance.HTTPInstance().stop_tracking_certificates() try: dsinstance.DsInstance().stop_tracking_certificates( ipaldap.realm_to_serverid(api.env.realm)) except (OSError, IOError): # When IPA is not installed, DS NSS DB does not exist pass krbinstance.KrbInstance().stop_tracking_certs() for basename in certdb.NSS_FILES: filename = os.path.join(paths.IPA_NSSDB_DIR, basename) try: ipautil.backup_file(filename) except OSError as e: logger.error("Failed to backup %s: %s", filename, e) tasks.remove_ca_certs_from_systemwide_ca_store()
def get_connection(self): ''' Create an ldapi connection and bind to it using autobind as root. ''' instance_name = ipaldap.realm_to_serverid(api.env.realm) if not services.knownservices.dirsrv.is_running(instance_name): raise admintool.ScriptError( "directory server instance is not running/configured") if self._conn is not None: return self._conn self._conn = ipaldap.LDAPClient.from_realm(api.env.realm) try: self._conn.external_bind() except Exception as e: raise admintool.ScriptError('Unable to bind to LDAP server: %s' % e) return self._conn
def init_api(self, **overrides): overrides.setdefault('confdir', paths.ETC_IPA) api.bootstrap(in_server=True, context='restore', **overrides) api.finalize() self.instances = [ipaldap.realm_to_serverid(api.env.realm)] self.backends = ['userRoot', 'ipaca'] # no IPA config means we are reinstalling from nothing so # there is nothing to test the DM password against. if os.path.exists(paths.IPA_DEFAULT_CONF): instance_name = ipapython.ipaldap.realm_to_serverid(api.env.realm) if not services.knownservices.dirsrv.is_running(instance_name): raise admintool.ScriptError( "directory server instance is not running") try: ReplicationManager(api.env.realm, api.env.host, self.dirman_password) except errors.ACIError: logger.error("Incorrect Directory Manager password provided") raise
def init_api(self, **overrides): overrides.setdefault('confdir', paths.ETC_IPA) api.bootstrap(in_server=True, context='restore', **overrides) api.finalize() self.instances = [ipaldap.realm_to_serverid(api.env.realm)] self.backends = ['userRoot', 'ipaca'] # no IPA config means we are reinstalling from nothing so # there is nothing to test the DM password against. if os.path.exists(paths.IPA_DEFAULT_CONF): instance_name = ipapython.ipaldap.realm_to_serverid(api.env.realm) if not services.knownservices.dirsrv.is_running(instance_name): raise admintool.ScriptError( "directory server instance is not running" ) try: ReplicationManager(api.env.realm, api.env.host, self.dirman_password) except errors.ACIError: logger.error("Incorrect Directory Manager password provided") raise
def test_ldapi_ok(self, mock_run): ldapi_socket = "ipasam:ldapi://%%2fvar%%2frun%%2fslapd-%s.socket" % \ realm_to_serverid(m_api.env.realm) run_result = namedtuple('run', ['returncode', 'output']) run_result.returncode = 0 run_result.output = '[global]\n\tpassdb backend=%s' % ldapi_socket mock_run.return_value = run_result framework = object() registry.initialize(framework, config.Config) registry.trust_controller = True f = IPATrustControllerConfCheck(registry) self.results = capture_results(f) assert len(self.results) == 1 result = self.results.results[0] assert result.result == constants.SUCCESS assert result.source == 'ipahealthcheck.ipa.trust' assert result.check == 'IPATrustControllerConfCheck' assert result.kw.get('key') == 'net conf list'
def install_ipa_certs(subject_base, ca_subject_dn, certs): """Print details and install renewed IPA certificates.""" for certtype, oldcert in certs: cert_path = "/etc/pki/pki-tomcat/certs/{}-renewed.crt" \ .format(oldcert.serial_number) cert = x509.load_certificate_from_file(cert_path) print_cert_info("Renewed IPA", certtype.value, cert) if certtype is IPACertType.IPARA: shutil.copyfile(cert_path, paths.RA_AGENT_PEM) cainstance.update_people_entry(cert) replicate_cert(subject_base, ca_subject_dn, cert) elif certtype is IPACertType.HTTPS: shutil.copyfile(cert_path, paths.HTTPD_CERT_FILE) elif certtype is IPACertType.LDAPS: ds_dbdir = dsinstance.config_dirname( realm_to_serverid(api.env.realm)) db = NSSDatabase(nssdir=ds_dbdir) db.delete_cert('Server-Cert') db.import_pem_cert('Server-Cert', EMPTY_TRUST_FLAGS, cert_path) elif certtype is IPACertType.KDC: shutil.copyfile(cert_path, paths.KDC_CERT)
def get_connection(self): ''' Create an ldapi connection and bind to it using autobind as root. ''' instance_name = ipaldap.realm_to_serverid(api.env.realm) if not services.knownservices.dirsrv.is_running(instance_name): raise admintool.ScriptError( "directory server instance is not running/configured" ) if self._conn is not None: return self._conn self._conn = ipaldap.LDAPClient.from_realm(api.env.realm) try: self._conn.external_bind() except Exception as e: raise admintool.ScriptError('Unable to bind to LDAP server: %s' % e) return self._conn
def install_ipa_certs(subject_base, ca_subject_dn, certs): """Print details and install renewed IPA certificates.""" for certtype, oldcert in certs: cert_path = RENEWED_CERT_PATH_TEMPLATE.format(oldcert.serial_number) cert = x509.load_certificate_from_file(cert_path) print_cert_info("Renewed IPA", certtype.value, cert) if certtype is IPACertType.IPARA: shutil.copyfile(cert_path, paths.RA_AGENT_PEM) cainstance.update_people_entry(cert) replicate_cert(subject_base, ca_subject_dn, cert) elif certtype is IPACertType.HTTPS: shutil.copyfile(cert_path, paths.HTTPD_CERT_FILE) elif certtype is IPACertType.LDAPS: serverid = realm_to_serverid(api.env.realm) ds = dsinstance.DsInstance(realm_name=api.env.realm) ds_dbdir = dsinstance.config_dirname(serverid) db = NSSDatabase(nssdir=ds_dbdir) ds_nickname = ds.get_server_cert_nickname(serverid) db.delete_cert(ds_nickname) db.import_pem_cert(ds_nickname, EMPTY_TRUST_FLAGS, cert_path) elif certtype is IPACertType.KDC: shutil.copyfile(cert_path, paths.KDC_CERT)
def __setup_sub_dict(self): if paths.NAMED_CRYPTO_POLICY_FILE is not None: crypto_policy = 'include "{}";'.format( paths.NAMED_CRYPTO_POLICY_FILE) else: crypto_policy = "// not available" self.sub_dict = dict( FQDN=self.fqdn, SERVER_ID=ipaldap.realm_to_serverid(self.realm), SUFFIX=self.suffix, BINDKEYS_FILE=paths.NAMED_BINDKEYS_FILE, MANAGED_KEYS_DIR=paths.NAMED_MANAGED_KEYS_DIR, ROOT_KEY=paths.NAMED_ROOT_KEY, NAMED_KEYTAB=self.keytab, RFC1912_ZONES=paths.NAMED_RFC1912_ZONES, NAMED_PID=paths.NAMED_PID, NAMED_VAR_DIR=paths.NAMED_VAR_DIR, BIND_LDAP_SO=paths.BIND_LDAP_SO, INCLUDE_CRYPTO_POLICY=crypto_policy, NAMED_DATA_DIR=constants.NAMED_DATA_DIR, NAMED_ZONE_COMMENT=constants.NAMED_ZONE_COMMENT, )
def test_source_ipahealthcheck_ipa_host_check_ipahostkeytab(self): """ Testcase checks behaviour of check IPAHostKeytab in source ipahealthcheck.ipa.host when dirsrv service is stopped and running on IPA master """ msg = ("Failed to obtain host TGT: Major (851968): " "Unspecified GSS failure. " "Minor code may provide more information, " "Minor (2529638972): Generic error (see e-text)") dirsrv_ipactl_status = 'Directory Service: STOPPED' api.env.realm = self.master.domain.name serverid = (realm_to_serverid(api.env.realm)).upper() dirsrv_service = "dirsrv@%s.service" % serverid self.master.run_command(["systemctl", "stop", dirsrv_service]) result = self.master.run_command(["ipactl", "status"]) self.master.run_command( [ "ipa-healthcheck", "--source", "ipahealthcheck.ipa.host", "--check", "IPAHostKeytab", "--output-file", HEALTHCHECK_OUTPUT_FILE, ], raiseonerr=False, ) contents = self.master.get_file_contents(HEALTHCHECK_OUTPUT_FILE, encoding="utf-8") data = json.loads(contents) if dirsrv_ipactl_status in result.stdout_text: assert data[0]["result"] == "ERROR" assert data[0]["kw"]["msg"] == msg else: assert data[0]["result"] == "SUCCESS" self.master.run_command(["systemctl", "start", dirsrv_service])
def is_dirsrv_debugging_enabled(): """ Check the 389-ds instance to see if debugging is enabled. If so we suppress that in our output. returns True or False """ debugging = False serverid = realm_to_serverid(api.env.realm) dselist = [config_dirname(serverid)] for dse in dselist: try: fd = open(dse + "dse.ldif", "r") except IOError: continue lines = fd.readlines() fd.close() for line in lines: if line.lower().startswith("nsslapd-errorlog-level"): _option, value = line.split(":") if int(value) > 0: debugging = True return debugging
def __setup_sub_dict(self): if paths.NAMED_CRYPTO_POLICY_FILE is not None: crypto_policy = 'include "{}";'.format( paths.NAMED_CRYPTO_POLICY_FILE ) else: crypto_policy = "// not available" self.sub_dict = dict( FQDN=self.fqdn, SERVER_ID=ipaldap.realm_to_serverid(self.realm), SUFFIX=self.suffix, BINDKEYS_FILE=paths.NAMED_BINDKEYS_FILE, MANAGED_KEYS_DIR=paths.NAMED_MANAGED_KEYS_DIR, ROOT_KEY=paths.NAMED_ROOT_KEY, NAMED_KEYTAB=self.keytab, RFC1912_ZONES=paths.NAMED_RFC1912_ZONES, NAMED_PID=paths.NAMED_PID, NAMED_VAR_DIR=paths.NAMED_VAR_DIR, BIND_LDAP_SO=paths.BIND_LDAP_SO, INCLUDE_CRYPTO_POLICY=crypto_policy, NAMED_DATA_DIR=constants.NAMED_DATA_DIR, NAMED_ZONE_COMMENT=constants.NAMED_ZONE_COMMENT, )
def run(self): options = self.options super(Backup, self).run() api.bootstrap(in_server=True, context='backup', confdir=paths.ETC_IPA) api.finalize() logger.info("Preparing backup on %s", api.env.host) pent = pwd.getpwnam(constants.DS_USER) self.top_dir = tempfile.mkdtemp("ipa") os.chown(self.top_dir, pent.pw_uid, pent.pw_gid) os.chmod(self.top_dir, 0o750) self.dir = os.path.join(self.top_dir, "ipa") os.mkdir(self.dir) os.chmod(self.dir, 0o750) os.chown(self.dir, pent.pw_uid, pent.pw_gid) self.tarfile = None self.header = os.path.join(self.top_dir, 'header') cwd = os.getcwd() try: dirsrv = services.knownservices.dirsrv self.add_instance_specific_data() # We need the dirsrv running to get the list of services dirsrv.start(capture_output=False) self.get_connection() self.create_header(options.data_only) if options.data_only: if not options.online: logger.info('Stopping Directory Server') dirsrv.stop(capture_output=False) else: logger.info('Stopping IPA services') run([paths.IPACTL, 'stop']) instance = ipaldap.realm_to_serverid(api.env.realm) if os.path.exists(paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE % instance): if os.path.exists(paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE % (instance, 'ipaca')): self.db2ldif(instance, 'ipaca', online=options.online) self.db2ldif(instance, 'userRoot', online=options.online) self.db2bak(instance, online=options.online) if not options.data_only: # create backup of auth configuration auth_backup_path = os.path.join(paths.VAR_LIB_IPA, 'auth_backup') tasks.backup_auth_configuration(auth_backup_path) self.file_backup(options) if options.data_only: if not options.online: logger.info('Starting Directory Server') dirsrv.start(capture_output=False) else: logger.info('Starting IPA service') run([paths.IPACTL, 'start']) # Compress after services are restarted to minimize # the unavailability window if not options.data_only: self.compress_file_backup() self.finalize_backup(options.data_only, options.gpg, options.gpg_keyring) finally: try: os.chdir(cwd) except Exception as e: logger.error('Cannot change directory to %s: %s', cwd, e) shutil.rmtree(self.top_dir)
def uninstall(installer): fstore = installer._fstore sstore = installer._sstore rv = 0 print("Shutting down all IPA services") try: services.knownservices.ipa.stop() except Exception: # Fallback to direct ipactl stop only if system command fails try: run([paths.IPACTL, "stop"], raiseonerr=False) except Exception: pass ipaclient.install.client.restore_time_sync(sstore, fstore) kra.uninstall() ca.uninstall() dns.uninstall() httpinstance.HTTPInstance(fstore).uninstall() krbinstance.KrbInstance(fstore).uninstall() dsinstance.DsInstance(fstore=fstore).uninstall() if _server_trust_ad_installed: adtrustinstance.ADTRUSTInstance(fstore).uninstall() # realm isn't used, but IPAKEMKeys parses /etc/ipa/default.conf # otherwise, see https://pagure.io/freeipa/issue/7474 . custodiainstance.CustodiaInstance(realm='REALM.INVALID').uninstall() otpdinstance.OtpdInstance().uninstall() tasks.restore_hostname(fstore, sstore) fstore.restore_all_files() try: os.remove(paths.ROOT_IPA_CACHE) except Exception: pass try: os.remove(paths.ROOT_IPA_CSR) except Exception: pass # ipa-client-install removes /etc/ipa/default.conf sstore._load() ipaclient.install.timeconf.restore_forced_timeservices(sstore) # Clean up group_exists (unused since IPA 2.2, not being set since 4.1) sstore.restore_state("install", "group_exists") services.knownservices.ipa.disable() # remove upgrade state file sysupgrade.remove_upgrade_file() if fstore.has_files(): logger.error('Some files have not been restored, see ' '%s/sysrestore.index', SYSRESTORE_DIR_PATH) has_state = False for module in IPA_MODULES: # from installutils if sstore.has_state(module): logger.error('Some installation state for %s has not been ' 'restored, see %s/sysrestore.state', module, SYSRESTORE_DIR_PATH) has_state = True rv = 1 if has_state: logger.error('Some installation state has not been restored.\n' 'This may cause re-installation to fail.\n' 'It should be safe to remove %s/sysrestore.state ' 'but it may\n' 'mean your system hasn\'t be restored to its ' 'pre-installation state.', SYSRESTORE_DIR_PATH) else: # sysrestore.state has no state left, remove it sysrestore = os.path.join(SYSRESTORE_DIR_PATH, 'sysrestore.state') installutils.remove_file(sysrestore) # Note that this name will be wrong after the first uninstall. dirname = dsinstance.config_dirname( ipaldap.realm_to_serverid(api.env.realm)) dirs = [dirname, paths.PKI_TOMCAT_ALIAS_DIR, paths.HTTPD_ALIAS_DIR] ids = certmonger.check_state(dirs) if ids: logger.error('Some certificates may still be tracked by ' 'certmonger.\n' 'This will cause re-installation to fail.\n' 'Start the certmonger service and list the ' 'certificates being tracked\n' ' # getcert list\n' 'These may be untracked by executing\n' ' # getcert stop-tracking -i <request_id>\n' 'for each id in: %s', ', '.join(ids)) # Remove the cert renewal lock file try: os.remove(paths.IPA_RENEWAL_LOCK) except OSError as e: if e.errno != errno.ENOENT: logger.warning("Failed to remove file %s: %s", paths.IPA_RENEWAL_LOCK, e) print("Removing IPA client configuration") try: result = run([paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended", "--uninstall"], raiseonerr=False, redirect_output=True) if result.returncode not in [0, 2]: raise RuntimeError("Failed to configure the client") except Exception: rv = 1 print("Uninstall of client side components failed!") sys.exit(rv)
def install_step_1(standalone, replica_config, options, custodia): if replica_config is not None and not replica_config.setup_ca: return realm_name = options.realm_name host_name = options.host_name subject_base = options._subject_base basedn = ipautil.realm_to_suffix(realm_name) ca = cainstance.CAInstance(realm=realm_name, host_name=host_name, custodia=custodia) ca.stop('pki-tomcat') # This is done within stopped_service context, which restarts CA ca.enable_client_auth_to_db() # Lightweight CA key retrieval is configured in step 1 instead # of CAInstance.configure_instance (which is invoked from step # 0) because kadmin_addprinc fails until krb5.conf is installed # by krb.create_instance. # ca.setup_lightweight_ca_key_retrieval() serverid = ipaldap.realm_to_serverid(realm_name) if standalone and replica_config is None: dirname = dsinstance.config_dirname(serverid) # Store the new IPA CA cert chain in DS NSS database and LDAP cadb = certs.CertDB(realm_name, nssdir=paths.PKI_TOMCAT_ALIAS_DIR, subject_base=subject_base) dsdb = certs.CertDB(realm_name, nssdir=dirname, subject_base=subject_base) cacert = cadb.get_cert_from_db('caSigningCert cert-pki-ca') nickname = certdb.get_ca_nickname(realm_name) trust_flags = certdb.IPA_CA_TRUST_FLAGS dsdb.add_cert(cacert, nickname, trust_flags) certstore.put_ca_cert_nss(api.Backend.ldap2, api.env.basedn, cacert, nickname, trust_flags, config_ipa=True, config_compat=True) # Store DS CA cert in Dogtag NSS database trust_flags = dict(reversed(dsdb.list_certs())) server_certs = dsdb.find_server_certs() trust_chain = dsdb.find_root_cert(server_certs[0][0])[:-1] nickname = trust_chain[-1] cert = dsdb.get_cert_from_db(nickname) cadb.add_cert(cert, nickname, trust_flags[nickname]) installutils.restart_dirsrv() ca.start('pki-tomcat') if standalone or replica_config is not None: # We need to restart apache as we drop a new config file in there services.knownservices.httpd.restart(capture_output=True) if standalone: # Install CA DNS records if bindinstance.dns_container_exists(basedn): bind = bindinstance.BindInstance() bind.update_system_records()
def install_check(standalone, replica_config, options): global external_cert_file global external_ca_file realm_name = options.realm_name host_name = options.host_name if replica_config is None: options._subject_base = options.subject_base options._ca_subject = options.ca_subject else: # during replica install, this gets invoked before local DS is # available, so use the remote api. _api = api if standalone else options._remote_api # for replica-install the knobs cannot be written, hence leading '_' options._subject_base = str(replica_config.subject_base) options._ca_subject = lookup_ca_subject(_api, options._subject_base) if replica_config is not None and not replica_config.setup_ca: return if replica_config is not None: if standalone and api.env.ra_plugin == 'selfsign': raise ScriptError('A selfsign CA can not be added') if standalone and not options.skip_conncheck: principal = options.principal replica_conn_check(replica_config.ca_host_name, host_name, realm_name, True, replica_config.ca_ds_port, options.admin_password, principal=principal, ca_cert_file=options.ca_cert_file) if options.skip_schema_check: logger.info("Skipping CA DS schema check") return if standalone: if api.Command.ca_is_enabled()['result']: raise ScriptError( "One or more CA masters are already present in IPA realm " "'%s'.\nIf you wish to replicate CA to this host, please " "re-run 'ipa-ca-install'\nwith a replica file generated on " "an existing CA master as argument." % realm_name) if options.external_cert_files: if not cainstance.is_step_one_done(): # This can happen if someone passes external_ca_file without # already having done the first stage of the CA install. raise ScriptError( "CA is not installed yet. To install with an external CA " "is a two-stage process.\nFirst run the installer with " "--external-ca.") external_cert_file, external_ca_file = installutils.load_external_cert( options.external_cert_files, options._ca_subject) elif options.external_ca: if cainstance.is_step_one_done(): raise ScriptError( "CA is already installed.\nRun the installer with " "--external-cert-file.") if os.path.isfile(paths.ROOT_IPA_CSR): raise ScriptError( "CA CSR file %s already exists.\nIn order to continue " "remove the file and run the installer again." % paths.ROOT_IPA_CSR) if not options.external_ca_type: options.external_ca_type = x509.ExternalCAType.GENERIC.value if options.external_ca_profile is not None: # check that profile is valid for the external ca type if options.external_ca_type \ not in options.external_ca_profile.valid_for: raise ScriptError( "External CA profile specification '{}' " "cannot be used with external CA type '{}'.".format( options.external_ca_profile.unparsed_input, options.external_ca_type)) if not options.external_cert_files: if not cainstance.check_ports(): print("IPA requires ports 8080 and 8443 for PKI, but one or more " "are currently in use.") raise ScriptError("Aborting installation") if standalone: dirname = dsinstance.config_dirname( ipaldap.realm_to_serverid(realm_name)) cadb = certs.CertDB(realm_name, nssdir=paths.PKI_TOMCAT_ALIAS_DIR, subject_base=options._subject_base) dsdb = certs.CertDB(realm_name, nssdir=dirname, subject_base=options._subject_base) # Check that we can add our CA cert to DS and PKI NSS databases for db in (cadb, dsdb): if not db.exists(): continue for nickname, _trust_flags in db.list_certs(): if nickname == certdb.get_ca_nickname(realm_name): raise ScriptError( "Certificate with nickname %s is present in %s, " "cannot continue." % (nickname, db.secdir)) cert = db.get_cert_from_db(nickname) if not cert: continue subject = DN(cert.subject) if subject == DN(options._ca_subject): raise ScriptError( "Certificate with subject %s is present in %s, " "cannot continue." % (subject, db.secdir))
def execute(self, **options): serverid = realm_to_serverid(self.api.env.realm) db = certs.CertDB(self.api.env.realm, nssdir=dsinstance.config_dirname(serverid)) ca_cert = None ca_enabled = self.api.Command.ca_is_enabled()['result'] if ca_enabled: ca_nickname = certdb.get_ca_nickname(self.api.env.realm) ca_subject = certstore.get_ca_subject( self.api.Backend.ldap2, self.api.env.container_ca, self.api.env.basedn) else: ca_nickname = None server_certs = db.find_server_certs() if server_certs: ca_chain = db.find_root_cert(server_certs[0][0])[:-1] if ca_chain: ca_nickname = ca_chain[-1] ldap = self.api.Backend.ldap2 for nickname, trust_flags in db.list_certs(): if trust_flags.has_key: continue cert = db.get_cert_from_db(nickname) subject = cert.subject if ca_enabled and subject == ca_subject: # When ca is enabled, we can have the IPA CA cert stored # in the nss db with a different nickname (for instance # when the server was installed with --subject to # customize the CA cert subject), but it must always be # stored in LDAP with the DN cn=$DOMAIN IPA CA # This is why we check the subject instead of the nickname here nickname = ca_nickname trust_flags = certdb.IPA_CA_TRUST_FLAGS trust, _ca, eku = certstore.trust_flags_to_key_policy(trust_flags) dn = DN(('cn', nickname), ('cn', 'certificates'), ('cn', 'ipa'), ('cn','etc'), self.api.env.basedn) entry = ldap.make_entry(dn) try: certstore.init_ca_entry(entry, cert, nickname, trust, eku) except Exception as e: logger.warning("Failed to create entry for %s: %s", nickname, e) continue if nickname == ca_nickname: ca_cert = cert config = entry.setdefault('ipaConfigString', []) if ca_enabled: config.append('ipaCa') config.append('ipaCa') try: ldap.add_entry(entry) except errors.DuplicateEntry: if nickname == ca_nickname and ca_enabled: try: ldap.update_entry(entry) except errors.EmptyModlist: pass if ca_cert: dn = DN(('cn', 'CACert'), ('cn', 'ipa'), ('cn','etc'), self.api.env.basedn) try: entry = ldap.get_entry(dn) except errors.NotFound: entry = ldap.make_entry(dn) entry['objectclass'] = ['nsContainer', 'pkiCA'] entry.single_value['cn'] = 'CAcert' entry.single_value['cACertificate;binary'] = ca_cert ldap.add_entry(entry) else: force_write = False try: _cert_bin = entry['cACertificate;binary'] except ValueError: # BZ 1644874 # sometimes the cert is badly stored, twice encoded # force write to fix the value logger.debug('Fixing the value of cACertificate;binary ' 'in entry %s', entry.dn) force_write = True if force_write or b'' in entry['cACertificate;binary']: entry.single_value['cACertificate;binary'] = ca_cert ldap.update_entry(entry) return False, []
def uninstall(installer): fstore = installer._fstore sstore = installer._sstore rv = 0 print("Shutting down all IPA services") try: services.knownservices.ipa.stop() except Exception: # Fallback to direct ipactl stop only if system command fails try: run([paths.IPACTL, "stop"], raiseonerr=False) except Exception: pass restore_time_sync(sstore, fstore) kra.uninstall() ca.uninstall() dns.uninstall() httpinstance.HTTPInstance(fstore).uninstall() krbinstance.KrbInstance(fstore).uninstall() dsinstance.DsInstance(fstore=fstore).uninstall() if _server_trust_ad_installed: adtrustinstance.ADTRUSTInstance(fstore).uninstall() # realm isn't used, but IPAKEMKeys parses /etc/ipa/default.conf # otherwise, see https://pagure.io/freeipa/issue/7474 . custodiainstance.CustodiaInstance(realm='REALM.INVALID').uninstall() otpdinstance.OtpdInstance().uninstall() tasks.restore_hostname(fstore, sstore) fstore.restore_all_files() try: os.remove(paths.ROOT_IPA_CACHE) except Exception: pass try: os.remove(paths.ROOT_IPA_CSR) except Exception: pass # ipa-client-install removes /etc/ipa/default.conf sstore._load() timeconf.restore_forced_timeservices(sstore) # Clean up group_exists (unused since IPA 2.2, not being set since 4.1) sstore.restore_state("install", "group_exists") services.knownservices.ipa.disable() # remove upgrade state file sysupgrade.remove_upgrade_file() tasks.restore_pkcs11_modules(fstore) if fstore.has_files(): logger.error('Some files have not been restored, see ' '%s/sysrestore.index', SYSRESTORE_DIR_PATH) has_state = False for module in IPA_MODULES: # from installutils if sstore.has_state(module): logger.error('Some installation state for %s has not been ' 'restored, see %s/sysrestore.state', module, SYSRESTORE_DIR_PATH) has_state = True rv = 1 if has_state: logger.error('Some installation state has not been restored.\n' 'This may cause re-installation to fail.\n' 'It should be safe to remove %s/sysrestore.state ' 'but it may\n' 'mean your system hasn\'t be restored to its ' 'pre-installation state.', SYSRESTORE_DIR_PATH) else: # sysrestore.state has no state left, remove it sysrestore = os.path.join(SYSRESTORE_DIR_PATH, 'sysrestore.state') ipautil.remove_file(sysrestore) # Note that this name will be wrong after the first uninstall. dirname = dsinstance.config_dirname( ipaldap.realm_to_serverid(api.env.realm)) dirs = [dirname, paths.PKI_TOMCAT_ALIAS_DIR, paths.HTTPD_ALIAS_DIR] ids = certmonger.check_state(dirs) if ids: logger.error('Some certificates may still be tracked by ' 'certmonger.\n' 'This will cause re-installation to fail.\n' 'Start the certmonger service and list the ' 'certificates being tracked\n' ' # getcert list\n' 'These may be untracked by executing\n' ' # getcert stop-tracking -i <request_id>\n' 'for each id in: %s', ', '.join(ids)) # Remove the cert renewal lock file try: os.remove(paths.IPA_RENEWAL_LOCK) except OSError as e: if e.errno != errno.ENOENT: logger.warning("Failed to remove file %s: %s", paths.IPA_RENEWAL_LOCK, e) print("Removing IPA client configuration") try: result = run([paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended", "--uninstall"], raiseonerr=False, redirect_output=True) if result.returncode not in [0, 2]: raise RuntimeError("Failed to configure the client") except Exception: rv = 1 print("Uninstall of client side components failed!") sys.exit(rv)
def install_check(standalone, replica_config, options): global external_cert_file global external_ca_file realm_name = options.realm_name host_name = options.host_name if replica_config is None: options._subject_base = options.subject_base options._ca_subject = options.ca_subject else: # during replica install, this gets invoked before local DS is # available, so use the remote api. _api = api if standalone else options._remote_api # for replica-install the knobs cannot be written, hence leading '_' options._subject_base = str(replica_config.subject_base) options._ca_subject = lookup_ca_subject(_api, options._subject_base) if replica_config is not None and not replica_config.setup_ca: return if replica_config is not None: if standalone and api.env.ra_plugin == 'selfsign': raise ScriptError('A selfsign CA can not be added') if standalone and not options.skip_conncheck: principal = options.principal replica_conn_check( replica_config.ca_host_name, host_name, realm_name, True, replica_config.ca_ds_port, options.admin_password, principal=principal, ca_cert_file=options.ca_cert_file) if options.skip_schema_check: logger.info("Skipping CA DS schema check") return if standalone: if api.Command.ca_is_enabled()['result']: raise ScriptError( "One or more CA masters are already present in IPA realm " "'%s'.\nIf you wish to replicate CA to this host, please " "re-run 'ipa-ca-install'\nwith a replica file generated on " "an existing CA master as argument." % realm_name ) if options.external_cert_files: if not cainstance.is_step_one_done(): # This can happen if someone passes external_ca_file without # already having done the first stage of the CA install. raise ScriptError( "CA is not installed yet. To install with an external CA " "is a two-stage process.\nFirst run the installer with " "--external-ca.") external_cert_file, external_ca_file = installutils.load_external_cert( options.external_cert_files, options._ca_subject) elif options.external_ca: if cainstance.is_step_one_done(): raise ScriptError( "CA is already installed.\nRun the installer with " "--external-cert-file.") if os.path.isfile(paths.ROOT_IPA_CSR): raise ScriptError( "CA CSR file %s already exists.\nIn order to continue " "remove the file and run the installer again." % paths.ROOT_IPA_CSR) if not options.external_ca_type: options.external_ca_type = \ cainstance.ExternalCAType.GENERIC.value if options.external_ca_profile is not None: # check that profile is valid for the external ca type if options.external_ca_type \ not in options.external_ca_profile.valid_for: raise ScriptError( "External CA profile specification '{}' " "cannot be used with external CA type '{}'." .format( options.external_ca_profile.unparsed_input, options.external_ca_type) ) if not options.external_cert_files: if not cainstance.check_ports(): print( "IPA requires ports 8080 and 8443 for PKI, but one or more " "are currently in use." ) raise ScriptError("Aborting installation") if standalone: dirname = dsinstance.config_dirname( ipaldap.realm_to_serverid(realm_name)) cadb = certs.CertDB(realm_name, nssdir=paths.PKI_TOMCAT_ALIAS_DIR, subject_base=options._subject_base) dsdb = certs.CertDB( realm_name, nssdir=dirname, subject_base=options._subject_base) # Check that we can add our CA cert to DS and PKI NSS databases for db in (cadb, dsdb): if not db.exists(): continue for nickname, _trust_flags in db.list_certs(): if nickname == certdb.get_ca_nickname(realm_name): raise ScriptError( "Certificate with nickname %s is present in %s, " "cannot continue." % (nickname, db.secdir)) cert = db.get_cert_from_db(nickname) if not cert: continue subject = DN(cert.subject) if subject == DN(options._ca_subject): raise ScriptError( "Certificate with subject %s is present in %s, " "cannot continue." % (subject, db.secdir))
def test_renew_expired_cert_replica(self, expire_certs): """Test renewal of certificates on replica with ipa-cert-fix This is to check that ipa-cert-fix renews the certificates on replica related: https://pagure.io/freeipa/issue/7885 """ # wait for cert expiry check_status(self.master, 8, "CA_UNREACHABLE") self.master.run_command(['ipa-cert-fix', '-v'], stdin_text='yes\n') check_status(self.master, 9, "MONITORING") # replica operations # 'Server-Cert cert-pki-ca' cert will be in CA_UNREACHABLE state cmd = self.replicas[0].run_command([ 'getcert', 'list', '-d', paths.PKI_TOMCAT_ALIAS_DIR, '-n', 'Server-Cert cert-pki-ca' ]) req_id = get_certmonger_fs_id(cmd.stdout_text) tasks.wait_for_certmonger_status(self.replicas[0], ('CA_UNREACHABLE'), req_id, timeout=600) # get initial expiry date to compare later with renewed cert initial_expiry = get_cert_expiry(self.replicas[0], paths.PKI_TOMCAT_ALIAS_DIR, 'Server-Cert cert-pki-ca') # check that HTTP,LDAP,PKINIT are renewed and in MONITORING state instance = realm_to_serverid(self.master.domain.realm) dirsrv_cert = paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % instance for cert in (paths.KDC_CERT, paths.HTTPD_CERT_FILE): cmd = self.replicas[0].run_command(['getcert', 'list', '-f', cert]) req_id = get_certmonger_fs_id(cmd.stdout_text) tasks.wait_for_certmonger_status(self.replicas[0], ('MONITORING'), req_id, timeout=600) cmd = self.replicas[0].run_command( ['getcert', 'list', '-d', dirsrv_cert]) req_id = get_certmonger_fs_id(cmd.stdout_text) tasks.wait_for_certmonger_status(self.replicas[0], ('MONITORING'), req_id, timeout=600) # check if replication working fine testuser = '******' password = '******' stdin = (f"{self.master.config.admin_password}\n" f"{self.master.config.admin_password}\n" f"{self.master.config.admin_password}\n") self.master.run_command(['kinit', 'admin'], stdin_text=stdin) tasks.user_add(self.master, testuser, password=password) self.replicas[0].run_command(['kinit', 'admin'], stdin_text=stdin) self.replicas[0].run_command(['ipa', 'user-show', testuser]) # renew shared certificates by resubmitting to certmonger cmd = self.replicas[0].run_command( ['getcert', 'list', '-f', paths.RA_AGENT_PEM]) req_id = get_certmonger_fs_id(cmd.stdout_text) if needs_resubmit(self.replicas[0], req_id): self.replicas[0].run_command(['getcert', 'resubmit', '-i', req_id]) tasks.wait_for_certmonger_status(self.replicas[0], ('MONITORING'), req_id, timeout=600) for cert_nick in ('auditSigningCert cert-pki-ca', 'ocspSigningCert cert-pki-ca', 'subsystemCert cert-pki-ca'): cmd = self.replicas[0].run_command([ 'getcert', 'list', '-d', paths.PKI_TOMCAT_ALIAS_DIR, '-n', cert_nick ]) req_id = get_certmonger_fs_id(cmd.stdout_text) if needs_resubmit(self.replicas[0], req_id): self.replicas[0].run_command( ['getcert', 'resubmit', '-i', req_id]) tasks.wait_for_certmonger_status(self.replicas[0], ('MONITORING'), req_id, timeout=600) self.replicas[0].run_command(['ipa-cert-fix', '-v'], stdin_text='yes\n') check_status(self.replicas[0], 9, "MONITORING") # Sometimes certmonger takes time to update the cert status # So check in nssdb instead of relying on getcert command renewed_expiry = get_cert_expiry(self.replicas[0], paths.PKI_TOMCAT_ALIAS_DIR, 'Server-Cert cert-pki-ca') assert renewed_expiry > initial_expiry
def install_step_1(standalone, replica_config, options, custodia): if replica_config is not None and not replica_config.setup_ca: return realm_name = options.realm_name host_name = options.host_name subject_base = options._subject_base basedn = ipautil.realm_to_suffix(realm_name) ca = cainstance.CAInstance( realm=realm_name, host_name=host_name, custodia=custodia ) ca.stop('pki-tomcat') # This is done within stopped_service context, which restarts CA ca.enable_client_auth_to_db() # Lightweight CA key retrieval is configured in step 1 instead # of CAInstance.configure_instance (which is invoked from step # 0) because kadmin_addprinc fails until krb5.conf is installed # by krb.create_instance. # ca.setup_lightweight_ca_key_retrieval() serverid = ipaldap.realm_to_serverid(realm_name) if standalone and replica_config is None: dirname = dsinstance.config_dirname(serverid) # Store the new IPA CA cert chain in DS NSS database and LDAP cadb = certs.CertDB( realm_name, nssdir=paths.PKI_TOMCAT_ALIAS_DIR, subject_base=subject_base) dsdb = certs.CertDB( realm_name, nssdir=dirname, subject_base=subject_base) cacert = cadb.get_cert_from_db('caSigningCert cert-pki-ca') nickname = certdb.get_ca_nickname(realm_name) trust_flags = certdb.IPA_CA_TRUST_FLAGS dsdb.add_cert(cacert, nickname, trust_flags) certstore.put_ca_cert_nss(api.Backend.ldap2, api.env.basedn, cacert, nickname, trust_flags, config_ipa=True, config_compat=True) # Store DS CA cert in Dogtag NSS database trust_flags = dict(reversed(dsdb.list_certs())) server_certs = dsdb.find_server_certs() trust_chain = dsdb.find_root_cert(server_certs[0][0])[:-1] nickname = trust_chain[-1] cert = dsdb.get_cert_from_db(nickname) cadb.add_cert(cert, nickname, trust_flags[nickname]) installutils.restart_dirsrv() ca.start('pki-tomcat') if standalone or replica_config is not None: # We need to restart apache as we drop a new config file in there services.knownservices.httpd.restart(capture_output=True) if standalone: # Install CA DNS records if bindinstance.dns_container_exists(basedn): bind = bindinstance.BindInstance() bind.update_system_records()
def check(self, instance=''): self.service_name = 'dirsrv' return super().check(realm_to_serverid(api.env.realm))
def run(self): if not is_ipa_configured(): print("IPA is not configured.") return 2 if not cainstance.is_ca_installed_locally(): print("CA is not installed on this server.") return 1 try: ipautil.run(['pki-server', 'cert-fix', '--help'], raiseonerr=True) except ipautil.CalledProcessError: print("The 'pki-server cert-fix' command is not available; " "cannot proceed.") return 1 api.bootstrap(in_server=True, confdir=paths.ETC_IPA) api.finalize() if not dsinstance.is_ds_running(realm_to_serverid(api.env.realm)): print("The LDAP server is not running; cannot proceed.") return 1 api.Backend.ldap2.connect() # ensure DS is up subject_base = dsinstance.DsInstance().find_subject_base() if not subject_base: raise RuntimeError("Cannot determine certificate subject base.") ca_subject_dn = ca.lookup_ca_subject(api, subject_base) now = datetime.datetime.now() + datetime.timedelta(weeks=2) certs, extra_certs, non_renewed = expired_certs(now) if not certs and not extra_certs: print("Nothing to do.") return 0 print(msg) print_intentions(certs, extra_certs, non_renewed) response = ipautil.user_input('Enter "yes" to proceed') if response.lower() != 'yes': print("Not proceeding.") return 0 print("Proceeding.") try: fix_certreq_directives(certs) run_cert_fix(certs, extra_certs) except ipautil.CalledProcessError: if any(x[0] is IPACertType.LDAPS for x in extra_certs + non_renewed): # The DS cert was expired. This will cause 'pki-server # cert-fix' to fail at the final restart, and return nonzero. # So this exception *might* be OK to ignore. # # If 'pki-server cert-fix' has written new certificates # corresponding to all the extra_certs, then ignore the # CalledProcessError and proceed to installing the IPA-specific # certs. Otherwise re-raise. if check_renewed_ipa_certs(extra_certs): pass else: raise else: raise # otherwise re-raise replicate_dogtag_certs(subject_base, ca_subject_dn, certs) install_ipa_certs(subject_base, ca_subject_dn, extra_certs) if any(x[0] != 'sslserver' for x in certs) \ or any(x[0] is IPACertType.IPARA for x in extra_certs): # we renewed a "shared" certificate, therefore we must # become the renewal master print("Becoming renewal master.") cainstance.CAInstance().set_renewal_master() print("Restarting IPA") ipautil.run(['ipactl', 'restart'], raiseonerr=True) print(renewal_note) return 0