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 __create_kra_agent(self): """ Create KRA agent, assign a certificate, and add the user to the appropriate groups for accessing KRA services. """ conn = api.Backend.ldap2 # get RA agent certificate cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM) # create ipakra user with RA agent certificate entry = conn.make_entry(KRA_AGENT_DN, objectClass=[ 'top', 'person', 'organizationalPerson', 'inetOrgPerson', 'cmsuser' ], uid=["ipakra"], sn=["IPA KRA User"], cn=["IPA KRA User"], usertype=["undefined"], userCertificate=[cert], description=[ '2;%s;%s;%s' % (cert.serial_number, self.ca_subject, DN(('CN', 'IPA RA'), self.subject_base)) ]) conn.add_entry(entry) # add ipakra user to Data Recovery Manager Agents group group_dn = DN(('cn', 'Data Recovery Manager Agents'), ('ou', 'groups'), KRA_BASEDN) conn.add_entry_to_group(KRA_AGENT_DN, group_dn, 'uniqueMember')
def check_ra_cert(config_data, cert_name='ipaCert'): from freeipa_health_checker import ldap_helper nssdb_dir = config_data['ck_ra_cert']['nssdb_dir'] pem_dir = config_data['ck_ra_cert']['pem_dir'] if os.path.exists(nssdb_dir): cert_data = commands_helper.get_cert(nssdb_dir, cert_name) cert = parser.nssdb_cert_to_basecertificate(cert_data) certificate = parser.BaseCertificate(serial_number=cert.serial_number) cert_serialnumber = certificate.serial_number cert_derdata = cert.der_data logger.info(messages.ra_cert_from(cert_name, nssdb_dir)) elif os.path.exists(pem_dir): from ipalib import x509 certificate = x509.load_certificate_from_file(pem_dir) cert_serialnumber = certificate.serial_number cert_derdata = certificate.der_data logger.info(messages.ra_cert_from(cert_name, pem_dir)) ldap_serialnumber, usercertificate = ldap_helper.get_ra_cert() certificates_are_same = usercertificate == cert_derdata logger.info(messages.certificate_der_data_are_equal(certificates_are_same)) return cert_serialnumber, ldap_serialnumber
def install(self): print("Installing CA certificate, please wait") options = self.options cert_filename = self.args[1] try: cert = x509.load_certificate_from_file(cert_filename) except IOError as e: raise admintool.ScriptError("Can't open \"%s\": %s" % (cert_filename, e)) except (TypeError, ValueError) as e: raise admintool.ScriptError("Not a valid certificate: %s" % e) nickname = options.nickname or str(DN(cert.subject)) ca_certs = certstore.get_ca_certs_nss(api.Backend.ldap2, api.env.basedn, api.env.realm, False) with certs.NSSDatabase() as tmpdb: tmpdb.create_db() tmpdb.add_cert(cert, nickname, EXTERNAL_CA_TRUST_FLAGS) for ca_cert, ca_nickname, ca_trust_flags in ca_certs: tmpdb.add_cert(ca_cert, ca_nickname, ca_trust_flags) try: tmpdb.verify_ca_cert_validity(nickname) except ValueError as e: raise admintool.ScriptError( "Not a valid CA certificate: %s (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)" % e) trust_flags = options.trust_flags.split(',') if (set(options.trust_flags) - set(',CPTcgpuw') or len(trust_flags) not in [3, 4]): raise admintool.ScriptError("Invalid trust flags") extra_flags = trust_flags[3:] extra_usages = set() if extra_flags: if 'C' in extra_flags[0]: extra_usages.add(x509.EKU_PKINIT_KDC) if 'T' in extra_flags[0]: extra_usages.add(x509.EKU_PKINIT_CLIENT_AUTH) trust_flags = parse_trust_flags(','.join(trust_flags[:3])) trust_flags = TrustFlags(trust_flags.has_key, trust_flags.trusted, trust_flags.ca, trust_flags.usages | extra_usages) try: certstore.put_ca_cert_nss(api.Backend.ldap2, api.env.basedn, cert, nickname, trust_flags) except ValueError as e: raise admintool.ScriptError( "Failed to install the certificate: %s" % e) print("CA certificate successfully installed")
def migrate_to_mod_ssl(self): """For upgrades only, migrate from mod_nss to mod_ssl""" db = certs.CertDB(api.env.realm, nssdir=paths.HTTPD_ALIAS_DIR) nickname = self.get_mod_nss_nickname() with tempfile.NamedTemporaryFile() as temp: pk12_password = ipautil.ipa_generate_password() pk12_pwdfile = ipautil.write_tmp_file(pk12_password) db.export_pkcs12(temp.name, pk12_pwdfile.name, nickname) certs.install_pem_from_p12(temp.name, pk12_password, paths.HTTPD_CERT_FILE) certs.install_key_from_p12(temp.name, pk12_password, paths.HTTPD_KEY_FILE) self.backup_ssl_conf() self.configure_mod_ssl_certs() self.set_mod_ssl_protocol() self.set_mod_ssl_logdir() self.__add_include() self.cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE) if self.ca_is_configured: db.untrack_server_cert(nickname) self.start_tracking_certificates() # remove nickname and CA certs from NSS db self.disable_nss_conf()
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 check_ra_cert(self): """Check the RA certificate subject & blob against LDAP""" if not self.ca.is_configured(): self.failure('Skipping RA check because CA not installed') return if not self.conn: self.failure('Skipping RA check because no LDAP connection') return cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM) serial_number = cert.serial_number subject = DN(cert.subject) issuer = DN(cert.issuer) description = '2;%d;%s;%s' % (serial_number, issuer, subject) logger.debug('RA agent description should be %s', description) db_filter = ldap2.ldap2.combine_filters([ ldap2.ldap2.make_filter({'objectClass': 'inetOrgPerson'}), ldap2.ldap2.make_filter( {'description': ';%s;%s' % (issuer, subject)}, exact=False, trailing_wildcard=False), ], ldap2.ldap2.MATCH_ALL) base_dn = DN(('o', 'ipaca')) try: entries = self.conn.get_entries(base_dn, self.conn.SCOPE_SUBTREE, db_filter) except errors.NotFound: self.failure('RA agent certificate not found in LDAP') return except Exception as e: self.failure('RA agent check failed %s' % e) return else: if len(entries) != 1: self.failure('Too many RA agent entries found') entry = entries[0] ra_desc = entry.get('description')[0] ra_certs = entry.get('usercertificate') if ra_desc != description: self.failure('RA agent description does not match ' '%s in LDAP and %s expected' % (ra_desc, description)) found = False for check in ra_certs: if isinstance(check, str): check = load_der_certificate(check) if check == cert: found = True break if not found: self.failure('RA agent certificate not found in LDAP')
def install(self): print("Installing CA certificate, please wait") options = self.options cert_filename = self.args[1] nss_cert = None try: try: nss_cert = x509.load_certificate_from_file(cert_filename) except IOError as e: raise admintool.ScriptError( "Can't open \"%s\": %s" % (cert_filename, e)) except (TypeError, NSPRError, ValueError) as e: raise admintool.ScriptError("Not a valid certificate: %s" % e) subject = nss_cert.subject cert = nss_cert.der_data finally: del nss_cert nickname = options.nickname or str(subject) ca_certs = certstore.get_ca_certs_nss(api.Backend.ldap2, api.env.basedn, api.env.realm, False) with certs.NSSDatabase() as tmpdb: pw = ipautil.write_tmp_file(ipautil.ipa_generate_password()) tmpdb.create_db(pw.name) tmpdb.add_cert(cert, nickname, 'C,,') for ca_cert, ca_nickname, ca_trust_flags in ca_certs: tmpdb.add_cert(ca_cert, ca_nickname, ca_trust_flags) try: tmpdb.verify_ca_cert_validity(nickname) except ValueError as e: raise admintool.ScriptError( "Not a valid CA certificate: %s (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)" % e) trust_flags = options.trust_flags if ((set(trust_flags) - set(',CPTcgpuw')) or len(trust_flags.split(',')) != 3): raise admintool.ScriptError("Invalid trust flags") try: certstore.put_ca_cert_nss( api.Backend.ldap2, api.env.basedn, cert, nickname, trust_flags) except ValueError as e: raise admintool.ScriptError( "Failed to install the certificate: %s" % e) print("CA certificate successfully installed")
def install_kdc_cert(self): ca_cert_file = paths.CA_BUNDLE_PEM pkcs12_file, pin, ca_cert = installutils.load_pkcs12( cert_files=self.args, key_password=self.options.pin, key_nickname=self.options.cert_name, ca_cert_files=[ca_cert_file], realm_name=api.env.realm) cdb = certs.CertDB(api.env.realm, nssdir=paths.IPA_NSSDB_DIR) # Check that the ca_cert is known and trusted with tempfile.NamedTemporaryFile() as temp: certs.install_pem_from_p12(pkcs12_file.name, pin, temp.name) kdc_cert = x509.load_certificate_from_file(temp.name) ca_certs = x509.load_certificate_list_from_file(ca_cert_file) try: verify_kdc_cert_validity(kdc_cert, ca_certs, api.env.realm) except ValueError as e: raise admintool.ScriptError( "Peer's certificate issuer is not trusted (%s). " "Please run ipa-cacert-manage install and ipa-certupdate " "to install the CA certificate." % str(e)) try: ca_enabled = api.Command.ca_is_enabled()['result'] if ca_enabled: certmonger.stop_tracking(certfile=paths.KDC_CERT) certs.install_pem_from_p12(pkcs12_file.name, pin, paths.KDC_CERT) certs.install_key_from_p12(pkcs12_file.name, pin, paths.KDC_KEY) if ca_enabled: # Start tracking only if the cert was issued by IPA CA # Retrieve IPA CA ipa_ca_cert = cdb.get_cert_from_db( get_ca_nickname(api.env.realm), pem=False) # And compare with the CA which signed this certificate if ca_cert == ipa_ca_cert: certmonger.start_tracking( (paths.KDC_CERT, paths.KDC_KEY), storage='FILE', profile='KDCs_PKINIT_Certs') except RuntimeError as e: raise admintool.ScriptError(str(e)) krb = krbinstance.KrbInstance() krb.init_info( realm_name=api.env.realm, host_name=api.env.host, ) krb.pkinit_enable()
def install(self): print("Installing CA certificate, please wait") options = self.options cert_filename = self.args[1] nss_cert = None try: try: nss_cert = x509.load_certificate_from_file(cert_filename) except IOError as e: raise admintool.ScriptError("Can't open \"%s\": %s" % (cert_filename, e)) except (TypeError, NSPRError, ValueError) as e: raise admintool.ScriptError("Not a valid certificate: %s" % e) subject = nss_cert.subject cert = nss_cert.der_data finally: del nss_cert nickname = options.nickname or str(subject) ca_certs = certstore.get_ca_certs_nss(api.Backend.ldap2, api.env.basedn, api.env.realm, False) with certs.NSSDatabase() as tmpdb: pw = ipautil.write_tmp_file(ipautil.ipa_generate_password()) tmpdb.create_db(pw.name) tmpdb.add_cert(cert, nickname, 'C,,') for ca_cert, ca_nickname, ca_trust_flags in ca_certs: tmpdb.add_cert(ca_cert, ca_nickname, ca_trust_flags) try: tmpdb.verify_ca_cert_validity(nickname) except ValueError as e: raise admintool.ScriptError( "Not a valid CA certificate: %s (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)" % e) trust_flags = options.trust_flags if ((set(trust_flags) - set(',CPTcgpuw')) or len(trust_flags.split(',')) != 3): raise admintool.ScriptError("Invalid trust flags") try: certstore.put_ca_cert_nss(api.Backend.ldap2, api.env.basedn, cert, nickname, trust_flags) except ValueError as e: raise admintool.ScriptError( "Failed to install the certificate: %s" % e) print("CA certificate successfully installed")
def install_kdc_cert(self): ca_cert_file = paths.CA_BUNDLE_PEM pkcs12_file, pin, ca_cert = installutils.load_pkcs12( cert_files=self.args, key_password=self.options.pin, key_nickname=self.options.cert_name, ca_cert_files=[ca_cert_file], realm_name=api.env.realm) cdb = certs.CertDB(api.env.realm, nssdir=paths.IPA_NSSDB_DIR) # Check that the ca_cert is known and trusted with tempfile.NamedTemporaryFile() as temp: certs.install_pem_from_p12(pkcs12_file.name, pin, temp.name) kdc_cert = x509.load_certificate_from_file(temp.name) ca_certs = x509.load_certificate_list_from_file(ca_cert_file) try: verify_kdc_cert_validity(kdc_cert, ca_certs, api.env.realm) except ValueError as e: raise admintool.ScriptError( "Peer's certificate issuer is not trusted (%s). " "Please run ipa-cacert-manage install and ipa-certupdate " "to install the CA certificate." % str(e)) try: ca_enabled = api.Command.ca_is_enabled()['result'] if ca_enabled: certmonger.stop_tracking(certfile=paths.KDC_CERT) certs.install_pem_from_p12(pkcs12_file.name, pin, paths.KDC_CERT) certs.install_key_from_p12(pkcs12_file.name, pin, paths.KDC_KEY) if ca_enabled: # Start tracking only if the cert was issued by IPA CA # Retrieve IPA CA ipa_ca_cert = cdb.get_cert_from_db(get_ca_nickname( api.env.realm), pem=False) # And compare with the CA which signed this certificate if ca_cert == ipa_ca_cert: certmonger.start_tracking((paths.KDC_CERT, paths.KDC_KEY), storage='FILE', profile='KDCs_PKINIT_Certs') except RuntimeError as e: raise admintool.ScriptError(str(e)) krb = krbinstance.KrbInstance() krb.init_info( realm_name=api.env.realm, host_name=api.env.host, ) krb.pkinit_enable()
def check_renewed_ipa_certs(certs): """ Check whether all expected IPA-specific certs (extra_certs) were renewed successfully. For now this subroutine just checks that the files that we expect ``pki-server cert-fix`` to have written do exist and contain an X.509 certificate. Return ``True`` if everything seems to be as expected, otherwise ``False``. """ for _certtype, oldcert in certs: cert_path = RENEWED_CERT_PATH_TEMPLATE.format(oldcert.serial_number) try: x509.load_certificate_from_file(cert_path) except (IOError, ValueError): return False return True
def start_tracking_certificates(self): cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE) if certs.is_ipa_issued_cert(api, cert): request_id = certmonger.start_tracking( certpath=(paths.HTTPD_CERT_FILE, paths.HTTPD_KEY_FILE), post_command='restart_httpd', storage='FILE' ) subject = str(DN(cert.subject)) certmonger.add_principal(request_id, self.principal) certmonger.add_subject(request_id, subject) else: logger.debug("Will not track HTTP server cert %s as it is not " "issued by IPA", cert.subject)
def start_tracking_certificates(self): cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE) if certs.is_ipa_issued_cert(api, cert): request_id = certmonger.start_tracking( certpath=(paths.HTTPD_CERT_FILE, paths.HTTPD_KEY_FILE), post_command='restart_httpd', storage='FILE') subject = str(DN(cert.subject)) certmonger.add_principal(request_id, self.principal) certmonger.add_subject(request_id, subject) else: logger.debug( "Will not track HTTP server cert %s as it is not " "issued by IPA", cert.subject)
def execute(self, **options): kra = krainstance.KRAInstance(self.api.env.realm) if not kra.is_installed(): return False, [] cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM) entry = self.api.Backend.ldap2.get_entry(krainstance.KRA_AGENT_DN) # check description attribute description_values = entry.get('description', []) if len(description_values) < 1: # missing 'description' attribute is unexpected, but we can # add it do_fix = True else: # There should only be one value, so we will take the first value. # But ignore the serial number when comparing, just in case. description = description_values[0] parts = description.split(';', 2) # see below for syntax if len(parts) < 3: do_fix = True # syntax error (not expected) elif parts[2] != '{};{}'.format(DN(cert.issuer), DN(cert.subject)): # issuer/subject does not match cert. THIS is the condition # caused by issue 8084, which we want to fix. do_fix = True else: do_fix = False # everything is fine if do_fix: # If other replicas have a different iteration of the IPA RA # cert (e.g. renewal was triggered prematurely on some master # and not on others) then authentication on those replicas will # fail. But the 'description' attribute needed fixing because # the issuer value was wrong, meaning authentication was broken # on ALL replicas. So even for the corner case where different # replicas have different IPA RA certs, updating the attribute # will at least mean THIS replica can authenticate to the KRA. logger.debug("Fixing KRA user entry 'description' attribute") entry['description'] = [ '2;{};{};{}'.format( cert.serial_number, DN(cert.issuer), DN(cert.subject) ) ] self.api.Backend.ldap2.update_entry(entry) return False, [] # don't restart DS; no LDAP updates to perform
def install(self): print("Installing CA certificate, please wait") options = self.options cert_filename = self.args[1] try: cert_obj = x509.load_certificate_from_file(cert_filename) except IOError as e: raise admintool.ScriptError( "Can't open \"%s\": %s" % (cert_filename, e)) except (TypeError, ValueError) as e: raise admintool.ScriptError("Not a valid certificate: %s" % e) cert = cert_obj.public_bytes(serialization.Encoding.DER) nickname = options.nickname or str(DN(cert_obj.subject)) ca_certs = certstore.get_ca_certs_nss(api.Backend.ldap2, api.env.basedn, api.env.realm, False) with certs.NSSDatabase() as tmpdb: tmpdb.create_db() tmpdb.add_cert(cert, nickname, 'C,,') for ca_cert, ca_nickname, ca_trust_flags in ca_certs: tmpdb.add_cert(ca_cert, ca_nickname, ca_trust_flags) try: tmpdb.verify_ca_cert_validity(nickname) except ValueError as e: raise admintool.ScriptError( "Not a valid CA certificate: %s (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)" % e) trust_flags = options.trust_flags if ((set(trust_flags) - set(',CPTcgpuw')) or len(trust_flags.split(',')) != 3): raise admintool.ScriptError("Invalid trust flags") try: certstore.put_ca_cert_nss( api.Backend.ldap2, api.env.basedn, cert, nickname, trust_flags) except ValueError as e: raise admintool.ScriptError( "Failed to install the certificate: %s" % e) print("CA certificate successfully installed")
def load_cert(self, domain): """Load cert from cache :param domain: IPA domain :return: cryptography.x509.Certificate or None """ filename = self._get_filename(domain) try: try: return x509.load_certificate_from_file(filename) except EnvironmentError as e: if e.errno != errno.ENOENT: raise except Exception: logger.warning("Failed to load %s", filename, exc_info=True)
def install(self): print "Installing CA certificate, please wait" options = self.options cert_filename = self.args[1] nss_cert = None try: try: nss_cert = x509.load_certificate_from_file(cert_filename) except IOError, e: raise admintool.ScriptError( "Can't open \"%s\": %s" % (cert_filename, e)) except (TypeError, NSPRError), e: raise admintool.ScriptError("Not a valid certificate: %s" % e)
def load_cert(self, domain): """Load cert from cache :param domain: IPA domain :return: cryptography.x509.Certificate or None """ filename = self._get_filename(domain) try: try: return x509.load_certificate_from_file(filename) except EnvironmentError as e: if e.errno != errno.ENOENT: raise except Exception: logger.warning("Failed to load %s", filename, exc_info=True)
def install(self): print "Installing CA certificate, please wait" options = self.options cert_filename = self.args[1] nss_cert = None try: try: nss_cert = x509.load_certificate_from_file(cert_filename) except IOError, e: raise admintool.ScriptError("Can't open \"%s\": %s" % (cert_filename, e)) except (TypeError, NSPRError), e: raise admintool.ScriptError("Not a valid certificate: %s" % e)
def start_tracking_certificates(self): key_passwd_file = paths.HTTPD_PASSWD_FILE_FMT.format(host=api.env.host) cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE) if certs.is_ipa_issued_cert(api, cert): request_id = certmonger.start_tracking( certpath=(paths.HTTPD_CERT_FILE, paths.HTTPD_KEY_FILE), post_command='restart_httpd', storage='FILE', profile=dogtag.DEFAULT_PROFILE, pinfile=key_passwd_file, dns=[self.fqdn, f'{IPA_CA_RECORD}.{api.env.domain}'], ) subject = str(DN(cert.subject)) certmonger.add_principal(request_id, self.principal) certmonger.add_subject(request_id, subject) else: logger.debug("Will not track HTTP server cert %s as it is not " "issued by IPA", cert.subject)
def __parse_crt_or_pem_cert(self, row): from ipalib import x509 cert = None try: cert = x509.load_certificate_from_file(row['path']) except IOError: self.logger.error(messages.cert_not_in_path("", row['path'])) return None trust_flags = None cert_name = row.get('name') if cert_name: trust_flags = commands_helper.get_certs_trust_flags( row['path'], cert_name) return parser.certdb_to_basecertificate(cert, cert_name, trust_flags)
def __create_kra_agent(self): """ Create KRA agent, assign a certificate, and add the user to the appropriate groups for accessing KRA services. """ # get RA agent certificate cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM) cert_data = cert.public_bytes(serialization.Encoding.DER) # connect to KRA database server_id = installutils.realm_to_serverid(api.env.realm) dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id conn = ldap2.ldap2(api, ldap_uri=dogtag_uri) conn.connect(autobind=True) # create ipakra user with RA agent certificate user_dn = DN(('uid', "ipakra"), ('ou', 'people'), self.basedn) entry = conn.make_entry( user_dn, objectClass=[ 'top', 'person', 'organizationalPerson', 'inetOrgPerson', 'cmsuser' ], uid=["ipakra"], sn=["IPA KRA User"], cn=["IPA KRA User"], usertype=["undefined"], userCertificate=[cert_data], description=[ '2;%s;%s;%s' % (cert.serial_number, DN( self.subject), DN(('CN', 'IPA RA'), self.subject_base)) ]) conn.add_entry(entry) # add ipakra user to Data Recovery Manager Agents group group_dn = DN(('cn', 'Data Recovery Manager Agents'), ('ou', 'groups'), self.basedn) conn.add_entry_to_group(user_dn, group_dn, 'uniqueMember') conn.disconnect()
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 migrate_to_mod_ssl(self): """For upgrades only, migrate from mod_nss to mod_ssl""" db = certs.CertDB(api.env.realm, nssdir=paths.HTTPD_ALIAS_DIR) nickname = self.get_mod_nss_nickname() with tempfile.NamedTemporaryFile() as temp: pk12_password = ipautil.ipa_generate_password() pk12_pwdfile = ipautil.write_tmp_file(pk12_password) db.export_pkcs12(temp.name, pk12_pwdfile.name, nickname) certs.install_pem_from_p12(temp.name, pk12_password, paths.HTTPD_CERT_FILE) passwd_fname = paths.HTTPD_PASSWD_FILE_FMT.format( host=api.env.host) with open(passwd_fname, 'wb') as passwd_file: os.fchmod(passwd_file.fileno(), 0o600) passwd_file.write( ipautil.ipa_generate_password().encode('utf-8')) certs.install_key_from_p12(temp.name, pk12_password, paths.HTTPD_KEY_FILE, out_passwd_fname=passwd_fname) self.backup_ssl_conf() self.configure_mod_ssl_certs() self.set_mod_ssl_protocol() self.set_mod_ssl_logdir() self.__add_include() self.cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE) if self.ca_is_configured: db.untrack_server_cert(nickname) self.start_tracking_certificates() # remove nickname and CA certs from NSS db self.disable_nss_conf()
def __create_kra_agent(self): """ Create KRA agent, assign a certificate, and add the user to the appropriate groups for accessing KRA services. """ # get RA agent certificate cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM) # connect to KRA database conn = ldap2.ldap2(api) conn.connect(autobind=True) # create ipakra user with RA agent certificate user_dn = DN(('uid', "ipakra"), ('ou', 'people'), self.basedn) entry = conn.make_entry( user_dn, objectClass=[ 'top', 'person', 'organizationalPerson', 'inetOrgPerson', 'cmsuser' ], uid=["ipakra"], sn=["IPA KRA User"], cn=["IPA KRA User"], usertype=["undefined"], userCertificate=[cert], description=[ '2;%s;%s;%s' % (cert.serial_number, DN( self.subject), DN(('CN', 'IPA RA'), self.subject_base)) ]) conn.add_entry(entry) # add ipakra user to Data Recovery Manager Agents group group_dn = DN(('cn', 'Data Recovery Manager Agents'), ('ou', 'groups'), self.basedn) conn.add_entry_to_group(user_dn, group_dn, 'uniqueMember') conn.disconnect()
def load_pkcs12(self, ca_chain_fname=paths.IPA_CA_CRT, **kwargs): # Note that the "installutils.load_pkcs12" is quite a complex function # which performs some checking based on its kwargs: # host_name performs NSSDatabase.verify_server_cert_validity() # realm performs NSSDatabase.verify_kdc_cert_validity() pkcs12_file, pin, ca_cert = installutils.load_pkcs12( cert_files=self.args, key_password=self.options.pin, key_nickname=self.options.cert_name, ca_cert_files=[ca_chain_fname], **kwargs) # Check that the ca_cert is known and trusted with tempfile.NamedTemporaryFile() as temp: certs.install_pem_from_p12(pkcs12_file.name, pin, temp.name) cert = x509.load_certificate_from_file(temp.name) with tempfile.NamedTemporaryFile("rb") as temp: certs.install_key_from_p12(pkcs12_file.name, pin, temp.name) key = x509.load_pem_private_key( temp.read(), None, backend=x509.default_backend()) return cert, key, ca_cert
def load_pkcs12(self, ca_chain_fname=paths.IPA_CA_CRT, **kwargs): # Note that the "installutils.load_pkcs12" is quite a complex function # which performs some checking based on its kwargs: # host_name performs NSSDatabase.verify_server_cert_validity() # realm performs NSSDatabase.verify_kdc_cert_validity() pkcs12_file, pin, ca_cert = installutils.load_pkcs12( cert_files=self.args, key_password=self.options.pin, key_nickname=self.options.cert_name, ca_cert_files=[ca_chain_fname], **kwargs) # Check that the ca_cert is known and trusted with tempfile.NamedTemporaryFile() as temp: certs.install_pem_from_p12(pkcs12_file.name, pin, temp.name) cert = x509.load_certificate_from_file(temp.name) with tempfile.NamedTemporaryFile("rb") as temp: certs.install_key_from_p12(pkcs12_file.name, pin, temp.name) key = x509.load_pem_private_key( temp.read(), None, backend=x509.default_backend()) return cert, key, ca_cert
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 __create_kra_agent(self): """ Create KRA agent, assign a certificate, and add the user to the appropriate groups for accessing KRA services. """ # get RA agent certificate cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM) cert_data = cert.public_bytes(serialization.Encoding.DER) # connect to KRA database conn = ldap2.ldap2(api) conn.connect(autobind=True) # create ipakra user with RA agent certificate user_dn = DN(('uid', "ipakra"), ('ou', 'people'), self.basedn) entry = conn.make_entry( user_dn, objectClass=['top', 'person', 'organizationalPerson', 'inetOrgPerson', 'cmsuser'], uid=["ipakra"], sn=["IPA KRA User"], cn=["IPA KRA User"], usertype=["undefined"], userCertificate=[cert_data], description=['2;%s;%s;%s' % ( cert.serial_number, DN(self.subject), DN(('CN', 'IPA RA'), self.subject_base))]) conn.add_entry(entry) # add ipakra user to Data Recovery Manager Agents group group_dn = DN(('cn', 'Data Recovery Manager Agents'), ('ou', 'groups'), self.basedn) conn.add_entry_to_group(user_dn, group_dn, 'uniqueMember') conn.disconnect()
def check(self): if not self.ca.is_configured(): logger.debug('CA is not configured, skipping RA Agent check') return try: cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM) except Exception as e: yield Result(self, constants.ERROR, error=str(e), msg='Unable to load RA cert: {error}') return serial_number = cert.serial_number subject = DN(cert.subject) issuer = DN(cert.issuer) description = '2;%d;%s;%s' % (serial_number, issuer, subject) logger.debug('RA agent description should be %s', description) db_filter = ldap2.ldap2.combine_filters([ ldap2.ldap2.make_filter({'objectClass': 'inetOrgPerson'}), ldap2.ldap2.make_filter({'sn': 'ipara'}), ldap2.ldap2.make_filter( {'description': ';%s;%s' % (issuer, subject)}, exact=False, trailing_wildcard=False), ], ldap2.ldap2.MATCH_ALL) base_dn = DN(('o', 'ipaca')) try: entries = self.conn.get_entries(base_dn, self.conn.SCOPE_SUBTREE, db_filter) except errors.NotFound: yield Result(self, constants.ERROR, description=description, msg='RA agent not found in LDAP') return except Exception as e: yield Result(self, constants.ERROR, error=str(e), msg='Retrieving RA agent from LDAP failed {error}') return else: logger.debug('RA agent description is %s', description) if len(entries) != 1: yield Result(self, constants.ERROR, found=len(entries), msg='Too many RA agent entries found, {found}') return entry = entries[0] raw_desc = entry.get('description') if raw_desc is None: yield Result(self, constants.ERROR, msg='RA agent is missing the description ' 'attribute or it is not readable') return ra_desc = raw_desc[0] ra_certs = entry.get('usercertificate') if ra_desc != description: yield Result(self, constants.ERROR, expected=description, got=ra_desc, msg='RA agent description does not match. Found ' '{got} in LDAP and expected {expected}') return found = False for candidate in ra_certs: if candidate == cert: found = True break if not found: yield Result(self, constants.ERROR, certfile=paths.RA_AGENT_PEM, dn=str(entry.dn), msg='RA agent certificate in {certfile} not ' 'found in LDAP userCertificate attribute ' 'for the entry {dn}') yield Result(self, constants.SUCCESS)
def replicate_dogtag_certs(subject_base, ca_subject_dn, certs): for certid, _oldcert in certs: cert_path = "/etc/pki/pki-tomcat/certs/{}.crt".format(certid) cert = x509.load_certificate_from_file(cert_path) print_cert_info("Renewed Dogtag", certid, cert) replicate_cert(subject_base, ca_subject_dn, cert)
def renew_external_step_2(self, ca, old_cert): print("Importing the renewed CA certificate, please wait") options = self.options conn = api.Backend.ldap2 cert_file, ca_file = installutils.load_external_cert( options.external_cert_files, x509.subject_base()) nss_cert = None nss.nss_init(paths.PKI_TOMCAT_ALIAS_DIR) try: nss_cert = x509.load_certificate(old_cert, x509.DER) subject = nss_cert.subject der_subject = x509.get_der_subject(old_cert, x509.DER) #pylint: disable=E1101 pkinfo = nss_cert.subject_public_key_info.format() #pylint: enable=E1101 nss_cert = x509.load_certificate_from_file(cert_file.name) cert = nss_cert.der_data if nss_cert.subject != subject: raise admintool.ScriptError( "Subject name mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") if x509.get_der_subject(cert, x509.DER) != der_subject: raise admintool.ScriptError( "Subject name encoding mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") #pylint: disable=E1101 if nss_cert.subject_public_key_info.format() != pkinfo: raise admintool.ScriptError( "Subject public key info mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") #pylint: enable=E1101 finally: del nss_cert nss.nss_shutdown() with certs.NSSDatabase() as tmpdb: pw = ipautil.write_tmp_file(ipautil.ipa_generate_password()) tmpdb.create_db(pw.name) tmpdb.add_cert(old_cert, 'IPA CA', 'C,,') try: tmpdb.add_cert(cert, 'IPA CA', 'C,,') except ipautil.CalledProcessError as e: raise admintool.ScriptError( "Not compatible with the current CA certificate: %s" % e) ca_certs = x509.load_certificate_list_from_file(ca_file.name) for ca_cert in ca_certs: tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,') del ca_certs del ca_cert try: tmpdb.verify_ca_cert_validity('IPA CA') except ValueError as e: raise admintool.ScriptError( "Not a valid CA certificate: %s (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)" % e) trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1] for nickname in trust_chain: try: ca_cert = tmpdb.get_cert(nickname) except RuntimeError: break certstore.put_ca_cert_nss(conn, api.env.basedn, ca_cert, nickname, ',,') dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn) try: entry = conn.get_entry(dn, ['usercertificate']) entry['usercertificate'] = [cert] conn.update_entry(entry) except errors.NotFound: entry = conn.make_entry( dn, objectclass=['top', 'pkiuser', 'nscontainer'], cn=[self.cert_nickname], usercertificate=[cert]) conn.add_entry(entry) except errors.EmptyModlist: pass try: ca.set_renewal_master() except errors.NotFound: raise admintool.ScriptError("CA renewal master not found") self.resubmit_request(ca, 'ipaRetrieval') print("CA certificate successfully renewed")
def __setup_ssl(self): key_passwd_file = paths.HTTPD_PASSWD_FILE_FMT.format(host=api.env.host) with open(key_passwd_file, 'wb') as f: os.fchmod(f.fileno(), 0o600) pkey_passwd = ipautil.ipa_generate_password().encode('utf-8') f.write(pkey_passwd) if self.pkcs12_info: p12_certs, p12_priv_keys = certs.pkcs12_to_certkeys( *self.pkcs12_info) keys_dict = { k.public_key().public_numbers(): k for k in p12_priv_keys } certs_keys = [ (c, keys_dict.get(c.public_key().public_numbers())) for c in p12_certs ] server_certs_keys = [ (c, k) for c, k in certs_keys if k is not None ] if not server_certs_keys: raise RuntimeError( "Could not find a suitable server cert in import in %s" % self.pkcs12_info[0] ) # We only handle one server cert self.cert = server_certs_keys[0][0] x509.write_certificate(self.cert, paths.HTTPD_CERT_FILE) x509.write_pem_private_key( server_certs_keys[0][1], paths.HTTPD_KEY_FILE, passwd=pkey_passwd ) if self.ca_is_configured: self.start_tracking_certificates() self.add_cert_to_service() else: if not self.promote: ca_args = [ paths.CERTMONGER_DOGTAG_SUBMIT, '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn, '--certfile', paths.RA_AGENT_PEM, '--keyfile', paths.RA_AGENT_KEY, '--cafile', paths.IPA_CA_CRT, '--agent-submit' ] helper = " ".join(ca_args) prev_helper = certmonger.modify_ca_helper('IPA', helper) else: prev_helper = None try: certmonger.request_and_wait_for_cert( certpath=(paths.HTTPD_CERT_FILE, paths.HTTPD_KEY_FILE), principal=self.principal, subject=str(DN(('CN', self.fqdn), self.subject_base)), ca='IPA', profile=dogtag.DEFAULT_PROFILE, dns=[self.fqdn], post_command='restart_httpd', storage='FILE', passwd_fname=key_passwd_file ) finally: if prev_helper is not None: certmonger.modify_ca_helper('IPA', prev_helper) self.cert = x509.load_certificate_from_file( paths.HTTPD_CERT_FILE ) if prev_helper is not None: self.add_cert_to_service() with open(paths.HTTPD_KEY_FILE, 'rb') as f: priv_key = x509.load_pem_private_key( f.read(), pkey_passwd, backend=x509.default_backend()) # Verify we have a valid server cert if (priv_key.public_key().public_numbers() != self.cert.public_key().public_numbers()): raise RuntimeError( "The public key of the issued HTTPD service certificate " "does not match its private key.") sysupgrade.set_upgrade_state('ssl.conf', 'migrated_to_mod_ssl', True)
def install(self): print("Installing CA certificate, please wait") options = self.options cert_filename = self.args[1] try: cert_obj = x509.load_certificate_from_file(cert_filename) except IOError as e: raise admintool.ScriptError( "Can't open \"%s\": %s" % (cert_filename, e)) except (TypeError, ValueError) as e: raise admintool.ScriptError("Not a valid certificate: %s" % e) cert = cert_obj.public_bytes(serialization.Encoding.DER) nickname = options.nickname or str(DN(cert_obj.subject)) ca_certs = certstore.get_ca_certs_nss(api.Backend.ldap2, api.env.basedn, api.env.realm, False) with certs.NSSDatabase() as tmpdb: tmpdb.create_db() tmpdb.add_cert(cert, nickname, EXTERNAL_CA_TRUST_FLAGS) for ca_cert, ca_nickname, ca_trust_flags in ca_certs: tmpdb.add_cert(ca_cert, ca_nickname, ca_trust_flags) try: tmpdb.verify_ca_cert_validity(nickname) except ValueError as e: raise admintool.ScriptError( "Not a valid CA certificate: %s (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)" % e) trust_flags = options.trust_flags.split(',') if (set(options.trust_flags) - set(',CPTcgpuw') or len(trust_flags) not in [3, 4]): raise admintool.ScriptError("Invalid trust flags") extra_flags = trust_flags[3:] extra_usages = set() if extra_flags: if 'C' in extra_flags[0]: extra_usages.add(x509.EKU_PKINIT_KDC) if 'T' in extra_flags[0]: extra_usages.add(x509.EKU_PKINIT_CLIENT_AUTH) trust_flags = parse_trust_flags(','.join(trust_flags[:3])) trust_flags = TrustFlags(trust_flags.has_key, trust_flags.trusted, trust_flags.ca, trust_flags.usages | extra_usages) try: certstore.put_ca_cert_nss( api.Backend.ldap2, api.env.basedn, cert, nickname, trust_flags) except ValueError as e: raise admintool.ScriptError( "Failed to install the certificate: %s" % e) print("CA certificate successfully installed")
def renew_external_step_2(self, ca, old_cert): print "Importing the renewed CA certificate, please wait" options = self.options cert_file, ca_file = installutils.load_external_cert( options.external_cert_files, x509.subject_base()) nss_cert = None nss.nss_init(ca.dogtag_constants.ALIAS_DIR) try: nss_cert = x509.load_certificate(old_cert, x509.DER) subject = nss_cert.subject der_subject = x509.get_der_subject(old_cert, x509.DER) #pylint: disable=E1101 pkinfo = nss_cert.subject_public_key_info.format() #pylint: enable=E1101 nss_cert = x509.load_certificate_from_file(cert_file.name) cert = nss_cert.der_data if nss_cert.subject != subject: raise admintool.ScriptError( "Subject name mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") if x509.get_der_subject(cert, x509.DER) != der_subject: raise admintool.ScriptError( "Subject name encoding mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") #pylint: disable=E1101 if nss_cert.subject_public_key_info.format() != pkinfo: raise admintool.ScriptError( "Subject public key info mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") #pylint: enable=E1101 finally: del nss_cert nss.nss_shutdown() with certs.NSSDatabase() as tmpdb: pw = ipautil.write_tmp_file(ipautil.ipa_generate_password()) tmpdb.create_db(pw.name) tmpdb.add_cert(old_cert, 'IPA CA', 'C,,') try: tmpdb.add_cert(cert, 'IPA CA', 'C,,') except ipautil.CalledProcessError, e: raise admintool.ScriptError( "Not compatible with the current CA certificate: %s" % e) ca_certs = x509.load_certificate_list_from_file(ca_file.name) for ca_cert in ca_certs: tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,') del ca_certs del ca_cert try: tmpdb.verify_ca_cert_validity('IPA CA') except ValueError, e: raise admintool.ScriptError( "Not a valid CA certificate: %s (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)" % e)
def __setup_ssl(self): key_passwd_file = paths.HTTPD_PASSWD_FILE_FMT.format(host=api.env.host) with open(key_passwd_file, 'wb') as f: os.fchmod(f.fileno(), 0o600) pkey_passwd = ipautil.ipa_generate_password().encode('utf-8') f.write(pkey_passwd) if self.pkcs12_info: p12_certs, p12_priv_keys = certs.pkcs12_to_certkeys( *self.pkcs12_info) keys_dict = { k.public_key().public_numbers(): k for k in p12_priv_keys } certs_keys = [(c, keys_dict.get(c.public_key().public_numbers())) for c in p12_certs] server_certs_keys = [(c, k) for c, k in certs_keys if k is not None] if not server_certs_keys: raise RuntimeError( "Could not find a suitable server cert in import in %s" % self.pkcs12_info[0]) # We only handle one server cert self.cert = server_certs_keys[0][0] x509.write_certificate(self.cert, paths.HTTPD_CERT_FILE) x509.write_pem_private_key(server_certs_keys[0][1], paths.HTTPD_KEY_FILE, passwd=pkey_passwd) if self.ca_is_configured: self.start_tracking_certificates() self.add_cert_to_service() else: if not self.promote: ca_args = [ paths.CERTMONGER_DOGTAG_SUBMIT, '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn, '--certfile', paths.RA_AGENT_PEM, '--keyfile', paths.RA_AGENT_KEY, '--cafile', paths.IPA_CA_CRT, '--agent-submit' ] helper = " ".join(ca_args) prev_helper = certmonger.modify_ca_helper('IPA', helper) else: prev_helper = None try: certmonger.request_and_wait_for_cert( certpath=(paths.HTTPD_CERT_FILE, paths.HTTPD_KEY_FILE), principal=self.principal, subject=str(DN(('CN', self.fqdn), self.subject_base)), ca='IPA', profile=dogtag.DEFAULT_PROFILE, dns=[self.fqdn], post_command='restart_httpd', storage='FILE', passwd_fname=key_passwd_file) finally: if prev_helper is not None: certmonger.modify_ca_helper('IPA', prev_helper) self.cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE) if prev_helper is not None: self.add_cert_to_service() with open(paths.HTTPD_KEY_FILE, 'rb') as f: priv_key = x509.load_pem_private_key( f.read(), pkey_passwd, backend=x509.default_backend()) # Verify we have a valid server cert if (priv_key.public_key().public_numbers() != self.cert.public_key().public_numbers()): raise RuntimeError( "The public key of the issued HTTPD service certificate " "does not match its private key.") sysupgrade.set_upgrade_state('ssl.conf', 'migrated_to_mod_ssl', True)
def check(self): # For simplicity use the expected certmonger tracking for the # list of certificates to check because it already filters out # based on whether the CA system is configure and whether the # certificates were issued by IPA. if not self.ca.is_configured(): logger.debug('CA is not configured, skipping revocation check') return requests = get_expected_requests(self.ca, self.ds, self.serverid) for request in requests: id = certmonger.get_request_id(request) if request.get('cert-file') is not None: certfile = request.get('cert-file') try: cert = x509.load_certificate_from_file(certfile) except Exception as e: yield Result(self, constants.ERROR, key=id, certfile=certfile, error=str(e), msg='Unable to open cert file {certfile}: ' '{error}') continue elif request.get('cert-database') is not None: nickname = request.get('cert-nickname') dbdir = request.get('cert-database') try: db = certdb.NSSDatabase(dbdir) except Exception as e: yield Result(self, constants.ERROR, key=id, dbdir=dbdir, error=str(e), msg='Unable to open NSS database {dbdir}: ' '{error}') continue try: cert = db.get_cert(nickname) except Exception as e: yield Result(self, constants.ERROR, key=id, dbdir=dbdir, nickname=nickname, error=str(e), msg='Unable to retrieve certificate ' '\'{nickname}\' from {dbdir}: {error}') continue else: yield Result(self, constants.ERROR, key=id, msg='Unable to to identify certificate storage ' 'type for request {key}') continue issued = is_ipa_issued_cert(api, cert) if issued is False: logger.debug('\'%s\' was not issued by IPA, skipping', DN(cert.subject)) continue if issued is None: logger.debug('LDAP is down, skipping \'%s\'', DN(cert.subject)) continue # Now we have the cert either way, check the recovation try: result = api.Command.cert_show(cert.serial_number, all=True) except Exception as e: yield Result(self, constants.ERROR, key=id, serial=cert.serial_number, error=str(e), msg='Request for certificate serial number ' '{serial} in request {key} failed: {error}') continue try: if result['result']['revoked']: reason = result['result']['revocation_reason'] reason_txt = self.revocation_reason[reason] yield Result(self, constants.ERROR, revocation_reason=reason_txt, key=id, msg='Certificate tracked by {key} is revoked ' '{revocation_reason}') else: yield Result(self, constants.SUCCESS, key=id) except Exception as e: yield Result(self, constants.ERROR, key=id, error=str(e), msg='Unable to determine revocation ' 'status for {key}: {error}')
def renew_external_step_2(self, ca, old_cert): print("Importing the renewed CA certificate, please wait") options = self.options conn = api.Backend.ldap2 cert_file, ca_file = installutils.load_external_cert( options.external_cert_files, x509.subject_base()) nss_cert = None nss.nss_init(paths.PKI_TOMCAT_ALIAS_DIR) try: nss_cert = x509.load_certificate(old_cert, x509.DER) subject = nss_cert.subject der_subject = x509.get_der_subject(old_cert, x509.DER) #pylint: disable=E1101 pkinfo = nss_cert.subject_public_key_info.format() #pylint: enable=E1101 nss_cert = x509.load_certificate_from_file(cert_file.name) cert = nss_cert.der_data if nss_cert.subject != subject: raise admintool.ScriptError( "Subject name mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") if x509.get_der_subject(cert, x509.DER) != der_subject: raise admintool.ScriptError( "Subject name encoding mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") #pylint: disable=E1101 if nss_cert.subject_public_key_info.format() != pkinfo: raise admintool.ScriptError( "Subject public key info mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") #pylint: enable=E1101 finally: del nss_cert nss.nss_shutdown() with certs.NSSDatabase() as tmpdb: pw = ipautil.write_tmp_file(ipautil.ipa_generate_password()) tmpdb.create_db(pw.name) tmpdb.add_cert(old_cert, 'IPA CA', 'C,,') try: tmpdb.add_cert(cert, 'IPA CA', 'C,,') except ipautil.CalledProcessError as e: raise admintool.ScriptError( "Not compatible with the current CA certificate: %s" % e) ca_certs = x509.load_certificate_list_from_file(ca_file.name) for ca_cert in ca_certs: tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,') del ca_certs del ca_cert try: tmpdb.verify_ca_cert_validity('IPA CA') except ValueError as e: raise admintool.ScriptError( "Not a valid CA certificate: %s (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)" % e) trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1] for nickname in trust_chain: try: ca_cert = tmpdb.get_cert(nickname) except RuntimeError: break certstore.put_ca_cert_nss( conn, api.env.basedn, ca_cert, nickname, ',,') dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn) try: entry = conn.get_entry(dn, ['usercertificate']) entry['usercertificate'] = [cert] conn.update_entry(entry) except errors.NotFound: entry = conn.make_entry( dn, objectclass=['top', 'pkiuser', 'nscontainer'], cn=[self.cert_nickname], usercertificate=[cert]) conn.add_entry(entry) except errors.EmptyModlist: pass try: ca.set_renewal_master() except errors.NotFound: raise admintool.ScriptError("CA renewal master not found") self.resubmit_request(ca, 'ipaRetrieval') print("CA certificate successfully renewed")
def get_expected_requests(ca, ds, serverid): """Provide the expected certmonger tracking request data This list is based in part on certificate_renewal_update() in ipaserver/install/server/upgrade.py and various start_tracking_certificates() methods in *instance.py. The list is filtered depending on whether a CA is running and the certificates have been issued by IPA. :param ca: the CAInstance :param ds: the DSInstance :param serverid: the DS serverid name """ template = paths.CERTMONGER_COMMAND_TEMPLATE if api.Command.ca_is_enabled()['result']: requests = [ { 'cert-file': paths.RA_AGENT_PEM, 'key-file': paths.RA_AGENT_KEY, 'ca-name': RENEWAL_CA_NAME, 'cert-presave-command': template % 'renew_ra_cert_pre', 'cert-postsave-command': template % 'renew_ra_cert', }, ] else: requests = [] if ca.is_configured(): dogtag_reqs = ca.tracking_reqs.items() kra = krainstance.KRAInstance(api.env.realm) if kra.is_installed(): dogtag_reqs = itertools.chain(dogtag_reqs, kra.tracking_reqs.items()) for nick, profile in dogtag_reqs: req = { 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR, 'cert-nickname': nick, 'ca-name': RENEWAL_CA_NAME, 'cert-presave-command': template % 'stop_pkicad', 'cert-postsave-command': (template % 'renew_ca_cert "{}"'.format(nick)), 'template-profile': profile, } requests.append(req) else: logger.debug('CA is not configured, skipping CA tracking') cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE) issued = is_ipa_issued_cert(api, cert) if issued is None: logger.debug('Unable to determine if \'%s\' was issued by IPA ' 'because no LDAP connection, assuming yes.') if issued or issued is None: requests.append({ 'cert-file': paths.HTTPD_CERT_FILE, 'key-file': paths.HTTPD_KEY_FILE, 'ca-name': 'IPA', 'cert-postsave-command': template % 'restart_httpd', }) else: logger.debug( 'HTTP cert not issued by IPA, \'%s\', skip tracking ' 'check', DN(cert.issuer)) # Check the ldap server cert if issued by IPA ds_nickname = ds.get_server_cert_nickname(serverid) ds_db_dirname = dsinstance.config_dirname(serverid) ds_db = certs.CertDB(api.env.realm, nssdir=ds_db_dirname) connected = api.Backend.ldap2.isconnected() if not connected: logger.debug('Unable to determine if \'%s\' was issued by IPA ' 'because no LDAP connection, assuming yes.') if not connected or ds_db.is_ipa_issued_cert(api, ds_nickname): requests.append({ 'cert-database': ds_db_dirname[:-1], 'cert-nickname': ds_nickname, 'ca-name': 'IPA', 'cert-postsave-command': '%s %s' % (template % 'restart_dirsrv', serverid), }) else: logger.debug('DS cert is not issued by IPA, skip tracking check') # Check if pkinit is enabled if os.path.exists(paths.KDC_CERT): pkinit_request_ca = krbinstance.get_pkinit_request_ca() requests.append({ 'cert-file': paths.KDC_CERT, 'key-file': paths.KDC_KEY, 'ca-name': pkinit_request_ca, 'cert-postsave-command': template % 'renew_kdc_cert', }) else: logger.debug('No KDC pkinit certificate') return requests
def check(self): fqdn = socket.getfqdn() requests = get_expected_requests(self.ca, self.ds, self.serverid) for request in requests: request_id = certmonger.get_request_id(request) if request_id is None: yield Result(self, constants.ERROR, key=request_id, msg='Found request id {key} but it is not tracked' 'by certmonger!?') continue ca_name = certmonger.get_request_value(request_id, 'ca-name') if ca_name != 'IPA': logger.debug('Skipping request %s with CA %s', request_id, ca_name) continue profile = certmonger.get_request_value(request_id, 'template_profile') if profile != 'caIPAserviceCert': logger.debug('Skipping request %s with profile %s', request_id, profile) continue certfile = None if request.get('cert-file') is not None: certfile = request.get('cert-file') try: cert = x509.load_certificate_from_file(certfile) except Exception as e: yield Result(self, constants.ERROR, key=request_id, certfile=certfile, error=str(e), msg='Unable to open cert file {certfile}: ' '{error}') continue elif request.get('cert-database') is not None: nickname = request.get('cert-nickname') dbdir = request.get('cert-database') try: db = certdb.NSSDatabase(dbdir) except Exception as e: yield Result(self, constants.ERROR, key=request_id, dbdir=dbdir, error=str(e), msg='Unable to open NSS database {dbdir}: ' '{error}') continue try: cert = db.get_cert(nickname) except Exception as e: yield Result(self, constants.ERROR, key=id, dbdir=dbdir, nickname=nickname, error=str(e), msg='Unable to retrieve certificate ' '\'{nickname}\' from {dbdir}: {error}') continue hostlist = [fqdn] if self.ca.is_configured() and certfile == paths.HTTPD_CERT_FILE: hostlist.append(f'{IPA_CA_RECORD}.{api.env.domain}') error = False for host in hostlist: if host not in cert.san_a_label_dns_names: error = True yield Result(self, constants.ERROR, key=request_id, hostname=host, san=cert.san_a_label_dns_names, ca=ca_name, profile=profile, msg='Certificate request id {key} with ' 'profile {profile} for CA {ca} does not ' 'have a DNS SAN {san} matching name ' '{hostname}') if not error: yield Result(self, constants.SUCCESS, key=request_id, hostname=hostlist, san=cert.san_a_label_dns_names, ca=ca_name, profile=profile)
def check(self): cm = certmonger._certmonger() all_requests = cm.obj_if.get_requests() for req in all_requests: request = certmonger._cm_dbus_object(cm.bus, cm, req, certmonger.DBUS_CM_REQUEST_IF, certmonger.DBUS_CM_IF, True) id = request.prop_if.Get(certmonger.DBUS_CM_REQUEST_IF, 'nickname') store = request.prop_if.Get(certmonger.DBUS_CM_REQUEST_IF, 'cert-storage') if store == 'FILE': certfile = str( request.prop_if.Get(certmonger.DBUS_CM_REQUEST_IF, 'cert-file')) try: cert = x509.load_certificate_from_file(certfile) except Exception as e: yield Result(self, constants.ERROR, key=id, certfile=certfile, error=str(e), msg='Request id {key}: Unable to open cert ' 'file \'{certfile}\': {error}') continue elif store == 'NSSDB': nickname = str( request.prop_if.Get(certmonger.DBUS_CM_REQUEST_IF, 'key_nickname')) dbdir = str( request.prop_if.Get(certmonger.DBUS_CM_REQUEST_IF, 'cert_database')) try: db = certdb.NSSDatabase(dbdir) except Exception as e: yield Result(self, constants.ERROR, key=id, dbdir=dbdir, error=str(e), msg='Request id {key}: Unable to open NSS ' 'database \'{dbdir}\': {error}') continue try: cert = db.get_cert(nickname) except Exception as e: yield Result(self, constants.ERROR, key=id, dbdir=dbdir, nickname=nickname, error=str(e), msg='Request id {key}: Unable to retrieve ' 'cert \'{nickname}\' from \'{dbdir}\': ' '{error}') continue else: yield Result(self, constants.ERROR, key=id, store=store, msg='Request id {key}: Unknown certmonger ' 'storage type: {store}') continue now = datetime.utcnow() notafter = cert.not_valid_after if now > notafter: yield Result(self, constants.ERROR, key=id, expiration_date=generalized_time(notafter), msg='Request id {key} expired on ' '{expiration_date}') continue delta = notafter - now diff = int(delta.total_seconds() / DAY) if diff < int(self.config.cert_expiration_days): yield Result(self, constants.WARNING, key=id, expiration_date=generalized_time(notafter), days=diff, msg='Request id {key} expires in {days} ' 'days. certmonger should renew this ' 'automatically. Watch the status with' 'getcert list -i {key}.') else: yield Result(self, constants.SUCCESS, key=id)