def renew(self): ca = cainstance.CAInstance(api.env.realm, certs.NSS_DIR) if not ca.is_configured(): raise admintool.ScriptError("CA is not configured on this system") criteria = { 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR, 'cert-nickname': self.cert_nickname, 'ca-name': 'dogtag-ipa-ca-renew-agent', } self.request_id = certmonger.get_request_id(criteria) if self.request_id is None: raise admintool.ScriptError( "CA certificate is not tracked by certmonger") self.log.debug("Found certmonger request id %r", self.request_id) db = certs.CertDB(api.env.realm, nssdir=paths.PKI_TOMCAT_ALIAS_DIR) cert = db.get_cert_from_db(self.cert_nickname, pem=False) options = self.options if options.external_cert_files: return self.renew_external_step_2(ca, cert) if options.self_signed is not None: self_signed = options.self_signed else: self_signed = x509.is_self_signed(cert, x509.DER) if self_signed: return self.renew_self_signed(ca) else: return self.renew_external_step_1(ca)
def renew(self): ca = cainstance.CAInstance(api.env.realm) if not ca.is_configured(): raise admintool.ScriptError("CA is not configured on this system") self.request_id = self._get_ca_request_id(RENEWAL_CA_NAME) if self.request_id is None: # if external CA renewal was interrupted, the request may have # been left with the "dogtag-ipa-ca-renew-agent-reuse" CA; # look for it too self.request_id = self._get_ca_request_id(RENEWAL_REUSE_CA_NAME) if self.request_id is None: raise admintool.ScriptError( "CA certificate is not tracked by certmonger") logger.debug("Found certmonger request id %r", self.request_id) db = certs.CertDB(api.env.realm, nssdir=paths.PKI_TOMCAT_ALIAS_DIR) cert = db.get_cert_from_db(self.cert_nickname) options = self.options if options.external_cert_files: return self.renew_external_step_2(ca, cert) if options.self_signed is not None: self_signed = options.self_signed else: self_signed = cert.is_self_signed() if self_signed: return self.renew_self_signed(ca) else: return self.renew_external_step_1(ca)
def __upload_ca_cert(self): """ Upload the CA certificate from the NSS database to the LDAP directory. """ dirname = config_dirname(self.serverid) dsdb = certs.CertDB(self.realm, nssdir=dirname, subject_base=self.subject_base) trust_flags = dict(reversed(dsdb.list_certs())) ldap_uri = ipaldap.get_ldap_uri(self.fqdn) conn = ipaldap.LDAPClient(ldap_uri) conn.simple_bind(bind_dn=ipaldap.DIRMAN_DN, bind_password=self.dm_password) nicknames = dsdb.find_root_cert(self.cacert_name)[:-1] for nickname in nicknames: cert = dsdb.get_cert_from_db(nickname, pem=False) certstore.put_ca_cert_nss(conn, self.suffix, cert, nickname, trust_flags[nickname]) nickname = self.cacert_name cert = dsdb.get_cert_from_db(nickname, pem=False) certstore.put_ca_cert_nss(conn, self.suffix, cert, nickname, trust_flags[nickname], config_ipa=self.ca_is_configured, config_compat=self.master_fqdn is None) conn.unbind()
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 check(self): expected_trust = { 'ocspSigningCert cert-pki-ca': 'u,u,u', 'subsystemCert cert-pki-ca': 'u,u,u', 'auditSigningCert cert-pki-ca': 'u,u,Pu', 'Server-Cert cert-pki-ca': 'u,u,u', } kra = krainstance.KRAInstance(api.env.realm) if kra.is_installed(): kra_trust = { 'transportCert cert-pki-kra': 'u,u,u', 'storageCert cert-pki-kra': 'u,u,u', 'auditSigningCert cert-pki-kra': 'u,u,Pu', } expected_trust.update(kra_trust) if not self.ca.is_configured(): logger.debug('CA is not configured, skipping NSS trust check') return db = certs.CertDB(api.env.realm, paths.PKI_TOMCAT_ALIAS_DIR) for nickname, _trust_flags in db.list_certs(): flags = certdb.unparse_trust_flags(_trust_flags) if nickname.startswith('caSigningCert cert-pki-ca'): expected = 'CTu,Cu,Cu' else: try: expected = expected_trust[nickname] except KeyError: # FIXME: is this a warning, skip? print("%s not found, assuming 3rd party" % nickname) continue try: expected_trust.pop(nickname) except KeyError: pass if flags != expected: yield Result( self, constants.ERROR, key=nickname, expected=expected, got=flags, nickname=nickname, dbdir=paths.PKI_TOMCAT_ALIAS_DIR, msg='Incorrect NSS trust for %s. Got %s expected %s' % (nickname, flags, expected)) continue else: yield Result(self, constants.SUCCESS, key=nickname) for nickname in expected_trust: yield Result(self, constants.ERROR, key=nickname, msg='Certificate %s missing while verifying trust' % nickname)
def stop_tracking_certificates(self, serverid=None): if serverid is None: serverid = self.get_state("serverid") if not serverid is None: # drop the trailing / off the config_dirname so the directory # will match what is in certmonger dirname = config_dirname(serverid)[:-1] dsdb = certs.CertDB(self.realm, nssdir=dirname) dsdb.untrack_server_cert(self.nickname)
def start_tracking_certificates(self): db = certs.CertDB(self.realm, nssdir=paths.HTTPD_ALIAS_DIR) nickname = self.get_mod_nss_nickname() if db.is_ipa_issued_cert(api, nickname): db.track_server_cert(nickname, self.principal, db.passwd_fname, 'restart_httpd') else: logger.debug( "Will not track HTTP server cert %s as it is not " "issued by IPA", nickname)
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 start_tracking_certificates(self, serverid): nickname = self.get_server_cert_nickname(serverid) dirname = config_dirname(serverid)[:-1] dsdb = certs.CertDB(self.realm, nssdir=dirname) if dsdb.is_ipa_issued_cert(api, nickname): dsdb.track_server_cert(nickname, self.principal, dsdb.passwd_fname, 'restart_dirsrv %s' % serverid) else: logger.debug( "Will not track DS server certificate %s as it is " "not issued by IPA", nickname)
def export_ra_pkcs12(self): agent_fd, agent_name = tempfile.mkstemp() os.write(agent_fd, self.dirman_password) os.close(agent_fd) try: db = certs.CertDB(api.env.realm, host_name=api.env.host) if db.has_nickname("ipaCert"): pkcs12_fname = os.path.join(self.dir, "ra.p12") db.export_pkcs12(pkcs12_fname, agent_name, "ipaCert") finally: os.remove(agent_name)
def __import_ca_certs(self): dirname = config_dirname(self.serverid) dsdb = certs.CertDB(self.realm, nssdir=dirname, subject_base=self.subject_base) ldap_uri = ipaldap.get_ldap_uri(self.fqdn) conn = ipaldap.LDAPClient(ldap_uri) conn.simple_bind(bind_dn=ipaldap.DIRMAN_DN, bind_password=self.dm_password) self.import_ca_certs(dsdb, self.ca_is_configured, conn) conn.unbind()
def __setup_pkinit(self): ca_db = certs.CertDB(self.realm, host_name=self.fqdn, subject_base=self.subject_base) if self.pkcs12_info: ca_db.install_pem_from_p12(self.pkcs12_info[0], self.pkcs12_info[1], paths.KDC_PEM) else: raise RuntimeError("PKI not supported yet\n") # Finally copy the cacert in the krb directory so we don't # have any selinux issues with the file context shutil.copyfile(CACERT, paths.CACERT_PEM)
def add_ca_cert(self, cacert_fname, cacert_name=''): """Add a CA certificate to the directory server cert db. We first have to shut down the directory server in case it has opened the cert db read-only. Then we use the CertDB class to add the CA cert. We have to provide a nickname, and we do not use 'IPA CA' since that's the default, so we use 'Imported CA' if none specified. Then we restart the server.""" # first make sure we have a valid cacert_fname try: if not os.access(cacert_fname, os.R_OK): root_logger.critical( "The given CA cert file named [%s] could not be read" % cacert_fname) return False except OSError as e: root_logger.critical( "The given CA cert file named [%s] could not be read: %s" % (cacert_fname, str(e))) return False # ok - ca cert file can be read # shutdown the server self.stop() dirname = config_dirname(installutils.realm_to_serverid(self.realm)) certdb = certs.CertDB( self.realm, nssdir=dirname, subject_base=self.subject_base, ca_subject=self.ca_subject, ) if not cacert_name or len(cacert_name) == 0: cacert_name = "Imported CA" # we can't pass in the nickname, so we set the instance variable certdb.cacert_name = cacert_name status = True try: certdb.load_cacert(cacert_fname, 'C,,') except ipautil.CalledProcessError as e: root_logger.critical( "Error importing CA cert file named [%s]: %s" % (cacert_fname, str(e))) status = False # restart the directory server self.start() return status
def __upload_ca_cert(self): """ Upload the CA certificate from the NSS database to the LDAP directory. """ dirname = config_dirname(self.serverid) dsdb = certs.CertDB(self.realm, nssdir=dirname, subject_base=self.subject_base) trust_flags = dict(reversed(dsdb.list_certs())) ldap_uri = ipaldap.get_ldap_uri(self.fqdn) conn = ipaldap.LDAPClient(ldap_uri) conn.simple_bind(bind_dn=ipaldap.DIRMAN_DN, bind_password=self.dm_password) nicknames = dsdb.find_root_cert(self.cacert_name)[:-1] for nickname in nicknames: cert = dsdb.get_cert_from_db(nickname) certstore.put_ca_cert_nss(conn, self.suffix, cert, nickname, trust_flags[nickname]) nickname = self.cacert_name cert = dsdb.get_cert_from_db(nickname) cacert_flags = trust_flags[nickname] if self.setup_pkinit: cacert_flags = TrustFlags( cacert_flags.has_key, cacert_flags.trusted, cacert_flags.ca, (cacert_flags.usages | {x509.EKU_PKINIT_CLIENT_AUTH, x509.EKU_PKINIT_KDC}), ) certstore.put_ca_cert_nss(conn, self.suffix, cert, nickname, cacert_flags, config_ipa=self.ca_is_configured, config_compat=self.master_fqdn is None) conn.unbind()
def execute(self, **options): ldap = self.obj.backend (cdn, ipa_config) = ldap.get_ipa_config() subject_base = ipa_config.get('ipacertificatesubjectbase', [None])[0] dirname = config_dirname(realm_to_serverid(api.env.realm)) certdb = certs.CertDB(api.env.realm, nssdir=dirname, subject_base=subject_base) dercert = certdb.get_cert_from_db(certdb.cacert_name, pem=False) updates = {} dn = DN(('cn', 'CACert'), ('cn', 'ipa'), ('cn','etc'), api.env.basedn) cacrt_entry = ['objectclass:nsContainer', 'objectclass:pkiCA', 'cn:CAcert', 'cACertificate;binary:%s' % dercert, ] updates[dn] = {'dn': dn, 'default': cacrt_entry} return (False, True, [updates])
def import_cert(self, dirname, pkcs12_passwd, old_cert, principal, command): pkcs12_file, pin, ca_cert = installutils.load_pkcs12( cert_files=self.args, key_password=pkcs12_passwd, key_nickname=self.options.cert_name, ca_cert_files=[paths.IPA_CA_CRT], host_name=api.env.host) dirname = os.path.normpath(dirname) cdb = certs.CertDB(api.env.realm, nssdir=dirname) # Check that the ca_cert is known and trusted self.check_chain(pkcs12_file.name, pin, cdb) try: ca_enabled = api.Command.ca_is_enabled()['result'] if ca_enabled: cdb.untrack_server_cert(old_cert) cdb.delete_cert(old_cert) prevs = cdb.find_server_certs() cdb.import_pkcs12(pkcs12_file.name, pin) news = cdb.find_server_certs() server_certs = [item for item in news if item not in prevs] server_cert = server_certs[0][0] 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)) # And compare with the CA which signed this certificate if ca_cert == ipa_ca_cert: cdb.track_server_cert(server_cert, principal, cdb.passwd_fname, command) except RuntimeError as e: raise admintool.ScriptError(str(e)) return server_cert
def renew_self_signed(self, ca): print("Renewing CA certificate, please wait") msg = "You cannot specify {} when renewing a self-signed CA" if self.options.external_ca_type: raise admintool.ScriptError(msg.format("--external-ca-type")) if self.options.external_ca_profile: raise admintool.ScriptError(msg.format("--external-ca-profile")) try: ca.set_renewal_master() except errors.NotFound: raise admintool.ScriptError("CA renewal master not found") self.resubmit_request() db = certs.CertDB(api.env.realm, nssdir=paths.PKI_TOMCAT_ALIAS_DIR) cert = db.get_cert_from_db(self.cert_nickname) update_ipa_ca_entry(api, cert) print("CA certificate successfully renewed")
def export_certdb(self, fname, passwd_fname): """Export a cert database :param fname: The file to export to (relative to the info directory) :param passwd_fname: File that holds the cert DB password """ hostname = self.replica_fqdn subject_base = self.subject_base ca_subject = ca.lookup_ca_subject(api, subject_base) nickname = "Server-Cert" try: db = certs.CertDB(api.env.realm, nssdir=self.dir, host_name=api.env.host, subject_base=subject_base, ca_subject=ca_subject) db.create_passwd_file() db.create_from_cacert() db.create_server_cert(nickname, hostname) pkcs12_fname = os.path.join(self.dir, fname + ".p12") try: db.export_pkcs12(pkcs12_fname, passwd_fname, nickname) except ipautil.CalledProcessError as e: logger.info("error exporting Server certificate: %s", e) installutils.remove_file(pkcs12_fname) installutils.remove_file(passwd_fname) self.remove_info_file("cert8.db") self.remove_info_file("key3.db") self.remove_info_file("secmod.db") self.remove_info_file("noise.txt") orig_filename = passwd_fname + ".orig" if ipautil.file_exists(orig_filename): installutils.remove_file(orig_filename) except errors.CertificateOperationError as e: raise admintool.ScriptError(str(e))
def __get_ds_cert(self): nssdb_dir = config_dirname(self.serverid) db = certs.CertDB( self.realm, nssdir=nssdb_dir, subject_base=self.subject_base, ca_subject=self.ca_subject, ) db.create_from_cacert() db.request_service_cert(self.nickname, self.principal, self.fqdn) db.create_pin_file() # Connect to self over ldapi as Directory Manager and configure SSL ldap_uri = ipaldap.get_ldap_uri(protocol='ldapi', realm=self.realm) conn = ipaldap.LDAPClient(ldap_uri) conn.external_bind() mod = [(ldap.MOD_REPLACE, "nsSSLClientAuth", "allowed"), (ldap.MOD_REPLACE, "nsSSL3Ciphers", "default"), (ldap.MOD_REPLACE, "allowWeakCipher", "off")] conn.modify_s(DN(('cn', 'encryption'), ('cn', 'config')), mod) mod = [(ldap.MOD_ADD, "nsslapd-security", "on")] conn.modify_s(DN(('cn', 'config')), mod) entry = conn.make_entry( DN(('cn', 'RSA'), ('cn', 'encryption'), ('cn', 'config')), objectclass=["top", "nsEncryptionModule"], cn=["RSA"], nsSSLPersonalitySSL=[self.nickname], nsSSLToken=["internal (software)"], nsSSLActivation=["on"], ) conn.add_entry(entry) conn.unbind() # check for open secure port 636 from now on self.open_ports.append(636)
def replace_key_cert_files(self, cert, key, cert_fname, key_fname, ca_cert, passwd_fname=None, profile=None, cmgr_post_command=None): try: ca_enabled = api.Command.ca_is_enabled()['result'] if ca_enabled: certmonger.stop_tracking(certfile=cert_fname) pkey_passwd = None if passwd_fname is not None: with open(passwd_fname, 'rb') as f: pkey_passwd = f.read() x509.write_certificate(cert, cert_fname) x509.write_pem_private_key(key, key_fname, pkey_passwd) if ca_enabled: # Start tracking only if the cert was issued by IPA CA # Retrieve IPA CA cdb = certs.CertDB(api.env.realm, nssdir=paths.IPA_NSSDB_DIR) ipa_ca_cert = cdb.get_cert_from_db( get_ca_nickname(api.env.realm)) # And compare with the CA which signed this certificate if ca_cert == ipa_ca_cert: req_id = certmonger.start_tracking( (cert_fname, key_fname), pinfile=passwd_fname, storage='FILE', post_command=cmgr_post_command) return req_id except RuntimeError as e: raise admintool.ScriptError(str(e)) return None
def check_cs_cfg(self): """Compare cert blob in NSS database to that stored in CS.cfg""" if not self.ca.is_configured(): logger.debug("No CA configured, skipping CS config check") return blobs = { 'auditSigningCert cert-pki-ca': 'ca.audit_signing.cert', 'ocspSigningCert cert-pki-ca': 'ca.ocsp_signing.cert', 'caSigningCert cert-pki-ca': 'ca.signing.cert', 'subsystemCert cert-pki-ca': 'ca.subsystem.cert', 'Server-Cert cert-pki-ca': 'ca.sslserver.cert' } db = certs.CertDB(api.env.realm, paths.PKI_TOMCAT_ALIAS_DIR) for nickname, _trust_flags in db.list_certs(): try: val = get_directive(paths.CA_CS_CFG_PATH, blobs[nickname], '=') except KeyError: print("%s not found, assuming 3rd party" % nickname) continue if val is None: self.failure('Certificate %s not found in %s' % (blobs[nickname], paths.CA_CS_CFG_PATH)) continue cert = db.get_cert_from_db(nickname) if isinstance(cert, string_types): pem = cert pem = pem.replace('\r\n', '') else: pem = cert.public_bytes(Encoding.PEM).decode() pem = pem.replace('\n', '') pem = pem.replace('-----BEGIN CERTIFICATE-----', '') pem = pem.replace('-----END CERTIFICATE-----', '') # TODO: Handle multi-valued certs. if pem.strip() != val: self.failure('Certificate %s does not match %s' % (blobs[nickname], paths.CA_CS_CFG_PATH))
def import_cert(self, dirname, pkcs12_passwd, old_cert, principal, command): pkcs12_file, pin, ca_cert = installutils.load_pkcs12( cert_files=self.args, key_password=pkcs12_passwd, key_nickname=self.options.cert_name, ca_cert_files=[CACERT], host_name=api.env.host) cdb = certs.CertDB(api.env.realm, nssdir=dirname) try: ca_enabled = api.Command.ca_is_enabled()['result'] if ca_enabled: cdb.untrack_server_cert(old_cert) cdb.delete_cert(old_cert) cdb.import_pkcs12(pkcs12_file.name, pin) server_cert = cdb.find_server_certs()[0][0] if ca_enabled: cdb.track_server_cert(server_cert, principal, cdb.passwd_fname, command) except RuntimeError, e: raise admintool.ScriptError(str(e))
def __enable_ssl(self): dirname = config_dirname(self.serverid) dsdb = certs.CertDB(self.realm, nssdir=dirname, subject_base=self.subject_base) if self.pkcs12_info: if self.ca_is_configured: trust_flags = 'CT,C,C' else: trust_flags = None dsdb.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1], ca_file=self.ca_file, trust_flags=trust_flags) server_certs = dsdb.find_server_certs() if len(server_certs) == 0: raise RuntimeError("Could not find a suitable server cert in import in %s" % self.pkcs12_info[0]) # We only handle one server cert self.nickname = server_certs[0][0] self.dercert = dsdb.get_cert_from_db(self.nickname, pem=False) if self.ca_is_configured: dsdb.track_server_cert( self.nickname, self.principal, dsdb.passwd_fname, 'restart_dirsrv %s' % self.serverid) else: cadb = certs.CertDB(self.realm, host_name=self.fqdn, subject_base=self.subject_base) # FIXME, need to set this nickname in the RA plugin cadb.export_ca_cert('ipaCert', False) dsdb.create_from_cacert(cadb.cacert_fname, passwd=None) ca_args = ['/usr/libexec/certmonger/dogtag-submit', '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn, '--dbdir', paths.HTTPD_ALIAS_DIR, '--nickname', 'ipaCert', '--sslpinfile', paths.ALIAS_PWDFILE_TXT, '--agent-submit'] helper = " ".join(ca_args) prev_helper = certmonger.modify_ca_helper('IPA', helper) try: cmd = 'restart_dirsrv %s' % self.serverid certmonger.request_and_wait_for_cert( nssdb=dirname, nickname=self.nickname, principal=self.principal, passwd_fname=dsdb.passwd_fname, subject=str(DN(('CN', self.fqdn), self.subject_base)), ca='IPA', profile=dogtag.DEFAULT_PROFILE, dns=[self.fqdn], post_command=cmd) finally: certmonger.modify_ca_helper('IPA', prev_helper) self.dercert = dsdb.get_cert_from_db(self.nickname, pem=False) dsdb.create_pin_file() self.cacert_name = dsdb.cacert_name ldap_uri = ipaldap.get_ldap_uri(self.fqdn) conn = ipaldap.LDAPClient(ldap_uri) conn.simple_bind(bind_dn=ipaldap.DIRMAN_DN, bind_password=self.dm_password) mod = [(ldap.MOD_REPLACE, "nsSSLClientAuth", "allowed"), (ldap.MOD_REPLACE, "nsSSL3Ciphers", "default"), (ldap.MOD_REPLACE, "allowWeakCipher", "off")] conn.modify_s(DN(('cn', 'encryption'), ('cn', 'config')), mod) mod = [(ldap.MOD_ADD, "nsslapd-security", "on")] conn.modify_s(DN(('cn', 'config')), mod) entry = conn.make_entry( DN(('cn', 'RSA'), ('cn', 'encryption'), ('cn', 'config')), objectclass=["top", "nsEncryptionModule"], cn=["RSA"], nsSSLPersonalitySSL=[self.nickname], nsSSLToken=["internal (software)"], nsSSLActivation=["on"], ) conn.add_entry(entry) conn.unbind() # check for open secure port 636 from now on self.open_ports.append(636)
def start_tracking_certificates(self, serverid): dirname = config_dirname(serverid)[:-1] dsdb = certs.CertDB(self.realm, nssdir=dirname) dsdb.track_server_cert(self.nickname, self.principal, dsdb.passwd_fname, 'restart_dirsrv %s' % serverid)
def start_tracking_certificates(self): db = certs.CertDB(self.realm) db.track_server_cert(self.cert_nickname, self.principal, db.passwd_fname, 'restart_httpd')
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 stop_tracking_certificates(self): db = certs.CertDB(api.env.realm) db.untrack_server_cert(self.cert_nickname)
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 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 execute(self, **options): db = certs.CertDB(self.api.env.realm, paths.HTTPD_ALIAS_DIR) 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) 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 if nickname == ca_nickname and ca_enabled: trust_flags = certdb.IPA_CA_TRUST_FLAGS cert = db.get_cert_from_db(nickname, pem=False) 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: self.log.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: if b'' in entry['cACertificate;binary']: entry.single_value['cACertificate;binary'] = ca_cert ldap.update_entry(entry) return False, []